1use serde::de::{self, Deserializer, MapAccess, Visitor};
8use serde::ser::{SerializeMap, Serializer};
9use serde::{Deserialize, Serialize};
10use serde_json::{Map, Value};
11
12#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub struct StructureMap {
16 #[serde(default = "resource_type")]
17 pub resource_type: String,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub id: Option<String>,
20 #[serde(default, skip_serializing_if = "Vec::is_empty")]
22 pub contained: Vec<Value>,
23 #[serde(default, skip_serializing_if = "Vec::is_empty")]
24 pub extension: Vec<Extension>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub url: Option<String>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub version: Option<String>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub name: Option<String>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub title: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub status: Option<String>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub experimental: Option<bool>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub date: Option<String>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub publisher: Option<String>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 pub description: Option<String>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 pub purpose: Option<String>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub copyright: Option<String>,
47 #[serde(default, skip_serializing_if = "Vec::is_empty")]
48 pub structure: Vec<Structure>,
49 #[serde(default, skip_serializing_if = "Vec::is_empty")]
50 pub import: Vec<String>,
51 #[serde(rename = "const", default, skip_serializing_if = "Vec::is_empty")]
52 pub constants: Vec<Constant>,
53 #[serde(default, skip_serializing_if = "Vec::is_empty")]
54 pub group: Vec<Group>,
55 #[serde(flatten)]
57 pub other: Map<String, Value>,
58}
59
60fn resource_type() -> String {
61 "StructureMap".to_owned()
62}
63
64impl StructureMap {
65 pub fn new() -> Self {
66 Self {
67 resource_type: resource_type(),
68 ..Self::default()
69 }
70 }
71}
72
73#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct Extension {
77 pub url: String,
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub value_string: Option<String>,
80 #[serde(flatten)]
81 pub other: Map<String, Value>,
82}
83
84impl Extension {
85 pub fn string(url: &str, value: impl Into<String>) -> Self {
86 Self {
87 url: url.to_owned(),
88 value_string: Some(value.into()),
89 other: Map::new(),
90 }
91 }
92}
93
94#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
96#[serde(rename_all = "camelCase")]
97pub struct Structure {
98 pub url: String,
99 pub mode: String,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub alias: Option<String>,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub documentation: Option<String>,
104 #[serde(flatten)]
105 pub other: Map<String, Value>,
106}
107
108#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
110#[serde(rename_all = "camelCase")]
111pub struct Constant {
112 pub name: String,
113 pub value: String,
114 #[serde(flatten)]
115 pub other: Map<String, Value>,
116}
117
118#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
119#[serde(rename_all = "camelCase")]
120pub struct Group {
121 pub name: String,
122 #[serde(skip_serializing_if = "Option::is_none")]
123 pub extends: Option<String>,
124 #[serde(skip_serializing_if = "Option::is_none")]
126 pub type_mode: Option<String>,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub documentation: Option<String>,
129 #[serde(default, skip_serializing_if = "Vec::is_empty")]
130 pub input: Vec<Input>,
131 #[serde(default, skip_serializing_if = "Vec::is_empty")]
132 pub rule: Vec<Rule>,
133 #[serde(flatten)]
134 pub other: Map<String, Value>,
135}
136
137#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
138#[serde(rename_all = "camelCase")]
139pub struct Input {
140 pub name: String,
141 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
142 pub type_name: Option<String>,
143 pub mode: String,
145 #[serde(skip_serializing_if = "Option::is_none")]
146 pub documentation: Option<String>,
147 #[serde(flatten)]
148 pub other: Map<String, Value>,
149}
150
151#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
152#[serde(rename_all = "camelCase")]
153pub struct Rule {
154 #[serde(skip_serializing_if = "Option::is_none")]
155 pub name: Option<String>,
156 #[serde(default, skip_serializing_if = "Vec::is_empty")]
157 pub source: Vec<Source>,
158 #[serde(default, skip_serializing_if = "Vec::is_empty")]
159 pub target: Vec<Target>,
160 #[serde(default, skip_serializing_if = "Vec::is_empty")]
161 pub rule: Vec<Rule>,
162 #[serde(default, skip_serializing_if = "Vec::is_empty")]
163 pub dependent: Vec<Dependent>,
164 #[serde(skip_serializing_if = "Option::is_none")]
165 pub documentation: Option<String>,
166 #[serde(flatten)]
167 pub other: Map<String, Value>,
168}
169
170#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
171#[serde(rename_all = "camelCase")]
172pub struct Source {
173 #[serde(default, skip_serializing_if = "Vec::is_empty")]
175 pub extension: Vec<Extension>,
176 pub context: String,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub min: Option<i64>,
179 #[serde(skip_serializing_if = "Option::is_none")]
180 pub max: Option<String>,
181 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
182 pub type_name: Option<String>,
183 #[serde(skip_serializing_if = "Option::is_none")]
185 pub default_value: Option<String>,
186 #[serde(skip_serializing_if = "Option::is_none")]
187 pub element: Option<String>,
188 #[serde(skip_serializing_if = "Option::is_none")]
189 pub list_mode: Option<String>,
190 #[serde(skip_serializing_if = "Option::is_none")]
191 pub variable: Option<String>,
192 #[serde(skip_serializing_if = "Option::is_none")]
193 pub condition: Option<String>,
194 #[serde(skip_serializing_if = "Option::is_none")]
195 pub check: Option<String>,
196 #[serde(skip_serializing_if = "Option::is_none")]
197 pub log_message: Option<String>,
198 #[serde(flatten)]
199 pub other: Map<String, Value>,
200}
201
202#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
203#[serde(rename_all = "camelCase")]
204pub struct Target {
205 #[serde(default, skip_serializing_if = "Vec::is_empty")]
206 pub extension: Vec<Extension>,
207 #[serde(skip_serializing_if = "Option::is_none")]
208 pub context: Option<String>,
209 #[serde(skip_serializing_if = "Option::is_none")]
211 pub context_type: Option<String>,
212 #[serde(skip_serializing_if = "Option::is_none")]
213 pub element: Option<String>,
214 #[serde(skip_serializing_if = "Option::is_none")]
215 pub variable: Option<String>,
216 #[serde(default, skip_serializing_if = "Vec::is_empty")]
217 pub list_mode: Vec<String>,
218 #[serde(skip_serializing_if = "Option::is_none")]
219 pub list_rule_id: Option<String>,
220 #[serde(skip_serializing_if = "Option::is_none")]
221 pub transform: Option<String>,
222 #[serde(default, skip_serializing_if = "Vec::is_empty")]
223 pub parameter: Vec<Parameter>,
224 #[serde(flatten)]
225 pub other: Map<String, Value>,
226}
227
228#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
230#[serde(rename_all = "camelCase")]
231pub struct Dependent {
232 pub name: String,
233 #[serde(default, skip_serializing_if = "Vec::is_empty")]
234 pub parameter: Vec<Parameter>,
235 #[serde(flatten)]
236 pub other: Map<String, Value>,
237}
238
239#[derive(Debug, Clone, PartialEq)]
242pub struct Parameter {
243 pub value: ParameterValue,
244 pub value_element: Option<Value>,
245}
246
247impl From<ParameterValue> for Parameter {
248 fn from(value: ParameterValue) -> Self {
249 Self {
250 value,
251 value_element: None,
252 }
253 }
254}
255
256#[derive(Debug, Clone, PartialEq)]
258pub enum ParameterValue {
259 Id(String),
261 String(String),
262 Boolean(bool),
263 Integer(i64),
264 Decimal(serde_json::Number),
265 Date(String),
266 Time(String),
267 DateTime(String),
268}
269
270impl ParameterValue {
271 fn key(&self) -> &'static str {
272 match self {
273 ParameterValue::Id(_) => "valueId",
274 ParameterValue::String(_) => "valueString",
275 ParameterValue::Boolean(_) => "valueBoolean",
276 ParameterValue::Integer(_) => "valueInteger",
277 ParameterValue::Decimal(_) => "valueDecimal",
278 ParameterValue::Date(_) => "valueDate",
279 ParameterValue::Time(_) => "valueTime",
280 ParameterValue::DateTime(_) => "valueDateTime",
281 }
282 }
283
284 fn json(&self) -> Value {
285 match self {
286 ParameterValue::Id(v)
287 | ParameterValue::String(v)
288 | ParameterValue::Date(v)
289 | ParameterValue::Time(v)
290 | ParameterValue::DateTime(v) => Value::String(v.clone()),
291 ParameterValue::Boolean(v) => Value::Bool(*v),
292 ParameterValue::Integer(v) => Value::from(*v),
293 ParameterValue::Decimal(v) => Value::Number(v.clone()),
294 }
295 }
296
297 fn from_json(key: &str, value: Value) -> Result<Option<Self>, String> {
298 let text = || {
299 value
300 .as_str()
301 .map(str::to_owned)
302 .ok_or_else(|| format!("{key} must be a string"))
303 };
304 Ok(Some(match key {
305 "valueId" => ParameterValue::Id(text()?),
306 "valueString" => ParameterValue::String(text()?),
307 "valueDate" => ParameterValue::Date(text()?),
308 "valueTime" => ParameterValue::Time(text()?),
309 "valueDateTime" => ParameterValue::DateTime(text()?),
310 "valueBoolean" => {
311 ParameterValue::Boolean(value.as_bool().ok_or("valueBoolean must be a boolean")?)
312 }
313 "valueInteger" => {
314 ParameterValue::Integer(value.as_i64().ok_or("valueInteger must be an integer")?)
315 }
316 "valueDecimal" => match value {
317 Value::Number(n) => ParameterValue::Decimal(n),
318 _ => return Err("valueDecimal must be a number".to_owned()),
319 },
320 _ => return Ok(None),
321 }))
322 }
323}
324
325impl Serialize for Parameter {
326 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
327 let key = self.value.key();
328 let mut map = serializer.serialize_map(None)?;
329 map.serialize_entry(key, &self.value.json())?;
330 if let Some(element) = &self.value_element {
331 map.serialize_entry(&format!("_{key}"), element)?;
332 }
333 map.end()
334 }
335}
336
337impl<'de> Deserialize<'de> for Parameter {
338 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
339 struct ParameterVisitor;
340
341 impl<'de> Visitor<'de> for ParameterVisitor {
342 type Value = Parameter;
343
344 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
345 f.write_str("a StructureMap parameter with one value[x] element")
346 }
347
348 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Parameter, A::Error> {
349 let mut value = None;
350 let mut value_element = None;
351 while let Some(key) = map.next_key::<String>()? {
352 let json: Value = map.next_value()?;
353 if key.starts_with("_value") {
354 value_element = Some(json);
355 } else if key.starts_with("value") {
356 value = Some(
357 ParameterValue::from_json(&key, json)
358 .map_err(de::Error::custom)?
359 .ok_or_else(|| {
360 de::Error::custom(format!("unsupported parameter type {key}"))
361 })?,
362 );
363 }
364 }
365 let value = value.ok_or_else(|| de::Error::custom("parameter has no value[x]"))?;
366 Ok(Parameter {
367 value,
368 value_element,
369 })
370 }
371 }
372
373 deserializer.deserialize_map(ParameterVisitor)
374 }
375}