automapper_validation/
workflow_schema.rs1use std::collections::BTreeMap;
11
12use crate::expr::{ConditionExpr, ConditionParser};
13use crate::{AhbCodeRule, AhbFieldRule, AhbWorkflow};
14
15pub fn ahb_workflow_from_pid_schema(schema: &serde_json::Value) -> Option<AhbWorkflow> {
21 let pid = schema.get("pid")?.as_str()?;
22 let beschreibung = schema.get("beschreibung")?.as_str().unwrap_or("");
23 let kommunikation_von = schema
24 .get("kommunikation_von")
25 .and_then(|v| v.as_str())
26 .map(|s| s.to_string());
27
28 let mut fields = Vec::new();
29
30 if let Some(groups) = schema.get("fields").and_then(|v| v.as_object()) {
32 for (_group_name, group) in groups {
33 let source_group = group
34 .get("source_group")
35 .and_then(|v| v.as_str())
36 .unwrap_or("");
37 let group_ahb_status = group
38 .get("ahb_status")
39 .and_then(|v| v.as_str())
40 .map(|s| s.to_string());
41 collect_fields_from_group(&mut fields, group, source_group, &group_ahb_status);
42 }
43 }
44
45 if let Some(root_segs) = schema.get("root_segments").and_then(|v| v.as_array()) {
47 for seg in root_segs {
48 collect_fields_from_segment(&mut fields, seg, "", &None);
49 }
50 }
51
52 let ub_definitions: BTreeMap<String, ConditionExpr> = schema
56 .get("ub_definitions")
57 .and_then(|v| v.as_object())
58 .map(|obj| {
59 obj.iter()
60 .filter_map(|(k, v)| {
61 let expr_str = v.as_str()?;
62 ConditionParser::parse(expr_str)
63 .ok()
64 .flatten()
65 .map(|expr| (k.clone(), expr))
66 })
67 .collect()
68 })
69 .unwrap_or_default();
70
71 fields.retain(|f| !f.segment_path.split('/').all(|p| p.starts_with("SG")));
75
76 Some(AhbWorkflow {
77 pruefidentifikator: pid.to_string(),
78 description: beschreibung.to_string(),
79 communication_direction: kommunikation_von,
80 fields,
81 ub_definitions,
82 })
83}
84
85fn collect_fields_from_group(
87 fields: &mut Vec<AhbFieldRule>,
88 group: &serde_json::Value,
89 group_path: &str,
90 parent_group_ahb_status: &Option<String>,
91) {
92 if let Some(segments) = group.get("segments").and_then(|v| v.as_array()) {
94 for seg in segments {
95 collect_fields_from_segment(fields, seg, group_path, parent_group_ahb_status);
96 }
97 }
98
99 if let Some(children) = group.get("children").and_then(|v| v.as_object()) {
101 for (_child_name, child) in children {
102 let child_source = child
103 .get("source_group")
104 .and_then(|v| v.as_str())
105 .unwrap_or("");
106 let child_path = if group_path.is_empty() {
107 child_source.to_string()
108 } else {
109 format!("{}/{}", group_path, child_source)
110 };
111 let child_group_status = child
112 .get("ahb_status")
113 .and_then(|v| v.as_str())
114 .map(|s| s.to_string());
115 collect_fields_from_group(fields, child, &child_path, &child_group_status);
116 }
117 }
118}
119
120fn collect_fields_from_segment(
122 fields: &mut Vec<AhbFieldRule>,
123 seg: &serde_json::Value,
124 group_path: &str,
125 parent_group_ahb_status: &Option<String>,
126) {
127 let seg_id = seg.get("id").and_then(|v| v.as_str()).unwrap_or("");
128 let seg_mig_number = seg
129 .get("mig_number")
130 .and_then(|v| v.as_str())
131 .map(|s| s.to_string());
132 let seg_ahb_status = seg
133 .get("ahb_status")
134 .and_then(|v| v.as_str())
135 .map(|s| s.to_string());
136
137 if let Some(elements) = seg.get("elements").and_then(|v| v.as_array()) {
138 for el in elements {
139 if el.get("composite").is_none() {
141 if let Some(de_id) = el.get("id").and_then(|v| v.as_str()) {
142 if let Some(ahb_status) = el.get("ahb_status").and_then(|v| v.as_str()) {
143 let segment_path = if group_path.is_empty() {
144 format!("{}/{}", seg_id, de_id)
145 } else {
146 format!("{}/{}/{}", group_path, seg_id, de_id)
147 };
148 let el_parent_status = el
154 .get("parent_group_ahb_status")
155 .and_then(|v| v.as_str())
156 .filter(|s| s.contains('['))
157 .map(|s| s.to_string())
158 .or_else(|| parent_group_ahb_status.clone());
159 let name = el
160 .get("name")
161 .and_then(|v| v.as_str())
162 .unwrap_or("")
163 .to_string();
164 let codes = collect_code_rules(el);
165 let element_index =
166 el.get("index").and_then(|v| v.as_u64()).map(|v| v as usize);
167 fields.push(AhbFieldRule {
168 segment_path,
169 name,
170 ahb_status: ahb_status.to_string(),
171 codes,
172 parent_group_ahb_status: el_parent_status,
173 segment_ahb_status: seg_ahb_status.clone(),
174 element_index,
175 component_index: None,
176 mig_number: seg_mig_number.clone(),
177 format: el.get("format").and_then(|v| v.as_str()).map(String::from),
178 });
179 }
180 }
181 }
182
183 if let Some(composite_id) = el.get("composite").and_then(|v| v.as_str()) {
185 if let Some(components) = el.get("components").and_then(|v| v.as_array()) {
186 for comp in components {
187 let comp_id = comp.get("id").and_then(|v| v.as_str()).unwrap_or("");
188 if let Some(ahb_status) = comp.get("ahb_status").and_then(|v| v.as_str()) {
189 let segment_path = if group_path.is_empty() {
190 format!("{}/{}/{}", seg_id, composite_id, comp_id)
191 } else {
192 format!("{}/{}/{}/{}", group_path, seg_id, composite_id, comp_id)
193 };
194 let comp_parent_status = comp
195 .get("parent_group_ahb_status")
196 .and_then(|v| v.as_str())
197 .filter(|s| s.contains('['))
198 .map(|s| s.to_string())
199 .or_else(|| parent_group_ahb_status.clone());
200 let name = comp
201 .get("name")
202 .and_then(|v| v.as_str())
203 .unwrap_or("")
204 .to_string();
205 let codes = collect_code_rules(comp);
206 let element_index =
207 el.get("index").and_then(|v| v.as_u64()).map(|v| v as usize);
208 let component_index = comp
209 .get("sub_index")
210 .and_then(|v| v.as_u64())
211 .map(|v| v as usize);
212 fields.push(AhbFieldRule {
213 segment_path,
214 name,
215 ahb_status: ahb_status.to_string(),
216 codes,
217 parent_group_ahb_status: comp_parent_status,
218 segment_ahb_status: seg_ahb_status.clone(),
219 element_index,
220 component_index,
221 mig_number: seg_mig_number.clone(),
222 format: comp
223 .get("format")
224 .and_then(|v| v.as_str())
225 .map(String::from),
226 });
227 }
228 }
229 }
230 }
231 }
232 }
233}
234
235fn collect_code_rules(el: &serde_json::Value) -> Vec<AhbCodeRule> {
237 let Some(codes) = el.get("codes").and_then(|v| v.as_array()) else {
238 return Vec::new();
239 };
240 codes
241 .iter()
242 .map(|c| AhbCodeRule {
243 value: c
244 .get("value")
245 .and_then(|v| v.as_str())
246 .unwrap_or("")
247 .to_string(),
248 description: c
249 .get("name")
250 .and_then(|v| v.as_str())
251 .unwrap_or("")
252 .to_string(),
253 ahb_status: c
254 .get("ahb_status")
255 .and_then(|v| v.as_str())
256 .unwrap_or("X")
257 .to_string(),
258 })
259 .collect()
260}