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 let package_conditions: BTreeMap<u32, ConditionExpr> = schema
73 .get("package_conditions")
74 .and_then(|v| v.as_object())
75 .map(|obj| {
76 obj.iter()
77 .filter_map(|(k, v)| {
78 let id = k.parse().ok()?;
79 ConditionParser::parse(v.as_str()?)
80 .ok()
81 .flatten()
82 .map(|expr| (id, expr))
83 })
84 .collect()
85 })
86 .unwrap_or_default();
87
88 fields.retain(|f| !f.segment_path.split('/').all(|p| p.starts_with("SG")));
92
93 Some(AhbWorkflow {
94 pruefidentifikator: pid.to_string(),
95 description: beschreibung.to_string(),
96 communication_direction: kommunikation_von,
97 fields,
98 ub_definitions,
99 package_conditions,
100 })
101}
102
103fn collect_fields_from_group(
105 fields: &mut Vec<AhbFieldRule>,
106 group: &serde_json::Value,
107 group_path: &str,
108 parent_group_ahb_status: &Option<String>,
109) {
110 if let Some(segments) = group.get("segments").and_then(|v| v.as_array()) {
112 for seg in segments {
113 collect_fields_from_segment(fields, seg, group_path, parent_group_ahb_status);
114 }
115 }
116
117 if let Some(children) = group.get("children").and_then(|v| v.as_object()) {
119 for (_child_name, child) in children {
120 let child_source = child
121 .get("source_group")
122 .and_then(|v| v.as_str())
123 .unwrap_or("");
124 let child_path = if group_path.is_empty() {
125 child_source.to_string()
126 } else {
127 format!("{}/{}", group_path, child_source)
128 };
129 let child_group_status = child
130 .get("ahb_status")
131 .and_then(|v| v.as_str())
132 .map(|s| s.to_string());
133 collect_fields_from_group(fields, child, &child_path, &child_group_status);
134 }
135 }
136}
137
138fn collect_fields_from_segment(
140 fields: &mut Vec<AhbFieldRule>,
141 seg: &serde_json::Value,
142 group_path: &str,
143 parent_group_ahb_status: &Option<String>,
144) {
145 let seg_id = seg.get("id").and_then(|v| v.as_str()).unwrap_or("");
146 let seg_mig_number = seg
147 .get("mig_number")
148 .and_then(|v| v.as_str())
149 .map(|s| s.to_string());
150 let seg_ahb_status = seg
151 .get("ahb_status")
152 .and_then(|v| v.as_str())
153 .map(|s| s.to_string());
154
155 if let Some(elements) = seg.get("elements").and_then(|v| v.as_array()) {
156 for el in elements {
157 if el.get("composite").is_none() {
159 if let Some(de_id) = el.get("id").and_then(|v| v.as_str()) {
160 if let Some(ahb_status) = el.get("ahb_status").and_then(|v| v.as_str()) {
161 let segment_path = if group_path.is_empty() {
162 format!("{}/{}", seg_id, de_id)
163 } else {
164 format!("{}/{}/{}", group_path, seg_id, de_id)
165 };
166 let el_parent_status = el
172 .get("parent_group_ahb_status")
173 .and_then(|v| v.as_str())
174 .filter(|s| s.contains('['))
175 .map(|s| s.to_string())
176 .or_else(|| parent_group_ahb_status.clone());
177 let name = el
178 .get("name")
179 .and_then(|v| v.as_str())
180 .unwrap_or("")
181 .to_string();
182 let codes = collect_code_rules(el);
183 let element_index =
184 el.get("index").and_then(|v| v.as_u64()).map(|v| v as usize);
185 fields.push(AhbFieldRule {
186 segment_path,
187 name,
188 ahb_status: ahb_status.to_string(),
189 codes,
190 parent_group_ahb_status: el_parent_status,
191 segment_ahb_status: seg_ahb_status.clone(),
192 element_index,
193 component_index: None,
194 mig_number: seg_mig_number.clone(),
195 format: el.get("format").and_then(|v| v.as_str()).map(String::from),
196 });
197 }
198 }
199 }
200
201 if let Some(composite_id) = el.get("composite").and_then(|v| v.as_str()) {
203 if let Some(components) = el.get("components").and_then(|v| v.as_array()) {
204 for comp in components {
205 let comp_id = comp.get("id").and_then(|v| v.as_str()).unwrap_or("");
206 if let Some(ahb_status) = comp.get("ahb_status").and_then(|v| v.as_str()) {
207 let segment_path = if group_path.is_empty() {
208 format!("{}/{}/{}", seg_id, composite_id, comp_id)
209 } else {
210 format!("{}/{}/{}/{}", group_path, seg_id, composite_id, comp_id)
211 };
212 let comp_parent_status = comp
213 .get("parent_group_ahb_status")
214 .and_then(|v| v.as_str())
215 .filter(|s| s.contains('['))
216 .map(|s| s.to_string())
217 .or_else(|| parent_group_ahb_status.clone());
218 let name = comp
219 .get("name")
220 .and_then(|v| v.as_str())
221 .unwrap_or("")
222 .to_string();
223 let codes = collect_code_rules(comp);
224 let element_index =
225 el.get("index").and_then(|v| v.as_u64()).map(|v| v as usize);
226 let component_index = comp
227 .get("sub_index")
228 .and_then(|v| v.as_u64())
229 .map(|v| v as usize);
230 fields.push(AhbFieldRule {
231 segment_path,
232 name,
233 ahb_status: ahb_status.to_string(),
234 codes,
235 parent_group_ahb_status: comp_parent_status,
236 segment_ahb_status: seg_ahb_status.clone(),
237 element_index,
238 component_index,
239 mig_number: seg_mig_number.clone(),
240 format: comp
241 .get("format")
242 .and_then(|v| v.as_str())
243 .map(String::from),
244 });
245 }
246 }
247 }
248 }
249 }
250 }
251}
252
253fn collect_code_rules(el: &serde_json::Value) -> Vec<AhbCodeRule> {
255 let Some(codes) = el.get("codes").and_then(|v| v.as_array()) else {
256 return Vec::new();
257 };
258 codes
259 .iter()
260 .map(|c| AhbCodeRule {
261 value: c
262 .get("value")
263 .and_then(|v| v.as_str())
264 .unwrap_or("")
265 .to_string(),
266 description: c
267 .get("name")
268 .and_then(|v| v.as_str())
269 .unwrap_or("")
270 .to_string(),
271 ahb_status: c
272 .get("ahb_status")
273 .and_then(|v| v.as_str())
274 .unwrap_or("X")
275 .to_string(),
276 })
277 .collect()
278}