1use super::JSONEval;
2use crate::jsoneval::eval_data::EvalData;
3use crate::jsoneval::json_parser;
4use crate::parse_schema;
5use crate::jsoneval::parsed_schema::ParsedSchema;
6use crate::jsoneval::parsed_schema_cache::PARSED_SCHEMA_CACHE;
7use crate::rlogic::{RLogic, RLogicConfig};
8
9use crate::time_block;
10
11use indexmap::IndexMap;
12use serde::de::Error as _;
13use serde_json::Value;
14use std::collections::HashMap;
15use std::sync::{Arc, Mutex, RwLock};
16
17
18impl Clone for JSONEval {
19 fn clone(&self) -> Self {
20 Self {
21 schema: Arc::clone(&self.schema),
22 engine: Arc::clone(&self.engine),
23 evaluations: self.evaluations.clone(),
24 tables: self.tables.clone(),
25 table_metadata: self.table_metadata.clone(),
26 dependencies: self.dependencies.clone(),
27 sorted_evaluations: self.sorted_evaluations.clone(),
28 dependents_evaluations: self.dependents_evaluations.clone(),
29 rules_evaluations: self.rules_evaluations.clone(),
30 fields_with_rules: self.fields_with_rules.clone(),
31 others_evaluations: self.others_evaluations.clone(),
32 value_evaluations: self.value_evaluations.clone(),
33 layout_paths: self.layout_paths.clone(),
34 options_templates: self.options_templates.clone(),
35 subforms: self.subforms.clone(),
36 reffed_by: self.reffed_by.clone(),
37 context: self.context.clone(),
38 data: self.data.clone(),
39 evaluated_schema: self.evaluated_schema.clone(),
40 eval_data: self.eval_data.clone(),
41 eval_lock: Mutex::new(()), cached_msgpack_schema: self.cached_msgpack_schema.clone(),
43 conditional_hidden_fields: self.conditional_hidden_fields.clone(),
44 conditional_readonly_fields: self.conditional_readonly_fields.clone(),
45 regex_cache: RwLock::new(HashMap::new()),
46 }
47 }
48}
49
50impl JSONEval {
51 pub fn new(
52 schema: &str,
53 context: Option<&str>,
54 data: Option<&str>,
55 ) -> Result<Self, serde_json::Error> {
56 time_block!("JSONEval::new() [total]", {
57 let schema_val: Value =
59 time_block!(" parse schema JSON", { serde_json::from_str(schema)? });
60 let context: Value = time_block!(" parse context JSON", {
61 json_parser::parse_json_str(context.unwrap_or("{}"))
62 .map_err(serde_json::Error::custom)?
63 });
64 let data: Value = time_block!(" parse data JSON", {
65 json_parser::parse_json_str(data.unwrap_or("{}"))
66 .map_err(serde_json::Error::custom)?
67 });
68 let evaluated_schema = schema_val.clone();
69 let engine_config = RLogicConfig::default();
71
72 let mut instance = time_block!(" create instance struct", {
73 Self {
74 schema: Arc::new(schema_val),
75 evaluations: Arc::new(IndexMap::new()),
76 tables: Arc::new(IndexMap::new()),
77 table_metadata: Arc::new(IndexMap::new()),
78 dependencies: Arc::new(IndexMap::new()),
79 sorted_evaluations: Arc::new(Vec::new()),
80 dependents_evaluations: Arc::new(IndexMap::new()),
81 rules_evaluations: Arc::new(Vec::new()),
82 fields_with_rules: Arc::new(Vec::new()),
83 others_evaluations: Arc::new(Vec::new()),
84 value_evaluations: Arc::new(Vec::new()),
85 layout_paths: Arc::new(Vec::new()),
86 options_templates: Arc::new(Vec::new()),
87 subforms: IndexMap::new(),
88 engine: Arc::new(RLogic::with_config(engine_config)),
89 reffed_by: Arc::new(IndexMap::new()),
90 context: context.clone(),
91 data: data.clone(),
92 evaluated_schema: evaluated_schema.clone(),
93 eval_data: EvalData::with_schema_data_context(
94 &evaluated_schema,
95 &data,
96 &context,
97 ),
98 eval_lock: Mutex::new(()),
99 cached_msgpack_schema: None,
100 conditional_hidden_fields: Arc::new(Vec::new()),
101 conditional_readonly_fields: Arc::new(Vec::new()),
102 regex_cache: RwLock::new(HashMap::new()),
103 }
104 });
105 time_block!(" parse_schema", {
106 parse_schema::legacy::parse_schema(&mut instance)
107 .map_err(serde_json::Error::custom)?
108 });
109 Ok(instance)
110 })
111 }
112
113 pub fn new_from_msgpack(
125 schema_msgpack: &[u8],
126 context: Option<&str>,
127 data: Option<&str>,
128 ) -> Result<Self, String> {
129 let cached_msgpack = schema_msgpack.to_vec();
131
132 let schema_val: Value = rmp_serde::from_slice(schema_msgpack)
134 .map_err(|e| format!("Failed to deserialize MessagePack schema: {}", e))?;
135
136 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))
137 .map_err(|e| format!("Failed to parse context: {}", e))?;
138 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))
139 .map_err(|e| format!("Failed to parse data: {}", e))?;
140 let evaluated_schema = schema_val.clone();
141 let engine_config = RLogicConfig::default();
142
143 let mut instance = Self {
144 schema: Arc::new(schema_val),
145 evaluations: Arc::new(IndexMap::new()),
146 tables: Arc::new(IndexMap::new()),
147 table_metadata: Arc::new(IndexMap::new()),
148 dependencies: Arc::new(IndexMap::new()),
149 sorted_evaluations: Arc::new(Vec::new()),
150 dependents_evaluations: Arc::new(IndexMap::new()),
151 rules_evaluations: Arc::new(Vec::new()),
152 fields_with_rules: Arc::new(Vec::new()),
153 others_evaluations: Arc::new(Vec::new()),
154 value_evaluations: Arc::new(Vec::new()),
155 layout_paths: Arc::new(Vec::new()),
156 options_templates: Arc::new(Vec::new()),
157 subforms: IndexMap::new(),
158 engine: Arc::new(RLogic::with_config(engine_config)),
159 reffed_by: Arc::new(IndexMap::new()),
160 context: context.clone(),
161 data: data.clone(),
162 evaluated_schema: evaluated_schema.clone(),
163 eval_data: EvalData::with_schema_data_context(&evaluated_schema, &data, &context),
164 eval_lock: Mutex::new(()),
165 cached_msgpack_schema: Some(cached_msgpack),
166 conditional_hidden_fields: Arc::new(Vec::new()),
167 conditional_readonly_fields: Arc::new(Vec::new()),
168 regex_cache: RwLock::new(HashMap::new()),
169 };
170 parse_schema::legacy::parse_schema(&mut instance)?;
171 Ok(instance)
172 }
173
174 pub fn with_parsed_schema(
202 parsed: Arc<ParsedSchema>,
203 context: Option<&str>,
204 data: Option<&str>,
205 ) -> Result<Self, String> {
206 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))
207 .map_err(|e| format!("Failed to parse context: {}", e))?;
208 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))
209 .map_err(|e| format!("Failed to parse data: {}", e))?;
210
211 let evaluated_schema = parsed.schema.clone();
212
213 let engine = parsed.engine.clone();
216
217 let mut subforms = IndexMap::new();
220 for (path, subform_parsed) in &parsed.subforms {
221 let subform_eval =
223 JSONEval::with_parsed_schema(subform_parsed.clone(), Some("{}"), None)?;
224 subforms.insert(path.clone(), Box::new(subform_eval));
225 }
226
227 let instance = Self {
228 schema: Arc::clone(&parsed.schema),
229 evaluations: Arc::clone(&parsed.evaluations),
230 tables: Arc::clone(&parsed.tables),
231 table_metadata: Arc::clone(&parsed.table_metadata),
232 dependencies: Arc::clone(&parsed.dependencies),
233 sorted_evaluations: Arc::clone(&parsed.sorted_evaluations),
234 dependents_evaluations: Arc::clone(&parsed.dependents_evaluations),
235 rules_evaluations: Arc::clone(&parsed.rules_evaluations),
236 fields_with_rules: Arc::clone(&parsed.fields_with_rules),
237 others_evaluations: Arc::clone(&parsed.others_evaluations),
238 value_evaluations: Arc::clone(&parsed.value_evaluations),
239 layout_paths: Arc::clone(&parsed.layout_paths),
240 options_templates: Arc::clone(&parsed.options_templates),
241 subforms,
242 engine,
243 reffed_by: Arc::clone(&parsed.reffed_by),
244 context: context.clone(),
245 data: data.clone(),
246 evaluated_schema: (*evaluated_schema).clone(),
247 eval_data: EvalData::with_schema_data_context(&evaluated_schema, &data, &context),
248 eval_lock: Mutex::new(()),
249 cached_msgpack_schema: None,
250 conditional_hidden_fields: Arc::clone(&parsed.conditional_hidden_fields),
251 conditional_readonly_fields: Arc::clone(&parsed.conditional_readonly_fields),
252 regex_cache: RwLock::new(HashMap::new()),
253 };
254 Ok(instance)
255 }
256
257 pub fn reload_schema(
258 &mut self,
259 schema: &str,
260 context: Option<&str>,
261 data: Option<&str>,
262 ) -> Result<(), String> {
263 let schema_val: Value =
265 serde_json::from_str(schema).map_err(|e| format!("failed to parse schema: {e}"))?;
266 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
267 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
268 self.schema = Arc::new(schema_val);
269 self.context = context.clone();
270 self.data = data.clone();
271 self.evaluated_schema = (*self.schema).clone();
272 self.engine = Arc::new(RLogic::new());
273 self.dependents_evaluations = Arc::new(IndexMap::new());
274 self.rules_evaluations = Arc::new(Vec::new());
275 self.fields_with_rules = Arc::new(Vec::new());
276 self.others_evaluations = Arc::new(Vec::new());
277 self.value_evaluations = Arc::new(Vec::new());
278 self.layout_paths = Arc::new(Vec::new());
279 self.options_templates = Arc::new(Vec::new());
280 self.subforms.clear();
281 parse_schema::legacy::parse_schema(self)?;
282
283 self.eval_data =
285 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
286
287 self.cached_msgpack_schema = None;
289
290 Ok(())
291 }
292
293 pub fn set_timezone_offset(&mut self, offset_minutes: Option<i32>) {
315 let mut config = RLogicConfig::default();
317 if let Some(offset) = offset_minutes {
318 config = config.with_timezone_offset(offset);
319 }
320
321 self.engine = Arc::new(RLogic::with_config(config));
324
325 let _ = parse_schema::legacy::parse_schema(self);
326 }
327
328 pub fn reload_schema_msgpack(
340 &mut self,
341 schema_msgpack: &[u8],
342 context: Option<&str>,
343 data: Option<&str>,
344 ) -> Result<(), String> {
345 let schema_val: Value = rmp_serde::from_slice(schema_msgpack)
347 .map_err(|e| format!("failed to deserialize MessagePack schema: {e}"))?;
348
349 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
350 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
351
352 self.schema = Arc::new(schema_val);
353 self.context = context.clone();
354 self.data = data.clone();
355 self.evaluated_schema = (*self.schema).clone();
356 self.engine = Arc::new(RLogic::new());
357 self.dependents_evaluations = Arc::new(IndexMap::new());
358 self.rules_evaluations = Arc::new(Vec::new());
359 self.fields_with_rules = Arc::new(Vec::new());
360 self.others_evaluations = Arc::new(Vec::new());
361 self.value_evaluations = Arc::new(Vec::new());
362 self.layout_paths = Arc::new(Vec::new());
363 self.options_templates = Arc::new(Vec::new());
364 self.subforms.clear();
365 parse_schema::legacy::parse_schema(self)?;
366
367 self.eval_data =
369 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
370
371 self.cached_msgpack_schema = Some(schema_msgpack.to_vec());
373
374 Ok(())
375 }
376
377 pub fn reload_schema_parsed(
391 &mut self,
392 parsed: Arc<ParsedSchema>,
393 context: Option<&str>,
394 data: Option<&str>,
395 ) -> Result<(), String> {
396 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
397 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
398
399 self.schema = Arc::clone(&parsed.schema);
401 self.evaluations = parsed.evaluations.clone();
402 self.tables = parsed.tables.clone();
403 self.table_metadata = parsed.table_metadata.clone();
404 self.dependencies = parsed.dependencies.clone();
405 self.sorted_evaluations = parsed.sorted_evaluations.clone();
406 self.dependents_evaluations = parsed.dependents_evaluations.clone();
407 self.rules_evaluations = parsed.rules_evaluations.clone();
408 self.fields_with_rules = parsed.fields_with_rules.clone();
409 self.others_evaluations = parsed.others_evaluations.clone();
410 self.value_evaluations = parsed.value_evaluations.clone();
411 self.layout_paths = parsed.layout_paths.clone();
412 self.options_templates = parsed.options_templates.clone();
413
414 self.engine = parsed.engine.clone();
416
417 let mut subforms = IndexMap::new();
419 for (path, subform_parsed) in &parsed.subforms {
420 let subform_eval =
421 JSONEval::with_parsed_schema(subform_parsed.clone(), Some("{}"), None)?;
422 subforms.insert(path.clone(), Box::new(subform_eval));
423 }
424 self.subforms = subforms;
425
426 self.context = context.clone();
427 self.data = data.clone();
428 self.evaluated_schema = (*self.schema).clone();
429
430 self.eval_data =
432 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
433
434 self.cached_msgpack_schema = None;
436
437 Ok(())
438 }
439
440 pub fn reload_schema_from_cache(
454 &mut self,
455 cache_key: &str,
456 context: Option<&str>,
457 data: Option<&str>,
458 ) -> Result<(), String> {
459 let parsed = PARSED_SCHEMA_CACHE
461 .get(cache_key)
462 .ok_or_else(|| format!("Schema '{}' not found in cache", cache_key))?;
463
464 self.reload_schema_parsed(parsed, context, data)
466 }
467}