use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BaseFacet {
#[serde(rename = "_producer")]
pub producer: String,
#[serde(rename = "_schemaURL")]
pub schema_url: String,
}
impl BaseFacet {
pub fn new(producer: &str, schema: &str) -> Self {
Self {
producer: producer.to_string(),
schema_url: format!("https://openlineage.io/spec/facets/{schema}"),
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct RunFacets {
#[serde(skip_serializing_if = "Option::is_none")]
pub processing_engine: Option<ProcessingEngineRunFacet>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent: Option<ParentRunFacet>,
#[serde(rename = "nominalTime", skip_serializing_if = "Option::is_none")]
pub nominal_time: Option<NominalTimeRunFacet>,
#[serde(rename = "errorMessage", skip_serializing_if = "Option::is_none")]
pub error_message: Option<ErrorMessageRunFacet>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProcessingEngineRunFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub version: String,
pub name: String,
#[serde(rename = "openlineageAdapterVersion")]
pub openlineage_adapter_version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ParentRunFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub run: ParentRun,
pub job: ParentJob,
#[serde(skip_serializing_if = "Option::is_none")]
pub root: Option<RootParent>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ParentRun {
#[serde(rename = "runId")]
pub run_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ParentJob {
pub namespace: String,
pub name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RootParent {
pub run: ParentRun,
pub job: ParentJob,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NominalTimeRunFacet {
#[serde(flatten)]
pub base: BaseFacet,
#[serde(rename = "nominalStartTime")]
pub nominal_start_time: String,
#[serde(rename = "nominalEndTime", skip_serializing_if = "Option::is_none")]
pub nominal_end_time: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ErrorMessageRunFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub message: String,
#[serde(rename = "programmingLanguage")]
pub programming_language: String,
#[serde(rename = "stackTrace", skip_serializing_if = "Option::is_none")]
pub stack_trace: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct JobFacets {
#[serde(skip_serializing_if = "Option::is_none")]
pub sql: Option<SqlJobFacet>,
#[serde(rename = "jobType", skip_serializing_if = "Option::is_none")]
pub job_type: Option<JobTypeJobFacet>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SqlJobFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub query: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JobTypeJobFacet {
#[serde(flatten)]
pub base: BaseFacet,
#[serde(rename = "processingType")]
pub processing_type: String,
pub integration: String,
#[serde(rename = "jobType")]
pub job_type: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DocumentationJobFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub description: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OwnershipJobFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub owners: Vec<Owner>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Owner {
pub name: String,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub type_: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TagsJobFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub tags: Vec<TagsJobFacetFields>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TagsJobFacetFields {
pub key: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct DatasetFacets {
#[serde(skip_serializing_if = "Option::is_none")]
pub schema: Option<SchemaDatasetFacet>,
#[serde(rename = "dataSource", skip_serializing_if = "Option::is_none")]
pub data_source: Option<DataSourceDatasetFacet>,
#[serde(rename = "columnLineage", skip_serializing_if = "Option::is_none")]
pub column_lineage: Option<ColumnLineageDatasetFacet>,
#[serde(skip_serializing_if = "Option::is_none")]
pub symlinks: Option<SymlinksDatasetFacet>,
#[serde(
rename = "lifecycleStateChange",
skip_serializing_if = "Option::is_none"
)]
pub lifecycle_state_change: Option<LifecycleStateChangeDatasetFacet>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct OutputDatasetFacets {
#[serde(rename = "outputStatistics", skip_serializing_if = "Option::is_none")]
pub output_statistics: Option<OutputStatisticsOutputDatasetFacet>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
impl OutputDatasetFacets {
pub fn is_empty(&self) -> bool {
self.output_statistics.is_none() && self.extra.is_empty()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OutputStatisticsOutputDatasetFacet {
#[serde(flatten)]
pub base: BaseFacet,
#[serde(rename = "rowCount", skip_serializing_if = "Option::is_none")]
pub row_count: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub size: Option<i64>,
#[serde(rename = "fileCount", skip_serializing_if = "Option::is_none")]
pub file_count: Option<i64>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct InputDatasetFacets {
#[serde(rename = "inputStatistics", skip_serializing_if = "Option::is_none")]
pub input_statistics: Option<InputStatisticsInputDatasetFacet>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
impl InputDatasetFacets {
pub fn is_empty(&self) -> bool {
self.input_statistics.is_none() && self.extra.is_empty()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InputStatisticsInputDatasetFacet {
#[serde(flatten)]
pub base: BaseFacet,
#[serde(rename = "rowCount", skip_serializing_if = "Option::is_none")]
pub row_count: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub size: Option<i64>,
#[serde(rename = "fileCount", skip_serializing_if = "Option::is_none")]
pub file_count: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SchemaDatasetFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub fields: Vec<SchemaField>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SchemaField {
pub name: String,
#[serde(rename = "type")]
pub type_: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataSourceDatasetFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub name: String,
pub uri: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymlinksDatasetFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub identifiers: Vec<SymlinkIdentifier>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymlinkIdentifier {
pub namespace: String,
pub name: String,
#[serde(rename = "type")]
pub type_: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LifecycleStateChangeDatasetFacet {
#[serde(flatten)]
pub base: BaseFacet,
#[serde(rename = "lifecycleStateChange")]
pub lifecycle_state_change: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ColumnLineageDatasetFacet {
#[serde(flatten)]
pub base: BaseFacet,
pub fields: std::collections::BTreeMap<String, FieldLineage>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub dataset: Vec<InputField>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldLineage {
#[serde(rename = "inputFields")]
pub input_fields: Vec<InputField>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InputField {
pub namespace: String,
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub field: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub transformations: Vec<Transformation>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Transformation {
#[serde(rename = "type")]
pub type_: TransformationType,
#[serde(skip_serializing_if = "Option::is_none")]
pub subtype: Option<String>,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub description: String,
#[serde(default)]
pub masking: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum TransformationType {
Direct,
Indirect,
}