xapi_rs/data/
context_group.rs1use crate::{
4 GroupId,
5 data::{DataError, Fingerprint, Group, ObjectType, Validate, ValidationError},
6 emit_error,
7};
8use core::fmt;
9use iri_string::types::{IriStr, IriString};
10use serde::{Deserialize, Serialize};
11use serde_with::skip_serializing_none;
12use std::hash::{Hash, Hasher};
13
14#[skip_serializing_none]
23#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
24#[serde(deny_unknown_fields)]
25#[serde(rename_all = "camelCase")]
26pub struct ContextGroup {
27 #[serde(default = "default_object_type")]
28 object_type: ObjectType,
29 group: Group,
30 relevant_types: Vec<IriString>,
31}
32
33#[skip_serializing_none]
34#[derive(Debug, Serialize)]
35#[serde(rename_all = "camelCase")]
36pub(crate) struct ContextGroupId {
37 object_type: ObjectType,
38 group: GroupId,
39 relevant_types: Vec<IriString>,
40}
41
42impl From<ContextGroup> for ContextGroupId {
43 fn from(value: ContextGroup) -> Self {
44 ContextGroupId {
45 object_type: ObjectType::ContextGroup,
46 group: GroupId::from(value.group),
47 relevant_types: value.relevant_types,
48 }
49 }
50}
51
52impl From<ContextGroupId> for ContextGroup {
53 fn from(value: ContextGroupId) -> Self {
54 ContextGroup {
55 object_type: ObjectType::ContextGroup,
56 group: Group::from(value.group),
57 relevant_types: value.relevant_types,
58 }
59 }
60}
61
62impl ContextGroup {
63 pub fn builder() -> ContextGroupBuilder {
65 ContextGroupBuilder::default()
66 }
67
68 pub fn check_object_type(&self) -> bool {
73 self.object_type == ObjectType::ContextGroup
74 }
75
76 pub fn group(&self) -> &Group {
78 &self.group
79 }
80
81 pub fn relevant_types(&self) -> &[IriString] {
83 self.relevant_types.as_ref()
84 }
85}
86
87impl Fingerprint for ContextGroup {
88 fn fingerprint<H: Hasher>(&self, state: &mut H) {
89 self.group.fingerprint(state);
90 for s in &self.relevant_types {
91 s.hash(state)
92 }
93 }
94}
95
96impl fmt::Display for ContextGroup {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 let mut vec = vec![];
99
100 vec.push(format!("group: {}", self.group));
101 vec.push(format!(
102 "relevantTypes: [{}]",
103 self.relevant_types
104 .iter()
105 .map(|x| x.to_string())
106 .collect::<Vec<_>>()
107 .join(", ")
108 ));
109
110 let res = vec
111 .iter()
112 .map(|x| x.to_string())
113 .collect::<Vec<_>>()
114 .join(", ");
115 write!(f, "ContextAgent{{ {res} }}")
116 }
117}
118
119impl Validate for ContextGroup {
120 fn validate(&self) -> Vec<ValidationError> {
121 let mut vec = vec![];
122
123 if !self.check_object_type() {
124 vec.push(ValidationError::WrongObjectType {
125 expected: ObjectType::ContextGroup,
126 found: self.object_type.to_string().into(),
127 })
128 }
129 vec.extend(self.group.validate());
130 if self.relevant_types.is_empty() {
131 vec.push(ValidationError::Empty("relevant_types".into()))
132 } else {
133 for iri in self.relevant_types.iter() {
134 if iri.is_empty() {
135 vec.push(ValidationError::InvalidIRI(iri.to_string().into()))
136 }
137 }
138 }
139
140 vec
141 }
142}
143
144#[derive(Debug, Default)]
146pub struct ContextGroupBuilder {
147 _group: Option<Group>,
148 _relevant_types: Vec<IriString>,
149}
150
151impl ContextGroupBuilder {
152 pub fn group(mut self, val: Group) -> Result<Self, DataError> {
156 val.check_validity()?;
157 self._group = Some(val);
158 Ok(self)
159 }
160
161 pub fn relevant_type(mut self, val: &str) -> Result<Self, DataError> {
165 if val.is_empty() {
166 emit_error!(DataError::Validation(ValidationError::Empty(
167 "relevant_type IRI".into()
168 )))
169 } else {
170 let iri = IriStr::new(val)?;
171 if self._relevant_types.is_empty() {
172 self._relevant_types = vec![];
173 }
174 self._relevant_types.push(iri.to_owned());
175 Ok(self)
176 }
177 }
178
179 pub fn build(self) -> Result<ContextGroup, DataError> {
183 if self._group.is_none() {
184 emit_error!(DataError::Validation(ValidationError::MissingField(
185 "group".into()
186 )))
187 } else if self._relevant_types.is_empty() {
188 emit_error!(DataError::Validation(ValidationError::Empty(
189 "relevant_types".into()
190 )))
191 } else {
192 let mut relevant_types = vec![];
193 for item in self._relevant_types.iter() {
194 let iri = IriString::try_from(item.as_str())?;
195 relevant_types.push(iri);
196 }
197
198 Ok(ContextGroup {
199 object_type: ObjectType::ContextGroup,
200 group: self._group.unwrap(),
201 relevant_types,
202 })
203 }
204 }
205}
206
207fn default_object_type() -> ObjectType {
208 ObjectType::ContextGroup
209}