automapper_validation/
workflow_schema.rs1use std::collections::HashMap;
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: HashMap<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 });
178 }
179 }
180 }
181
182 if let Some(composite_id) = el.get("composite").and_then(|v| v.as_str()) {
184 if let Some(components) = el.get("components").and_then(|v| v.as_array()) {
185 for comp in components {
186 let comp_id = comp.get("id").and_then(|v| v.as_str()).unwrap_or("");
187 if let Some(ahb_status) = comp.get("ahb_status").and_then(|v| v.as_str()) {
188 let segment_path = if group_path.is_empty() {
189 format!("{}/{}/{}", seg_id, composite_id, comp_id)
190 } else {
191 format!("{}/{}/{}/{}", group_path, seg_id, composite_id, comp_id)
192 };
193 let comp_parent_status = comp
194 .get("parent_group_ahb_status")
195 .and_then(|v| v.as_str())
196 .filter(|s| s.contains('['))
197 .map(|s| s.to_string())
198 .or_else(|| parent_group_ahb_status.clone());
199 let name = comp
200 .get("name")
201 .and_then(|v| v.as_str())
202 .unwrap_or("")
203 .to_string();
204 let codes = collect_code_rules(comp);
205 let element_index =
206 el.get("index").and_then(|v| v.as_u64()).map(|v| v as usize);
207 let component_index = comp
208 .get("sub_index")
209 .and_then(|v| v.as_u64())
210 .map(|v| v as usize);
211 fields.push(AhbFieldRule {
212 segment_path,
213 name,
214 ahb_status: ahb_status.to_string(),
215 codes,
216 parent_group_ahb_status: comp_parent_status,
217 segment_ahb_status: seg_ahb_status.clone(),
218 element_index,
219 component_index,
220 mig_number: seg_mig_number.clone(),
221 });
222 }
223 }
224 }
225 }
226 }
227 }
228}
229
230fn collect_code_rules(el: &serde_json::Value) -> Vec<AhbCodeRule> {
232 let Some(codes) = el.get("codes").and_then(|v| v.as_array()) else {
233 return Vec::new();
234 };
235 codes
236 .iter()
237 .map(|c| AhbCodeRule {
238 value: c
239 .get("value")
240 .and_then(|v| v.as_str())
241 .unwrap_or("")
242 .to_string(),
243 description: c
244 .get("name")
245 .and_then(|v| v.as_str())
246 .unwrap_or("")
247 .to_string(),
248 ahb_status: c
249 .get("ahb_status")
250 .and_then(|v| v.as_str())
251 .unwrap_or("X")
252 .to_string(),
253 })
254 .collect()
255}