json_eval_rs/jsoneval/
subform_methods.rs

1// Subform methods for isolated array field evaluation
2
3use crate::JSONEval;
4use crate::ReturnFormat;
5use crate::jsoneval::cancellation::CancellationToken;
6use serde_json::Value;
7
8impl JSONEval {
9    /// Evaluate a subform with data
10    /// Evaluate a subform with data and optional selective paths
11    pub fn evaluate_subform(
12        &mut self,
13        subform_path: &str,
14        data: &str,
15        context: Option<&str>,
16        paths: Option<&[String]>,
17        token: Option<&CancellationToken>,
18    ) -> Result<(), String> {
19        let subform = self
20            .subforms
21            .get_mut(subform_path)
22            .ok_or_else(|| format!("Subform not found: {}", subform_path))?;
23
24        subform.evaluate(data, context, paths, token)
25    }
26
27    /// Validate subform data against its schema rules
28    pub fn validate_subform(
29        &mut self,
30        subform_path: &str,
31        data: &str,
32        context: Option<&str>,
33        paths: Option<&[String]>,
34        token: Option<&CancellationToken>,
35    ) -> Result<crate::ValidationResult, String> {
36        let subform = self
37            .subforms
38            .get_mut(subform_path)
39            .ok_or_else(|| format!("Subform not found: {}", subform_path))?;
40
41        subform.validate(data, context, paths, token)
42    }
43
44    /// Evaluate dependents in subform when a field changes
45    pub fn evaluate_dependents_subform(
46        &mut self,
47        subform_path: &str,
48        changed_paths: &[String],
49        data: Option<&str>,
50        context: Option<&str>,
51        re_evaluate: bool,
52        token: Option<&CancellationToken>,
53        canceled_paths: Option<&mut Vec<String>>,
54    ) -> Result<Value, String> {
55        let subform = self
56            .subforms
57            .get_mut(subform_path)
58            .ok_or_else(|| format!("Subform not found: {}", subform_path))?;
59
60        subform.evaluate_dependents(changed_paths, data, context, re_evaluate, token, canceled_paths)
61    }
62
63    /// Resolve layout for subform
64    pub fn resolve_layout_subform(
65        &mut self,
66        subform_path: &str,
67        evaluate: bool,
68    ) -> Result<(), String> {
69        let subform = self
70            .subforms
71            .get_mut(subform_path)
72            .ok_or_else(|| format!("Subform not found: {}", subform_path))?;
73
74        let _ = subform.resolve_layout(evaluate);
75        Ok(())
76    }
77
78    /// Get evaluated schema from subform
79    pub fn get_evaluated_schema_subform(
80        &mut self,
81        subform_path: &str,
82        resolve_layout: bool,
83    ) -> Value {
84        if let Some(subform) = self.subforms.get_mut(subform_path) {
85            subform.get_evaluated_schema(resolve_layout)
86        } else {
87            Value::Null
88        }
89    }
90
91    /// Get schema value from subform in nested object format (all .value fields).
92    pub fn get_schema_value_subform(&mut self, subform_path: &str) -> Value {
93        if let Some(subform) = self.subforms.get_mut(subform_path) {
94            subform.get_schema_value()
95        } else {
96            Value::Null
97        }
98    }
99
100    /// Get schema values from subform as a flat array of path-value pairs.
101    pub fn get_schema_value_array_subform(&self, subform_path: &str) -> Value {
102        if let Some(subform) = self.subforms.get(subform_path) {
103            subform.get_schema_value_array()
104        } else {
105            Value::Array(vec![])
106        }
107    }
108
109    /// Get schema values from subform as a flat object with dotted path keys.
110    pub fn get_schema_value_object_subform(&self, subform_path: &str) -> Value {
111        if let Some(subform) = self.subforms.get(subform_path) {
112            subform.get_schema_value_object()
113        } else {
114            Value::Object(serde_json::Map::new())
115        }
116    }
117
118    /// Get evaluated schema without $params from subform
119    pub fn get_evaluated_schema_without_params_subform(
120        &mut self,
121        subform_path: &str,
122        resolve_layout: bool,
123    ) -> Value {
124        if let Some(subform) = self.subforms.get_mut(subform_path) {
125            subform.get_evaluated_schema_without_params(resolve_layout)
126        } else {
127            Value::Null
128        }
129    }
130
131    /// Get evaluated schema by specific path from subform
132    pub fn get_evaluated_schema_by_path_subform(
133        &mut self,
134        subform_path: &str,
135        schema_path: &str,
136        skip_layout: bool,
137    ) -> Option<Value> {
138        if let Some(subform) = self.subforms.get_mut(subform_path) {
139            Some(subform.get_evaluated_schema_by_paths(&[schema_path.to_string()], skip_layout, Some(ReturnFormat::Nested)))
140        } else {
141            None
142        }
143    }
144
145    /// Get evaluated schema by multiple paths from subform
146    pub fn get_evaluated_schema_by_paths_subform(
147        &mut self,
148        subform_path: &str,
149        schema_paths: &[String],
150        skip_layout: bool,
151        format: Option<crate::ReturnFormat>,
152    ) -> Value {
153        if let Some(subform) = self.subforms.get_mut(subform_path) {
154            subform.get_evaluated_schema_by_paths(schema_paths, skip_layout, Some(format.unwrap_or(ReturnFormat::Flat)))
155        } else {
156            match format.unwrap_or_default() {
157                crate::ReturnFormat::Array => Value::Array(vec![]),
158                _ => Value::Object(serde_json::Map::new()),
159            }
160        }
161    }
162
163    /// Get schema by specific path from subform
164    pub fn get_schema_by_path_subform(
165        &self,
166        subform_path: &str,
167        schema_path: &str,
168    ) -> Option<Value> {
169        if let Some(subform) = self.subforms.get(subform_path) {
170            subform.get_schema_by_path(schema_path)
171        } else {
172            None
173        }
174    }
175
176    /// Get schema by multiple paths from subform
177    pub fn get_schema_by_paths_subform(
178        &self,
179        subform_path: &str,
180        schema_paths: &[String],
181        format: Option<crate::ReturnFormat>,
182    ) -> Value {
183        if let Some(subform) = self.subforms.get(subform_path) {
184            subform.get_schema_by_paths(schema_paths, Some(format.unwrap_or(ReturnFormat::Flat)))
185        } else {
186            match format.unwrap_or_default() {
187                crate::ReturnFormat::Array => Value::Array(vec![]),
188                _ => Value::Object(serde_json::Map::new()),
189            }
190        }
191    }
192
193    /// Get list of available subform paths
194    pub fn get_subform_paths(&self) -> Vec<String> {
195        self.subforms.keys().cloned().collect()
196    }
197
198    /// Check if a subform exists at the given path
199    pub fn has_subform(&self, subform_path: &str) -> bool {
200        self.subforms.contains_key(subform_path)
201    }
202}