sdmx_json/structure/
constraints.rs

1use crate::primitives::{Annotation, Link};
2use crate::structure::CommonArtefactType;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::HashMap;
6use std::convert::Infallible;
7use std::str::FromStr;
8
9/// A subset of the definition of the allowable (or available)
10/// content of a dataset.
11#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
12#[serde(rename_all = "camelCase")]
13pub struct DataConstraint {
14	#[serde(flatten)]
15	pub artefact: CommonArtefactType,
16	pub role: Role,
17	#[serde(skip_serializing_if = "Option::is_none")]
18	pub constraint_attachment: Option<ConstraintAttachment>,
19	#[serde(skip_serializing_if = "Option::is_none")]
20	pub cube_regions: Option<Vec<CubeRegion>>,
21	#[serde(skip_serializing_if = "Option::is_none")]
22	pub data_key_sets: Option<Vec<DataKeySet>>,
23	#[serde(skip_serializing_if = "Option::is_none")]
24	pub release_calendar: Option<ReleaseCalendar>,
25	#[serde(skip_serializing_if = "Option::is_none")]
26	#[serde(flatten)]
27	pub other: Option<HashMap<String, Value>>,
28}
29
30/// A subset of the definition of the allowable (or available)
31/// content of a metadata set.
32#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
33#[serde(rename_all = "camelCase")]
34pub struct MetadataConstraint {
35	#[serde(flatten)]
36	pub artefact: CommonArtefactType,
37	pub role: Role,
38	#[serde(skip_serializing_if = "Option::is_none")]
39	pub constraint_attachment: Option<MetadataConstraintAttachment>,
40	#[serde(skip_serializing_if = "Option::is_none")]
41	pub metadata_target_regions: Option<Vec<MetadataTargetRegion>>,
42	#[serde(skip_serializing_if = "Option::is_none")]
43	pub release_calendar: Option<ReleaseCalendar>,
44	#[serde(skip_serializing_if = "Option::is_none")]
45	#[serde(flatten)]
46	pub other: Option<HashMap<String, Value>>,
47}
48
49/// The purpose of a constraint, which informs the constraint
50/// if the data is actually present, or if it defines what
51/// data is allowed.
52#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
53pub enum Role {
54	Actual,
55	Allowed,
56}
57
58/// A collection of references to data-constrainable artefacts.
59#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
60#[serde(rename_all = "camelCase")]
61pub struct ConstraintAttachment {
62	#[serde(skip_serializing_if = "Option::is_none")]
63	pub data_provider: Option<String>,
64	#[serde(skip_serializing_if = "Option::is_none")]
65	pub data_structures: Option<Vec<String>>,
66	#[serde(skip_serializing_if = "Option::is_none")]
67	pub dataflows: Option<Vec<String>>,
68	#[serde(skip_serializing_if = "Option::is_none")]
69	pub provision_agreements: Option<Vec<String>>,
70	#[serde(skip_serializing_if = "Option::is_none")]
71	pub simple_data_sources: Option<Vec<String>>,
72	#[serde(skip_serializing_if = "Option::is_none")]
73	pub queryable_data_sources: Option<QueryableDataSource>,
74	#[serde(skip_serializing_if = "Option::is_none")]
75	#[serde(flatten)]
76	pub other: Option<HashMap<String, Value>>,
77}
78
79/// A collection of references to metadata-constrainable artefacts.
80#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
81#[serde(rename_all = "camelCase")]
82pub struct MetadataConstraintAttachment {
83	#[serde(skip_serializing_if = "Option::is_none")]
84	pub metadata_provider: Option<String>,
85	#[serde(skip_serializing_if = "Option::is_none")]
86	pub metadata_sets: Option<Vec<String>>,
87	#[serde(skip_serializing_if = "Option::is_none")]
88	pub metadata_structures: Option<Vec<String>>,
89	#[serde(skip_serializing_if = "Option::is_none")]
90	pub metadataflows: Option<Vec<String>>,
91	#[serde(skip_serializing_if = "Option::is_none")]
92	pub metadata_provision_agreements: Option<Vec<String>>,
93	#[serde(skip_serializing_if = "Option::is_none")]
94	pub simple_data_sources: Option<Vec<String>>,
95	#[serde(skip_serializing_if = "Option::is_none")]
96	pub queryable_data_sources: Option<QueryableDataSource>,
97	#[serde(skip_serializing_if = "Option::is_none")]
98	#[serde(flatten)]
99	pub other: Option<HashMap<String, Value>>,
100}
101
102/// A data source which accepts a standard SDMX query message
103/// and responds appropriately.
104#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
105#[serde(rename_all = "camelCase")]
106pub struct QueryableDataSource {
107	pub is_rest_datasource: bool,
108	pub is_web_service_datasource: bool,
109	#[serde(skip_serializing_if = "Option::is_none")]
110	pub data_url: Option<String>,
111	#[serde(skip_serializing_if = "Option::is_none")]
112	pub wadl_url: Option<String>,
113	#[serde(skip_serializing_if = "Option::is_none")]
114	pub wsdl_url: Option<String>,
115	#[serde(skip_serializing_if = "Option::is_none")]
116	#[serde(flatten)]
117	pub other: Option<HashMap<String, Value>>,
118}
119
120/// A subset of data within multi-dimensional data.
121#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
122#[serde(rename_all = "camelCase")]
123pub struct CubeRegion {
124	#[serde(skip_serializing_if = "Option::is_none")]
125	pub annotations: Option<Vec<Annotation>>,
126	#[serde(skip_serializing_if = "Option::is_none")]
127	pub links: Option<Vec<Link>>,
128	#[serde(skip_serializing_if = "Option::is_none")]
129	pub include: Option<bool>,
130	#[serde(skip_serializing_if = "Option::is_none")]
131	pub components: Option<Vec<ComponentValueSet>>,
132	#[serde(skip_serializing_if = "Option::is_none")]
133	pub key_values: Option<Vec<CubeRegionKey>>,
134	#[serde(skip_serializing_if = "Option::is_none")]
135	#[serde(flatten)]
136	pub other: Option<HashMap<String, Value>>,
137}
138
139/// The structure for providing values for data attributes,
140/// measures, or metadata attributes.
141#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
142#[serde(rename_all = "camelCase")]
143pub struct ComponentValueSet {
144	pub id: String,
145	#[serde(skip_serializing_if = "Option::is_none")]
146	pub include: Option<bool>,
147	#[serde(skip_serializing_if = "Option::is_none")]
148	pub remove_prefix: Option<bool>,
149	#[serde(skip_serializing_if = "Option::is_none")]
150	pub time_range: Option<TimeRangeValue>,
151	#[serde(skip_serializing_if = "Option::is_none")]
152	pub values: Option<Vec<StringOrScv>>,
153	#[serde(skip_serializing_if = "Option::is_none")]
154	#[serde(flatten)]
155	pub other: Option<HashMap<String, Value>>,
156}
157
158/// A string or simple component value.
159#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
160#[serde(rename_all = "camelCase")]
161pub enum StringOrScv {
162	String(String),
163	SimpleComponent(SimpleComponentValue),
164}
165
166impl From<String> for StringOrScv {
167	fn from(value: String) -> Self {
168		Self::String(value)
169	}
170}
171
172impl From<SimpleComponentValue> for StringOrScv {
173	fn from(value: SimpleComponentValue) -> Self {
174		Self::SimpleComponent(value)
175	}
176}
177
178impl From<&str> for StringOrScv {
179	fn from(value: &str) -> Self {
180		Self::String(value.to_owned())
181	}
182}
183
184impl FromStr for StringOrScv {
185	type Err = Infallible;
186	fn from_str(s: &str) -> Result<Self, Self::Err> {
187		Ok(Self::String(s.to_owned()))
188	}
189}
190
191/// A time period value expressed as a range.
192#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
193#[serde(rename_all = "camelCase")]
194pub enum TimeRangeValue {
195	After(TimeAfterPeriod),
196	Before(TimeBeforePeriod),
197	Between(TimeBetweenPeriod),
198}
199
200#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
201#[serde(rename_all = "camelCase")]
202pub struct TimeAfterPeriod {
203	pub after_period: TimePeriodRange,
204}
205
206#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
207#[serde(rename_all = "camelCase")]
208pub struct TimeBeforePeriod {
209	pub before_period: TimePeriodRange,
210}
211
212#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
213#[serde(rename_all = "camelCase")]
214pub struct TimeBetweenPeriod {
215	pub end_period: TimePeriodRange,
216	pub start_period: TimePeriodRange,
217}
218
219/// A time period that describes whether a period
220/// is inclusive in a range.
221#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
222#[serde(rename_all = "camelCase")]
223pub struct TimePeriodRange {
224	#[serde(skip_serializing_if = "Option::is_none")]
225	pub period: Option<String>,
226	#[serde(skip_serializing_if = "Option::is_none")]
227	pub is_inclusive: Option<bool>,
228	#[serde(skip_serializing_if = "Option::is_none")]
229	#[serde(flatten)]
230	pub other: Option<HashMap<String, Value>>,
231}
232
233/// A simple value for a component.
234#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
235#[serde(rename_all = "camelCase")]
236pub struct SimpleComponentValue {
237	pub value: String,
238	#[serde(skip_serializing_if = "Option::is_none")]
239	pub lang: Option<String>,
240	pub cascade_values: CascadeValues,
241	#[serde(skip_serializing_if = "Option::is_none")]
242	pub valid_from: Option<String>,
243	#[serde(skip_serializing_if = "Option::is_none")]
244	pub valid_to: Option<String>,
245	#[serde(skip_serializing_if = "Option::is_none")]
246	#[serde(flatten)]
247	pub other: Option<HashMap<String, Value>>,
248}
249
250/// Indicates whether a value should be cascaded.
251#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
252pub enum CascadeValues {
253	Boolean(bool),
254	#[serde(rename = "excluderoot")]
255	ExcludeRoot,
256}
257
258impl From<bool> for CascadeValues {
259	fn from(value: bool) -> Self {
260		Self::Boolean(value)
261	}
262}
263
264/// A set of values for a dimension that defines
265/// a data cube region.
266#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
267#[serde(rename_all = "camelCase")]
268pub struct CubeRegionKey {
269	pub id: String,
270	#[serde(skip_serializing_if = "Option::is_none")]
271	pub include: Option<bool>,
272	#[serde(skip_serializing_if = "Option::is_none")]
273	pub remove_prefix: Option<bool>,
274	#[serde(skip_serializing_if = "Option::is_none")]
275	pub valid_from: Option<String>,
276	#[serde(skip_serializing_if = "Option::is_none")]
277	pub valid_to: Option<String>,
278	#[serde(skip_serializing_if = "Option::is_none")]
279	pub time_range: Option<TimeRangeValue>,
280	#[serde(skip_serializing_if = "Option::is_none")]
281	pub values: Option<Vec<StringOrScv>>,
282	#[serde(skip_serializing_if = "Option::is_none")]
283	#[serde(flatten)]
284	pub other: Option<HashMap<String, Value>>,
285}
286
287/// A collection of full or partial data keys (dimension values).
288#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
289#[serde(rename_all = "camelCase")]
290pub struct DataKeySet {
291	pub is_included: bool,
292	pub keys: Vec<DataKey>,
293	#[serde(skip_serializing_if = "Option::is_none")]
294	#[serde(flatten)]
295	pub other: Option<HashMap<String, Value>>,
296}
297
298/// A region which defines a distinct full or partial data key.
299#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
300#[serde(rename_all = "camelCase")]
301pub struct DataKey {
302	#[serde(skip_serializing_if = "Option::is_none")]
303	pub annotations: Option<Vec<Annotation>>,
304	#[serde(skip_serializing_if = "Option::is_none")]
305	pub links: Option<Vec<Link>>,
306	pub include: bool,
307	#[serde(skip_serializing_if = "Option::is_none")]
308	pub valid_from: Option<String>,
309	#[serde(skip_serializing_if = "Option::is_none")]
310	pub valid_to: Option<String>,
311	pub key_values: Vec<DataKeyValue>,
312	pub components: Vec<DataComponentValueSet>,
313	#[serde(skip_serializing_if = "Option::is_none")]
314	#[serde(flatten)]
315	pub other: Option<HashMap<String, Value>>,
316}
317
318/// A dimension value for the purpose of defining a distinct data key.
319#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
320#[serde(rename_all = "camelCase")]
321pub struct DataKeyValue {
322	pub id: String,
323	#[serde(skip_serializing_if = "Option::is_none")]
324	pub include: Option<bool>,
325	#[serde(skip_serializing_if = "Option::is_none")]
326	pub remove_prefix: Option<bool>,
327	pub value: String,
328	#[serde(skip_serializing_if = "Option::is_none")]
329	#[serde(flatten)]
330	pub other: Option<HashMap<String, Value>>,
331}
332
333/// The structure for providing values for data attributes,
334/// measures, or metadata attributes.
335#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
336#[serde(rename_all = "camelCase")]
337pub struct DataComponentValueSet {
338	pub id: String,
339	#[serde(skip_serializing_if = "Option::is_none")]
340	pub include: Option<bool>,
341	#[serde(skip_serializing_if = "Option::is_none")]
342	pub remove_prefix: Option<bool>,
343	#[serde(skip_serializing_if = "Option::is_none")]
344	pub time_range: Option<TimeRangeValue>,
345	pub values: Vec<StringOrDcv>,
346	#[serde(skip_serializing_if = "Option::is_none")]
347	#[serde(flatten)]
348	pub other: Option<HashMap<String, Value>>,
349}
350
351/// A string or data component value.
352#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
353#[serde(rename_all = "camelCase")]
354pub enum StringOrDcv {
355	String(String),
356	Dcv(DataComponentValue),
357}
358
359impl From<String> for StringOrDcv {
360	fn from(value: String) -> Self {
361		Self::String(value)
362	}
363}
364
365impl From<DataComponentValue> for StringOrDcv {
366	fn from(value: DataComponentValue) -> Self {
367		Self::Dcv(value)
368	}
369}
370
371impl From<&str> for StringOrDcv {
372	fn from(value: &str) -> Self {
373		Self::String(value.to_owned())
374	}
375}
376
377impl FromStr for StringOrDcv {
378	type Err = Infallible;
379	fn from_str(s: &str) -> Result<Self, Self::Err> {
380		Ok(Self::String(s.to_owned()))
381	}
382}
383
384/// A simple value for a component.
385#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
386#[serde(rename_all = "camelCase")]
387pub struct DataComponentValue {
388	#[serde(skip_serializing_if = "Option::is_none")]
389	pub cascade_values: Option<CascadeValues>,
390	#[serde(skip_serializing_if = "Option::is_none")]
391	pub lang: Option<String>,
392	pub value: String,
393	#[serde(skip_serializing_if = "Option::is_none")]
394	#[serde(flatten)]
395	pub other: Option<HashMap<String, Value>>,
396}
397
398/// Describes the report structure and the metadata target
399/// from that structure on which the region is based.
400#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
401#[serde(rename_all = "camelCase")]
402pub struct MetadataTargetRegion {
403	#[serde(skip_serializing_if = "Option::is_none")]
404	pub annotations: Option<Vec<Annotation>>,
405	#[serde(skip_serializing_if = "Option::is_none")]
406	pub links: Option<Vec<Link>>,
407	#[serde(skip_serializing_if = "Option::is_none")]
408	pub include: Option<bool>,
409	#[serde(skip_serializing_if = "Option::is_none")]
410	pub components: Option<Vec<MetadataAttributeValueSet>>,
411	#[serde(skip_serializing_if = "Option::is_none")]
412	pub valid_from: Option<String>,
413	#[serde(skip_serializing_if = "Option::is_none")]
414	pub valid_to: Option<String>,
415	#[serde(skip_serializing_if = "Option::is_none")]
416	#[serde(flatten)]
417	pub other: Option<HashMap<String, Value>>,
418}
419
420/// Describes the vaues provided for a metadata attribute.
421#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
422#[serde(rename_all = "camelCase")]
423pub struct MetadataAttributeValueSet {
424	pub id: String,
425	#[serde(skip_serializing_if = "Option::is_none")]
426	pub include: Option<bool>,
427	#[serde(skip_serializing_if = "Option::is_none")]
428	pub remove_prefix: Option<bool>,
429	#[serde(skip_serializing_if = "Option::is_none")]
430	pub time_range: Option<TimeRangeValue>,
431	#[serde(skip_serializing_if = "Option::is_none")]
432	pub values: Option<Vec<StringOrScv>>,
433	#[serde(skip_serializing_if = "Option::is_none")]
434	#[serde(flatten)]
435	pub other: Option<HashMap<String, Value>>,
436}
437
438/// The timing of releases of the constrained data.
439#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
440pub struct ReleaseCalendar {
441	pub offset: String,
442	pub periodicity: String,
443	pub tolerance: String,
444	#[serde(skip_serializing_if = "Option::is_none")]
445	#[serde(flatten)]
446	pub other: Option<HashMap<String, Value>>,
447}
448
449impl_artefact!(DataConstraint, MetadataConstraint);
450
451impl_extendable!(
452	DataConstraint,
453	MetadataConstraint,
454	ConstraintAttachment,
455	MetadataConstraintAttachment,
456	QueryableDataSource,
457	CubeRegion,
458	ComponentValueSet,
459	TimePeriodRange,
460	SimpleComponentValue,
461	CubeRegionKey,
462	DataKeySet,
463	DataKey,
464	DataKeyValue,
465	DataComponentValueSet,
466	DataComponentValue,
467	MetadataTargetRegion,
468	MetadataAttributeValueSet,
469	ReleaseCalendar,
470);