xapi_rs/data/
context_agent.rs1use crate::{
4 AgentId, DataError,
5 data::{Agent, Fingerprint, 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]
22#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
23#[serde(deny_unknown_fields)]
24#[serde(rename_all = "camelCase")]
25pub struct ContextAgent {
26 #[serde(default = "default_object_type")]
27 object_type: ObjectType,
28 agent: Agent,
29 relevant_types: Vec<IriString>,
42}
43
44#[skip_serializing_none]
45#[derive(Debug, Serialize)]
46#[serde(rename_all = "camelCase")]
47pub(crate) struct ContextAgentId {
48 object_type: ObjectType,
49 agent: AgentId,
50 relevant_types: Vec<IriString>,
51}
52
53impl From<ContextAgent> for ContextAgentId {
54 fn from(value: ContextAgent) -> Self {
55 ContextAgentId {
56 object_type: ObjectType::ContextAgent,
57 agent: AgentId::from(value.agent),
58 relevant_types: value.relevant_types,
59 }
60 }
61}
62
63impl From<ContextAgentId> for ContextAgent {
64 fn from(value: ContextAgentId) -> Self {
65 ContextAgent {
66 object_type: ObjectType::ContextAgent,
67 agent: Agent::from(value.agent),
68 relevant_types: value.relevant_types,
69 }
70 }
71}
72
73impl ContextAgent {
74 pub fn builder() -> ContextAgentBuilder {
76 ContextAgentBuilder::default()
77 }
78
79 pub fn check_object_type(&self) -> bool {
84 self.object_type == ObjectType::ContextAgent
85 }
86
87 pub fn agent(&self) -> &Agent {
89 &self.agent
90 }
91
92 pub fn relevant_types(&self) -> &[IriString] {
94 self.relevant_types.as_ref()
95 }
96}
97
98impl Fingerprint for ContextAgent {
99 fn fingerprint<H: Hasher>(&self, state: &mut H) {
100 self.agent.fingerprint(state);
101 for s in &self.relevant_types {
102 s.hash(state)
103 }
104 }
105}
106
107impl fmt::Display for ContextAgent {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 let mut vec = vec![];
110
111 vec.push(format!("agent: {}", self.agent));
112 vec.push(format!(
113 "relevantTypes: [{}]",
114 self.relevant_types
115 .iter()
116 .map(|x| x.to_string())
117 .collect::<Vec<_>>()
118 .join(", ")
119 ));
120
121 let res = vec
122 .iter()
123 .map(|x| x.to_string())
124 .collect::<Vec<_>>()
125 .join(", ");
126 write!(f, "ContextAgent{{ {res} }}")
127 }
128}
129
130impl Validate for ContextAgent {
131 fn validate(&self) -> Vec<ValidationError> {
132 let mut vec = vec![];
133
134 if !self.check_object_type() {
135 vec.push(ValidationError::WrongObjectType {
136 expected: ObjectType::ContextAgent,
137 found: self.object_type.to_string().into(),
138 })
139 }
140 vec.extend(self.agent.validate());
141 if self.relevant_types.is_empty() {
142 vec.push(ValidationError::Empty("relevant_types".into()))
143 } else {
144 for iri in self.relevant_types.iter() {
145 if iri.is_empty() {
146 vec.push(ValidationError::InvalidIRI(iri.to_string().into()))
147 }
148 }
149 }
150
151 vec
152 }
153}
154
155#[derive(Debug, Default)]
157pub struct ContextAgentBuilder {
158 _agent: Option<Agent>,
159 _relevant_types: Vec<IriString>,
160}
161
162impl ContextAgentBuilder {
163 pub fn agent(mut self, val: Agent) -> Result<Self, DataError> {
167 val.check_validity()?;
168 self._agent = Some(val);
169 Ok(self)
170 }
171
172 pub fn relevant_type(mut self, val: &str) -> Result<Self, DataError> {
176 if val.is_empty() {
177 emit_error!(DataError::Validation(ValidationError::Empty(
178 "relevant-type IRI".into()
179 )))
180 } else {
181 let iri = IriStr::new(val)?;
182 if self._relevant_types.is_empty() {
183 self._relevant_types = vec![];
184 }
185 self._relevant_types.push(iri.to_owned());
186 Ok(self)
187 }
188 }
189
190 pub fn build(self) -> Result<ContextAgent, DataError> {
194 if self._agent.is_none() {
195 emit_error!(DataError::Validation(ValidationError::MissingField(
196 "agent".into()
197 )))
198 } else if self._relevant_types.is_empty() {
199 emit_error!(DataError::Validation(ValidationError::Empty(
200 "relevant_types".into()
201 )))
202 } else {
203 let mut relevant_types = vec![];
204 for item in self._relevant_types.iter() {
205 let iri = IriString::try_from(item.as_str())?;
206 relevant_types.push(iri);
207 }
208
209 Ok(ContextAgent {
210 object_type: ObjectType::ContextAgent,
211 agent: self._agent.unwrap(),
212 relevant_types,
213 })
214 }
215 }
216}
217
218fn default_object_type() -> ObjectType {
219 ObjectType::ContextAgent
220}