// Code generated by sidekick. DO NOT EDIT.
//
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation
import GoogleCloudWkt

/// Represents a user-visible job which provides the insights for the related
/// data source.
///
/// For example:
///
/// * Data quality: generates queries based on the rules and runs against the
///   data to get data quality check results. For more information, see [Auto
///   data quality
///   overview](https://cloud.google.com/dataplex/docs/auto-data-quality-overview).
/// * Data profile: analyzes the data in tables and generates insights about
///   the structure, content and relationships (such as null percent,
///   cardinality, min/max/mean, etc). For more information, see [About data
///   profiling](https://cloud.google.com/dataplex/docs/data-profiling-overview).
/// * Data discovery: scans data in Cloud Storage buckets to extract and then
///   catalog metadata. For more information, see [Discover and catalog Cloud
///   Storage data](https://cloud.google.com/bigquery/docs/automatic-discovery).
/// * Data documentation: analyzes the table or dataset metadata and generates
///   insights. For tables, insights include descriptions and sample SQL
///   queries. For datasets, insights include descriptions, schema relationships
///   and sample SQL queries. For more information, see [Generate data insights
///   in BigQuery](https://cloud.google.com/bigquery/docs/data-insights).
public struct DataScan: Codable, Equatable, GoogleCloudWkt._AnyPackable,
  Sendable
{
  /// Output only. Identifier. The relative resource name of the scan, of the
  /// form: `projects/{project}/locations/{location_id}/dataScans/{datascan_id}`,
  /// where `project` refers to a *project_id* or *project_number* and
  /// `location_id` refers to a Google Cloud region.
  public var name: Swift.String = Swift.String()

  /// Output only. System generated globally unique ID for the scan. This ID will
  /// be different if the scan is deleted and re-created with the same name.
  public var uid: Swift.String = Swift.String()

  /// Optional. Description of the scan.
  ///
  /// * Must be between 1-1024 characters.
  public var description: Swift.String = Swift.String()

  /// Optional. User friendly display name.
  ///
  /// * Must be between 1-256 characters.
  public var displayName: Swift.String = Swift.String()

  /// Optional. User-defined labels for the scan.
  public var labels: [Swift.String: Swift.String] = [:]

  /// Output only. Current state of the DataScan.
  public var state: State = State()

  /// Output only. The time when the scan was created.
  public var createTime: GoogleCloudWkt.Timestamp? = nil

  /// Output only. The time when the scan was last updated.
  public var updateTime: GoogleCloudWkt.Timestamp? = nil

  /// Required. The data source for DataScan.
  public var data: DataSource? = nil

  /// Optional. DataScan execution settings.
  ///
  /// If not specified, the fields in it will use their default values.
  public var executionSpec: DataScan.ExecutionSpec? = nil

  /// Output only. Status of the data scan execution.
  public var executionStatus: DataScan.ExecutionStatus? = nil

  /// Output only. The type of DataScan.
  public var type: DataScanType = DataScanType()

  /// Optional. Immutable. The identity to run the datascan.
  /// If not specified, defaults to the Dataplex Service Agent.
  public var executionIdentity: ExecutionIdentity? = nil

  /// Data scan related setting.
  /// The settings are required and immutable. After you configure the settings
  /// for one type of data scan, you can't change the data scan to a different
  /// type of data scan.
  public var spec: OneOf_Spec? = nil

  /// The result of the data scan.
  public var result: OneOf_Result? = nil

  /// Initialize a new instance of `DataScan`.
  public init() {}

  /// Use `config` to return a new instance of this object, with some fields updated.
  ///
  /// Commonly used to initialize the value, for example:
  ///
  /// ```
  /// let value = DataScan().with { $0.name = ... }
  /// ```
  public func with(_ config: (inout Self) throws -> Swift.Void) rethrows -> Self {
    var copy = self
    try config(&copy)
    return copy
  }

  private enum CodingKeys: Swift.String, CodingKey {
    case name = "name"
    case uid = "uid"
    case description = "description"
    case displayName = "displayName"
    case labels = "labels"
    case state = "state"
    case createTime = "createTime"
    case updateTime = "updateTime"
    case data = "data"
    case executionSpec = "executionSpec"
    case executionStatus = "executionStatus"
    case type = "type"
    case dataQualitySpec = "dataQualitySpec"
    case dataProfileSpec = "dataProfileSpec"
    case dataDiscoverySpec = "dataDiscoverySpec"
    case dataDocumentationSpec = "dataDocumentationSpec"
    case dataQualityResult = "dataQualityResult"
    case dataProfileResult = "dataProfileResult"
    case dataDiscoveryResult = "dataDiscoveryResult"
    case dataDocumentationResult = "dataDocumentationResult"
    case executionIdentity = "executionIdentity"
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    self.name = try container.decode(Swift.String.self, forKey: .name)
    self.uid = try container.decode(Swift.String.self, forKey: .uid)
    self.description = try container.decode(Swift.String.self, forKey: .description)
    self.displayName = try container.decode(Swift.String.self, forKey: .displayName)
    self.labels = try container.decode([Swift.String: Swift.String].self, forKey: .labels)
    self.state = try container.decode(State.self, forKey: .state)
    self.createTime = try container.decodeIfPresent(
      GoogleCloudWkt.Timestamp.self, forKey: .createTime)
    self.updateTime = try container.decodeIfPresent(
      GoogleCloudWkt.Timestamp.self, forKey: .updateTime)
    self.data = try container.decodeIfPresent(DataSource.self, forKey: .data)
    self.executionSpec = try container.decodeIfPresent(
      DataScan.ExecutionSpec.self, forKey: .executionSpec)
    self.executionStatus = try container.decodeIfPresent(
      DataScan.ExecutionStatus.self, forKey: .executionStatus)
    self.type = try container.decode(DataScanType.self, forKey: .type)
    self.executionIdentity = try container.decodeIfPresent(
      ExecutionIdentity.self, forKey: .executionIdentity)

    var spec: OneOf_Spec? = nil
    let specCheckAndSet = {
      if spec != nil {
        throw DecodingError.dataCorrupted(
          DecodingError.Context(
            codingPath: decoder.codingPath, debugDescription: "Multiple values set for oneof 'spec'"
          ))
      }
      spec = $0
    }
    if let dataQualitySpec = try container.decodeIfPresent(
      DataQualitySpec?.self, forKey: .dataQualitySpec)
    {
      try specCheckAndSet(.dataQualitySpec(dataQualitySpec))
    }
    if let dataProfileSpec = try container.decodeIfPresent(
      DataProfileSpec?.self, forKey: .dataProfileSpec)
    {
      try specCheckAndSet(.dataProfileSpec(dataProfileSpec))
    }
    if let dataDiscoverySpec = try container.decodeIfPresent(
      DataDiscoverySpec?.self, forKey: .dataDiscoverySpec)
    {
      try specCheckAndSet(.dataDiscoverySpec(dataDiscoverySpec))
    }
    if let dataDocumentationSpec = try container.decodeIfPresent(
      DataDocumentationSpec?.self, forKey: .dataDocumentationSpec)
    {
      try specCheckAndSet(.dataDocumentationSpec(dataDocumentationSpec))
    }
    self.spec = spec

    var result: OneOf_Result? = nil
    let resultCheckAndSet = {
      if result != nil {
        throw DecodingError.dataCorrupted(
          DecodingError.Context(
            codingPath: decoder.codingPath,
            debugDescription: "Multiple values set for oneof 'result'"))
      }
      result = $0
    }
    if let dataQualityResult = try container.decodeIfPresent(
      DataQualityResult?.self, forKey: .dataQualityResult)
    {
      try resultCheckAndSet(.dataQualityResult(dataQualityResult))
    }
    if let dataProfileResult = try container.decodeIfPresent(
      DataProfileResult?.self, forKey: .dataProfileResult)
    {
      try resultCheckAndSet(.dataProfileResult(dataProfileResult))
    }
    if let dataDiscoveryResult = try container.decodeIfPresent(
      DataDiscoveryResult?.self, forKey: .dataDiscoveryResult)
    {
      try resultCheckAndSet(.dataDiscoveryResult(dataDiscoveryResult))
    }
    if let dataDocumentationResult = try container.decodeIfPresent(
      DataDocumentationResult?.self, forKey: .dataDocumentationResult)
    {
      try resultCheckAndSet(.dataDocumentationResult(dataDocumentationResult))
    }
    self.result = result
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(self.name, forKey: .name)
    try container.encode(self.uid, forKey: .uid)
    try container.encode(self.description, forKey: .description)
    try container.encode(self.displayName, forKey: .displayName)
    try container.encode(self.labels, forKey: .labels)
    try container.encode(self.state, forKey: .state)
    try container.encode(self.createTime, forKey: .createTime)
    try container.encode(self.updateTime, forKey: .updateTime)
    try container.encode(self.data, forKey: .data)
    try container.encode(self.executionSpec, forKey: .executionSpec)
    try container.encode(self.executionStatus, forKey: .executionStatus)
    try container.encode(self.type, forKey: .type)
    try container.encode(self.executionIdentity, forKey: .executionIdentity)

    if let choice = self.spec {
      switch choice {
      case .dataQualitySpec(let value):
        try container.encode(value, forKey: .dataQualitySpec)
      case .dataProfileSpec(let value):
        try container.encode(value, forKey: .dataProfileSpec)
      case .dataDiscoverySpec(let value):
        try container.encode(value, forKey: .dataDiscoverySpec)
      case .dataDocumentationSpec(let value):
        try container.encode(value, forKey: .dataDocumentationSpec)
      }
    }

    if let choice = self.result {
      switch choice {
      case .dataQualityResult(let value):
        try container.encode(value, forKey: .dataQualityResult)
      case .dataProfileResult(let value):
        try container.encode(value, forKey: .dataProfileResult)
      case .dataDiscoveryResult(let value):
        try container.encode(value, forKey: .dataDiscoveryResult)
      case .dataDocumentationResult(let value):
        try container.encode(value, forKey: .dataDocumentationResult)
      }
    }
  }

  /// DataScan execution settings.
  public struct ExecutionSpec: Codable, Equatable, GoogleCloudWkt._AnyPackable,
    Sendable
  {
    /// Optional. Spec related to how often and when a scan should be triggered.
    ///
    /// If not specified, the default is `OnDemand`, which means the scan will
    /// not run until the user calls `RunDataScan` API.
    public var trigger: Trigger? = nil

    /// Spec related to incremental scan of the data
    ///
    /// When an option is selected for incremental scan, it cannot be unset or
    /// changed. If not specified, a data scan will run for all data in the
    /// table.
    public var incremental: OneOf_Incremental? = nil

    /// Initialize a new instance of `ExecutionSpec`.
    public init() {}

    /// Use `config` to return a new instance of this object, with some fields updated.
    ///
    /// Commonly used to initialize the value, for example:
    ///
    /// ```
    /// let value = ExecutionSpec().with { $0.trigger = ... }
    /// ```
    public func with(_ config: (inout Self) throws -> Swift.Void) rethrows -> Self {
      var copy = self
      try config(&copy)
      return copy
    }

    private enum CodingKeys: Swift.String, CodingKey {
      case trigger = "trigger"
      case field = "field"
    }

    public init(from decoder: Decoder) throws {
      let container = try decoder.container(keyedBy: CodingKeys.self)
      self.trigger = try container.decodeIfPresent(Trigger.self, forKey: .trigger)

      var incremental: OneOf_Incremental? = nil
      let incrementalCheckAndSet = {
        if incremental != nil {
          throw DecodingError.dataCorrupted(
            DecodingError.Context(
              codingPath: decoder.codingPath,
              debugDescription: "Multiple values set for oneof 'incremental'"))
        }
        incremental = $0
      }
      if let field = try container.decodeIfPresent(Swift.String.self, forKey: .field) {
        try incrementalCheckAndSet(.field(field))
      }
      self.incremental = incremental
    }

    public func encode(to encoder: Encoder) throws {
      var container = encoder.container(keyedBy: CodingKeys.self)
      try container.encode(self.trigger, forKey: .trigger)

      if let choice = self.incremental {
        switch choice {
        case .field(let value):
          try container.encode(value, forKey: .field)
        }
      }
    }

    /// Spec related to incremental scan of the data
    ///
    /// When an option is selected for incremental scan, it cannot be unset or
    /// changed. If not specified, a data scan will run for all data in the
    /// table.
    public enum OneOf_Incremental: Codable, Equatable, Sendable {
      /// Immutable. The unnested field (of type *Date* or *Timestamp*) that
      /// contains values which monotonically increase over time.
      ///
      /// If not specified, a data scan will run for all data in the table.
      case field(Swift.String)
    }

    public static var _anyTypeUrl: Swift.String {
      return "type.googleapis.com/google.cloud.dataplex.v1.DataScan.ExecutionSpec"
    }
    public init(fromAny any: GoogleCloudWkt.`Any`) throws {
      self = try GoogleCloudWkt._slowAnyDeserialize(Self.self, from: any)
    }
    public func _pack() throws -> GoogleCloudWkt.Struct {
      return try GoogleCloudWkt._slowAnySerialize(message: self)
    }
  }

  /// Status of the data scan execution.
  public struct ExecutionStatus: Codable, Equatable, GoogleCloudWkt._AnyPackable,
    Sendable
  {
    /// Optional. The time when the latest DataScanJob started.
    public var latestJobStartTime: GoogleCloudWkt.Timestamp? = nil

    /// Optional. The time when the latest DataScanJob ended.
    public var latestJobEndTime: GoogleCloudWkt.Timestamp? = nil

    /// Optional. The time when the DataScanJob execution was created.
    public var latestJobCreateTime: GoogleCloudWkt.Timestamp? = nil

    /// Initialize a new instance of `ExecutionStatus`.
    public init() {}

    /// Use `config` to return a new instance of this object, with some fields updated.
    ///
    /// Commonly used to initialize the value, for example:
    ///
    /// ```
    /// let value = ExecutionStatus().with { $0.latestJobStartTime = ... }
    /// ```
    public func with(_ config: (inout Self) throws -> Swift.Void) rethrows -> Self {
      var copy = self
      try config(&copy)
      return copy
    }

    public static var _anyTypeUrl: Swift.String {
      return "type.googleapis.com/google.cloud.dataplex.v1.DataScan.ExecutionStatus"
    }
    public init(fromAny any: GoogleCloudWkt.`Any`) throws {
      self = try GoogleCloudWkt._slowAnyDeserialize(Self.self, from: any)
    }
    public func _pack() throws -> GoogleCloudWkt.Struct {
      return try GoogleCloudWkt._slowAnySerialize(message: self)
    }
  }

  /// Data scan related setting.
  /// The settings are required and immutable. After you configure the settings
  /// for one type of data scan, you can't change the data scan to a different
  /// type of data scan.
  public enum OneOf_Spec: Codable, Equatable, Sendable {
    /// Settings for a data quality scan.
    indirect case dataQualitySpec(DataQualitySpec?)
    /// Settings for a data profile scan.
    indirect case dataProfileSpec(DataProfileSpec?)
    /// Settings for a data discovery scan.
    indirect case dataDiscoverySpec(DataDiscoverySpec?)
    /// Settings for a data documentation scan.
    indirect case dataDocumentationSpec(DataDocumentationSpec?)
  }

  /// The result of the data scan.
  public enum OneOf_Result: Codable, Equatable, Sendable {
    /// Output only. The result of a data quality scan.
    indirect case dataQualityResult(DataQualityResult?)
    /// Output only. The result of a data profile scan.
    indirect case dataProfileResult(DataProfileResult?)
    /// Output only. The result of a data discovery scan.
    indirect case dataDiscoveryResult(DataDiscoveryResult?)
    /// Output only. The result of a data documentation scan.
    indirect case dataDocumentationResult(DataDocumentationResult?)
  }

  public static var _anyTypeUrl: Swift.String {
    return "type.googleapis.com/google.cloud.dataplex.v1.DataScan"
  }
  public init(fromAny any: GoogleCloudWkt.`Any`) throws {
    self = try GoogleCloudWkt._slowAnyDeserialize(Self.self, from: any)
  }
  public func _pack() throws -> GoogleCloudWkt.Struct {
    return try GoogleCloudWkt._slowAnySerialize(message: self)
  }
}
