a2ui_base/model/
data_context.rs1use std::collections::HashMap;
4
5use serde_json::Value;
6
7use super::data_model::DataModel;
8use crate::protocol::common_types::{
9 DynamicBoolean, DynamicBooleanCondition, DynamicNumber, DynamicString,
10 DynamicValue, FunctionCall,
11};
12
13pub struct DataContext<'a> {
20 data_model: &'a DataModel,
21 base_path: String,
22 functions: &'a HashMap<String, Box<dyn crate::catalog::function_api::FunctionImplementation>>,
23}
24
25impl<'a> DataContext<'a> {
26 pub fn new(
28 data_model: &'a DataModel,
29 functions: &'a HashMap<String, Box<dyn crate::catalog::function_api::FunctionImplementation>>,
30 ) -> Self {
31 Self {
32 data_model,
33 base_path: String::new(),
34 functions,
35 }
36 }
37
38 pub fn nested(&self, relative_path: &str) -> DataContext<'a> {
40 let new_base = if self.base_path.is_empty() {
41 format!("/{}", relative_path)
42 } else {
43 format!("{}/{}", self.base_path, relative_path)
44 };
45 DataContext {
46 data_model: self.data_model,
47 base_path: new_base,
48 functions: self.functions,
49 }
50 }
51
52 pub fn base_path(&self) -> &str {
54 &self.base_path
55 }
56
57 pub fn resolve_pointer(&self, path: &str) -> String {
59 if path.starts_with('/') {
60 path.to_string()
61 } else if path.is_empty() {
62 self.base_path.clone()
63 } else if self.base_path.is_empty() {
64 format!("/{}", path)
65 } else {
66 format!("{}/{}", self.base_path, path)
67 }
68 }
69
70 pub fn get(&self, path: &str) -> Option<Value> {
72 let pointer = self.resolve_pointer(path);
73 self.data_model.get(&pointer).cloned()
74 }
75
76 pub fn resolve_dynamic_string(&self, ds: &DynamicString) -> String {
78 match ds {
79 DynamicString::Literal(s) => s.clone(),
80 DynamicString::Binding(b) => self.resolve_binding_to_string(&b.path),
81 DynamicString::Function(fc) => {
82 let result = self.execute_function(fc);
83 value_to_string(&result)
84 }
85 }
86 }
87
88 pub fn resolve_dynamic_number(&self, dn: &DynamicNumber) -> f64 {
90 match dn {
91 DynamicNumber::Literal(n) => *n,
92 DynamicNumber::Binding(b) => self
93 .resolve_binding(&b.path)
94 .and_then(|v| v.as_f64())
95 .unwrap_or(0.0),
96 DynamicNumber::Function(fc) => {
97 let result = self.execute_function(fc);
98 result.as_f64().unwrap_or(0.0)
99 }
100 }
101 }
102
103 pub fn resolve_dynamic_boolean(&self, db: &DynamicBoolean) -> bool {
105 match db {
106 DynamicBoolean::Literal(b) => *b,
107 DynamicBoolean::Binding(b) => self
108 .resolve_binding(&b.path)
109 .and_then(|v| v.as_bool())
110 .unwrap_or(false),
111 DynamicBoolean::Function(fc) => {
112 let result = self.execute_function(fc);
113 result.as_bool().unwrap_or(false)
114 }
115 }
116 }
117
118 pub fn resolve_dynamic_boolean_condition(&self, db: &DynamicBooleanCondition) -> bool {
120 match db {
121 DynamicBooleanCondition::Literal(b) => *b,
122 DynamicBooleanCondition::Binding(b) => self
123 .resolve_binding(&b.path)
124 .and_then(|v| v.as_bool())
125 .unwrap_or(false),
126 DynamicBooleanCondition::Function(fc) => {
127 let result = self.execute_function(fc);
128 result.as_bool().unwrap_or(false)
129 }
130 }
131 }
132
133 pub fn resolve_dynamic_value(&self, dv: &DynamicValue) -> Value {
135 match dv {
136 DynamicValue::String(s) => Value::String(s.clone()),
137 DynamicValue::Number(n) => serde_json::json!(*n),
138 DynamicValue::Boolean(b) => Value::Bool(*b),
139 DynamicValue::Array(arr) => Value::Array(arr.clone()),
140 DynamicValue::Binding(b) => self.resolve_binding(&b.path).unwrap_or(Value::Null),
141 DynamicValue::Function(fc) => self.execute_function(fc),
142 }
143 }
144
145 fn resolve_binding(&self, path: &str) -> Option<Value> {
147 let pointer = self.resolve_pointer(path);
148 self.data_model.get(&pointer).cloned()
149 }
150
151 fn resolve_binding_to_string(&self, path: &str) -> String {
153 self.resolve_binding(path)
154 .map(|v| value_to_string(&v))
155 .unwrap_or_default()
156 }
157
158 pub fn call_function_by_name(
162 &self,
163 name: &str,
164 args: &HashMap<String, Value>,
165 ) -> Option<Value> {
166 let func = self.functions.get(name)?;
167 let mut resolved_args = HashMap::new();
169 for (key, val) in args {
170 let resolved = self.resolve_arg_value(val);
171 resolved_args.insert(key.clone(), resolved);
172 }
173 func.execute(&resolved_args, self).ok()
174 }
175
176 fn execute_function(&self, fc: &FunctionCall) -> Value {
178 let Some(func) = self.functions.get(&fc.call) else {
179 return Value::Null;
180 };
181
182 let mut resolved_args = HashMap::new();
184 for (key, val) in &fc.args {
185 let resolved = self.resolve_arg_value(val);
187 resolved_args.insert(key.clone(), resolved);
188 }
189
190 match func.execute(&resolved_args, self) {
191 Ok(v) => v,
192 Err(_) => Value::Null,
193 }
194 }
195
196 fn resolve_arg_value(&self, val: &Value) -> Value {
198 if let Some(obj) = val.as_object() {
199 if let Some(path) = obj.get("path").and_then(|v| v.as_str()) {
200 return self.resolve_binding(path).unwrap_or(Value::Null);
201 }
202 if let Some(call) = obj.get("call").and_then(|v| v.as_str()) {
203 let args = obj
204 .get("args")
205 .and_then(|v| v.as_object())
206 .map(|m| {
207 m.iter()
208 .map(|(k, v)| (k.clone(), self.resolve_arg_value(v)))
209 .collect::<HashMap<_, _>>()
210 })
211 .unwrap_or_default();
212 let fc = FunctionCall {
213 call: call.to_string(),
214 args,
215 };
216 return self.execute_function(&fc);
217 }
218 }
219 val.clone()
220 }
221}
222
223pub fn value_to_string(v: &Value) -> String {
225 match v {
226 Value::String(s) => s.clone(),
227 Value::Number(n) => n.to_string(),
228 Value::Bool(b) => b.to_string(),
229 Value::Null => String::new(),
230 Value::Array(_) | Value::Object(_) => v.to_string(),
231 }
232}