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