sz_configtool_lib/
datasources.rs1use crate::error::{Result, SzConfigError};
2use crate::helpers;
3use serde_json::{Value, json};
4
5#[derive(Debug, Clone, Default)]
11pub struct AddDataSourceParams<'a> {
12 pub code: &'a str,
13 pub retention_level: Option<&'a str>,
14 pub conversational: Option<&'a str>,
15 pub reliability: Option<i64>,
16}
17
18#[derive(Debug, Clone, Default)]
20pub struct SetDataSourceParams<'a> {
21 pub code: &'a str,
22 pub retention_level: Option<&'a str>,
23 pub conversational: Option<&'a str>,
24 pub reliability: Option<i64>,
25}
26
27impl<'a> TryFrom<&'a Value> for AddDataSourceParams<'a> {
28 type Error = SzConfigError;
29
30 fn try_from(json: &'a Value) -> Result<Self> {
31 let code = json
32 .get("code")
33 .and_then(|v| v.as_str())
34 .ok_or_else(|| SzConfigError::MissingField("code".to_string()))?;
35
36 Ok(Self {
37 code,
38 retention_level: json.get("retentionLevel").and_then(|v| v.as_str()),
39 conversational: json.get("conversational").and_then(|v| v.as_str()),
40 reliability: json.get("reliability").and_then(|v| v.as_i64()),
41 })
42 }
43}
44
45impl<'a> TryFrom<&'a Value> for SetDataSourceParams<'a> {
46 type Error = SzConfigError;
47
48 fn try_from(json: &'a Value) -> Result<Self> {
49 let code = json
50 .get("code")
51 .and_then(|v| v.as_str())
52 .ok_or_else(|| SzConfigError::MissingField("code".to_string()))?;
53
54 Ok(Self {
55 code,
56 retention_level: json.get("retentionLevel").and_then(|v| v.as_str()),
57 conversational: json.get("conversational").and_then(|v| v.as_str()),
58 reliability: json.get("reliability").and_then(|v| v.as_i64()),
59 })
60 }
61}
62
63pub fn add_data_source(config_json: &str, params: AddDataSourceParams) -> Result<String> {
77 let mut config: Value =
78 serde_json::from_str(config_json).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
79
80 let dsrcs = config
81 .get_mut("G2_CONFIG")
82 .and_then(|g| g.get_mut("CFG_DSRC"))
83 .and_then(|v| v.as_array_mut())
84 .ok_or_else(|| SzConfigError::MissingSection("CFG_DSRC".to_string()))?;
85
86 let code_upper = params.code.to_uppercase();
88 if dsrcs
89 .iter()
90 .any(|d| d["DSRC_CODE"].as_str() == Some(&code_upper))
91 {
92 return Err(SzConfigError::AlreadyExists(format!(
93 "Data source already exists: {code_upper}"
94 )));
95 }
96
97 let next_id = helpers::get_next_id_from_array(dsrcs, "DSRC_ID")?;
98
99 let retention = if let Some(level) = params.retention_level {
101 let level_upper = level.to_uppercase();
103 match level_upper.as_str() {
104 "REMEMBER" => "Remember",
105 "FORGET" => "Forget",
106 _ => {
107 return Err(SzConfigError::InvalidInput(format!(
108 "Invalid RETENTIONLEVEL value '{level}'. Must be 'Remember' or 'Forget'"
109 )));
110 }
111 }
112 } else {
113 "Remember"
114 };
115
116 let conversational_flag = if let Some(conv) = params.conversational {
117 let conv_upper = conv.to_uppercase();
119 match conv_upper.as_str() {
120 "YES" => "Yes",
121 "NO" => "No",
122 _ => {
123 return Err(SzConfigError::InvalidInput(format!(
124 "Invalid CONVERSATIONAL value '{conv}'. Must be 'Yes' or 'No'"
125 )));
126 }
127 }
128 } else {
129 "No"
130 };
131
132 let reliability_score = params.reliability.unwrap_or(1);
133
134 dsrcs.push(json!({
135 "DSRC_ID": next_id,
136 "DSRC_CODE": code_upper.clone(),
137 "DSRC_DESC": code_upper, "DSRC_RELY": reliability_score,
139 "RETENTION_LEVEL": retention,
140 "CONVERSATIONAL": conversational_flag,
141 }));
142
143 serde_json::to_string(&config).map_err(|e| SzConfigError::JsonParse(e.to_string()))
144}
145
146pub fn delete_data_source(config_json: &str, code: &str) -> Result<String> {
161 let mut config: Value =
162 serde_json::from_str(config_json).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
163
164 let dsrcs = config
165 .get_mut("G2_CONFIG")
166 .and_then(|g| g.get_mut("CFG_DSRC"))
167 .and_then(|v| v.as_array_mut())
168 .ok_or_else(|| SzConfigError::MissingSection("CFG_DSRC".to_string()))?;
169
170 let code_upper = code.to_uppercase();
171
172 let dsrc_to_delete = dsrcs
174 .iter()
175 .find(|d| d["DSRC_CODE"].as_str() == Some(&code_upper))
176 .ok_or_else(|| SzConfigError::NotFound(format!("Data source not found: {code_upper}")))?;
177
178 if let Some(dsrc_id) = dsrc_to_delete.get("DSRC_ID").and_then(|v| v.as_i64()) {
180 if dsrc_id <= 2 {
181 return Err(SzConfigError::InvalidInput(format!(
182 "The {code_upper} data source cannot be deleted"
183 )));
184 }
185 }
186
187 let original_len = dsrcs.len();
189 dsrcs.retain(|d| d["DSRC_CODE"].as_str() != Some(&code_upper));
190
191 if dsrcs.len() == original_len {
192 return Err(SzConfigError::NotFound(format!(
193 "Data source not found: {code_upper}"
194 )));
195 }
196
197 serde_json::to_string(&config).map_err(|e| SzConfigError::JsonParse(e.to_string()))
198}
199
200pub fn get_data_source(config_json: &str, code: &str) -> Result<Value> {
214 let config: Value =
215 serde_json::from_str(config_json).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
216
217 let code_upper = code.to_uppercase();
218 config
219 .get("G2_CONFIG")
220 .and_then(|g| g.get("CFG_DSRC"))
221 .and_then(|v| v.as_array())
222 .ok_or_else(|| SzConfigError::MissingSection("CFG_DSRC".to_string()))?
223 .iter()
224 .find(|d| d["DSRC_CODE"].as_str() == Some(&code_upper))
225 .cloned()
226 .ok_or_else(|| SzConfigError::NotFound(format!("Data source not found: {code_upper}")))
227}
228
229pub fn list_data_sources(config_json: &str) -> Result<Vec<Value>> {
242 let config: Value =
243 serde_json::from_str(config_json).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
244
245 let dsrcs = config
246 .get("G2_CONFIG")
247 .and_then(|g| g.get("CFG_DSRC"))
248 .and_then(|v| v.as_array())
249 .ok_or_else(|| SzConfigError::MissingSection("CFG_DSRC".to_string()))?;
250
251 Ok(dsrcs
252 .iter()
253 .map(|item| {
254 json!({
255 "id": item.get("DSRC_ID").and_then(|v| v.as_i64()).unwrap_or(0),
256 "dataSource": item.get("DSRC_CODE").and_then(|v| v.as_str()).unwrap_or("")
257 })
258 })
259 .collect())
260}
261
262pub fn set_data_source(config_json: &str, params: SetDataSourceParams) -> Result<String> {
276 let mut config: Value =
277 serde_json::from_str(config_json).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
278
279 let code_upper = params.code.to_uppercase();
280 let dsrcs = config
281 .get_mut("G2_CONFIG")
282 .and_then(|g| g.get_mut("CFG_DSRC"))
283 .and_then(|v| v.as_array_mut())
284 .ok_or_else(|| SzConfigError::MissingSection("CFG_DSRC".to_string()))?;
285
286 let dsrc = dsrcs
287 .iter_mut()
288 .find(|d| d["DSRC_CODE"].as_str() == Some(&code_upper))
289 .ok_or_else(|| SzConfigError::NotFound(format!("Data source not found: {code_upper}")))?;
290
291 if let Some(dsrc_obj) = dsrc.as_object_mut() {
293 if let Some(retention) = params.retention_level {
294 dsrc_obj.insert("RETENTION_LEVEL".to_string(), json!(retention));
295 }
296 if let Some(conversational) = params.conversational {
297 dsrc_obj.insert("CONVERSATIONAL".to_string(), json!(conversational));
298 }
299 if let Some(reliability) = params.reliability {
300 dsrc_obj.insert("DSRC_RELY".to_string(), json!(reliability));
301 }
302 }
303
304 serde_json::to_string(&config).map_err(|e| SzConfigError::JsonParse(e.to_string()))
305}