autosar_data_abstraction/ecu_configuration/definition/
reference.rs1use crate::{
2 AbstractionElement, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
3 ecu_configuration::{EcucCommonAttributes, EcucDefinitionElement},
4};
5use autosar_data::{Element, ElementName};
6
7use super::{AbstractEcucContainerDef, EcucContainerDef, EcucDestinationUriDef};
8
9pub trait AbstractEcucReferenceDef: AbstractionElement + EcucCommonAttributes + EcucDefinitionElement {}
13
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19pub struct EcucForeignReferenceDef(Element);
20abstraction_element!(EcucForeignReferenceDef, EcucForeignReferenceDef);
21impl IdentifiableAbstractionElement for EcucForeignReferenceDef {}
22impl EcucCommonAttributes for EcucForeignReferenceDef {}
23impl EcucDefinitionElement for EcucForeignReferenceDef {}
24impl AbstractEcucReferenceDef for EcucForeignReferenceDef {}
25
26impl EcucForeignReferenceDef {
27 pub(crate) fn new(name: &str, references_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
28 let ecuc_foreign_reference_def_elem =
29 references_elem.create_named_sub_element(ElementName::EcucForeignReferenceDef, name)?;
30 let ecuc_foreign_reference_def = Self(ecuc_foreign_reference_def_elem);
31 ecuc_foreign_reference_def.set_origin(origin)?;
32
33 Ok(ecuc_foreign_reference_def)
34 }
35
36 pub fn set_destination_type(&self, destination_type: Option<&str>) -> Result<(), AutosarAbstractionError> {
38 if let Some(destination_type) = destination_type {
39 self.element()
40 .get_or_create_sub_element(ElementName::DestinationType)?
41 .set_character_data(destination_type)?;
42 } else {
43 let _ = self.element().remove_sub_element_kind(ElementName::DestinationType);
44 }
45
46 Ok(())
47 }
48
49 #[must_use]
51 pub fn destination_type(&self) -> Option<String> {
52 self.element()
53 .get_sub_element(ElementName::DestinationType)?
54 .character_data()?
55 .string_value()
56 }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Hash)]
64pub struct EcucInstanceReferenceDef(Element);
65abstraction_element!(EcucInstanceReferenceDef, EcucInstanceReferenceDef);
66impl IdentifiableAbstractionElement for EcucInstanceReferenceDef {}
67impl EcucCommonAttributes for EcucInstanceReferenceDef {}
68impl EcucDefinitionElement for EcucInstanceReferenceDef {}
69impl AbstractEcucReferenceDef for EcucInstanceReferenceDef {}
70
71impl EcucInstanceReferenceDef {
72 pub(crate) fn new(name: &str, references_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
73 let ecuc_instance_reference_def_elem =
74 references_elem.create_named_sub_element(ElementName::EcucInstanceReferenceDef, name)?;
75 let ecuc_instance_reference_def = Self(ecuc_instance_reference_def_elem);
76 ecuc_instance_reference_def.set_origin(origin)?;
77
78 Ok(ecuc_instance_reference_def)
79 }
80
81 pub fn set_destination_type(&self, destination_type: Option<&str>) -> Result<(), AutosarAbstractionError> {
83 if let Some(destination_type) = destination_type {
84 self.element()
85 .get_or_create_sub_element(ElementName::DestinationType)?
86 .set_character_data(destination_type)?;
87 } else {
88 let _ = self.element().remove_sub_element_kind(ElementName::DestinationType);
89 }
90
91 Ok(())
92 }
93
94 #[must_use]
96 pub fn destination_type(&self) -> Option<String> {
97 self.element()
98 .get_sub_element(ElementName::DestinationType)?
99 .character_data()?
100 .string_value()
101 }
102
103 pub fn set_destination_context(&self, destination_context: Option<&str>) -> Result<(), AutosarAbstractionError> {
109 if let Some(destination_context) = destination_context {
110 self.element()
111 .get_or_create_sub_element(ElementName::DestinationContext)?
112 .set_character_data(destination_context)?;
113 } else {
114 let _ = self.element().remove_sub_element_kind(ElementName::DestinationContext);
115 }
116
117 Ok(())
118 }
119
120 #[must_use]
124 pub fn destination_context(&self) -> Option<String> {
125 self.element()
126 .get_sub_element(ElementName::DestinationContext)?
127 .character_data()?
128 .string_value()
129 }
130}
131
132#[derive(Debug, Clone, PartialEq, Eq, Hash)]
137pub struct EcucChoiceReferenceDef(Element);
138abstraction_element!(EcucChoiceReferenceDef, EcucChoiceReferenceDef);
139impl IdentifiableAbstractionElement for EcucChoiceReferenceDef {}
140impl EcucCommonAttributes for EcucChoiceReferenceDef {}
141impl EcucDefinitionElement for EcucChoiceReferenceDef {}
142impl AbstractEcucReferenceDef for EcucChoiceReferenceDef {}
143
144impl EcucChoiceReferenceDef {
145 pub(crate) fn new(name: &str, references_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
146 let ecu_choice_reference_def_elem =
147 references_elem.create_named_sub_element(ElementName::EcucChoiceReferenceDef, name)?;
148 let ecu_choice_reference_def = Self(ecu_choice_reference_def_elem);
149 ecu_choice_reference_def.set_origin(origin)?;
150
151 Ok(ecu_choice_reference_def)
152 }
153
154 pub fn add_destination<T: AbstractEcucContainerDef>(&self, destination: &T) -> Result<(), AutosarAbstractionError> {
156 let dest_refs = self.element().get_or_create_sub_element(ElementName::DestinationRefs)?;
157 dest_refs
158 .create_sub_element(ElementName::DestinationRef)?
159 .set_reference_target(destination.element())?;
160
161 Ok(())
162 }
163
164 pub fn destination_refs(&self) -> impl Iterator<Item = EcucContainerDef> + Send + 'static {
166 self.element()
167 .get_sub_element(ElementName::DestinationRefs)
168 .into_iter()
169 .flat_map(|dest_refs| dest_refs.sub_elements())
170 .filter_map(|dest_ref| {
171 dest_ref
172 .get_reference_target()
173 .ok()
174 .and_then(|elem| elem.try_into().ok())
175 })
176 }
177}
178
179#[derive(Debug, Clone, PartialEq, Eq, Hash)]
183pub struct EcucReferenceDef(Element);
184abstraction_element!(EcucReferenceDef, EcucReferenceDef);
185impl IdentifiableAbstractionElement for EcucReferenceDef {}
186impl EcucCommonAttributes for EcucReferenceDef {}
187impl EcucDefinitionElement for EcucReferenceDef {}
188impl AbstractEcucReferenceDef for EcucReferenceDef {}
189
190impl EcucReferenceDef {
191 pub(crate) fn new(name: &str, references_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
192 let ecu_reference_def_elem = references_elem.create_named_sub_element(ElementName::EcucReferenceDef, name)?;
193 let ecu_reference_def = Self(ecu_reference_def_elem);
194 ecu_reference_def.set_origin(origin)?;
195
196 Ok(ecu_reference_def)
197 }
198
199 pub fn set_destination<T: AbstractEcucContainerDef>(
201 &self,
202 destination: Option<&T>,
203 ) -> Result<(), AutosarAbstractionError> {
204 if let Some(destination) = destination {
205 self.element()
206 .get_or_create_sub_element(ElementName::DestinationRef)?
207 .set_reference_target(destination.element())?;
208 } else {
209 let _ = self.element().remove_sub_element_kind(ElementName::DestinationRef);
210 }
211
212 Ok(())
213 }
214
215 #[must_use]
217 pub fn destination(&self) -> Option<EcucContainerDef> {
218 self.element()
219 .get_sub_element(ElementName::DestinationRef)
220 .and_then(|dest_ref| dest_ref.get_reference_target().ok())
221 .and_then(|elem| elem.try_into().ok())
222 }
223}
224
225#[derive(Debug, Clone, PartialEq, Eq, Hash)]
229pub struct EcucUriReferenceDef(Element);
230abstraction_element!(EcucUriReferenceDef, EcucUriReferenceDef);
231impl IdentifiableAbstractionElement for EcucUriReferenceDef {}
232impl EcucCommonAttributes for EcucUriReferenceDef {}
233impl EcucDefinitionElement for EcucUriReferenceDef {}
234impl AbstractEcucReferenceDef for EcucUriReferenceDef {}
235
236impl EcucUriReferenceDef {
237 pub(crate) fn new(name: &str, references_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
238 let ecu_uri_reference_def_elem =
239 references_elem.create_named_sub_element(ElementName::EcucUriReferenceDef, name)?;
240 let ecu_uri_reference_def = Self(ecu_uri_reference_def_elem);
241 ecu_uri_reference_def.set_origin(origin)?;
242
243 Ok(ecu_uri_reference_def)
244 }
245
246 pub fn set_destination_uri(
248 &self,
249 destination_uri: Option<&EcucDestinationUriDef>,
250 ) -> Result<(), AutosarAbstractionError> {
251 if let Some(destination_uri) = destination_uri {
252 self.element()
253 .get_or_create_sub_element(ElementName::DestinationUriRef)?
254 .set_reference_target(destination_uri.element())?;
255 } else {
256 let _ = self.element().remove_sub_element_kind(ElementName::DestinationUriRef);
257 }
258
259 Ok(())
260 }
261
262 #[must_use]
264 pub fn destination_uri(&self) -> Option<EcucDestinationUriDef> {
265 self.element()
266 .get_sub_element(ElementName::DestinationUriRef)?
267 .get_reference_target()
268 .ok()?
269 .try_into()
270 .ok()
271 }
272}
273
274#[derive(Debug, Clone, PartialEq, Eq, Hash)]
279pub enum EcucAnyReferenceDef {
280 Foreign(EcucForeignReferenceDef),
282 Instance(EcucInstanceReferenceDef),
284 Choice(EcucChoiceReferenceDef),
286 Normal(EcucReferenceDef),
288 Uri(EcucUriReferenceDef),
290}
291
292impl AbstractionElement for EcucAnyReferenceDef {
293 fn element(&self) -> &Element {
294 match self {
295 EcucAnyReferenceDef::Foreign(elem) => elem.element(),
296 EcucAnyReferenceDef::Instance(elem) => elem.element(),
297 EcucAnyReferenceDef::Choice(elem) => elem.element(),
298 EcucAnyReferenceDef::Normal(elem) => elem.element(),
299 EcucAnyReferenceDef::Uri(elem) => elem.element(),
300 }
301 }
302}
303
304impl TryFrom<Element> for EcucAnyReferenceDef {
305 type Error = AutosarAbstractionError;
306
307 fn try_from(element: Element) -> Result<Self, Self::Error> {
308 match element.element_name() {
309 ElementName::EcucForeignReferenceDef => Ok(EcucAnyReferenceDef::Foreign(element.try_into()?)),
310 ElementName::EcucInstanceReferenceDef => Ok(EcucAnyReferenceDef::Instance(element.try_into()?)),
311 ElementName::EcucChoiceReferenceDef => Ok(EcucAnyReferenceDef::Choice(element.try_into()?)),
312 ElementName::EcucReferenceDef => Ok(EcucAnyReferenceDef::Normal(element.try_into()?)),
313 ElementName::EcucUriReferenceDef => Ok(EcucAnyReferenceDef::Uri(element.try_into()?)),
314 _ => Err(AutosarAbstractionError::ConversionError {
315 element,
316 dest: "EcucAnyReferenceDef".to_string(),
317 }),
318 }
319 }
320}
321
322impl IdentifiableAbstractionElement for EcucAnyReferenceDef {}
323impl EcucDefinitionElement for EcucAnyReferenceDef {}
324impl EcucCommonAttributes for EcucAnyReferenceDef {}
325impl AbstractEcucReferenceDef for EcucAnyReferenceDef {}
326
327#[cfg(test)]
330mod test {
331 use crate::{
332 AbstractionElement, AutosarModelAbstraction,
333 ecu_configuration::{EcucContainerDef, EcucDestinationUriNestingContract},
334 };
335 use autosar_data::AutosarVersion;
336
337 #[test]
338 fn test_foreign_reference_def() {
339 let model = AutosarModelAbstraction::create("file.arxml", AutosarVersion::LATEST);
340 let pkg = model.get_or_create_package("/pkg").unwrap();
341
342 let ecuc_module_def = pkg.create_ecuc_module_def("module").unwrap();
343 let container = ecuc_module_def.create_param_conf_container_def("container").unwrap();
344 let foreign_ref = container.create_foreign_reference_def("foreign_ref", "origin").unwrap();
345 assert_eq!(container.references().count(), 1);
346
347 assert_eq!(foreign_ref.destination_type(), None);
348 foreign_ref.set_destination_type(Some("type")).unwrap();
349 assert_eq!(foreign_ref.destination_type(), Some("type".to_string()));
350 assert_eq!(container.references().next().unwrap().element(), foreign_ref.element());
351 }
352
353 #[test]
354 fn test_instance_reference_def() {
355 let model = AutosarModelAbstraction::create("file.arxml", AutosarVersion::LATEST);
356 let pkg = model.get_or_create_package("/pkg").unwrap();
357
358 let ecuc_module_def = pkg.create_ecuc_module_def("module").unwrap();
359 let container = ecuc_module_def.create_param_conf_container_def("container").unwrap();
360 let instance_ref = container
361 .create_instance_reference_def("instance_ref", "origin")
362 .unwrap();
363 assert_eq!(container.references().count(), 1);
364
365 assert_eq!(instance_ref.destination_type(), None);
366 instance_ref.set_destination_type(Some("type")).unwrap();
367 assert_eq!(instance_ref.destination_type(), Some("type".to_string()));
368
369 assert_eq!(instance_ref.destination_context(), None);
370 instance_ref.set_destination_context(Some("context")).unwrap();
371 assert_eq!(instance_ref.destination_context(), Some("context".to_string()));
372 assert_eq!(container.references().next().unwrap().element(), instance_ref.element());
373 }
374
375 #[test]
376 fn test_choice_reference_def() {
377 let model = AutosarModelAbstraction::create("file.arxml", AutosarVersion::LATEST);
378 let pkg = model.get_or_create_package("/pkg").unwrap();
379
380 let ecuc_module_def = pkg.create_ecuc_module_def("module").unwrap();
381 let container = ecuc_module_def.create_param_conf_container_def("container").unwrap();
382 let choice_ref = container.create_choice_reference_def("choice_ref", "origin").unwrap();
383 assert_eq!(container.references().count(), 1);
384
385 assert_eq!(choice_ref.destination_refs().count(), 0);
386 let dest = container.create_param_conf_container_def("dest").unwrap();
387 choice_ref.add_destination(&dest).unwrap();
388 assert_eq!(choice_ref.destination_refs().count(), 1);
389 assert_eq!(container.references().next().unwrap().element(), choice_ref.element());
390 }
391
392 #[test]
393 fn test_reference_def() {
394 let model = AutosarModelAbstraction::create("file.arxml", AutosarVersion::LATEST);
395 let pkg = model.get_or_create_package("/pkg").unwrap();
396
397 let ecuc_module_def = pkg.create_ecuc_module_def("module").unwrap();
398 let container = ecuc_module_def.create_param_conf_container_def("container").unwrap();
399 let reference = container.create_reference_def("reference", "origin").unwrap();
400 assert_eq!(container.references().count(), 1);
401
402 assert_eq!(reference.destination(), None);
403 let dest = container.create_param_conf_container_def("dest").unwrap();
404 reference.set_destination(Some(&dest)).unwrap();
405 assert_eq!(reference.destination().unwrap(), EcucContainerDef::ParamConf(dest));
406 assert_eq!(container.references().next().unwrap().element(), reference.element());
407 }
408
409 #[test]
410 fn test_uri_reference_def() {
411 let model = AutosarModelAbstraction::create("file.arxml", AutosarVersion::LATEST);
412 let pkg = model.get_or_create_package("/pkg").unwrap();
413
414 let ecuc_module_def = pkg.create_ecuc_module_def("module").unwrap();
415 let container = ecuc_module_def.create_param_conf_container_def("container").unwrap();
416 let uri_ref = container.create_uri_reference_def("uri_ref", "origin").unwrap();
417 assert_eq!(container.references().count(), 1);
418
419 let uri_def_set = pkg.create_ecuc_destination_uri_def_set("uri_def").unwrap();
420 let uri_def = uri_def_set
421 .create_destination_uri_def("uri", EcucDestinationUriNestingContract::VertexOfTargetContainer)
422 .unwrap();
423
424 assert_eq!(uri_ref.destination_uri(), None);
425 uri_ref.set_destination_uri(Some(&uri_def)).unwrap();
426 assert_eq!(uri_ref.destination_uri(), Some(uri_def));
427 assert_eq!(container.references().next().unwrap().element(), uri_ref.element());
428 }
429}