use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::analysis::AnalysisFinding;
use crate::model::{
Expression, Function, Input, Lineage, Metadata, Output, Rule, SemanticAction,
TransformationSemantics, Versioning,
};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlanIdentity {
pub dtcs_version: String,
pub id: String,
pub name: String,
pub version: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlanNode {
pub id: String,
pub kind: PlanNodeKind,
pub object_ref: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "camelCase")]
pub enum PlanNodeKind {
SemanticAction(SemanticAction),
Expression(Expression),
Rule(Rule),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum DependencyReason {
Lineage,
FieldRead,
FieldWrite,
ExplicitOrder,
RulePhase,
InterfaceCondition,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlanDependency {
pub from: String,
pub to: String,
pub reason: DependencyReason,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct InterfaceConditionRef {
pub interface_id: String,
pub is_input: bool,
pub rule_id: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlanGuarantees {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub semantics: Option<TransformationSemantics>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub input_preconditions: Vec<InterfaceConditionRef>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub output_postconditions: Vec<InterfaceConditionRef>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TransformationPlan {
pub identity: PlanIdentity,
pub inputs: Vec<Input>,
pub outputs: Vec<Output>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub functions: Vec<Function>,
pub nodes: Vec<PlanNode>,
pub dependencies: Vec<PlanDependency>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub lineage: Option<Lineage>,
pub guarantees: PlanGuarantees,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub versioning: Option<Versioning>,
#[serde(default, skip_serializing_if = "IndexMap::is_empty")]
pub extensions: IndexMap<String, Value>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub findings: Vec<AnalysisFinding>,
}