1use crate::state::oca::layout::credential::Layout as CredentialLayout;
2use crate::state::oca::layout::form::Layout as FormLayout;
3use crate::state::oca::overlay::cardinality::Cardinalitys;
4use crate::state::oca::overlay::character_encoding::CharacterEncodings;
5use crate::state::oca::overlay::conditional::Conditionals;
6use crate::state::oca::overlay::conformance::Conformances;
7use crate::state::oca::overlay::entry::Entries;
8use crate::state::oca::overlay::entry_code::EntryCodes;
9#[cfg(feature = "format_overlay")]
10use crate::state::oca::overlay::format::Formats;
11use crate::state::oca::overlay::information::Information;
12use crate::state::oca::overlay::label::Labels;
13use crate::state::oca::overlay::meta::Metas;
14use crate::state::oca::overlay::unit::{AttributeUnit, Unit};
15use indexmap::IndexMap;
16use linked_hash_map::LinkedHashMap;
17use said::sad::{SerializationFormats, SAD};
18use said::version::SerializationInfo;
19use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer};
20use std::collections::HashMap;
21pub mod capture_base;
22mod layout;
23pub mod overlay;
24use crate::state::{
25 attribute::Attribute,
26 oca::{capture_base::CaptureBase, overlay::Overlay},
27};
28use convert_case::{Case, Casing};
29use isolang::Language;
30use oca_ast::ast::{
31 CaptureContent, Command, CommandType, Content, NestedValue, OCAAst, ObjectKind, OverlayType,
32};
33#[derive(Clone)]
54pub struct OCABox {
55 pub attributes: HashMap<String, Attribute>,
56 pub credential_layouts: Option<Vec<CredentialLayout>>,
57 pub form_layouts: Option<Vec<FormLayout>>,
58 pub mappings: Option<Vec<overlay::AttributeMapping>>,
59 pub meta: Option<HashMap<Language, HashMap<String, String>>>,
60 pub classification: Option<String>,
61}
62
63impl Default for OCABox {
64 fn default() -> Self {
65 Self::new()
66 }
67}
68
69impl OCABox {
70 pub fn new() -> Self {
71 OCABox {
72 attributes: HashMap::new(),
73 credential_layouts: None,
74 form_layouts: None,
75 mappings: None,
76 meta: None,
77 classification: None,
78 }
79 }
80 pub fn remove_attribute(&mut self, attr_name: &String) {
83 self.attributes.remove(attr_name);
84 }
85 pub fn add_attribute(&mut self, attribute: Attribute) {
90 if let Some(attr) = self.get_attribute_mut(&attribute.name) {
91 attr.merge(&attribute);
92 } else {
93 self.attributes.insert(attribute.name.clone(), attribute);
94 }
95 }
96 pub fn get_attribute_by_name(&self, name: &str) -> Option<&Attribute> {
97 self.attributes.get(name)
98 }
99
100 pub fn add_attribute_mapping(&mut self, mapping: overlay::AttributeMapping) {
101 match self.mappings {
102 Some(ref mut mappings) => mappings.push(mapping),
103 None => self.mappings = Some(vec![mapping]),
104 }
105 }
106 pub fn add_classification(&mut self, classification: String) {
107 self.classification = Some(classification);
108 }
109
110 pub fn remove_classification(&mut self) {
111 self.classification = None;
112 }
113
114 pub fn generate_bundle(&mut self) -> OCABundle {
115 let mut capture_base = self.generate_capture_base();
116 let mut overlays = self.generate_overlays();
117
118 capture_base.sign();
119
120 let cb_said = capture_base.said.as_ref();
121 overlays.iter_mut().for_each(|x| x.sign(cb_said.unwrap()));
122
123 let mut oca_bundle = OCABundle {
124 said: None,
125 capture_base,
126 overlays,
127 };
128
129 oca_bundle.compute_digest();
130 oca_bundle
131 }
132
133 fn generate_overlays(&mut self) -> Vec<DynOverlay> {
134 let mut overlays: Vec<DynOverlay> = Vec::new();
135 if let Some(mappings) = &self.mappings {
136 for mapping in mappings {
137 overlays.push(Box::new(mapping.clone()));
138 }
139 }
140 if let Some(meta) = &self.meta {
141 for (lang, attr_pairs) in meta {
142 let meta_ov = overlay::Meta::new(*lang, attr_pairs.clone());
143 overlays.push(Box::new(meta_ov));
144 }
145 }
146 if let Some(layouts) = &self.form_layouts {
147 for layout in layouts {
148 let layout_ov = overlay::FormLayout::new(layout.clone());
149 overlays.push(Box::new(layout_ov));
150 }
151 }
152 if let Some(layouts) = &self.credential_layouts {
153 for layout in layouts {
154 let layout_ov = overlay::CredentialLayout::new(layout.clone());
155 overlays.push(Box::new(layout_ov));
156 }
157 }
158
159 for attribute in self.attributes.values() {
160 if attribute.encoding.is_some() {
161 let mut encoding_ov = overlays
162 .iter_mut()
163 .find(|x| x.overlay_type().eq(&OverlayType::CharacterEncoding));
164 if encoding_ov.is_none() {
165 overlays.push(Box::new(overlay::CharacterEncoding::new()));
166 encoding_ov = overlays.last_mut();
167 }
168 if let Some(ov) = encoding_ov {
169 ov.add(attribute);
170 }
171 }
172
173 #[cfg(feature = "format_overlay")]
174 if attribute.format.is_some() {
175 let mut format_ov = overlays
176 .iter_mut()
177 .find(|x| x.overlay_type().eq(&OverlayType::Format));
178 if format_ov.is_none() {
179 overlays.push(Box::new(overlay::Format::new()));
180 format_ov = overlays.last_mut();
181 }
182 if let Some(ov) = format_ov {
183 ov.add(attribute);
184 }
185 }
186
187 if attribute.conformance.is_some() {
188 let mut conformance_ov = overlays
189 .iter_mut()
190 .find(|x| x.overlay_type().eq(&OverlayType::Conformance));
191 if conformance_ov.is_none() {
192 overlays.push(Box::new(overlay::Conformance::new()));
193 conformance_ov = overlays.last_mut();
194 }
195 if let Some(ov) = conformance_ov {
196 ov.add(attribute);
197 }
198 }
199
200 if attribute.cardinality.is_some() {
201 let mut cardinality_ov = overlays
202 .iter_mut()
203 .find(|x| x.overlay_type().eq(&OverlayType::Cardinality));
204 if cardinality_ov.is_none() {
205 overlays.push(Box::new(overlay::Cardinality::new()));
206 cardinality_ov = overlays.last_mut();
207 }
208 if let Some(ov) = cardinality_ov {
209 ov.add(attribute);
210 }
211 }
212
213 if attribute.condition.is_some() {
214 let mut conditional_ov = overlays
215 .iter_mut()
216 .find(|x| x.overlay_type().eq(&OverlayType::Conditional));
217 if conditional_ov.is_none() {
218 overlays.push(Box::new(overlay::Conditional::new()));
219 conditional_ov = overlays.last_mut();
220 }
221 if let Some(ov) = conditional_ov {
222 ov.add(attribute);
223 }
224 }
225
226 if let Some(units) = &attribute.units {
227 for measurement_system in units.keys() {
228 let mut unit_ov = overlays.iter_mut().find(|x| {
229 if let Some(x_unit) = x.as_any().downcast_ref::<overlay::Unit>() {
230 x_unit.measurement_system() == Some(measurement_system)
231 } else {
232 false
233 }
234 });
235 if unit_ov.is_none() {
236 overlays.push(Box::new(overlay::Unit::new(measurement_system.clone())));
237 unit_ov = overlays.last_mut();
238 }
239 if let Some(ov) = unit_ov {
240 ov.add(attribute);
241 }
242 }
243 }
244
245 if attribute.entry_codes.is_some() {
246 let mut entry_code_ov = overlays
247 .iter_mut()
248 .find(|x| x.overlay_type().eq(&OverlayType::EntryCode));
249 if entry_code_ov.is_none() {
250 overlays.push(Box::new(overlay::EntryCode::new()));
251 entry_code_ov = overlays.last_mut();
252 }
253 if let Some(ov) = entry_code_ov {
254 ov.add(attribute);
255 }
256 }
257
258 if let Some(entries) = &attribute.entries {
259 for lang in entries.keys() {
260 let mut entry_ov = overlays.iter_mut().find(|x| {
261 x.overlay_type().eq(&OverlayType::Entry) && x.language() == Some(lang)
262 });
263 if entry_ov.is_none() {
264 overlays.push(Box::new(overlay::Entry::new(*lang)));
265 entry_ov = overlays.last_mut();
266 }
267 if let Some(ov) = entry_ov {
268 ov.add(attribute);
269 }
270 }
271 }
272
273 if let Some(labels) = &attribute.labels {
274 for lang in labels.keys() {
275 let mut label_ov = overlays.iter_mut().find(|x| {
276 x.overlay_type().eq(&OverlayType::Label) && x.language() == Some(lang)
277 });
278 if label_ov.is_none() {
279 overlays.push(Box::new(overlay::Label::new(*lang)));
280 label_ov = overlays.last_mut();
281 }
282 if let Some(ov) = label_ov {
283 ov.add(attribute);
284 }
285 }
286 }
287
288 if let Some(information) = &attribute.informations {
289 for lang in information.keys() {
290 let mut info_ov = overlays.iter_mut().find(|x| {
291 x.overlay_type().eq(&OverlayType::Information) && x.language() == Some(lang)
292 });
293 if info_ov.is_none() {
294 overlays.push(Box::new(overlay::Information::new(*lang)));
295 info_ov = overlays.last_mut();
296 }
297 if let Some(ov) = info_ov {
298 ov.add(attribute);
299 }
300 }
301 }
302 }
303
304 overlays
305 }
306 fn generate_capture_base(&mut self) -> CaptureBase {
307 let mut capture_base = CaptureBase::new();
308 if let Some(classification) = &self.classification {
309 capture_base.set_classification(classification);
310 }
311 for attribute in self.attributes.values() {
312 capture_base.add(attribute);
313 }
314 capture_base
315 }
316 fn get_attribute_mut(&mut self, name: &str) -> Option<&mut Attribute> {
317 self.attributes.get_mut(name)
318 }
319}
320
321pub type DynOverlay = Box<dyn Overlay + Send + Sync + 'static>;
322
323impl<'de> Deserialize<'de> for DynOverlay {
324 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
325 where
326 D: Deserializer<'de>,
327 {
328 let de_overlay = serde_value::Value::deserialize(deserializer)?;
329 if let serde_value::Value::Map(ref overlay) = de_overlay {
330 if let Some(de_overlay_type) =
331 overlay.get(&serde_value::Value::String("type".to_string()))
332 {
333 let overlay_type = de_overlay_type
334 .clone()
335 .deserialize_into::<OverlayType>()
336 .map_err(|e| serde::de::Error::custom(format!("Overlay type: {e}")))?;
337
338 match overlay_type {
339 OverlayType::AttributeMapping => {
340 return Ok(Box::new(
341 de_overlay
342 .deserialize_into::<overlay::AttributeMapping>()
343 .map_err(|e| {
344 serde::de::Error::custom(format!(
345 "Attribute Mapping overlay: {e}"
346 ))
347 })?,
348 ));
349 }
350 OverlayType::CharacterEncoding => {
351 return Ok(Box::new(
352 de_overlay
353 .deserialize_into::<overlay::CharacterEncoding>()
354 .map_err(|e| {
355 serde::de::Error::custom(format!(
356 "Character Encoding overlay: {e}"
357 ))
358 })?,
359 ));
360 }
361 OverlayType::Cardinality => {
362 return Ok(Box::new(
363 de_overlay
364 .deserialize_into::<overlay::Cardinality>()
365 .map_err(|e| {
366 serde::de::Error::custom(format!("Cardinality overlay: {e}"))
367 })?,
368 ));
369 }
370 OverlayType::Conformance => {
371 return Ok(Box::new(
372 de_overlay
373 .deserialize_into::<overlay::Conformance>()
374 .map_err(|e| {
375 serde::de::Error::custom(format!("Conformance overlay: {e}"))
376 })?,
377 ));
378 }
379 OverlayType::Conditional => {
380 return Ok(Box::new(
381 de_overlay
382 .deserialize_into::<overlay::Conditional>()
383 .map_err(|e| {
384 serde::de::Error::custom(format!("Conditional overlay: {e}"))
385 })?,
386 ));
387 }
388 OverlayType::Entry => {
389 return Ok(Box::new(
390 de_overlay
391 .deserialize_into::<overlay::Entry>()
392 .map_err(|e| {
393 serde::de::Error::custom(format!("Entry overlay: {e}"))
394 })?,
395 ));
396 }
397 OverlayType::EntryCode => {
398 return Ok(Box::new(
399 de_overlay
400 .deserialize_into::<overlay::EntryCode>()
401 .map_err(|e| {
402 serde::de::Error::custom(format!("Entry Code overlay: {e}"))
403 })?,
404 ));
405 }
406 OverlayType::EntryCodeMapping => {
407 return Ok(Box::new(
408 de_overlay
409 .deserialize_into::<overlay::EntryCodeMapping>()
410 .map_err(|e| {
411 serde::de::Error::custom(format!(
412 "Entry Code Mapping overlay: {e}"
413 ))
414 })?,
415 ));
416 }
417 OverlayType::Unit => {
418 return Ok(Box::new(
419 de_overlay
420 .deserialize_into::<overlay::Unit>()
421 .map_err(|e| {
422 serde::de::Error::custom(format!("Unit overlay: {e}"))
423 })?,
424 ));
425 }
426
427 #[cfg(feature = "format_overlay")]
428 OverlayType::Format => {
429 return Ok(Box::new(
430 de_overlay
431 .deserialize_into::<overlay::Format>()
432 .map_err(|e| {
433 serde::de::Error::custom(format!("Format overlay: {e}"))
434 })?,
435 ));
436 }
437
438 OverlayType::Information => {
439 return Ok(Box::new(
440 de_overlay
441 .deserialize_into::<overlay::Information>()
442 .map_err(|e| {
443 serde::de::Error::custom(format!("Information overlay: {e}"))
444 })?,
445 ));
446 }
447 OverlayType::Label => {
448 return Ok(Box::new(
449 de_overlay
450 .deserialize_into::<overlay::Label>()
451 .map_err(|e| {
452 serde::de::Error::custom(format!("Label overlay: {e}"))
453 })?,
454 ));
455 }
456 OverlayType::Meta => {
457 return Ok(Box::new(
458 de_overlay
459 .deserialize_into::<overlay::Meta>()
460 .map_err(|e| {
461 serde::de::Error::custom(format!("Meta overlay: {e}"))
462 })?,
463 ));
464 }
465
466 OverlayType::Subset => {
485 return Ok(Box::new(
486 de_overlay
487 .deserialize_into::<overlay::Subset>()
488 .map_err(|e| {
489 serde::de::Error::custom(format!("Subset overlay: {e}"))
490 })?,
491 ));
492 }
493 OverlayType::Standard => {
494 return Ok(Box::new(
495 de_overlay
496 .deserialize_into::<overlay::Standard>()
497 .map_err(|e| {
498 serde::de::Error::custom(format!("Standard overlay: {e}"))
499 })?,
500 ));
501 }
502 _ => {
503 return Err(serde::de::Error::custom(format!(
504 "Overlay type not supported: {:?}",
505 overlay_type
506 )));
507 }
508 }
509 } else {
510 return Err(serde::de::Error::missing_field("type"));
511 }
512 }
513
514 Err(serde::de::Error::custom(format!(
515 "overlay must be an object, got: {de_overlay:?}"
516 )))
517 }
518}
519
520pub fn serialize_overlays<S>(overlays: &Vec<DynOverlay>, s: S) -> Result<S::Ok, S::Error>
521where
522 S: Serializer,
523{
524 use serde_value::Value;
525 #[derive(Serialize)]
526 #[serde(untagged)]
527 enum OverlayValue {
528 Array(Vec<DynOverlay>),
529 Object(Box<dyn Overlay + Send>),
530 }
531
532 let mut overlays_map: LinkedHashMap<Value, OverlayValue> = LinkedHashMap::new();
533 let overlays_order = [
534 OverlayType::CharacterEncoding,
535 OverlayType::Format,
536 OverlayType::Meta,
537 OverlayType::Label,
538 OverlayType::Information,
539 OverlayType::Standard,
540 OverlayType::Conditional,
541 OverlayType::Conformance,
542 OverlayType::EntryCode,
543 OverlayType::Entry,
544 OverlayType::Cardinality,
545 OverlayType::Unit,
546 OverlayType::AttributeMapping,
547 OverlayType::EntryCodeMapping,
548 OverlayType::UnitMapping,
549 OverlayType::Subset,
550 ];
553 for o_type in overlays_order {
554 for overlay in overlays {
555 let o_type_str = o_type.to_string().to_case(Case::Snake);
556 if overlay.overlay_type().eq(&o_type) {
557 match overlay.language() {
558 Some(_) => {
559 if let Some(OverlayValue::Array(ov)) =
560 overlays_map.get_mut(&Value::String(o_type_str.clone()))
561 {
562 ov.push(overlay.clone());
563 } else {
564 overlays_map.insert(
565 Value::String(o_type_str.clone()),
566 OverlayValue::Array(vec![overlay.clone()]),
567 );
568 }
569 }
570 None => {
571 overlays_map.insert(
572 Value::String(o_type_str),
573 OverlayValue::Object(overlay.clone()),
574 );
575 }
576 }
577 }
578 }
579 }
580
581 let mut ser = s.serialize_map(Some(overlays_map.len()))?;
582 for (ov_type, v) in overlays_map.iter_mut() {
583 if let OverlayValue::Array(ov) = v {
584 ov.sort_by(|a, b| {
585 if let Some(a_lang) = a.language() {
586 if let Some(b_lang) = b.language() {
587 a_lang.cmp(b_lang)
588 } else {
589 std::cmp::Ordering::Equal
590 }
591 } else {
592 std::cmp::Ordering::Equal
593 }
594 });
595 }
596
597 ser.serialize_entry(ov_type, v)?;
598 }
599 ser.end()
600}
601
602fn deserialize_overlays<'de, D>(deserializer: D) -> Result<Vec<DynOverlay>, D::Error>
603where
604 D: serde::de::Deserializer<'de>,
605{
606 struct OverlaysVisitor;
607
608 impl<'de> serde::de::Visitor<'de> for OverlaysVisitor {
609 type Value = Vec<DynOverlay>;
610
611 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
612 formatter.write_str("vector of overlays")
613 }
614
615 fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
616 where
617 V: serde::de::MapAccess<'de>,
618 {
619 let mut overlays = vec![];
620
621 while let Some((_, value)) = map.next_entry::<String, serde_value::Value>()? {
622 if let serde_value::Value::Seq(ov) = value {
623 for o in ov {
624 overlays.push(o.deserialize_into().unwrap());
625 }
626 } else if let serde_value::Value::Map(_) = value {
627 overlays.push(value.deserialize_into().unwrap());
628 }
629 }
630
631 Ok(overlays)
632 }
633 }
634
635 deserializer.deserialize_any(OverlaysVisitor)
636}
637
638impl std::fmt::Debug for DynOverlay {
639 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
640 write!(
641 f,
642 "DynOverlay {{ overlay_type: {}, attributes: {:?} }}",
643 self.overlay_type(),
644 self.attributes()
645 )
646 }
647}
648
649#[derive(SAD, Serialize, Debug, Deserialize, Clone)]
650#[version(protocol = "OCAB", major = 1, minor = 0)]
651pub struct OCABundle {
653 #[said]
654 #[serde(rename = "d")]
655 pub said: Option<said::SelfAddressingIdentifier>,
656 pub capture_base: CaptureBase,
657 #[serde(
658 serialize_with = "serialize_overlays",
659 deserialize_with = "deserialize_overlays"
660 )]
661 pub overlays: Vec<DynOverlay>,
662}
663
664impl From<OCABundle> for OCABox {
665 fn from(oca_bundle: OCABundle) -> Self {
666 let mut oca_box = OCABox::new();
667 oca_box.add_classification(oca_bundle.capture_base.classification);
668
669 let mut attributes: HashMap<String, Attribute> = HashMap::new();
670 for (attr_name, attr_type) in oca_bundle.capture_base.attributes {
671 let attr = Attribute {
672 name: attr_name.clone(),
673 attribute_type: Some(attr_type),
674 ..Default::default()
677 };
678 attributes.insert(attr_name.clone(), attr);
679 }
680 for attr_name in oca_bundle.capture_base.flagged_attributes {
681 attributes.get_mut(&attr_name).unwrap().set_flagged();
682 }
683
684 let meta_overlays = oca_bundle
685 .overlays
686 .iter()
687 .filter_map(|x| x.as_any().downcast_ref::<overlay::Meta>())
688 .collect::<Vec<_>>();
689 for overlay in meta_overlays {
690 for (meta_name, meta_value) in overlay.attr_pairs.iter() {
691 oca_box.add_meta(
692 *overlay.language().unwrap(),
693 meta_name.clone(),
694 meta_value.clone(),
695 );
696 }
697 }
698
699 let character_encoding_overlays = oca_bundle
700 .overlays
701 .iter()
702 .filter_map(|x| x.as_any().downcast_ref::<overlay::CharacterEncoding>())
703 .collect::<Vec<_>>();
704 for overlay in character_encoding_overlays {
705 for (attr_name, encoding) in overlay.attribute_character_encoding.iter() {
706 attributes
707 .get_mut(attr_name)
708 .unwrap()
709 .set_encoding(*encoding);
710 }
711 }
712
713 let conformance_overlays = oca_bundle
714 .overlays
715 .iter()
716 .filter_map(|x| x.as_any().downcast_ref::<overlay::Conformance>())
717 .collect::<Vec<_>>();
718 for overlay in conformance_overlays {
719 for (attr_name, conformance) in overlay.attribute_conformance.iter() {
720 attributes
721 .get_mut(attr_name)
722 .unwrap()
723 .set_conformance(conformance.clone());
724 }
725 }
726
727 let conditional_overlays = oca_bundle
728 .overlays
729 .iter()
730 .filter_map(|x| x.as_any().downcast_ref::<overlay::Conditional>())
731 .collect::<Vec<_>>();
732 for overlay in conditional_overlays {
733 let re = regex::Regex::new(r"\$\{(\d+)\}").unwrap();
734
735 for (attr_name, condition) in overlay.attribute_conditions.iter() {
736 let condition_dependencies = overlay.attribute_dependencies.get(attr_name).unwrap(); let cond = re
738 .replace_all(condition, |caps: ®ex::Captures| {
739 let dep = condition_dependencies[caps[1].parse::<usize>().unwrap()].clone();
740 format!("${{{}}}", dep)
741 })
742 .to_string();
743
744 attributes
745 .get_mut(attr_name)
746 .unwrap()
747 .set_condition(cond.clone());
748 }
749 }
750
751 let cardinality_overlays = oca_bundle
752 .overlays
753 .iter()
754 .filter_map(|x| x.as_any().downcast_ref::<overlay::Cardinality>())
755 .collect::<Vec<_>>();
756 for overlay in cardinality_overlays {
757 for (attr_name, cardinality) in overlay.attribute_cardinality.iter() {
758 attributes
759 .get_mut(attr_name)
760 .unwrap()
761 .set_cardinality(cardinality.clone());
762 }
763 }
764
765 #[cfg(feature = "format_overlay")]
766 {
767 let format_overlays = oca_bundle
768 .overlays
769 .iter()
770 .filter_map(|x| x.as_any().downcast_ref::<overlay::Format>())
771 .collect::<Vec<_>>();
772 for overlay in format_overlays {
773 for (attr_name, format) in overlay.attribute_formats.iter() {
774 attributes
775 .get_mut(attr_name)
776 .unwrap()
777 .set_format(format.clone());
778 }
779 }
780 }
781
782 let unit_overlays = oca_bundle
783 .overlays
784 .iter()
785 .filter_map(|x| x.as_any().downcast_ref::<overlay::Unit>())
786 .collect::<Vec<_>>();
787 for overlay in unit_overlays {
788 for (attr_name, unit) in overlay.attribute_units.iter() {
789 attributes
790 .get_mut(attr_name)
791 .unwrap()
792 .set_unit(AttributeUnit {
793 measurement_system: overlay.measurement_system().unwrap().clone(),
794 unit: unit.clone(),
795 });
796 }
797 }
798
799 let entry_code_overlays = oca_bundle
800 .overlays
801 .iter()
802 .filter_map(|x| x.as_any().downcast_ref::<overlay::EntryCode>())
803 .collect::<Vec<_>>();
804 for overlay in entry_code_overlays {
805 for (attr_name, entry_code) in overlay.attribute_entry_codes.iter() {
806 attributes
807 .get_mut(attr_name)
808 .unwrap()
809 .set_entry_codes(entry_code.clone());
810 }
811 }
812
813 let entry_overlays = oca_bundle
814 .overlays
815 .iter()
816 .filter_map(|x| x.as_any().downcast_ref::<overlay::Entry>())
817 .collect::<Vec<_>>();
818 for overlay in entry_overlays {
819 for (attr_name, entries) in overlay.attribute_entries.iter() {
820 attributes
821 .get_mut(attr_name)
822 .unwrap()
823 .set_entry(*overlay.language().unwrap(), entries.clone());
824 }
825 }
826
827 let label_overlays = oca_bundle
828 .overlays
829 .iter()
830 .filter_map(|x| x.as_any().downcast_ref::<overlay::Label>())
831 .collect::<Vec<_>>();
832 for overlay in label_overlays {
833 for (attr_name, label) in overlay.attribute_labels.iter() {
834 attributes
835 .get_mut(attr_name)
836 .unwrap()
837 .set_label(*overlay.language().unwrap(), label.clone());
838 }
839 }
840
841 let information_overlays = oca_bundle
842 .overlays
843 .iter()
844 .filter_map(|x| x.as_any().downcast_ref::<overlay::Information>())
845 .collect::<Vec<_>>();
846 for overlay in information_overlays {
847 for (attr_name, information) in overlay.attribute_information.iter() {
848 attributes
849 .get_mut(attr_name)
850 .unwrap()
851 .set_information(*overlay.language().unwrap(), information.clone());
852 }
853 }
854
855 for (_, attribute) in attributes {
856 oca_box.add_attribute(attribute);
857 }
858
859 oca_box
860 }
861}
862
863impl OCABundle {
864 pub fn fill_said(&mut self) {
865 self.compute_digest();
866 }
867
868 pub fn to_ast(&self) -> OCAAst {
869 let mut ast = OCAAst::new();
870
871 let mut properties = None;
872 if !self.capture_base.classification.is_empty() {
873 properties = Some(IndexMap::new());
874 properties.as_mut().unwrap().insert(
875 "classification".to_string(),
876 NestedValue::Value(self.capture_base.classification.clone()),
877 );
878 }
879
880 let mut attributes = IndexMap::new();
881 self.capture_base
882 .attributes
883 .iter()
884 .for_each(|(attr_name, attr_type)| {
885 attributes.insert(attr_name.clone(), attr_type.clone());
886 });
887
888 let command = Command {
889 kind: CommandType::Add,
890 object_kind: ObjectKind::CaptureBase(CaptureContent {
891 attributes: Some(self.capture_base.attributes.clone().into_iter().collect()),
893 properties,
894 flagged_attributes: None,
895 }),
896 };
897 ast.commands.push(command);
898
899 self.overlays.iter().for_each(|overlay| {
900 match overlay.overlay_type() {
901 OverlayType::CharacterEncoding => {
902 let character_encoding = overlay
903 .as_any()
904 .downcast_ref::<overlay::CharacterEncoding>()
905 .unwrap();
906 let mut attributes = IndexMap::new();
907 for (attr_name, encoding) in
908 character_encoding.attribute_character_encoding.iter()
909 {
910 let encoding_val = serde_json::to_value(encoding).unwrap();
911 attributes.insert(
912 attr_name.clone(),
913 NestedValue::Value(encoding_val.as_str().unwrap().to_string()),
914 );
915 }
916 let command = Command {
917 kind: CommandType::Add,
918 object_kind: ObjectKind::Overlay(
919 OverlayType::CharacterEncoding,
920 Content {
921 attributes: Some(attributes),
922 properties: None,
923 },
924 ),
925 };
926 ast.commands.push(command);
927 }
928 #[cfg(feature = "format_overlay")]
929 OverlayType::Format => {
930 let format = overlay.as_any().downcast_ref::<overlay::Format>().unwrap();
931 let mut attributes = IndexMap::new();
932 for (attr_name, format) in format.attribute_formats.iter() {
933 attributes.insert(attr_name.clone(), NestedValue::Value(format.clone()));
934 }
935 let command = Command {
936 kind: CommandType::Add,
937 object_kind: ObjectKind::Overlay(
938 OverlayType::Format,
939 Content {
940 attributes: Some(attributes),
941 properties: None,
942 },
943 ),
944 };
945 ast.commands.push(command);
946 }
947 OverlayType::Meta => {
948 let meta = overlay.as_any().downcast_ref::<overlay::Meta>().unwrap();
949 let mut properties = IndexMap::new();
950 properties.insert(
951 "lang".to_string(),
952 NestedValue::Value(
953 meta.language().unwrap().to_639_1().unwrap().to_string(),
954 ),
955 );
956 for (meta_name, meta_value) in meta.attr_pairs.iter() {
957 properties
958 .insert(meta_name.clone(), NestedValue::Value(meta_value.clone()));
959 }
960 let command = Command {
961 kind: CommandType::Add,
962 object_kind: ObjectKind::Overlay(
963 OverlayType::Meta,
964 Content {
965 attributes: None,
966 properties: Some(properties),
967 },
968 ),
969 };
970 ast.commands.push(command);
971 }
972 OverlayType::Label => {
973 let label = overlay.as_any().downcast_ref::<overlay::Label>().unwrap();
974 let mut properties = IndexMap::new();
975 properties.insert(
976 "lang".to_string(),
977 NestedValue::Value(
978 label.language().unwrap().to_639_1().unwrap().to_string(),
979 ),
980 );
981 let mut attributes = IndexMap::new();
982 for (attr_name, label) in label.attribute_labels.iter() {
983 attributes.insert(attr_name.clone(), NestedValue::Value(label.clone()));
984 }
985 let command = Command {
986 kind: CommandType::Add,
987 object_kind: ObjectKind::Overlay(
988 OverlayType::Label,
989 Content {
990 attributes: Some(attributes),
991 properties: Some(properties),
992 },
993 ),
994 };
995 ast.commands.push(command);
996 }
997 OverlayType::Information => {
998 let information = overlay
999 .as_any()
1000 .downcast_ref::<overlay::Information>()
1001 .unwrap();
1002 let mut properties = IndexMap::new();
1003 properties.insert(
1004 "lang".to_string(),
1005 NestedValue::Value(
1006 information
1007 .language()
1008 .unwrap()
1009 .to_639_1()
1010 .unwrap()
1011 .to_string(),
1012 ),
1013 );
1014 let mut attributes = IndexMap::new();
1015 for (attr_name, information) in information.attribute_information.iter() {
1016 attributes
1017 .insert(attr_name.clone(), NestedValue::Value(information.clone()));
1018 }
1019 let command = Command {
1020 kind: CommandType::Add,
1021 object_kind: ObjectKind::Overlay(
1022 OverlayType::Information,
1023 Content {
1024 attributes: Some(attributes),
1025 properties: Some(properties),
1026 },
1027 ),
1028 };
1029 ast.commands.push(command);
1030 }
1031 OverlayType::Conditional => {
1032 let conditional = overlay
1033 .as_any()
1034 .downcast_ref::<overlay::Conditional>()
1035 .unwrap();
1036 let mut attributes = IndexMap::new();
1037 let re = regex::Regex::new(r"\$\{(\d+)\}").unwrap();
1038 for (attr_name, condition) in conditional.attribute_conditions.iter() {
1039 let condition_dependencies =
1040 conditional.attribute_dependencies.get(attr_name).unwrap(); let cond = re
1042 .replace_all(condition, |caps: ®ex::Captures| {
1043 let dep = condition_dependencies[caps[1].parse::<usize>().unwrap()]
1044 .clone();
1045 format!("${{{}}}", dep)
1046 })
1047 .to_string();
1048
1049 attributes.insert(attr_name.clone(), NestedValue::Value(cond.clone()));
1050 }
1051 let command = Command {
1052 kind: CommandType::Add,
1053 object_kind: ObjectKind::Overlay(
1054 OverlayType::Conditional,
1055 Content {
1056 attributes: Some(attributes),
1057 properties: None,
1058 },
1059 ),
1060 };
1061 ast.commands.push(command);
1062 }
1063 OverlayType::Conformance => {
1064 let conformance = overlay
1065 .as_any()
1066 .downcast_ref::<overlay::Conformance>()
1067 .unwrap();
1068 let mut attributes = IndexMap::new();
1069 for (attr_name, conformance) in conformance.attribute_conformance.iter() {
1070 attributes
1071 .insert(attr_name.clone(), NestedValue::Value(conformance.clone()));
1072 }
1073 let command = Command {
1074 kind: CommandType::Add,
1075 object_kind: ObjectKind::Overlay(
1076 OverlayType::Conformance,
1077 Content {
1078 attributes: Some(attributes),
1079 properties: None,
1080 },
1081 ),
1082 };
1083 ast.commands.push(command);
1084 }
1085 OverlayType::EntryCode => {
1086 let entry_code = overlay
1087 .as_any()
1088 .downcast_ref::<overlay::EntryCode>()
1089 .unwrap();
1090 let mut attributes = IndexMap::new();
1091 for (attr_name, entry_code) in entry_code.attribute_entry_codes.iter() {
1092 match entry_code {
1093 crate::state::entry_codes::EntryCodes::Sai(said) => {
1094 attributes.insert(
1095 attr_name.clone(),
1096 NestedValue::Value(said.to_string()),
1097 );
1098 }
1099 crate::state::entry_codes::EntryCodes::Array(entry_codes) => {
1100 attributes.insert(
1101 attr_name.clone(),
1102 NestedValue::Array(
1103 entry_codes
1104 .iter()
1105 .map(|code| NestedValue::Value(code.clone()))
1106 .collect(),
1107 ),
1108 );
1109 }
1110 crate::state::entry_codes::EntryCodes::Object(grouped_entry_codes) => {
1111 attributes.insert(
1112 attr_name.clone(),
1113 NestedValue::Object(
1114 grouped_entry_codes
1115 .iter()
1116 .map(|(k, v)| {
1117 let codes = v
1118 .iter()
1119 .map(|code| NestedValue::Value(code.clone()))
1120 .collect();
1121 (k.clone(), NestedValue::Array(codes))
1122 })
1123 .collect(),
1124 ),
1125 );
1126 }
1127 }
1128 }
1129 let command = Command {
1130 kind: CommandType::Add,
1131 object_kind: ObjectKind::Overlay(
1132 OverlayType::EntryCode,
1133 Content {
1134 attributes: Some(attributes),
1135 properties: None,
1136 },
1137 ),
1138 };
1139 ast.commands.push(command);
1140 }
1141 OverlayType::Entry => {
1142 let entry = overlay.as_any().downcast_ref::<overlay::Entry>().unwrap();
1143 let mut properties = IndexMap::new();
1144 properties.insert(
1145 "lang".to_string(),
1146 NestedValue::Value(
1147 entry.language().unwrap().to_639_1().unwrap().to_string(),
1148 ),
1149 );
1150 let mut attributes = IndexMap::new();
1151 for (attr_name, entries) in entry.attribute_entries.iter() {
1152 match entries {
1153 crate::state::entries::EntriesElement::Sai(said) => {
1154 attributes.insert(
1155 attr_name.clone(),
1156 NestedValue::Value(said.to_string()),
1157 );
1158 }
1159 crate::state::entries::EntriesElement::Object(entries) => {
1160 attributes.insert(
1161 attr_name.clone(),
1162 NestedValue::Object(
1163 entries
1164 .iter()
1165 .map(|(k, v)| {
1166 (k.clone(), NestedValue::Value(v.clone()))
1167 })
1168 .collect(),
1169 ),
1170 );
1171 }
1172 }
1173 }
1174 let command = Command {
1175 kind: CommandType::Add,
1176 object_kind: ObjectKind::Overlay(
1177 OverlayType::Entry,
1178 Content {
1179 attributes: Some(attributes),
1180 properties: Some(properties),
1181 },
1182 ),
1183 };
1184 ast.commands.push(command);
1185 }
1186 OverlayType::Cardinality => {
1187 let cardinality = overlay
1188 .as_any()
1189 .downcast_ref::<overlay::Cardinality>()
1190 .unwrap();
1191 let mut attributes = IndexMap::new();
1192 for (attr_name, cardinality) in cardinality.attribute_cardinality.iter() {
1193 attributes
1194 .insert(attr_name.clone(), NestedValue::Value(cardinality.clone()));
1195 }
1196 let command = Command {
1197 kind: CommandType::Add,
1198 object_kind: ObjectKind::Overlay(
1199 OverlayType::Cardinality,
1200 Content {
1201 attributes: Some(attributes),
1202 properties: None,
1203 },
1204 ),
1205 };
1206 ast.commands.push(command);
1207 }
1208 OverlayType::Unit => {
1209 let unit_ov = overlay.as_any().downcast_ref::<overlay::Unit>().unwrap();
1210 let mut properties = IndexMap::new();
1211 let unit_system_val =
1212 serde_json::to_value(unit_ov.measurement_system().unwrap()).unwrap();
1213 properties.insert(
1214 "unit_system".to_string(),
1215 NestedValue::Value(unit_system_val.as_str().unwrap().to_string()),
1216 );
1217 let mut attributes = IndexMap::new();
1218 for (attr_name, unit) in unit_ov.attribute_units.iter() {
1219 let unit_val = serde_json::to_value(unit).unwrap();
1220 attributes.insert(
1221 attr_name.clone(),
1222 NestedValue::Value(unit_val.as_str().unwrap().to_string()),
1223 );
1224 }
1225 let command = Command {
1226 kind: CommandType::Add,
1227 object_kind: ObjectKind::Overlay(
1228 OverlayType::Unit,
1229 Content {
1230 attributes: Some(attributes),
1231 properties: Some(properties),
1232 },
1233 ),
1234 };
1235 ast.commands.push(command);
1236 }
1237 _ => {}
1238 }
1239 });
1240
1241 ast
1242 }
1243}
1244
1245#[cfg(test)]
1271mod tests {
1272 use maplit::hashmap;
1273 use oca_ast::ast::{NestedAttrType, RefValue};
1274 use said::SelfAddressingIdentifier;
1275
1276 use super::*;
1277 use crate::state::{attribute::AttributeType, entries::EntriesElement};
1278
1279 #[test]
1280 fn build_oca_bundle() {
1281 let mut oca = OCABox::new();
1282 oca.add_classification("test".to_string());
1283 oca.add_meta(Language::Eng, "name".to_string(), "test name".to_string());
1284 oca.add_meta(
1285 Language::Eng,
1286 "description".to_string(),
1287 "test desc".to_string(),
1288 );
1289 let mut attr_remove = Attribute::new("removeme".to_string());
1290 attr_remove.set_attribute_type(NestedAttrType::Value(AttributeType::Text));
1291 oca.add_attribute(attr_remove);
1292
1293 let mut attr = Attribute::new("first_name".to_string());
1294 attr.set_attribute_type(NestedAttrType::Value(AttributeType::Text));
1295 oca.add_attribute(attr);
1296
1297 let mut attr2 = Attribute::new("gender".to_string());
1298 let entries = EntriesElement::Object(hashmap! {});
1299 attr2.set_entry(Language::Eng, entries);
1300 oca.remove_attribute(&"removeme".to_string());
1301
1302 let mut attr = Attribute::new("last_name".to_string());
1303 attr.set_attribute_type(NestedAttrType::Value(AttributeType::Text));
1304 oca.add_attribute(attr);
1305 let oca_bundle = oca.generate_bundle();
1307 let said = oca_bundle.said;
1311 let oca_bundle = oca.generate_bundle();
1312 let oca_bundle_json = serde_json::to_string_pretty(&oca_bundle).unwrap();
1313 let said2 = oca_bundle.said;
1314 println!("{}", oca_bundle_json);
1315 assert_eq!(said, said2);
1316 }
1317
1318 #[test]
1319 fn load_oca_box_from_oca_bundle() {
1320 let mut oca = OCABox::new();
1321 oca.add_meta(Language::Eng, "name".to_string(), "test name".to_string());
1322 oca.add_meta(
1323 Language::Eng,
1324 "description".to_string(),
1325 "test desc".to_string(),
1326 );
1327 let mut attr = Attribute::new("first_name".to_string());
1328 attr.set_attribute_type(NestedAttrType::Value(AttributeType::Text));
1329 oca.add_attribute(attr);
1330
1331 let mut attr = Attribute::new("last_name".to_string());
1332 attr.set_attribute_type(NestedAttrType::Value(AttributeType::Text));
1333 attr.set_condition("string.len(${first_name}) > 0".to_string());
1334 oca.add_attribute(attr);
1335
1336 let mut attr = Attribute::new("ref".to_string());
1337 let said = SelfAddressingIdentifier::default();
1338 attr.set_attribute_type(NestedAttrType::Reference(RefValue::Said(said)));
1339 oca.add_attribute(attr);
1340
1341 let oca_bundle = oca.generate_bundle();
1342 let said = oca_bundle.said.clone();
1343
1344 let mut oca_box = OCABox::from(oca_bundle);
1345 let oca_bundle = oca_box.generate_bundle();
1346 let said2 = oca_bundle.said;
1347
1348 assert_eq!(said, said2);
1349 }
1350}
1351
1352