1use super::JSONEval;
2use crate::jsoneval::eval_cache::EvalCache;
3use crate::jsoneval::eval_data::EvalData;
4use crate::jsoneval::json_parser;
5use crate::parse_schema;
6use crate::jsoneval::parsed_schema::ParsedSchema;
7use crate::jsoneval::parsed_schema_cache::PARSED_SCHEMA_CACHE;
8use crate::rlogic::{RLogic, RLogicConfig};
9
10use crate::time_block;
11
12use indexmap::IndexMap;
13use serde::de::Error as _;
14use serde_json::Value;
15use std::collections::HashMap;
16use std::sync::{Arc, Mutex, RwLock};
17
18
19impl Clone for JSONEval {
20 fn clone(&self) -> Self {
21 Self {
22 cache_enabled: self.cache_enabled,
23 schema: Arc::clone(&self.schema),
24 engine: Arc::clone(&self.engine),
25 evaluations: self.evaluations.clone(),
26 tables: self.tables.clone(),
27 table_metadata: self.table_metadata.clone(),
28 dependencies: self.dependencies.clone(),
29 sorted_evaluations: self.sorted_evaluations.clone(),
30 dependents_evaluations: self.dependents_evaluations.clone(),
31 rules_evaluations: self.rules_evaluations.clone(),
32 fields_with_rules: self.fields_with_rules.clone(),
33 others_evaluations: self.others_evaluations.clone(),
34 value_evaluations: self.value_evaluations.clone(),
35 layout_paths: self.layout_paths.clone(),
36 options_templates: self.options_templates.clone(),
37 subforms: self.subforms.clone(),
38 reffed_by: self.reffed_by.clone(),
39 context: self.context.clone(),
40 data: self.data.clone(),
41 evaluated_schema: self.evaluated_schema.clone(),
42 eval_data: self.eval_data.clone(),
43 eval_cache: EvalCache::new(), eval_lock: Mutex::new(()), cached_msgpack_schema: self.cached_msgpack_schema.clone(),
46 conditional_hidden_fields: self.conditional_hidden_fields.clone(),
47 conditional_readonly_fields: self.conditional_readonly_fields.clone(),
48 regex_cache: RwLock::new(HashMap::new()),
49 }
50 }
51}
52
53impl JSONEval {
54 pub fn new(
55 schema: &str,
56 context: Option<&str>,
57 data: Option<&str>,
58 ) -> Result<Self, serde_json::Error> {
59 time_block!("JSONEval::new() [total]", {
60 let schema_val: Value =
62 time_block!(" parse schema JSON", { serde_json::from_str(schema)? });
63 let context: Value = time_block!(" parse context JSON", {
64 json_parser::parse_json_str(context.unwrap_or("{}"))
65 .map_err(serde_json::Error::custom)?
66 });
67 let data: Value = time_block!(" parse data JSON", {
68 json_parser::parse_json_str(data.unwrap_or("{}"))
69 .map_err(serde_json::Error::custom)?
70 });
71 let evaluated_schema = schema_val.clone();
72 let engine_config = RLogicConfig::default();
74
75 let mut instance = time_block!(" create instance struct", {
76 Self {
77 schema: Arc::new(schema_val),
78 evaluations: Arc::new(IndexMap::new()),
79 tables: Arc::new(IndexMap::new()),
80 table_metadata: Arc::new(IndexMap::new()),
81 dependencies: Arc::new(IndexMap::new()),
82 sorted_evaluations: Arc::new(Vec::new()),
83 dependents_evaluations: Arc::new(IndexMap::new()),
84 rules_evaluations: Arc::new(Vec::new()),
85 fields_with_rules: Arc::new(Vec::new()),
86 others_evaluations: Arc::new(Vec::new()),
87 value_evaluations: Arc::new(Vec::new()),
88 layout_paths: Arc::new(Vec::new()),
89 options_templates: Arc::new(Vec::new()),
90 subforms: IndexMap::new(),
91 engine: Arc::new(RLogic::with_config(engine_config)),
92 reffed_by: Arc::new(IndexMap::new()),
93 context: context.clone(),
94 data: data.clone(),
95 evaluated_schema: evaluated_schema.clone(),
96 eval_data: EvalData::with_schema_data_context(
97 &evaluated_schema,
98 &data,
99 &context,
100 ),
101 eval_cache: EvalCache::new(),
102 cache_enabled: true, eval_lock: Mutex::new(()),
104 cached_msgpack_schema: None,
105 conditional_hidden_fields: Arc::new(Vec::new()),
106 conditional_readonly_fields: Arc::new(Vec::new()),
107 regex_cache: RwLock::new(HashMap::new()),
108 }
109 });
110 time_block!(" parse_schema", {
111 parse_schema::legacy::parse_schema(&mut instance)
112 .map_err(serde_json::Error::custom)?
113 });
114 Ok(instance)
115 })
116 }
117
118 pub fn new_from_msgpack(
130 schema_msgpack: &[u8],
131 context: Option<&str>,
132 data: Option<&str>,
133 ) -> Result<Self, String> {
134 let cached_msgpack = schema_msgpack.to_vec();
136
137 let schema_val: Value = rmp_serde::from_slice(schema_msgpack)
139 .map_err(|e| format!("Failed to deserialize MessagePack schema: {}", e))?;
140
141 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))
142 .map_err(|e| format!("Failed to parse context: {}", e))?;
143 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))
144 .map_err(|e| format!("Failed to parse data: {}", e))?;
145 let evaluated_schema = schema_val.clone();
146 let engine_config = RLogicConfig::default();
147
148 let mut instance = Self {
149 schema: Arc::new(schema_val),
150 evaluations: Arc::new(IndexMap::new()),
151 tables: Arc::new(IndexMap::new()),
152 table_metadata: Arc::new(IndexMap::new()),
153 dependencies: Arc::new(IndexMap::new()),
154 sorted_evaluations: Arc::new(Vec::new()),
155 dependents_evaluations: Arc::new(IndexMap::new()),
156 rules_evaluations: Arc::new(Vec::new()),
157 fields_with_rules: Arc::new(Vec::new()),
158 others_evaluations: Arc::new(Vec::new()),
159 value_evaluations: Arc::new(Vec::new()),
160 layout_paths: Arc::new(Vec::new()),
161 options_templates: Arc::new(Vec::new()),
162 subforms: IndexMap::new(),
163 engine: Arc::new(RLogic::with_config(engine_config)),
164 reffed_by: Arc::new(IndexMap::new()),
165 context: context.clone(),
166 data: data.clone(),
167 evaluated_schema: evaluated_schema.clone(),
168 eval_data: EvalData::with_schema_data_context(&evaluated_schema, &data, &context),
169 eval_cache: EvalCache::new(),
170 cache_enabled: true, eval_lock: Mutex::new(()),
172 cached_msgpack_schema: Some(cached_msgpack),
173 conditional_hidden_fields: Arc::new(Vec::new()),
174 conditional_readonly_fields: Arc::new(Vec::new()),
175 regex_cache: RwLock::new(HashMap::new()),
176 };
177 parse_schema::legacy::parse_schema(&mut instance)?;
178 Ok(instance)
179 }
180
181 pub fn with_parsed_schema(
209 parsed: Arc<ParsedSchema>,
210 context: Option<&str>,
211 data: Option<&str>,
212 ) -> Result<Self, String> {
213 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))
214 .map_err(|e| format!("Failed to parse context: {}", e))?;
215 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))
216 .map_err(|e| format!("Failed to parse data: {}", e))?;
217
218 let evaluated_schema = parsed.schema.clone();
219
220 let engine = parsed.engine.clone();
223
224 let mut subforms = IndexMap::new();
227 for (path, subform_parsed) in &parsed.subforms {
228 let subform_eval =
230 JSONEval::with_parsed_schema(subform_parsed.clone(), Some("{}"), None)?;
231 subforms.insert(path.clone(), Box::new(subform_eval));
232 }
233
234 let instance = Self {
235 schema: Arc::clone(&parsed.schema),
236 evaluations: Arc::clone(&parsed.evaluations),
238 tables: Arc::clone(&parsed.tables),
239 table_metadata: Arc::clone(&parsed.table_metadata),
240 dependencies: Arc::clone(&parsed.dependencies),
241 sorted_evaluations: Arc::clone(&parsed.sorted_evaluations),
242 dependents_evaluations: Arc::clone(&parsed.dependents_evaluations),
243 rules_evaluations: Arc::clone(&parsed.rules_evaluations),
244 fields_with_rules: Arc::clone(&parsed.fields_with_rules),
245 others_evaluations: Arc::clone(&parsed.others_evaluations),
246 value_evaluations: Arc::clone(&parsed.value_evaluations),
247 layout_paths: Arc::clone(&parsed.layout_paths),
248 options_templates: Arc::clone(&parsed.options_templates),
249 subforms,
250 engine,
251 reffed_by: Arc::clone(&parsed.reffed_by),
252 context: context.clone(),
253 data: data.clone(),
254 evaluated_schema: (*evaluated_schema).clone(),
255 eval_data: EvalData::with_schema_data_context(&evaluated_schema, &data, &context),
256 eval_cache: EvalCache::new(),
257 cache_enabled: true, eval_lock: Mutex::new(()),
259 cached_msgpack_schema: None,
260 conditional_hidden_fields: Arc::clone(&parsed.conditional_hidden_fields),
261 conditional_readonly_fields: Arc::clone(&parsed.conditional_readonly_fields),
262 regex_cache: RwLock::new(HashMap::new()),
263 };
264
265 Ok(instance)
266 }
267
268 pub fn reload_schema(
269 &mut self,
270 schema: &str,
271 context: Option<&str>,
272 data: Option<&str>,
273 ) -> Result<(), String> {
274 let schema_val: Value =
276 serde_json::from_str(schema).map_err(|e| format!("failed to parse schema: {e}"))?;
277 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
278 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
279 self.schema = Arc::new(schema_val);
280 self.context = context.clone();
281 self.data = data.clone();
282 self.evaluated_schema = (*self.schema).clone();
283 self.engine = Arc::new(RLogic::new());
284 self.dependents_evaluations = Arc::new(IndexMap::new());
285 self.rules_evaluations = Arc::new(Vec::new());
286 self.fields_with_rules = Arc::new(Vec::new());
287 self.others_evaluations = Arc::new(Vec::new());
288 self.value_evaluations = Arc::new(Vec::new());
289 self.layout_paths = Arc::new(Vec::new());
290 self.options_templates = Arc::new(Vec::new());
291 self.subforms.clear();
292 parse_schema::legacy::parse_schema(self)?;
293
294 self.eval_data =
296 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
297
298 self.eval_cache.clear();
300
301 self.cached_msgpack_schema = None;
303
304 Ok(())
305 }
306
307 pub fn set_timezone_offset(&mut self, offset_minutes: Option<i32>) {
329 let mut config = RLogicConfig::default();
331 if let Some(offset) = offset_minutes {
332 config = config.with_timezone_offset(offset);
333 }
334
335 self.engine = Arc::new(RLogic::with_config(config));
338
339 let _ = parse_schema::legacy::parse_schema(self);
342
343 self.eval_cache.clear();
345 }
346
347 pub fn reload_schema_msgpack(
359 &mut self,
360 schema_msgpack: &[u8],
361 context: Option<&str>,
362 data: Option<&str>,
363 ) -> Result<(), String> {
364 let schema_val: Value = rmp_serde::from_slice(schema_msgpack)
366 .map_err(|e| format!("failed to deserialize MessagePack schema: {e}"))?;
367
368 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
369 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
370
371 self.schema = Arc::new(schema_val);
372 self.context = context.clone();
373 self.data = data.clone();
374 self.evaluated_schema = (*self.schema).clone();
375 self.engine = Arc::new(RLogic::new());
376 self.dependents_evaluations = Arc::new(IndexMap::new());
377 self.rules_evaluations = Arc::new(Vec::new());
378 self.fields_with_rules = Arc::new(Vec::new());
379 self.others_evaluations = Arc::new(Vec::new());
380 self.value_evaluations = Arc::new(Vec::new());
381 self.layout_paths = Arc::new(Vec::new());
382 self.options_templates = Arc::new(Vec::new());
383 self.subforms.clear();
384 parse_schema::legacy::parse_schema(self)?;
385
386 self.eval_data =
388 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
389
390 self.eval_cache.clear();
392
393 self.cached_msgpack_schema = Some(schema_msgpack.to_vec());
395
396 Ok(())
397 }
398
399 pub fn reload_schema_parsed(
413 &mut self,
414 parsed: Arc<ParsedSchema>,
415 context: Option<&str>,
416 data: Option<&str>,
417 ) -> Result<(), String> {
418 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
419 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
420
421 self.schema = Arc::clone(&parsed.schema);
423 self.evaluations = parsed.evaluations.clone();
424 self.tables = parsed.tables.clone();
425 self.table_metadata = parsed.table_metadata.clone();
426 self.dependencies = parsed.dependencies.clone();
427 self.sorted_evaluations = parsed.sorted_evaluations.clone();
428 self.dependents_evaluations = parsed.dependents_evaluations.clone();
429 self.rules_evaluations = parsed.rules_evaluations.clone();
430 self.fields_with_rules = parsed.fields_with_rules.clone();
431 self.others_evaluations = parsed.others_evaluations.clone();
432 self.value_evaluations = parsed.value_evaluations.clone();
433 self.layout_paths = parsed.layout_paths.clone();
434 self.options_templates = parsed.options_templates.clone();
435
436 self.engine = parsed.engine.clone();
438
439 let mut subforms = IndexMap::new();
441 for (path, subform_parsed) in &parsed.subforms {
442 let subform_eval =
443 JSONEval::with_parsed_schema(subform_parsed.clone(), Some("{}"), None)?;
444 subforms.insert(path.clone(), Box::new(subform_eval));
445 }
446 self.subforms = subforms;
447
448 self.context = context.clone();
449 self.data = data.clone();
450 self.evaluated_schema = (*self.schema).clone();
451
452 self.eval_data =
454 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
455
456 self.eval_cache.clear();
458
459 self.cached_msgpack_schema = None;
461
462 Ok(())
463 }
464
465 pub fn reload_schema_from_cache(
479 &mut self,
480 cache_key: &str,
481 context: Option<&str>,
482 data: Option<&str>,
483 ) -> Result<(), String> {
484 let parsed = PARSED_SCHEMA_CACHE
486 .get(cache_key)
487 .ok_or_else(|| format!("Schema '{}' not found in cache", cache_key))?;
488
489 self.reload_schema_parsed(parsed, context, data)
491 }
492}