sz_configtool_lib/functions/
expression.rs1use crate::error::SzConfigError;
7use crate::helpers::{
8 add_to_config_array, delete_from_config_array, find_in_config_array, get_next_id,
9};
10use serde_json::{Value, json};
11
12#[derive(Debug, Clone, Default)]
18pub struct AddExpressionFunctionParams<'a> {
19 pub connect_str: &'a str,
20 pub description: Option<&'a str>,
21 pub language: Option<&'a str>,
22}
23
24impl<'a> TryFrom<&'a Value> for AddExpressionFunctionParams<'a> {
25 type Error = SzConfigError;
26
27 fn try_from(json: &'a Value) -> Result<Self, SzConfigError> {
28 Ok(Self {
29 connect_str: json
30 .get("connectStr")
31 .and_then(|v| v.as_str())
32 .ok_or_else(|| SzConfigError::MissingField("connectStr".to_string()))?,
33 description: json.get("description").and_then(|v| v.as_str()),
34 language: json.get("language").and_then(|v| v.as_str()),
35 })
36 }
37}
38
39#[derive(Debug, Clone, Default)]
41pub struct SetExpressionFunctionParams<'a> {
42 pub connect_str: Option<&'a str>,
43 pub description: Option<&'a str>,
44 pub language: Option<&'a str>,
45}
46
47pub fn add_expression_function(
60 config_json: &str,
61 efunc_code: &str,
62 params: AddExpressionFunctionParams,
63) -> Result<(String, Value), SzConfigError> {
64 let efunc_code = efunc_code.to_uppercase();
65
66 if find_in_config_array(config_json, "CFG_EFUNC", "EFUNC_CODE", &efunc_code)?.is_some() {
68 return Err(SzConfigError::validation(format!(
69 "Expression function already exists: {efunc_code}"
70 )));
71 }
72
73 let config_data: Value =
75 serde_json::from_str(config_json).map_err(|e| SzConfigError::json_parse(e.to_string()))?;
76 let efunc_id = get_next_id(&config_data, "G2_CONFIG.CFG_EFUNC", "EFUNC_ID", 1)?;
77
78 let mut new_record = json!({
80 "EFUNC_ID": efunc_id,
81 "EFUNC_CODE": efunc_code,
82 "CONNECT_STR": params.connect_str,
83 });
84
85 new_record["EFUNC_DESC"] = match params.description {
87 Some(desc) => json!(desc),
88 None => Value::Null,
89 };
90 new_record["LANGUAGE"] = match params.language {
91 Some(lang) => json!(lang),
92 None => Value::Null,
93 };
94
95 let modified_json = add_to_config_array(config_json, "CFG_EFUNC", new_record.clone())?;
97
98 Ok((modified_json, new_record))
99}
100
101pub fn delete_expression_function(
113 config_json: &str,
114 efunc_code: &str,
115) -> Result<(String, Value), SzConfigError> {
116 let efunc_code = efunc_code.to_uppercase();
117
118 let function = find_in_config_array(config_json, "CFG_EFUNC", "EFUNC_CODE", &efunc_code)?
120 .ok_or_else(|| {
121 SzConfigError::not_found(format!("Expression function not found: {efunc_code}"))
122 })?;
123
124 let modified_json =
126 delete_from_config_array(config_json, "CFG_EFUNC", "EFUNC_CODE", &efunc_code)?;
127
128 Ok((modified_json, function))
129}
130
131pub fn get_expression_function(
143 config_json: &str,
144 efunc_code: &str,
145) -> Result<Value, SzConfigError> {
146 let efunc_code = efunc_code.to_uppercase();
147
148 find_in_config_array(config_json, "CFG_EFUNC", "EFUNC_CODE", &efunc_code)?.ok_or_else(|| {
149 SzConfigError::not_found(format!("Expression function not found: {efunc_code}"))
150 })
151}
152
153pub fn list_expression_functions(config_json: &str) -> Result<Vec<Value>, SzConfigError> {
164 let config_data: Value =
165 serde_json::from_str(config_json).map_err(|e| SzConfigError::json_parse(e.to_string()))?;
166
167 let items: Vec<Value> = if let Some(g2_config) = config_data.get("G2_CONFIG")
168 && let Some(array) = g2_config.get("CFG_EFUNC")
169 && let Some(items) = array.as_array()
170 {
171 items
172 .iter()
173 .map(|item| {
174 json!({
175 "id": item.get("EFUNC_ID").and_then(|v| v.as_i64()).unwrap_or(0),
176 "function": item.get("EFUNC_CODE").and_then(|v| v.as_str()).unwrap_or(""),
177 "connectStr": item.get("CONNECT_STR").and_then(|v| v.as_str()).unwrap_or(""),
178 "language": item.get("LANGUAGE").and_then(|v| v.as_str()).unwrap_or("")
179 })
180 })
181 .collect()
182 } else {
183 Vec::new()
184 };
185
186 Ok(items)
187}
188
189pub fn set_expression_function(
202 config_json: &str,
203 efunc_code: &str,
204 params: SetExpressionFunctionParams,
205) -> Result<(String, Value), SzConfigError> {
206 let efunc_code = efunc_code.to_uppercase();
207
208 let mut function = find_in_config_array(config_json, "CFG_EFUNC", "EFUNC_CODE", &efunc_code)?
210 .ok_or_else(|| {
211 SzConfigError::not_found(format!("Expression function not found: {efunc_code}"))
212 })?;
213
214 if let Some(obj) = function.as_object_mut() {
216 if let Some(conn) = params.connect_str {
217 obj.insert("CONNECT_STR".to_string(), json!(conn));
218 }
219 if let Some(desc) = params.description {
220 obj.insert("EFUNC_DESC".to_string(), json!(desc));
221 }
222 if let Some(lang) = params.language {
223 obj.insert("LANGUAGE".to_string(), json!(lang));
224 }
225 }
226
227 let temp_json = delete_from_config_array(config_json, "CFG_EFUNC", "EFUNC_CODE", &efunc_code)?;
229 let modified_json = add_to_config_array(&temp_json, "CFG_EFUNC", function.clone())?;
230
231 Ok((modified_json, function))
232}
233
234#[cfg(test)]
235mod tests {
236 use super::*;
237
238 fn get_test_config() -> String {
239 json!({
240 "G2_CONFIG": {
241 "CFG_EFUNC": [
242 {
243 "EFUNC_ID": 1,
244 "EFUNC_CODE": "EXPR_FEAT",
245 "CONNECT_STR": "g2ExprFeat",
246 "LANGUAGE": "en"
247 }
248 ]
249 }
250 })
251 .to_string()
252 }
253
254 #[test]
255 fn test_add_expression_function() {
256 let config = get_test_config();
257 let result = add_expression_function(
258 &config,
259 "custom_expr",
260 AddExpressionFunctionParams {
261 connect_str: "g2CustomExpr",
262 description: Some("Custom expression"),
263 language: Some("en"),
264 },
265 );
266 assert!(result.is_ok());
267 let (modified, record) = result.unwrap();
268 assert!(modified.contains("CUSTOM_EXPR"));
269 assert_eq!(record["EFUNC_CODE"], "CUSTOM_EXPR");
270 }
271
272 #[test]
273 fn test_list_expression_functions() {
274 let config = get_test_config();
275 let result = list_expression_functions(&config);
276 assert!(result.is_ok());
277 let items = result.unwrap();
278 assert_eq!(items.len(), 1);
279 assert_eq!(items[0]["function"], "EXPR_FEAT");
280 }
281}