sz_configtool_lib/functions/
comparison.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 AddComparisonFunctionParams<'a> {
19 pub connect_str: &'a str,
20 pub description: Option<&'a str>,
21 pub language: Option<&'a str>,
22 pub anon_support: Option<&'a str>,
23}
24
25impl<'a> TryFrom<&'a Value> for AddComparisonFunctionParams<'a> {
26 type Error = SzConfigError;
27
28 fn try_from(json: &'a Value) -> Result<Self, SzConfigError> {
29 Ok(Self {
30 connect_str: json
31 .get("connectStr")
32 .and_then(|v| v.as_str())
33 .ok_or_else(|| SzConfigError::MissingField("connectStr".to_string()))?,
34 description: json.get("description").and_then(|v| v.as_str()),
35 language: json.get("language").and_then(|v| v.as_str()),
36 anon_support: json.get("anonSupport").and_then(|v| v.as_str()),
37 })
38 }
39}
40
41#[derive(Debug, Clone, Default)]
43pub struct SetComparisonFunctionParams<'a> {
44 pub connect_str: Option<&'a str>,
45 pub description: Option<&'a str>,
46 pub language: Option<&'a str>,
47 pub anon_support: Option<&'a str>,
48}
49
50pub fn add_comparison_function(
63 config_json: &str,
64 cfunc_code: &str,
65 params: AddComparisonFunctionParams,
66) -> Result<(String, Value), SzConfigError> {
67 let cfunc_code = cfunc_code.to_uppercase();
68
69 if find_in_config_array(config_json, "CFG_CFUNC", "CFUNC_CODE", &cfunc_code)?.is_some() {
71 return Err(SzConfigError::validation(format!(
72 "Comparison function already exists: {cfunc_code}"
73 )));
74 }
75
76 let anon_support = if let Some(val) = params.anon_support {
78 let val_upper = val.to_uppercase();
79 match val_upper.as_str() {
80 "YES" => "Yes",
81 "NO" => "No",
82 _ => {
83 return Err(SzConfigError::validation(format!(
84 "Invalid ANON_SUPPORT value '{val}'. Must be 'Yes' or 'No'"
85 )));
86 }
87 }
88 } else {
89 "No"
90 };
91
92 let config_data: Value =
94 serde_json::from_str(config_json).map_err(|e| SzConfigError::json_parse(e.to_string()))?;
95 let cfunc_id = get_next_id(&config_data, "G2_CONFIG.CFG_CFUNC", "CFUNC_ID", 1)?;
96
97 let mut new_record = json!({
99 "CFUNC_ID": cfunc_id,
100 "CFUNC_CODE": cfunc_code,
101 "CONNECT_STR": params.connect_str,
102 "ANON_SUPPORT": anon_support,
103 });
104
105 new_record["CFUNC_DESC"] = match params.description {
107 Some(desc) => json!(desc),
108 None => Value::Null,
109 };
110 new_record["LANGUAGE"] = match params.language {
111 Some(lang) => json!(lang),
112 None => Value::Null,
113 };
114
115 let modified_json = add_to_config_array(config_json, "CFG_CFUNC", new_record.clone())?;
117
118 Ok((modified_json, new_record))
119}
120
121pub fn delete_comparison_function(
133 config_json: &str,
134 cfunc_code: &str,
135) -> Result<(String, Value), SzConfigError> {
136 let cfunc_code = cfunc_code.to_uppercase();
137
138 let function = find_in_config_array(config_json, "CFG_CFUNC", "CFUNC_CODE", &cfunc_code)?
140 .ok_or_else(|| {
141 SzConfigError::not_found(format!("Comparison function not found: {cfunc_code}"))
142 })?;
143
144 let modified_json =
146 delete_from_config_array(config_json, "CFG_CFUNC", "CFUNC_CODE", &cfunc_code)?;
147
148 Ok((modified_json, function))
149}
150
151pub fn get_comparison_function(
163 config_json: &str,
164 cfunc_code: &str,
165) -> Result<Value, SzConfigError> {
166 let cfunc_code = cfunc_code.to_uppercase();
167
168 find_in_config_array(config_json, "CFG_CFUNC", "CFUNC_CODE", &cfunc_code)?.ok_or_else(|| {
169 SzConfigError::not_found(format!("Comparison function not found: {cfunc_code}"))
170 })
171}
172
173pub fn list_comparison_functions(config_json: &str) -> Result<Vec<Value>, SzConfigError> {
184 let config_data: Value =
185 serde_json::from_str(config_json).map_err(|e| SzConfigError::json_parse(e.to_string()))?;
186
187 let items: Vec<Value> = if let Some(g2_config) = config_data.get("G2_CONFIG")
188 && let Some(array) = g2_config.get("CFG_CFUNC")
189 && let Some(items) = array.as_array()
190 {
191 items
192 .iter()
193 .map(|item| {
194 json!({
195 "id": item.get("CFUNC_ID").and_then(|v| v.as_i64()).unwrap_or(0),
196 "function": item.get("CFUNC_CODE").and_then(|v| v.as_str()).unwrap_or(""),
197 "connectStr": item.get("CONNECT_STR").and_then(|v| v.as_str()).unwrap_or(""),
198 "language": item.get("LANGUAGE").and_then(|v| v.as_str()).unwrap_or(""),
199 "anonSupport": item.get("ANON_SUPPORT").and_then(|v| v.as_str()).unwrap_or("")
200 })
201 })
202 .collect()
203 } else {
204 Vec::new()
205 };
206
207 Ok(items)
208}
209
210pub fn set_comparison_function(
223 config_json: &str,
224 cfunc_code: &str,
225 params: SetComparisonFunctionParams,
226) -> Result<(String, Value), SzConfigError> {
227 let cfunc_code = cfunc_code.to_uppercase();
228
229 let mut function = find_in_config_array(config_json, "CFG_CFUNC", "CFUNC_CODE", &cfunc_code)?
231 .ok_or_else(|| {
232 SzConfigError::not_found(format!("Comparison function not found: {cfunc_code}"))
233 })?;
234
235 if let Some(obj) = function.as_object_mut() {
237 if let Some(conn) = params.connect_str {
238 obj.insert("CONNECT_STR".to_string(), json!(conn));
239 }
240 if let Some(desc) = params.description {
241 obj.insert("CFUNC_DESC".to_string(), json!(desc));
242 }
243 if let Some(lang) = params.language {
244 obj.insert("LANGUAGE".to_string(), json!(lang));
245 }
246 if let Some(anon) = params.anon_support {
247 obj.insert("ANON_SUPPORT".to_string(), json!(anon));
248 }
249 }
250
251 let temp_json = delete_from_config_array(config_json, "CFG_CFUNC", "CFUNC_CODE", &cfunc_code)?;
253 let modified_json = add_to_config_array(&temp_json, "CFG_CFUNC", function.clone())?;
254
255 Ok((modified_json, function))
256}
257
258pub fn add_comparison_func_return_code(
272 config_json: &str,
273 cfunc_code: &str,
274 cfrtn_code: &str,
275 cfrtn_desc: Option<&str>,
276) -> Result<(String, Value), SzConfigError> {
277 let cfunc_code = cfunc_code.to_uppercase();
278 let cfrtn_code = cfrtn_code.to_uppercase();
279
280 let config_data: Value =
282 serde_json::from_str(config_json).map_err(|e| SzConfigError::json_parse(e.to_string()))?;
283
284 let cfunc = find_in_config_array(config_json, "CFG_CFUNC", "CFUNC_CODE", &cfunc_code)?
285 .ok_or_else(|| {
286 SzConfigError::not_found(format!("Comparison function not found: {cfunc_code}"))
287 })?;
288
289 let cfunc_id = cfunc
290 .get("CFUNC_ID")
291 .and_then(|v| v.as_i64())
292 .ok_or_else(|| SzConfigError::validation("CFUNC_ID not found"))?;
293
294 if let Some(g2_config) = config_data.get("G2_CONFIG")
296 && let Some(array) = g2_config.get("CFG_CFRTN")
297 && let Some(items) = array.as_array()
298 && items.iter().any(|item| {
299 item.get("CFUNC_ID").and_then(|v| v.as_i64()) == Some(cfunc_id)
300 && item.get("CFRTN_CODE").and_then(|v| v.as_str()) == Some(&cfrtn_code)
301 })
302 {
303 return Err(SzConfigError::validation(format!(
304 "Return code {cfrtn_code} already exists for function {cfunc_code}"
305 )));
306 }
307
308 let cfrtn_id = get_next_id(&config_data, "G2_CONFIG.CFG_CFRTN", "CFRTN_ID", 1)?;
310
311 let mut new_record = json!({
313 "CFRTN_ID": cfrtn_id,
314 "CFUNC_ID": cfunc_id,
315 "CFRTN_CODE": cfrtn_code,
316 });
317
318 new_record["CFRTN_DESC"] = match cfrtn_desc {
320 Some(desc) => json!(desc),
321 None => Value::Null,
322 };
323
324 let modified_json = add_to_config_array(config_json, "CFG_CFRTN", new_record.clone())?;
326
327 Ok((modified_json, new_record))
328}
329
330#[cfg(test)]
331mod tests {
332 use super::*;
333
334 fn get_test_config() -> String {
335 json!({
336 "G2_CONFIG": {
337 "CFG_CFUNC": [
338 {
339 "CFUNC_ID": 1,
340 "CFUNC_CODE": "CMP_NAME",
341 "CONNECT_STR": "g2CmpName",
342 "LANGUAGE": "en"
343 }
344 ],
345 "CFG_CFRTN": []
346 }
347 })
348 .to_string()
349 }
350
351 #[test]
352 fn test_add_comparison_function() {
353 let config = get_test_config();
354 let result = add_comparison_function(
355 &config,
356 "custom_cmp",
357 AddComparisonFunctionParams {
358 connect_str: "g2CustomCmp",
359 description: Some("Custom compare"),
360 language: Some("en"),
361 anon_support: Some("Yes"),
362 },
363 );
364 assert!(result.is_ok());
365 let (modified, record) = result.unwrap();
366 assert!(modified.contains("CUSTOM_CMP"));
367 assert_eq!(record["CFUNC_CODE"], "CUSTOM_CMP");
368 }
369
370 #[test]
371 fn test_list_comparison_functions() {
372 let config = get_test_config();
373 let result = list_comparison_functions(&config);
374 assert!(result.is_ok());
375 let items = result.unwrap();
376 assert_eq!(items.len(), 1);
377 assert_eq!(items[0]["function"], "CMP_NAME");
378 }
379}