1use crate::{
2 AbstractionElement, ArPackage, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
3};
4use autosar_data::{Element, ElementName, EnumItem};
5
6mod container;
7mod parameter;
8mod reference;
9
10pub use container::*;
11pub use parameter::*;
12pub use reference::*;
13
14pub trait EcucCommonAttributes: EcucDefinitionElement {
18 fn set_multiplicity_config_classes(
23 &self,
24 config: &[(EcucConfigurationClass, EcucConfigurationVariant)],
25 ) -> Result<(), AutosarAbstractionError> {
26 set_config_classes(
27 self.element(),
28 ElementName::MultiplicityConfigClasses,
29 ElementName::EcucMultiplicityConfigurationClass,
30 config,
31 )?;
32 Ok(())
33 }
34
35 #[must_use]
37 fn multiplicity_config_classes(&self) -> Vec<(EcucConfigurationClass, EcucConfigurationVariant)> {
38 get_config_classes(self.element(), ElementName::MultiplicityConfigClasses)
39 }
40
41 fn set_origin(&self, origin: &str) -> Result<(), AutosarAbstractionError> {
46 self.element()
47 .get_or_create_sub_element(ElementName::Origin)?
48 .set_character_data(origin)?;
49 Ok(())
50 }
51
52 #[must_use]
57 fn origin(&self) -> Option<String> {
58 self.element()
59 .get_sub_element(ElementName::Origin)?
60 .character_data()?
61 .string_value()
62 }
63
64 fn set_post_build_variant_multiplicity(
69 &self,
70 post_build_variant_multiplicity: Option<bool>,
71 ) -> Result<(), AutosarAbstractionError> {
72 if let Some(post_build_variant_multiplicity) = post_build_variant_multiplicity {
73 self.element()
74 .get_or_create_sub_element(ElementName::PostBuildVariantMultiplicity)?
75 .set_character_data(post_build_variant_multiplicity)?;
76 } else {
77 let _ = self
78 .element()
79 .remove_sub_element_kind(ElementName::PostBuildVariantMultiplicity);
80 }
81
82 Ok(())
83 }
84
85 #[must_use]
90 fn post_build_variant_multiplicity(&self) -> Option<bool> {
91 self.element()
92 .get_sub_element(ElementName::PostBuildVariantMultiplicity)?
93 .character_data()?
94 .parse_bool()
95 }
96
97 fn set_post_build_variant_value(
102 &self,
103 post_build_variant_value: Option<bool>,
104 ) -> Result<(), AutosarAbstractionError> {
105 if let Some(post_build_variant_value) = post_build_variant_value {
106 self.element()
107 .get_or_create_sub_element(ElementName::PostBuildVariantValue)?
108 .set_character_data(post_build_variant_value)?;
109 } else {
110 let _ = self
111 .element()
112 .remove_sub_element_kind(ElementName::PostBuildVariantValue);
113 }
114
115 Ok(())
116 }
117
118 #[must_use]
123 fn post_build_variant_value(&self) -> Option<bool> {
124 self.element()
125 .get_sub_element(ElementName::PostBuildVariantValue)?
126 .character_data()?
127 .parse_bool()
128 }
129
130 fn set_requires_index(&self, requires_index: Option<bool>) -> Result<(), AutosarAbstractionError> {
132 if let Some(requires_index) = requires_index {
133 self.element()
134 .get_or_create_sub_element(ElementName::RequiresIndex)?
135 .set_character_data(requires_index)?;
136 } else {
137 let _ = self.element().remove_sub_element_kind(ElementName::RequiresIndex);
138 }
139
140 Ok(())
141 }
142
143 #[must_use]
145 fn requires_index(&self) -> Option<bool> {
146 self.element()
147 .get_sub_element(ElementName::RequiresIndex)?
148 .character_data()?
149 .parse_bool()
150 }
151
152 fn set_value_config_classes(
158 &self,
159 config: &[(EcucConfigurationClass, EcucConfigurationVariant)],
160 ) -> Result<(), AutosarAbstractionError> {
161 set_config_classes(
162 self.element(),
163 ElementName::ValueConfigClasses,
164 ElementName::EcucValueConfigurationClass,
165 config,
166 )?;
167 Ok(())
168 }
169
170 #[must_use]
175 fn value_config_classes(&self) -> Vec<(EcucConfigurationClass, EcucConfigurationVariant)> {
176 get_config_classes(self.element(), ElementName::ValueConfigClasses)
177 }
178
179 fn set_with_auto(&self, with_auto: Option<bool>) -> Result<(), AutosarAbstractionError> {
183 if let Some(with_auto) = with_auto {
184 self.element()
185 .get_or_create_sub_element(ElementName::WithAuto)?
186 .set_character_data(with_auto)?;
187 } else {
188 let _ = self.element().remove_sub_element_kind(ElementName::WithAuto);
189 }
190
191 Ok(())
192 }
193
194 fn with_auto(&self) -> Option<bool> {
196 self.element()
197 .get_sub_element(ElementName::WithAuto)?
198 .character_data()?
199 .parse_bool()
200 }
201}
202
203pub trait EcucDefinitionElement: AbstractionElement {
205 fn set_lower_multiplicity(&self, lower_multiplicity: Option<u32>) -> Result<(), AutosarAbstractionError> {
207 if let Some(lower_multiplicity) = lower_multiplicity {
208 self.element()
209 .get_or_create_sub_element(ElementName::LowerMultiplicity)?
210 .set_character_data(lower_multiplicity as u64)?;
211 } else {
212 let _ = self.element().remove_sub_element_kind(ElementName::LowerMultiplicity);
213 }
214
215 Ok(())
216 }
217
218 #[must_use]
220 fn lower_multiplicity(&self) -> Option<u32> {
221 self.element()
222 .get_sub_element(ElementName::LowerMultiplicity)
223 .and_then(|elem| elem.character_data())
224 .and_then(|cdata| cdata.parse_integer())
225 }
226
227 fn set_upper_multiplicity(&self, upper_multiplicity: Option<u32>) -> Result<(), AutosarAbstractionError> {
229 if let Some(upper_multiplicity) = upper_multiplicity {
230 self.element()
231 .get_or_create_sub_element(ElementName::UpperMultiplicity)?
232 .set_character_data(upper_multiplicity as u64)?;
233 } else {
234 let _ = self.element().remove_sub_element_kind(ElementName::UpperMultiplicity);
235 }
236
237 Ok(())
238 }
239
240 #[must_use]
242 fn upper_multiplicity(&self) -> Option<u32> {
243 self.element()
244 .get_sub_element(ElementName::UpperMultiplicity)
245 .and_then(|elem| elem.character_data())
246 .and_then(|cdata| cdata.parse_integer())
247 }
248
249 fn set_upper_multiplicity_infinite(&self, infinite: Option<bool>) -> Result<(), AutosarAbstractionError> {
255 if let Some(infinite) = infinite {
256 self.element()
257 .get_or_create_sub_element(ElementName::UpperMultiplicityInfinite)?
258 .set_character_data(infinite)?;
259 if infinite {
260 let _ = self.element().remove_sub_element_kind(ElementName::UpperMultiplicity);
261 }
262 } else {
263 let _ = self
264 .element()
265 .remove_sub_element_kind(ElementName::UpperMultiplicityInfinite);
266 }
267
268 Ok(())
269 }
270
271 #[must_use]
273 fn upper_multiplicity_infinite(&self) -> Option<bool> {
274 self.element()
275 .get_sub_element(ElementName::UpperMultiplicityInfinite)
276 .and_then(|elem| elem.character_data())
277 .and_then(|cdata| cdata.parse_bool())
278 }
279}
280
281#[derive(Debug, Clone, PartialEq, Eq, Hash)]
285pub struct EcucDefinitionCollection(Element);
286abstraction_element!(EcucDefinitionCollection, EcucDefinitionCollection);
287impl IdentifiableAbstractionElement for EcucDefinitionCollection {}
288
289impl EcucDefinitionCollection {
290 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
291 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
292 let ecuc_definition_collection_elem =
293 elements.create_named_sub_element(ElementName::EcucDefinitionCollection, name)?;
294
295 Ok(Self(ecuc_definition_collection_elem))
296 }
297
298 pub fn add_module_def(&self, module_def: &EcucModuleDef) -> Result<(), AutosarAbstractionError> {
300 self.element()
301 .get_or_create_sub_element(ElementName::ModuleRefs)?
302 .create_sub_element(ElementName::ModuleRef)?
303 .set_reference_target(module_def.element())?;
304 Ok(())
305 }
306
307 pub fn module_defs(&self) -> impl Iterator<Item = EcucModuleDef> + Send + use<> {
309 self.element()
310 .get_sub_element(ElementName::ModuleRefs)
311 .into_iter()
312 .flat_map(|module_refs_elem| module_refs_elem.sub_elements())
313 .filter_map(|module_ref_elem| module_ref_elem.get_reference_target().ok())
314 .filter_map(|module_def_elem| EcucModuleDef::try_from(module_def_elem).ok())
315 }
316}
317
318#[derive(Debug, Clone, PartialEq, Eq, Hash)]
322pub struct EcucModuleDef(Element);
323abstraction_element!(EcucModuleDef, EcucModuleDef);
324impl IdentifiableAbstractionElement for EcucModuleDef {}
325impl EcucDefinitionElement for EcucModuleDef {}
326
327impl EcucModuleDef {
328 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
329 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
330 let ecuc_module_def_elem = elements.create_named_sub_element(ElementName::EcucModuleDef, name)?;
331
332 Ok(Self(ecuc_module_def_elem))
333 }
334
335 pub fn create_choice_container_def(&self, name: &str) -> Result<EcucChoiceContainerDef, AutosarAbstractionError> {
337 let containers_elem = self.element().get_or_create_sub_element(ElementName::Containers)?;
338 EcucChoiceContainerDef::new(name, &containers_elem)
339 }
340
341 pub fn create_param_conf_container_def(
343 &self,
344 name: &str,
345 ) -> Result<EcucParamConfContainerDef, AutosarAbstractionError> {
346 let containers_elem = self.element().get_or_create_sub_element(ElementName::Containers)?;
347 EcucParamConfContainerDef::new(name, &containers_elem)
348 }
349
350 pub fn containers(&self) -> impl Iterator<Item = EcucContainerDef> + Send + use<> {
352 self.element()
353 .get_sub_element(ElementName::Containers)
354 .into_iter()
355 .flat_map(|containers_elem| containers_elem.sub_elements())
356 .filter_map(|container_elem| EcucContainerDef::try_from(container_elem).ok())
357 }
358
359 pub fn set_api_service_prefix(&self, prefix: Option<&str>) -> Result<(), AutosarAbstractionError> {
364 if let Some(prefix) = prefix {
365 self.element()
366 .get_or_create_sub_element(ElementName::ApiServicePrefix)?
367 .set_character_data(prefix)?;
368 } else {
369 let _ = self.element().remove_sub_element_kind(ElementName::ApiServicePrefix);
370 }
371
372 Ok(())
373 }
374
375 #[must_use]
380 pub fn api_service_prefix(&self) -> Option<String> {
381 self.element()
382 .get_sub_element(ElementName::ApiServicePrefix)
383 .and_then(|elem| elem.character_data())
384 .and_then(|cdata| cdata.string_value())
385 }
386
387 pub fn set_supported_config_variants(
389 &self,
390 variants: &[EcucConfigurationVariant],
391 ) -> Result<(), AutosarAbstractionError> {
392 let _ = self
394 .element()
395 .remove_sub_element_kind(ElementName::SupportedConfigVariants);
396
397 let supported_config_variants_elem = self
399 .element()
400 .create_sub_element(ElementName::SupportedConfigVariants)?;
401 for variant in variants {
402 let variant_elem =
403 supported_config_variants_elem.create_sub_element(ElementName::SupportedConfigVariant)?;
404 variant_elem.set_character_data::<EnumItem>((*variant).into())?;
405 }
406
407 Ok(())
408 }
409
410 #[must_use]
412 pub fn supported_config_variants(&self) -> Vec<EcucConfigurationVariant> {
413 self.element()
414 .get_sub_element(ElementName::SupportedConfigVariants)
415 .map(|elem| {
416 elem.sub_elements()
417 .filter_map(|variant_elem| {
418 variant_elem
419 .character_data()
420 .and_then(|cdata| cdata.enum_value())
421 .and_then(|enum_item| EcucConfigurationVariant::try_from(enum_item).ok())
422 })
423 .collect()
424 })
425 .unwrap_or_default()
426 }
427
428 pub fn set_post_build_variant_support(&self, support: Option<bool>) -> Result<(), AutosarAbstractionError> {
430 if let Some(support) = support {
431 self.element()
432 .get_or_create_sub_element(ElementName::PostBuildVariantSupport)?
433 .set_character_data(support)?;
434 } else {
435 let _ = self
436 .element()
437 .remove_sub_element_kind(ElementName::PostBuildVariantSupport);
438 }
439
440 Ok(())
441 }
442
443 #[must_use]
445 pub fn post_build_variant_support(&self) -> Option<bool> {
446 self.element()
447 .get_sub_element(ElementName::PostBuildVariantSupport)
448 .and_then(|elem| elem.character_data())
449 .and_then(|cdata| cdata.parse_bool())
450 }
451
452 pub fn set_category(&self, category: Option<EcucModuleDefCategory>) -> Result<(), AutosarAbstractionError> {
454 if let Some(category) = category {
455 self.element()
456 .get_or_create_sub_element(ElementName::Category)?
457 .set_character_data(category.to_string())?;
458 } else {
459 let _ = self.element().remove_sub_element_kind(ElementName::Category);
460 }
461
462 Ok(())
463 }
464
465 #[must_use]
467 pub fn category(&self) -> Option<EcucModuleDefCategory> {
468 self.element()
469 .get_sub_element(ElementName::Category)
470 .and_then(|elem| elem.character_data())
471 .and_then(|cdata| cdata.string_value())
472 .and_then(|value| EcucModuleDefCategory::try_from(value.as_str()).ok())
473 }
474
475 pub fn set_refined_module_def(
479 &self,
480 refined_module_def: Option<&EcucModuleDef>,
481 ) -> Result<(), AutosarAbstractionError> {
482 if let Some(refined_module_def) = refined_module_def {
483 self.element()
484 .get_or_create_sub_element(ElementName::RefinedModuleDefRef)?
485 .set_reference_target(refined_module_def.element())?;
486 } else {
487 let _ = self.element().remove_sub_element_kind(ElementName::RefinedModuleDefRef);
488 }
489
490 Ok(())
491 }
492
493 #[must_use]
497 pub fn refined_module_def(&self) -> Option<EcucModuleDef> {
498 self.element()
499 .get_sub_element(ElementName::RefinedModuleDefRef)
500 .and_then(|elem| elem.get_reference_target().ok())
501 .and_then(|target| EcucModuleDef::try_from(target).ok())
502 }
503}
504
505#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
510pub enum EcucConfigurationVariant {
511 PreconfiguredConfiguration,
513 RecommendedConfiguration,
515 VariantLinkTime,
517 VariantPostBuild,
519 VariantPreCompile,
521 VariantPostBuildLoadable,
523 VariantPostBuildSelectable,
525}
526
527impl From<EcucConfigurationVariant> for EnumItem {
528 fn from(value: EcucConfigurationVariant) -> Self {
529 match value {
530 EcucConfigurationVariant::PreconfiguredConfiguration => Self::PreconfiguredConfiguration,
531 EcucConfigurationVariant::RecommendedConfiguration => Self::RecommendedConfiguration,
532 EcucConfigurationVariant::VariantLinkTime => Self::VariantLinkTime,
533 EcucConfigurationVariant::VariantPostBuild => Self::VariantPostBuild,
534 EcucConfigurationVariant::VariantPreCompile => Self::VariantPreCompile,
535 EcucConfigurationVariant::VariantPostBuildLoadable => Self::VariantPostBuildLoadable,
536 EcucConfigurationVariant::VariantPostBuildSelectable => Self::VariantPostBuildSelectable,
537 }
538 }
539}
540
541impl TryFrom<EnumItem> for EcucConfigurationVariant {
542 type Error = AutosarAbstractionError;
543
544 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
545 match value {
546 EnumItem::PreconfiguredConfiguration => Ok(Self::PreconfiguredConfiguration),
547 EnumItem::RecommendedConfiguration => Ok(Self::RecommendedConfiguration),
548 EnumItem::VariantLinkTime => Ok(Self::VariantLinkTime),
549 EnumItem::VariantPostBuild => Ok(Self::VariantPostBuild),
550 EnumItem::VariantPreCompile => Ok(Self::VariantPreCompile),
551 EnumItem::VariantPostBuildLoadable => Ok(Self::VariantPostBuildLoadable),
552 EnumItem::VariantPostBuildSelectable => Ok(Self::VariantPostBuildSelectable),
553 _ => Err(AutosarAbstractionError::ValueConversionError {
554 value: value.to_string(),
555 dest: "EcucConfigurationVariant".to_string(),
556 }),
557 }
558 }
559}
560
561#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
565pub enum EcucConfigurationClass {
566 Link,
568 PostBuild,
570 PreCompile,
572 PublishedInformation,
574}
575
576impl From<EcucConfigurationClass> for EnumItem {
577 fn from(value: EcucConfigurationClass) -> Self {
578 match value {
579 EcucConfigurationClass::Link => Self::Link,
580 EcucConfigurationClass::PostBuild => Self::PostBuild,
581 EcucConfigurationClass::PreCompile => Self::PreCompile,
582 EcucConfigurationClass::PublishedInformation => Self::PublishedInformation,
583 }
584 }
585}
586
587impl TryFrom<EnumItem> for EcucConfigurationClass {
588 type Error = AutosarAbstractionError;
589
590 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
591 match value {
592 EnumItem::Link => Ok(Self::Link),
593 EnumItem::PostBuild => Ok(Self::PostBuild),
594 EnumItem::PreCompile => Ok(Self::PreCompile),
595 EnumItem::PublishedInformation => Ok(Self::PublishedInformation),
596 _ => Err(AutosarAbstractionError::ValueConversionError {
597 value: value.to_string(),
598 dest: "EcucConfigurationClass".to_string(),
599 }),
600 }
601 }
602}
603
604#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
608pub enum EcucModuleDefCategory {
609 StandardizedModuleDefinition,
611 VendorSpecificModuleDefinition,
613}
614
615impl std::fmt::Display for EcucModuleDefCategory {
616 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
617 match self {
618 EcucModuleDefCategory::StandardizedModuleDefinition => write!(f, "STANDARDIZED_MODULE_DEFINITION"),
619 EcucModuleDefCategory::VendorSpecificModuleDefinition => write!(f, "VENDOR_SPECIFIC_MODULE_DEFINITION"),
620 }
621 }
622}
623
624impl TryFrom<&str> for EcucModuleDefCategory {
625 type Error = AutosarAbstractionError;
626
627 fn try_from(value: &str) -> Result<Self, Self::Error> {
628 match value {
629 "STANDARDIZED_MODULE_DEFINITION" => Ok(Self::StandardizedModuleDefinition),
630 "VENDOR_SPECIFIC_MODULE_DEFINITION" => Ok(Self::VendorSpecificModuleDefinition),
631 _ => Err(AutosarAbstractionError::ValueConversionError {
632 value: value.to_string(),
633 dest: "EcucModuleDefCategory".to_string(),
634 }),
635 }
636 }
637}
638
639fn set_config_classes(
643 base: &Element,
644 element_name_l1: ElementName,
645 element_name_l2: ElementName,
646 config: &[(EcucConfigurationClass, EcucConfigurationVariant)],
647) -> Result<(), AutosarAbstractionError> {
648 let _ = base.remove_sub_element_kind(element_name_l1);
651
652 if !config.is_empty() {
653 let config_classes = base.create_sub_element(element_name_l1)?;
655 for (config_class, variant) in config {
656 let ecuc_config_class_elem = config_classes.create_sub_element(element_name_l2)?;
657 ecuc_config_class_elem
658 .create_sub_element(ElementName::ConfigClass)?
659 .set_character_data::<EnumItem>((*config_class).into())?;
660 ecuc_config_class_elem
661 .create_sub_element(ElementName::ConfigVariant)?
662 .set_character_data::<EnumItem>((*variant).into())?;
663 }
664 }
665
666 Ok(())
667}
668
669fn get_config_classes(
671 base: &Element,
672 element_name_l1: ElementName,
673) -> Vec<(EcucConfigurationClass, EcucConfigurationVariant)> {
674 base.get_sub_element(element_name_l1)
675 .into_iter()
676 .flat_map(|config_classes| config_classes.sub_elements())
677 .filter_map(|config_class| {
678 let class = config_class
679 .get_sub_element(ElementName::ConfigClass)?
680 .character_data()?
681 .enum_value()?;
682 let variant = config_class
683 .get_sub_element(ElementName::ConfigVariant)?
684 .character_data()?
685 .enum_value()?;
686 Some((
687 EcucConfigurationClass::try_from(class).ok()?,
688 EcucConfigurationVariant::try_from(variant).ok()?,
689 ))
690 })
691 .collect()
692}
693
694#[derive(Debug, Clone, PartialEq, Eq, Hash)]
698pub struct EcucDestinationUriDefSet(Element);
699abstraction_element!(EcucDestinationUriDefSet, EcucDestinationUriDefSet);
700impl IdentifiableAbstractionElement for EcucDestinationUriDefSet {}
701
702impl EcucDestinationUriDefSet {
703 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
704 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
705 let ecuc_destination_uri_def_set_elem =
706 elements.create_named_sub_element(ElementName::EcucDestinationUriDefSet, name)?;
707
708 Ok(Self(ecuc_destination_uri_def_set_elem))
709 }
710
711 pub fn create_destination_uri_def(
713 &self,
714 name: &str,
715 contract: EcucDestinationUriNestingContract,
716 ) -> Result<EcucDestinationUriDef, AutosarAbstractionError> {
717 let defs = self
718 .element()
719 .get_or_create_sub_element(ElementName::DestinationUriDefs)?;
720 EcucDestinationUriDef::new(name, &defs, contract)
721 }
722
723 pub fn destination_uri_defs(&self) -> impl Iterator<Item = EcucDestinationUriDef> + Send + use<> {
725 self.element()
726 .get_sub_element(ElementName::DestinationUriDefs)
727 .into_iter()
728 .flat_map(|defs_elem| defs_elem.sub_elements())
729 .filter_map(|def_elem| EcucDestinationUriDef::try_from(def_elem).ok())
730 }
731}
732
733#[derive(Debug, Clone, PartialEq, Eq, Hash)]
737pub struct EcucDestinationUriDef(Element);
738abstraction_element!(EcucDestinationUriDef, EcucDestinationUriDef);
739impl IdentifiableAbstractionElement for EcucDestinationUriDef {}
740
741impl EcucDestinationUriDef {
742 pub(crate) fn new(
744 name: &str,
745 parent: &Element,
746 contract: EcucDestinationUriNestingContract,
747 ) -> Result<Self, AutosarAbstractionError> {
748 let ecuc_destination_uri_def_elem =
749 parent.create_named_sub_element(ElementName::EcucDestinationUriDef, name)?;
750
751 let ecuc_destination_uri_def = Self(ecuc_destination_uri_def_elem);
752 ecuc_destination_uri_def.set_nesting_contract(contract)?;
753
754 Ok(ecuc_destination_uri_def)
755 }
756
757 pub fn set_nesting_contract(
759 &self,
760 contract: EcucDestinationUriNestingContract,
761 ) -> Result<(), AutosarAbstractionError> {
762 self.element()
763 .get_or_create_sub_element(ElementName::DestinationUriPolicy)?
764 .get_or_create_sub_element(ElementName::DestinationUriNestingContract)?
765 .set_character_data::<EnumItem>(contract.into())?;
766 Ok(())
767 }
768
769 #[must_use]
771 pub fn nesting_contract(&self) -> Option<EcucDestinationUriNestingContract> {
772 self.element()
773 .get_sub_element(ElementName::DestinationUriPolicy)?
774 .get_sub_element(ElementName::DestinationUriNestingContract)?
775 .character_data()?
776 .enum_value()
777 .and_then(|enum_item| EcucDestinationUriNestingContract::try_from(enum_item).ok())
778 }
779
780 pub fn create_param_conf_container_def(
782 &self,
783 name: &str,
784 ) -> Result<EcucParamConfContainerDef, AutosarAbstractionError> {
785 let containers = self
786 .element()
787 .get_or_create_sub_element(ElementName::DestinationUriPolicy)?
788 .get_or_create_sub_element(ElementName::Containers)?;
789 EcucParamConfContainerDef::new(name, &containers)
790 }
791
792 pub fn create_choice_container_def(&self, name: &str) -> Result<EcucChoiceContainerDef, AutosarAbstractionError> {
794 let containers = self
795 .element()
796 .get_or_create_sub_element(ElementName::DestinationUriPolicy)?
797 .get_or_create_sub_element(ElementName::Containers)?;
798 EcucChoiceContainerDef::new(name, &containers)
799 }
800
801 pub fn containers(&self) -> impl Iterator<Item = EcucContainerDef> + Send + use<> {
803 self.element()
804 .get_sub_element(ElementName::DestinationUriPolicy)
805 .and_then(|dup_elem| dup_elem.get_sub_element(ElementName::Containers))
806 .into_iter()
807 .flat_map(|policy_elem| policy_elem.sub_elements())
808 .filter_map(|container_elem| EcucContainerDef::try_from(container_elem).ok())
809 }
810
811 }
814
815#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
819pub enum EcucDestinationUriNestingContract {
820 LeafOfTargetContainer,
822 TargetContainer,
824 VertexOfTargetContainer,
826}
827
828impl From<EcucDestinationUriNestingContract> for EnumItem {
829 fn from(value: EcucDestinationUriNestingContract) -> Self {
830 match value {
831 EcucDestinationUriNestingContract::LeafOfTargetContainer => Self::LeafOfTargetContainer,
832 EcucDestinationUriNestingContract::TargetContainer => Self::TargetContainer,
833 EcucDestinationUriNestingContract::VertexOfTargetContainer => Self::VertexOfTargetContainer,
834 }
835 }
836}
837
838impl TryFrom<EnumItem> for EcucDestinationUriNestingContract {
839 type Error = AutosarAbstractionError;
840
841 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
842 match value {
843 EnumItem::LeafOfTargetContainer => Ok(Self::LeafOfTargetContainer),
844 EnumItem::TargetContainer => Ok(Self::TargetContainer),
845 EnumItem::VertexOfTargetContainer => Ok(Self::VertexOfTargetContainer),
846 _ => Err(AutosarAbstractionError::ValueConversionError {
847 value: value.to_string(),
848 dest: "EcucDestinationUriNestingContract".to_string(),
849 }),
850 }
851 }
852}
853
854#[cfg(test)]
857mod test {
858 use super::*;
859 use crate::AutosarModelAbstraction;
860 use autosar_data::AutosarVersion;
861
862 #[test]
863 fn ecuc_module_def() {
864 let model = AutosarModelAbstraction::create("file.arxml", AutosarVersion::LATEST);
865 let package = model.get_or_create_package("/package").unwrap();
866
867 let ecuc_definition_collection = package.create_ecuc_definition_collection("collection").unwrap();
868 assert_eq!(ecuc_definition_collection.module_defs().count(), 0);
869
870 let ecuc_module_def = package.create_ecuc_module_def("module_def").unwrap();
871 ecuc_definition_collection.add_module_def(&ecuc_module_def).unwrap();
872 assert_eq!(ecuc_definition_collection.module_defs().count(), 1);
873
874 assert_eq!(ecuc_module_def.api_service_prefix(), None);
875 assert_eq!(
876 ecuc_module_def.supported_config_variants(),
877 Vec::<EcucConfigurationVariant>::new()
878 );
879 assert_eq!(ecuc_module_def.post_build_variant_support(), None);
880 assert_eq!(ecuc_module_def.category(), None);
881 assert_eq!(ecuc_module_def.refined_module_def(), None);
882 assert_eq!(ecuc_module_def.lower_multiplicity(), None);
883 assert_eq!(ecuc_module_def.upper_multiplicity(), None);
884 assert_eq!(ecuc_module_def.upper_multiplicity_infinite(), None);
885
886 let base_ecuc_module_def = package.create_ecuc_module_def("base_module_def").unwrap();
887 ecuc_module_def
888 .set_refined_module_def(Some(&base_ecuc_module_def))
889 .unwrap();
890 assert_eq!(ecuc_module_def.refined_module_def(), Some(base_ecuc_module_def.clone()));
891 ecuc_module_def.set_api_service_prefix(Some("prefix")).unwrap();
892 assert_eq!(ecuc_module_def.api_service_prefix(), Some("prefix".to_string()));
893 ecuc_module_def
894 .set_supported_config_variants(&[
895 EcucConfigurationVariant::PreconfiguredConfiguration,
896 EcucConfigurationVariant::VariantLinkTime,
897 ])
898 .unwrap();
899 assert_eq!(
900 ecuc_module_def.supported_config_variants(),
901 vec![
902 EcucConfigurationVariant::PreconfiguredConfiguration,
903 EcucConfigurationVariant::VariantLinkTime
904 ]
905 );
906 ecuc_module_def.set_post_build_variant_support(Some(true)).unwrap();
907 assert_eq!(ecuc_module_def.post_build_variant_support(), Some(true));
908 ecuc_module_def
909 .set_category(Some(EcucModuleDefCategory::VendorSpecificModuleDefinition))
910 .unwrap();
911 assert_eq!(
912 ecuc_module_def.category(),
913 Some(EcucModuleDefCategory::VendorSpecificModuleDefinition)
914 );
915 ecuc_module_def.set_lower_multiplicity(Some(1)).unwrap();
916 assert_eq!(ecuc_module_def.lower_multiplicity(), Some(1));
917 ecuc_module_def.set_upper_multiplicity(Some(2)).unwrap();
918 assert_eq!(ecuc_module_def.upper_multiplicity(), Some(2));
919 ecuc_module_def.set_upper_multiplicity_infinite(Some(true)).unwrap();
920 assert_eq!(ecuc_module_def.upper_multiplicity_infinite(), Some(true));
921 }
922
923 #[test]
924 fn ecuc_configuration_variant_enum_conversion() {
925 let variants = [
926 EcucConfigurationVariant::PreconfiguredConfiguration,
927 EcucConfigurationVariant::RecommendedConfiguration,
928 EcucConfigurationVariant::VariantLinkTime,
929 EcucConfigurationVariant::VariantPostBuild,
930 EcucConfigurationVariant::VariantPreCompile,
931 EcucConfigurationVariant::VariantPostBuildLoadable,
932 EcucConfigurationVariant::VariantPostBuildSelectable,
933 ];
934
935 for variant in &variants {
936 let enum_item: EnumItem = (*variant).into();
937 let converted_variant = EcucConfigurationVariant::try_from(enum_item).unwrap();
938 assert_eq!(*variant, converted_variant);
939 }
940 }
941
942 #[test]
943 fn destionation_uri_defs() {
944 let model = AutosarModelAbstraction::create("file.arxml", AutosarVersion::LATEST);
945 let package = model.get_or_create_package("/package").unwrap();
946
947 let ecuc_destination_uri_def_set = package
948 .create_ecuc_destination_uri_def_set("destination_uri_def_set")
949 .unwrap();
950 assert_eq!(ecuc_destination_uri_def_set.destination_uri_defs().count(), 0);
951
952 let ecuc_destination_uri_def = ecuc_destination_uri_def_set
953 .create_destination_uri_def(
954 "destination_uri_def",
955 EcucDestinationUriNestingContract::LeafOfTargetContainer,
956 )
957 .unwrap();
958 assert_eq!(ecuc_destination_uri_def_set.destination_uri_defs().count(), 1);
959
960 assert_eq!(
961 ecuc_destination_uri_def.nesting_contract(),
962 Some(EcucDestinationUriNestingContract::LeafOfTargetContainer)
963 );
964 assert_eq!(ecuc_destination_uri_def.containers().count(), 0);
965
966 let _param_conf_container_def = ecuc_destination_uri_def
967 .create_param_conf_container_def("param_conf_container")
968 .unwrap();
969 assert_eq!(ecuc_destination_uri_def.containers().count(), 1);
970
971 let _choice_container_def = ecuc_destination_uri_def
972 .create_choice_container_def("choice_container")
973 .unwrap();
974 assert_eq!(ecuc_destination_uri_def.containers().count(), 2);
975 }
976}