1pub mod data_validator;
12pub use oca_ast_semantics::ast::{
13 recursive_attributes::NestedAttrTypeFrame, AttributeType, NestedAttrType,
14 OverlayType, RefValue,
15};
16
17pub use oca_bundle_semantics::state::validator::validate as validate_semantics;
59pub use oca_bundle_semantics::{
60 controller::load_oca as load,
61 state::{
62 attribute::Attribute,
63 oca::{overlay, OCABox, OCABundle},
64 validator::{SemanticValidationStatus, Validator as OCAValidator},
65 },
66};
67pub use oca_rs::facade::{
68 build::{build_from_ocafile, parse_oca_bundle_to_ocafile},
69 Facade,
70};
71use oca_rs::{EncodeBundle, HashFunctionCode, SerializationFormats};
72use std::collections::HashMap;
73use std::sync::{Arc, Mutex, Weak};
74
75pub trait ToJSON {
76 fn get_json_bundle(&self) -> String;
77}
78
79impl ToJSON for OCABundle {
80 fn get_json_bundle(&self) -> String {
81 let code = HashFunctionCode::Blake3_256;
82 let format = SerializationFormats::JSON;
83
84 String::from_utf8(self.encode(&code, &format).unwrap()).unwrap()
85 }
86}
87
88lazy_static::lazy_static! {
89 static ref INFO_CACHE: Mutex<HashMap<usize, Weak<OCABundleInfo>>> = Mutex::new(HashMap::new());
90}
91
92pub trait WithInfo {
93 fn info(&self) -> Arc<OCABundleInfo>;
94}
95
96impl WithInfo for OCABundle {
97 fn info(&self) -> Arc<OCABundleInfo> {
98 let key = self as *const OCABundle as usize;
99 let mut cache = INFO_CACHE.lock().unwrap();
100 if let Some(weak_info) = cache.get(&key) {
101 if let Some(info) = weak_info.upgrade() {
102 return info;
103 }
104 }
105
106 let new_info = Arc::new(OCABundleInfo::new(self));
107 cache.insert(key, Arc::downgrade(&new_info));
108 new_info
109 }
110}
111
112pub struct OCABundleInfo {
113 attributes: HashMap<String, Attribute>,
114 pub meta: HashMap<String, HashMap<String, String>>,
115 pub links: Vec<overlay::Link>,
116 pub framings: Vec<overlay::AttributeFraming>,
117}
118
119impl OCABundleInfo {
120 pub fn new(bundle: &OCABundle) -> Self {
121 let mut meta = HashMap::new();
122 let oca_box = OCABox::from(bundle.clone());
123 if let Some(m) = oca_box.meta {
124 m.iter().for_each(|(k, v)| {
125 meta.insert(k.to_639_3().to_string(), v.to_owned());
126 })
127 }
128
129 let mut overlays = bundle.overlays.clone();
130 let links: Vec<overlay::Link> = overlays
131 .iter_mut()
132 .filter(|o| o.as_any().downcast_ref::<overlay::Link>().is_some())
133 .map(|o| {
134 o.as_any()
135 .downcast_ref::<overlay::Link>()
136 .unwrap()
137 .to_owned()
138 })
139 .collect();
140 let framings: Vec<overlay::AttributeFraming> = overlays
141 .iter_mut()
142 .filter(|o| {
143 o.as_any()
144 .downcast_ref::<overlay::AttributeFraming>()
145 .is_some()
146 })
147 .map(|o| {
148 o.as_any()
149 .downcast_ref::<overlay::AttributeFraming>()
150 .unwrap()
151 .to_owned()
152 })
153 .collect();
154
155 Self {
156 attributes: oca_box.attributes,
157 meta,
158 links,
159 framings,
160 }
161 }
162
163 pub fn attributes(&self) -> impl Iterator<Item = &Attribute> {
164 self.attributes.values()
165 }
166
167 pub fn attribute(&self, name: &str) -> Option<&Attribute> {
168 self.attributes.get(name)
169 }
170}