use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use super::{
Expression, Function, Input, Lineage, Metadata, Output, Rule, SemanticAction,
TransformationSemantics, Versioning,
};
pub const SUPPORTED_DTCS_VERSIONS: &[&str] = &["1.0.0", "1.0.0-draft"];
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TransformationContract {
pub dtcs_version: String,
pub id: String,
pub name: String,
pub version: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
#[serde(default)]
pub inputs: Vec<Input>,
#[serde(default)]
pub outputs: Vec<Output>,
#[serde(default)]
pub semantic_actions: Vec<SemanticAction>,
#[serde(default)]
pub expressions: Vec<Expression>,
#[serde(default)]
pub functions: Vec<Function>,
#[serde(default)]
pub rules: Vec<Rule>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub lineage: Option<Lineage>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub versioning: Option<Versioning>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub semantics: Option<TransformationSemantics>,
#[serde(default, flatten)]
pub extensions: IndexMap<String, Value>,
}
impl TransformationContract {
#[must_use]
pub fn validate(&self) -> crate::ValidationReport {
crate::validate(self)
}
#[must_use]
pub fn declared_field_names(&self) -> Vec<String> {
let mut names = Vec::new();
for input in &self.inputs {
if let Some(schema) = &input.schema {
for field in &schema.fields {
names.push(field.name.clone());
}
}
}
for output in &self.outputs {
if let Some(schema) = &output.schema {
for field in &schema.fields {
names.push(field.name.clone());
}
}
}
names
}
#[must_use]
pub fn interface_ids(&self) -> Vec<String> {
self.inputs
.iter()
.map(|i| i.id.clone())
.chain(self.outputs.iter().map(|o| o.id.clone()))
.collect()
}
}