operaton_task_worker/structures/
process_variables.rs1use std::collections::HashMap;
2use serde::{Deserialize, Serialize};
3use log::error;
4
5#[derive(Debug, Serialize, Deserialize)]
6#[serde(rename_all = "camelCase")]
7pub struct JsonValue {
8 data_format_name: String,
9
10 value: serde_json::Value,
11
12 string: bool,
13
14 object: bool,
15
16 boolean: bool,
17
18 number: bool,
19
20 array: bool,
21
22 #[serde(rename = "null")]
23 null_val: bool,
24
25 node_type: String,
26}
27
28#[derive(Debug, Serialize, Deserialize)]
29pub struct JsonVar {
30 #[serde(rename = "value")]
31 pub json_value: JsonValue,
32
33 #[serde(rename = "valueInfo")]
34 pub value_info: HashMap<String, serde_json::Value>,
35}
36
37#[derive(Debug, Serialize, Deserialize)]
38pub struct BoolVar {
39 pub value: bool,
40
41 #[serde(rename = "valueInfo")]
42 pub value_info: HashMap<String, serde_json::Value>,
43}
44
45#[derive(Debug, Serialize, Deserialize)]
46pub struct StringVar {
47 pub value: String,
48
49 #[serde(rename = "valueInfo")]
50 pub value_info: HashMap<String, serde_json::Value>,
51}
52
53#[derive(Debug)]
54pub enum ProcessInstanceVariable {
55 Json(JsonVar),
56 Boolean(BoolVar),
57 String(StringVar),
58}
59
60impl ProcessInstanceVariable {
61 pub fn as_bool(&self) -> Option<bool> {
62 match self {
63 ProcessInstanceVariable::Boolean(b) => Some(b.value),
64 _ => None,
65 }
66 }
67 pub fn as_str(&self) -> Option<&str> {
68 match self {
69 ProcessInstanceVariable::String(s) => Some(&s.value),
70 _ => None,
71 }
72 }
73 pub fn as_json(&self) -> Option<&serde_json::Value> {
74 match self {
75 ProcessInstanceVariable::Json(j) => Some(&j.json_value.value),
76 _ => None,
77 }
78 }
79}
80
81#[derive(Deserialize)]
83pub struct Entry {
84 #[serde(rename = "type")]
85 typ: String,
86
87 #[serde(default)]
88 #[allow(dead_code)]
89 name: String,
90
91 value: serde_json::Value,
92
93 #[serde(rename = "valueInfo")]
94 value_info: HashMap<String, serde_json::Value>,
95}
96
97impl<'de> Deserialize<'de> for ProcessInstanceVariable {
98 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
99 where
100 D: serde::Deserializer<'de>,
101 {
102 let map = HashMap::<String, Entry>::deserialize(deserializer)?;
103
104 for (_, entry) in map {
107 return match entry.typ.as_str() {
108 "Json" => {
109 let json_var = JsonVar {
110 json_value: serde_json::from_value(entry.value).map_err(serde::de::Error::custom)?,
111 value_info: entry.value_info,
112 };
113 Ok(ProcessInstanceVariable::Json(json_var))
114 }
115 "Boolean" => {
116 let bool_var = BoolVar {
117 value: serde_json::from_value(entry.value).map_err(serde::de::Error::custom)?,
118 value_info: entry.value_info,
119 };
120 Ok(ProcessInstanceVariable::Boolean(bool_var))
121 },
122 "String" => {
123 let string_var = StringVar {
124 value: serde_json::from_value(entry.value).map_err(serde::de::Error::custom)?,
125 value_info: entry.value_info,
126 };
127 Ok(ProcessInstanceVariable::String(string_var))
128 },
129 _ => Err(serde::de::Error::custom(format!("unknown type: {}", entry.typ))),
130 };
131 }
132
133 Err(serde::de::Error::custom("no valid entries found"))
134 }
135}
136
137pub fn parse_process_instance_variables(json_str: &str) -> HashMap<String, ProcessInstanceVariable> {
138 let parsed_map: HashMap<String, Entry> = serde_json::from_str(json_str).unwrap_or_else(|_| {
140 error!("Error while parsing \"{}\", ignoring it for now.", json_str);
141 HashMap::new()
142 });
143 let mut result = HashMap::new();
144 for (name, entry) in parsed_map {
145 let parsed_var = match entry.typ.as_str() {
146 "Json" => ProcessInstanceVariable::Json(JsonVar {
147 json_value: serde_json::from_value(entry.value).unwrap(),
148 value_info: entry.value_info,
149 }),
150 "Boolean" => ProcessInstanceVariable::Boolean(BoolVar {
151 value: serde_json::from_value(entry.value).unwrap(),
152 value_info: entry.value_info,
153 }),
154 "String" => ProcessInstanceVariable::String(StringVar {
155 value: serde_json::from_value(entry.value).unwrap(),
156 value_info: entry.value_info,
157 }),
158 _ => continue,
159 };
160 result.insert(name, parsed_var);
161 }
162 result
163}
164
165#[cfg(test)]
166mod test {
167 use crate::structures::process_variables::parse_process_instance_variables;
168
169 #[test]
170 fn test_module_parsing() {
171 let response_string: &str = "{\"checklist_vj3ler\":{\"type\":\"Json\",\"value\":{\"dataFormatName\":\"application/json\",\"value\":false,\"string\":false,\"object\":false,\"boolean\":false,\"number\":false,\"array\":true,\"null\":false,\"nodeType\":\"ARRAY\"},\"valueInfo\":{}},\"checkbox_6ow5yg\":{\"type\":\"Boolean\",\"value\":true,\"valueInfo\":{}}}";
172 let variables = parse_process_instance_variables(response_string);
173 dbg!(&variables);
174 assert!(!variables.is_empty())
175 }
176}