Skip to main content

mig_types/schema/
mig.rs

1use serde::{Deserialize, Serialize};
2
3use super::common::{Cardinality, CodeDefinition};
4
5/// Complete MIG schema for a message type.
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct MigSchema {
8    /// The EDIFACT message type (e.g., "UTILMD", "ORDERS").
9    pub message_type: String,
10    /// Optional variant (e.g., "Strom", "Gas").
11    pub variant: Option<String>,
12    /// Version number from the MIG (e.g., "S2.1", "1.4a").
13    pub version: String,
14    /// Publication date string.
15    pub publication_date: String,
16    /// Author (typically "BDEW").
17    pub author: String,
18    /// Format version directory (e.g., "FV2504").
19    pub format_version: String,
20    /// Path to the source XML file.
21    pub source_file: String,
22    /// Top-level segment definitions (not in groups).
23    pub segments: Vec<MigSegment>,
24    /// Segment group definitions (contain more segments).
25    pub segment_groups: Vec<MigSegmentGroup>,
26}
27
28/// A segment (S_*) definition from the MIG.
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct MigSegment {
31    /// Segment identifier (e.g., "UNH", "BGM", "NAD").
32    pub id: String,
33    /// Human-readable name.
34    pub name: String,
35    /// Description of the segment.
36    pub description: Option<String>,
37    /// Position counter (e.g., "0010", "0020").
38    pub counter: Option<String>,
39    /// Nesting level (0=root, 1=first level, etc.).
40    pub level: i32,
41    /// Sequence number within the message.
42    pub number: Option<String>,
43    /// Standard maximum repetitions.
44    pub max_rep_std: i32,
45    /// Specification maximum repetitions.
46    pub max_rep_spec: i32,
47    /// Standard status (M=Mandatory, C=Conditional, etc.).
48    pub status_std: Option<String>,
49    /// Specification status (M, R, D, O, N).
50    pub status_spec: Option<String>,
51    /// Example EDIFACT string.
52    pub example: Option<String>,
53    /// Direct child data elements.
54    pub data_elements: Vec<MigDataElement>,
55    /// Child composite elements.
56    pub composites: Vec<MigComposite>,
57}
58
59impl MigSegment {
60    /// Returns the effective cardinality based on spec or std status.
61    pub fn cardinality(&self) -> Cardinality {
62        let status = self
63            .status_spec
64            .as_deref()
65            .or(self.status_std.as_deref())
66            .unwrap_or("C");
67        Cardinality::from_status(status)
68    }
69
70    /// Returns the effective max repetitions (spec overrides std).
71    pub fn max_rep(&self) -> i32 {
72        self.max_rep_spec.max(self.max_rep_std)
73    }
74}
75
76/// A segment group (G_SG*) definition from the MIG.
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct MigSegmentGroup {
79    /// Group identifier (e.g., "SG1", "SG2", "SG10").
80    pub id: String,
81    /// Human-readable name.
82    pub name: String,
83    /// Description of the segment group.
84    pub description: Option<String>,
85    /// Position counter (e.g., "0070", "0500").
86    pub counter: Option<String>,
87    /// Nesting level.
88    pub level: i32,
89    /// Standard maximum repetitions.
90    pub max_rep_std: i32,
91    /// Specification maximum repetitions.
92    pub max_rep_spec: i32,
93    /// Standard status.
94    pub status_std: Option<String>,
95    /// Specification status.
96    pub status_spec: Option<String>,
97    /// Segments directly in this group.
98    pub segments: Vec<MigSegment>,
99    /// Nested segment groups.
100    pub nested_groups: Vec<MigSegmentGroup>,
101    /// Optional variant qualifier code for the entry segment.
102    /// When set, the assembler only matches segments whose entry qualifier
103    /// equals this code (e.g., "Z98" for SEQ+Z98, "ZD5" for SEQ+ZD5).
104    #[serde(default, skip_serializing_if = "Option::is_none")]
105    pub variant_code: Option<String>,
106    /// Position of the variant qualifier in the entry segment:
107    /// (element_index, component_index). Defaults to (0, 0) when absent.
108    /// Some segments have the qualifier in a composite at a non-zero position
109    /// (e.g., CCI with qualifier in C240/D7037 at element index 2).
110    #[serde(default, skip_serializing_if = "Option::is_none")]
111    pub variant_qualifier_position: Option<(usize, usize)>,
112    /// All allowed qualifier codes for this variant (assembler matches ANY).
113    #[serde(default)]
114    pub variant_codes: Vec<String>,
115    /// Number of MIG XML variants that were merged into this group definition.
116    /// When multiple SG2 definitions (MS, MR, DP, etc.) are merged into one,
117    /// this holds the count of merged variants. Used to compute the correct
118    /// max_reps for PID schema generation (variant count, not max of individual max_reps).
119    #[serde(default, skip_serializing_if = "Option::is_none")]
120    pub merged_variant_count: Option<u32>,
121}
122
123impl MigSegmentGroup {
124    /// Returns the effective cardinality.
125    pub fn cardinality(&self) -> Cardinality {
126        let status = self
127            .status_spec
128            .as_deref()
129            .or(self.status_std.as_deref())
130            .unwrap_or("C");
131        Cardinality::from_status(status)
132    }
133}
134
135/// A composite element (C_*) definition from the MIG.
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct MigComposite {
138    /// Composite identifier (e.g., "S009", "C002").
139    pub id: String,
140    /// Human-readable name.
141    pub name: String,
142    /// Description.
143    pub description: Option<String>,
144    /// Standard status.
145    pub status_std: Option<String>,
146    /// Specification status.
147    pub status_spec: Option<String>,
148    /// Child data elements within this composite.
149    pub data_elements: Vec<MigDataElement>,
150    /// Position of this composite within its parent segment (0-based).
151    pub position: usize,
152}
153
154/// A data element (D_*) definition from the MIG.
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct MigDataElement {
157    /// Element identifier (e.g., "0062", "3035").
158    pub id: String,
159    /// Human-readable name.
160    pub name: String,
161    /// Description.
162    pub description: Option<String>,
163    /// Standard status.
164    pub status_std: Option<String>,
165    /// Specification status.
166    pub status_spec: Option<String>,
167    /// Standard format (e.g., "an..14", "n13").
168    pub format_std: Option<String>,
169    /// Specification format.
170    pub format_spec: Option<String>,
171    /// Allowed code values, if restricted.
172    pub codes: Vec<CodeDefinition>,
173    /// Position within parent (0-based).
174    pub position: usize,
175}