1use crate::{
7 AbstractionElement, ArPackage, AutosarAbstractionError, Element, IdentifiableAbstractionElement,
8 abstraction_element,
9};
10use autosar_data::ElementName;
11
12mod connector;
13mod interface;
14mod internal_behavior;
15mod mode;
16mod port;
17
18pub use connector::*;
19pub use interface::*;
20pub use internal_behavior::*;
21pub use mode::*;
22pub use port::*;
23
24pub trait AbstractSwComponentType: IdentifiableAbstractionElement {
28 fn instances(&self) -> Vec<ComponentPrototype> {
30 let model_result = self.element().model();
31 let path_result = self.element().path();
32 if let (Ok(model), Ok(path)) = (model_result, path_result) {
33 model
34 .get_references_to(&path)
35 .iter()
36 .filter_map(|e| {
37 e.upgrade()
38 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
39 .and_then(|elem| ComponentPrototype::try_from(elem).ok())
40 })
41 .collect()
42 } else {
43 vec![]
44 }
45 }
46
47 fn parent_compositions(&self) -> Vec<CompositionSwComponentType> {
49 self.instances()
50 .iter()
51 .filter_map(|swcp| swcp.element().named_parent().ok().flatten())
52 .filter_map(|elem| CompositionSwComponentType::try_from(elem).ok())
53 .collect()
54 }
55
56 fn create_r_port<T: AbstractPortInterface>(
58 &self,
59 name: &str,
60 port_interface: &T,
61 ) -> Result<RPortPrototype, AutosarAbstractionError> {
62 let ports = self.element().get_or_create_sub_element(ElementName::Ports)?;
63 RPortPrototype::new(name, &ports, port_interface)
64 }
65
66 fn create_p_port<T: AbstractPortInterface>(
68 &self,
69 name: &str,
70 port_interface: &T,
71 ) -> Result<PPortPrototype, AutosarAbstractionError> {
72 let ports = self.element().get_or_create_sub_element(ElementName::Ports)?;
73 PPortPrototype::new(name, &ports, port_interface)
74 }
75
76 fn create_pr_port<T: AbstractPortInterface>(
78 &self,
79 name: &str,
80 port_interface: &T,
81 ) -> Result<PRPortPrototype, AutosarAbstractionError> {
82 let ports = self.element().get_or_create_sub_element(ElementName::Ports)?;
83 PRPortPrototype::new(name, &ports, port_interface)
84 }
85
86 fn ports(&self) -> impl Iterator<Item = PortPrototype> + Send + 'static {
88 self.element()
89 .get_sub_element(ElementName::Ports)
90 .into_iter()
91 .flat_map(|ports| ports.sub_elements())
92 .filter_map(|elem| PortPrototype::try_from(elem).ok())
93 }
94
95 fn create_port_group(&self, name: &str) -> Result<PortGroup, AutosarAbstractionError> {
97 let port_groups = self.element().get_or_create_sub_element(ElementName::PortGroups)?;
98 PortGroup::new(name, &port_groups)
99 }
100}
101
102pub trait AtomicSwComponentType: AbstractSwComponentType {
108 fn create_swc_internal_behavior(&self, name: &str) -> Result<SwcInternalBehavior, AutosarAbstractionError> {
114 let internal_behaviors = self
115 .element()
116 .get_or_create_sub_element(ElementName::InternalBehaviors)?;
117 SwcInternalBehavior::new(name, &internal_behaviors)
118 }
119
120 fn swc_internal_behaviors(&self) -> impl Iterator<Item = SwcInternalBehavior> + Send + 'static {
122 self.element()
123 .get_sub_element(ElementName::InternalBehaviors)
124 .into_iter()
125 .flat_map(|internal_behaviors| internal_behaviors.sub_elements())
126 .filter_map(|elem| SwcInternalBehavior::try_from(elem).ok())
127 }
128}
129
130#[derive(Debug, Clone, PartialEq, Eq, Hash)]
136pub struct CompositionSwComponentType(Element);
137abstraction_element!(CompositionSwComponentType, CompositionSwComponentType);
138impl IdentifiableAbstractionElement for CompositionSwComponentType {}
139
140impl CompositionSwComponentType {
141 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
143 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
144 let composition = elements.create_named_sub_element(ElementName::CompositionSwComponentType, name)?;
145 Ok(Self(composition))
146 }
147
148 pub fn is_parent_of<T: AbstractSwComponentType>(&self, other: &T) -> bool {
150 let mut work_items = other.parent_compositions();
153 let mut counter = 1000; while !work_items.is_empty() && counter > 0 {
155 counter -= 1;
156 if work_items.contains(self) {
157 return true;
158 }
159 let item = work_items.pop().unwrap();
161 work_items.extend(item.parent_compositions());
162 }
163
164 false
165 }
166
167 pub fn create_component<T: Into<SwComponentType> + Clone>(
171 &self,
172 name: &str,
173 component_type: &T,
174 ) -> Result<SwComponentPrototype, AutosarAbstractionError> {
175 let component_type = component_type.clone().into();
176 if let SwComponentType::Composition(composition_component) = &component_type {
177 if composition_component.is_parent_of(self) {
178 return Err(AutosarAbstractionError::InvalidParameter(
179 "Creating a cycle in the composition hierarchy".to_string(),
180 ));
181 }
182 }
183
184 let components = self.element().get_or_create_sub_element(ElementName::Components)?;
185 SwComponentPrototype::new(name, &components, &component_type)
186 }
187
188 pub fn components(&self) -> impl Iterator<Item = SwComponentPrototype> + Send + 'static {
190 self.element()
191 .get_sub_element(ElementName::Components)
192 .into_iter()
193 .flat_map(|components| components.sub_elements())
194 .filter_map(|elem| SwComponentPrototype::try_from(elem).ok())
195 }
196
197 pub fn create_delegation_connector<T1: Into<PortPrototype> + Clone, T2: Into<PortPrototype> + Clone>(
201 &self,
202 name: &str,
203 inner_port: &T1,
204 inner_sw_prototype: &SwComponentPrototype,
205 outer_port: &T2,
206 ) -> Result<DelegationSwConnector, AutosarAbstractionError> {
207 self.create_delegation_connector_internal(
208 name,
209 &inner_port.clone().into(),
210 inner_sw_prototype,
211 &outer_port.clone().into(),
212 )
213 }
214
215 fn create_delegation_connector_internal(
218 &self,
219 name: &str,
220 inner_port: &PortPrototype,
221 inner_sw_prototype: &SwComponentPrototype,
222 outer_port: &PortPrototype,
223 ) -> Result<DelegationSwConnector, AutosarAbstractionError> {
224 let interface_1 = inner_port.port_interface()?;
226 let interface_2 = outer_port.port_interface()?;
227 if std::mem::discriminant(&interface_1) != std::mem::discriminant(&interface_2) {
228 return Err(AutosarAbstractionError::InvalidParameter(
229 "The interfaces of the two ports are not compatible".to_string(),
230 ));
231 }
232
233 let inner_swc_from_port = SwComponentType::try_from(inner_port.element().named_parent()?.unwrap())?;
235 let inner_swc_from_component =
236 inner_sw_prototype
237 .component_type()
238 .ok_or(AutosarAbstractionError::InvalidParameter(
239 "The inner component is incomplete and lacks a type reference".to_string(),
240 ))?;
241 if inner_swc_from_port != inner_swc_from_component {
242 return Err(AutosarAbstractionError::InvalidParameter(
243 "The inner port must be part of the inner component".to_string(),
244 ));
245 }
246
247 let swc_self = self.clone().into();
248 let outer_swc_from_port = SwComponentType::try_from(outer_port.element().named_parent()?.unwrap())?;
249 if outer_swc_from_port != swc_self {
250 return Err(AutosarAbstractionError::InvalidParameter(
251 "The outer port must be part of the composition".to_string(),
252 ));
253 }
254
255 let connectors = self.element().get_or_create_sub_element(ElementName::Connectors)?;
257
258 DelegationSwConnector::new(
259 name,
260 &connectors,
261 inner_port, inner_sw_prototype,
263 outer_port, )
265 }
266
267 pub fn create_assembly_connector<T1: Into<PortPrototype> + Clone, T2: Into<PortPrototype> + Clone>(
271 &self,
272 name: &str,
273 port_1: &T1,
274 sw_prototype_1: &SwComponentPrototype,
275 port_2: &T2,
276 sw_prototype_2: &SwComponentPrototype,
277 ) -> Result<AssemblySwConnector, AutosarAbstractionError> {
278 self.create_assembly_connector_internal(
279 name,
280 &port_1.clone().into(),
281 sw_prototype_1,
282 &port_2.clone().into(),
283 sw_prototype_2,
284 )
285 }
286
287 fn create_assembly_connector_internal(
288 &self,
289 name: &str,
290 port_1: &PortPrototype,
291 sw_prototype_1: &SwComponentPrototype,
292 port_2: &PortPrototype,
293 sw_prototype_2: &SwComponentPrototype,
294 ) -> Result<AssemblySwConnector, AutosarAbstractionError> {
295 let interface_1 = port_1.port_interface()?;
297 let interface_2 = port_2.port_interface()?;
298 if std::mem::discriminant(&interface_1) != std::mem::discriminant(&interface_2) {
299 return Err(AutosarAbstractionError::InvalidParameter(
300 "The interfaces of the two ports are not compatible".to_string(),
301 ));
302 }
303
304 let swc_1_from_port = SwComponentType::try_from(port_1.element().named_parent()?.unwrap())?;
306 let swc_1_from_component = sw_prototype_1
307 .component_type()
308 .ok_or(AutosarAbstractionError::InvalidParameter(
309 "SW component prototype 1 is incomplete and lacks a type reference".to_string(),
310 ))?;
311 if swc_1_from_port != swc_1_from_component {
312 return Err(AutosarAbstractionError::InvalidParameter(
313 "The first port must be part of the first software component".to_string(),
314 ));
315 }
316
317 let swc_2_from_port = SwComponentType::try_from(port_2.element().named_parent()?.unwrap())?;
318 let swc_2_from_component = sw_prototype_2
319 .component_type()
320 .ok_or(AutosarAbstractionError::InvalidParameter(
321 "SW component prototype 2 is incomplete and lacks a type reference".to_string(),
322 ))?;
323 if swc_2_from_port != swc_2_from_component {
324 return Err(AutosarAbstractionError::InvalidParameter(
325 "The second port must be part of the second software component".to_string(),
326 ));
327 }
328
329 if &sw_prototype_1.parent_composition()? != self {
331 return Err(AutosarAbstractionError::InvalidParameter(
332 "The first software component must be part of the composition".to_string(),
333 ));
334 }
335 if &sw_prototype_2.parent_composition()? != self {
336 return Err(AutosarAbstractionError::InvalidParameter(
337 "The second software component must be part of the composition".to_string(),
338 ));
339 }
340
341 let connectors = self.element().get_or_create_sub_element(ElementName::Connectors)?;
343 AssemblySwConnector::new(name, &connectors, port_1, sw_prototype_1, port_2, sw_prototype_2)
344 }
345
346 pub fn create_pass_through_connector<T1: Into<PortPrototype> + Clone, T2: Into<PortPrototype> + Clone>(
350 &self,
351 name: &str,
352 port_1: &T1,
353 port_2: &T2,
354 ) -> Result<PassThroughSwConnector, AutosarAbstractionError> {
355 self.create_pass_through_connector_internal(name, &port_1.clone().into(), &port_2.clone().into())
356 }
357
358 fn create_pass_through_connector_internal(
359 &self,
360 name: &str,
361 port_1: &PortPrototype,
362 port_2: &PortPrototype,
363 ) -> Result<PassThroughSwConnector, AutosarAbstractionError> {
364 let interface_1 = port_1.port_interface()?;
366 let interface_2 = port_2.port_interface()?;
367 if std::mem::discriminant(&interface_1) != std::mem::discriminant(&interface_2) {
368 return Err(AutosarAbstractionError::InvalidParameter(
369 "The interfaces of the two ports are not compatible".to_string(),
370 ));
371 }
372
373 let swc_1 = SwComponentType::try_from(port_1.element().named_parent()?.unwrap())?;
375 let swc_2 = SwComponentType::try_from(port_2.element().named_parent()?.unwrap())?;
376 let swc_self = self.clone().into();
377
378 if swc_1 != swc_self || swc_2 != swc_self {
380 return Err(AutosarAbstractionError::InvalidParameter(
381 "The ports must be part of the composition".to_string(),
382 ));
383 }
384
385 let connectors = self.element().get_or_create_sub_element(ElementName::Connectors)?;
386 PassThroughSwConnector::new(name, &connectors, port_1, port_2)
387 }
388
389 pub fn connectors(&self) -> impl Iterator<Item = SwConnector> + Send + 'static {
391 self.element()
392 .get_sub_element(ElementName::Connectors)
393 .into_iter()
394 .flat_map(|connectors| connectors.sub_elements())
395 .filter_map(|elem| SwConnector::try_from(elem).ok())
396 }
397}
398
399impl AbstractSwComponentType for CompositionSwComponentType {}
400
401#[derive(Debug, Clone, PartialEq, Eq, Hash)]
407pub struct ApplicationSwComponentType(Element);
408abstraction_element!(ApplicationSwComponentType, ApplicationSwComponentType);
409impl IdentifiableAbstractionElement for ApplicationSwComponentType {}
410
411impl ApplicationSwComponentType {
412 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
414 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
415 let application = elements.create_named_sub_element(ElementName::ApplicationSwComponentType, name)?;
416 Ok(Self(application))
417 }
418}
419
420impl AbstractSwComponentType for ApplicationSwComponentType {}
421impl AtomicSwComponentType for ApplicationSwComponentType {}
422
423#[derive(Debug, Clone, PartialEq, Eq, Hash)]
429pub struct ComplexDeviceDriverSwComponentType(Element);
430abstraction_element!(ComplexDeviceDriverSwComponentType, ComplexDeviceDriverSwComponentType);
431impl IdentifiableAbstractionElement for ComplexDeviceDriverSwComponentType {}
432
433impl ComplexDeviceDriverSwComponentType {
434 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
436 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
437 let cdd = elements.create_named_sub_element(ElementName::ComplexDeviceDriverSwComponentType, name)?;
438 Ok(Self(cdd))
439 }
440}
441
442impl AbstractSwComponentType for ComplexDeviceDriverSwComponentType {}
443impl AtomicSwComponentType for ComplexDeviceDriverSwComponentType {}
444
445#[derive(Debug, Clone, PartialEq, Eq, Hash)]
452pub struct ServiceSwComponentType(Element);
453abstraction_element!(ServiceSwComponentType, ServiceSwComponentType);
454impl IdentifiableAbstractionElement for ServiceSwComponentType {}
455
456impl ServiceSwComponentType {
457 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
459 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
460 let service = elements.create_named_sub_element(ElementName::ServiceSwComponentType, name)?;
461 Ok(Self(service))
462 }
463}
464
465impl AbstractSwComponentType for ServiceSwComponentType {}
466impl AtomicSwComponentType for ServiceSwComponentType {}
467
468#[derive(Debug, Clone, PartialEq, Eq, Hash)]
474pub struct SensorActuatorSwComponentType(Element);
475abstraction_element!(SensorActuatorSwComponentType, SensorActuatorSwComponentType);
476impl IdentifiableAbstractionElement for SensorActuatorSwComponentType {}
477
478impl SensorActuatorSwComponentType {
479 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
481 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
482 let sensor_actuator = elements.create_named_sub_element(ElementName::SensorActuatorSwComponentType, name)?;
483 Ok(Self(sensor_actuator))
484 }
485}
486
487impl AbstractSwComponentType for SensorActuatorSwComponentType {}
488impl AtomicSwComponentType for SensorActuatorSwComponentType {}
489
490#[derive(Debug, Clone, PartialEq, Eq, Hash)]
497pub struct EcuAbstractionSwComponentType(Element);
498abstraction_element!(EcuAbstractionSwComponentType, EcuAbstractionSwComponentType);
499impl IdentifiableAbstractionElement for EcuAbstractionSwComponentType {}
500
501impl EcuAbstractionSwComponentType {
502 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
504 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
505 let ecu_abstraction = elements.create_named_sub_element(ElementName::EcuAbstractionSwComponentType, name)?;
506 Ok(Self(ecu_abstraction))
507 }
508}
509
510impl AbstractSwComponentType for EcuAbstractionSwComponentType {}
511impl AtomicSwComponentType for EcuAbstractionSwComponentType {}
512
513#[derive(Debug, Clone, PartialEq, Eq, Hash)]
517pub enum SwComponentType {
518 Composition(CompositionSwComponentType),
520 Application(ApplicationSwComponentType),
522 ComplexDeviceDriver(ComplexDeviceDriverSwComponentType),
524 Service(ServiceSwComponentType),
526 SensorActuator(SensorActuatorSwComponentType),
528 EcuAbstraction(EcuAbstractionSwComponentType),
530}
531
532impl AbstractionElement for SwComponentType {
533 fn element(&self) -> &Element {
534 match self {
535 SwComponentType::Composition(comp) => comp.element(),
536 SwComponentType::Application(app) => app.element(),
537 SwComponentType::ComplexDeviceDriver(cdd) => cdd.element(),
538 SwComponentType::Service(service) => service.element(),
539 SwComponentType::SensorActuator(sensor_actuator) => sensor_actuator.element(),
540 SwComponentType::EcuAbstraction(ecu_abstraction) => ecu_abstraction.element(),
541 }
542 }
543}
544
545impl IdentifiableAbstractionElement for SwComponentType {}
546
547impl TryFrom<Element> for SwComponentType {
548 type Error = AutosarAbstractionError;
549
550 fn try_from(element: Element) -> Result<Self, Self::Error> {
551 match element.element_name() {
552 ElementName::CompositionSwComponentType => {
553 Ok(SwComponentType::Composition(CompositionSwComponentType(element)))
554 }
555 ElementName::ApplicationSwComponentType => {
556 Ok(SwComponentType::Application(ApplicationSwComponentType(element)))
557 }
558 ElementName::ComplexDeviceDriverSwComponentType => Ok(SwComponentType::ComplexDeviceDriver(
559 ComplexDeviceDriverSwComponentType(element),
560 )),
561 ElementName::ServiceSwComponentType => Ok(SwComponentType::Service(ServiceSwComponentType(element))),
562 ElementName::SensorActuatorSwComponentType => {
563 Ok(SwComponentType::SensorActuator(SensorActuatorSwComponentType(element)))
564 }
565 ElementName::EcuAbstractionSwComponentType => {
566 Ok(SwComponentType::EcuAbstraction(EcuAbstractionSwComponentType(element)))
567 }
568 _ => Err(AutosarAbstractionError::ConversionError {
569 element,
570 dest: "SwComponentType".to_string(),
571 }),
572 }
573 }
574}
575
576impl From<CompositionSwComponentType> for SwComponentType {
577 fn from(comp: CompositionSwComponentType) -> Self {
578 SwComponentType::Composition(comp)
579 }
580}
581
582impl From<ApplicationSwComponentType> for SwComponentType {
583 fn from(app: ApplicationSwComponentType) -> Self {
584 SwComponentType::Application(app)
585 }
586}
587
588impl From<ComplexDeviceDriverSwComponentType> for SwComponentType {
589 fn from(cdd: ComplexDeviceDriverSwComponentType) -> Self {
590 SwComponentType::ComplexDeviceDriver(cdd)
591 }
592}
593
594impl From<ServiceSwComponentType> for SwComponentType {
595 fn from(service: ServiceSwComponentType) -> Self {
596 SwComponentType::Service(service)
597 }
598}
599
600impl From<SensorActuatorSwComponentType> for SwComponentType {
601 fn from(sensor_actuator: SensorActuatorSwComponentType) -> Self {
602 SwComponentType::SensorActuator(sensor_actuator)
603 }
604}
605
606impl From<EcuAbstractionSwComponentType> for SwComponentType {
607 fn from(ecu_abstraction: EcuAbstractionSwComponentType) -> Self {
608 SwComponentType::EcuAbstraction(ecu_abstraction)
609 }
610}
611
612impl AbstractSwComponentType for SwComponentType {}
613
614#[derive(Debug, Clone, PartialEq, Eq, Hash)]
618pub struct SwComponentPrototype(Element);
619abstraction_element!(SwComponentPrototype, SwComponentPrototype);
620impl IdentifiableAbstractionElement for SwComponentPrototype {}
621
622impl SwComponentPrototype {
623 fn new(
624 name: &str,
625 components: &Element,
626 component_type: &SwComponentType,
627 ) -> Result<Self, AutosarAbstractionError> {
628 let component = components.create_named_sub_element(ElementName::SwComponentPrototype, name)?;
629 component
630 .create_sub_element(ElementName::TypeTref)?
631 .set_reference_target(component_type.element())?;
632
633 Ok(Self(component))
634 }
635
636 #[must_use]
638 pub fn component_type(&self) -> Option<SwComponentType> {
639 let component_elem = self
640 .element()
641 .get_sub_element(ElementName::TypeTref)?
642 .get_reference_target()
643 .ok()?;
644 SwComponentType::try_from(component_elem).ok()
645 }
646
647 pub fn parent_composition(&self) -> Result<CompositionSwComponentType, AutosarAbstractionError> {
649 let parent = self.element().named_parent()?.unwrap();
650 CompositionSwComponentType::try_from(parent)
651 }
652}
653
654#[derive(Debug, Clone, PartialEq, Eq, Hash)]
658pub struct RootSwCompositionPrototype(Element);
659abstraction_element!(RootSwCompositionPrototype, RootSwCompositionPrototype);
660impl IdentifiableAbstractionElement for RootSwCompositionPrototype {}
661
662impl RootSwCompositionPrototype {
663 pub(crate) fn new(
664 name: &str,
665 root_compositions: &Element,
666 composition_type: &CompositionSwComponentType,
667 ) -> Result<Self, AutosarAbstractionError> {
668 let root_composition =
669 root_compositions.create_named_sub_element(ElementName::RootSwCompositionPrototype, name)?;
670 root_composition
671 .create_sub_element(ElementName::SoftwareCompositionTref)?
672 .set_reference_target(composition_type.element())?;
673
674 Ok(Self(root_composition))
675 }
676
677 #[must_use]
679 pub fn composition(&self) -> Option<CompositionSwComponentType> {
680 let composition_elem = self
681 .element()
682 .get_sub_element(ElementName::SoftwareCompositionTref)?
683 .get_reference_target()
684 .ok()?;
685 CompositionSwComponentType::try_from(composition_elem).ok()
686 }
687}
688
689#[derive(Debug, Clone, PartialEq, Eq, Hash)]
693pub enum ComponentPrototype {
694 SwComponent(SwComponentPrototype),
696 RootComposition(RootSwCompositionPrototype),
698}
699
700impl AbstractionElement for ComponentPrototype {
701 fn element(&self) -> &Element {
702 match self {
703 ComponentPrototype::SwComponent(swcp) => swcp.element(),
704 ComponentPrototype::RootComposition(root) => root.element(),
705 }
706 }
707}
708
709impl TryFrom<Element> for ComponentPrototype {
710 type Error = AutosarAbstractionError;
711
712 fn try_from(element: Element) -> Result<Self, Self::Error> {
713 match element.element_name() {
714 ElementName::SwComponentPrototype => Ok(ComponentPrototype::SwComponent(SwComponentPrototype(element))),
715 ElementName::RootSwCompositionPrototype => {
716 Ok(ComponentPrototype::RootComposition(RootSwCompositionPrototype(element)))
717 }
718 _ => Err(AutosarAbstractionError::ConversionError {
719 element,
720 dest: "ComponentPrototype".to_string(),
721 }),
722 }
723 }
724}
725
726impl IdentifiableAbstractionElement for ComponentPrototype {}
727
728impl ComponentPrototype {
729 #[must_use]
730 pub fn component_type(&self) -> Option<SwComponentType> {
732 match self {
733 ComponentPrototype::SwComponent(swcp) => swcp.component_type(),
734 ComponentPrototype::RootComposition(rc) => rc.composition().map(std::convert::Into::into),
735 }
736 }
737
738 pub fn parent_composition(&self) -> Result<Option<CompositionSwComponentType>, AutosarAbstractionError> {
742 match self {
743 ComponentPrototype::SwComponent(swcp) => swcp.parent_composition().map(Some),
744 ComponentPrototype::RootComposition(_) => Ok(None),
745 }
746 }
747}
748
749#[cfg(test)]
752mod test {
753 use super::*;
754 use crate::{AutosarModelAbstraction, SystemCategory};
755 use autosar_data::AutosarVersion;
756
757 #[test]
758 fn software_compositions() {
759 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
760 let package = model.get_or_create_package("/package").unwrap();
761
762 let comp1 = CompositionSwComponentType::new("comp1", &package).unwrap();
763 let comp2 = CompositionSwComponentType::new("comp2", &package).unwrap();
764 let comp3 = CompositionSwComponentType::new("comp3", &package).unwrap();
765 let comp4 = CompositionSwComponentType::new("comp4", &package).unwrap();
766
767 comp1.create_component("comp2", &comp2.clone()).unwrap();
768 comp2.create_component("comp3", &comp3.clone()).unwrap();
769 comp3.create_component("comp4", &comp4.clone()).unwrap();
770
771 assert_eq!(comp1.instances().len(), 0);
772 assert_eq!(comp2.instances().len(), 1);
773 assert_eq!(comp3.instances().len(), 1);
774 assert_eq!(comp4.instances().len(), 1);
775
776 assert!(comp1.is_parent_of(&comp2));
777 assert!(comp1.is_parent_of(&comp3));
778 assert!(comp1.is_parent_of(&comp4));
779
780 assert!(!comp2.is_parent_of(&comp1));
781 assert!(comp2.is_parent_of(&comp3));
782 assert!(comp2.is_parent_of(&comp4));
783
784 assert!(!comp3.is_parent_of(&comp1));
785 assert!(!comp3.is_parent_of(&comp2));
786 assert!(comp3.is_parent_of(&comp4));
787
788 assert!(!comp4.is_parent_of(&comp1));
789 assert!(!comp4.is_parent_of(&comp2));
790 assert!(!comp4.is_parent_of(&comp3));
791 }
792
793 #[test]
794 fn root_composition() {
795 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
796 let package = model.get_or_create_package("/package").unwrap();
797
798 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
799 let comp = CompositionSwComponentType::new("comp", &package).unwrap();
800 let root_sw_component_prototype = system.set_root_sw_composition("root", &comp).unwrap();
801
802 assert_eq!(
803 ComponentPrototype::RootComposition(root_sw_component_prototype),
804 comp.instances()[0]
805 );
806 assert_eq!(comp.instances().len(), 1);
807 }
808
809 #[test]
810 fn components() {
811 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
812 let package = model.get_or_create_package("/package").unwrap();
813
814 let comp = CompositionSwComponentType::new("comp", &package).unwrap();
815 let app = ApplicationSwComponentType::new("app", &package).unwrap();
816 let cdd = ComplexDeviceDriverSwComponentType::new("cdd", &package).unwrap();
817 let service = ServiceSwComponentType::new("service", &package).unwrap();
818 let sensor_actuator = SensorActuatorSwComponentType::new("sensor_actuator", &package).unwrap();
819 let ecu_abstraction = EcuAbstractionSwComponentType::new("ecu_abstraction", &package).unwrap();
820
821 let container_comp = CompositionSwComponentType::new("container_comp", &package).unwrap();
822 let comp_prototype = container_comp.create_component("comp", &comp.clone()).unwrap();
823 let _app_prototype = container_comp.create_component("app", &app.clone()).unwrap();
824 let _cdd_prototype = container_comp.create_component("cdd", &cdd.clone()).unwrap();
825 let _service_prototype = container_comp.create_component("service", &service.clone()).unwrap();
826 let _sensor_actuator_prototype = container_comp
827 .create_component("sensor_actuator", &sensor_actuator.clone())
828 .unwrap();
829 let _ecu_abstraction_prototype = container_comp
830 .create_component("ecu_abstraction", &ecu_abstraction.clone())
831 .unwrap();
832
833 assert_eq!(container_comp.components().count(), 6);
834 let mut comp_prototype_iter = container_comp.components();
835 assert_eq!(
836 comp_prototype_iter.next().unwrap().component_type().unwrap(),
837 comp.clone().into()
838 );
839 assert_eq!(
840 comp_prototype_iter.next().unwrap().component_type().unwrap(),
841 app.into()
842 );
843 assert_eq!(
844 comp_prototype_iter.next().unwrap().component_type().unwrap(),
845 cdd.into()
846 );
847 assert_eq!(
848 comp_prototype_iter.next().unwrap().component_type().unwrap(),
849 service.into()
850 );
851 assert_eq!(
852 comp_prototype_iter.next().unwrap().component_type().unwrap(),
853 sensor_actuator.into()
854 );
855 assert_eq!(
856 comp_prototype_iter.next().unwrap().component_type().unwrap(),
857 ecu_abstraction.into()
858 );
859 assert!(comp_prototype_iter.next().is_none());
860
861 let component_prototype = ComponentPrototype::SwComponent(comp_prototype);
862 assert_eq!(component_prototype.component_type().unwrap(), comp.into());
863 }
864
865 #[test]
866 fn ports_and_connectors() {
867 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
868 let package = model.get_or_create_package("/package").unwrap();
869
870 let comp_parent_type = package.create_composition_sw_component_type("comp_parent").unwrap();
873 let comp_child_type = package.create_composition_sw_component_type("comp_child").unwrap();
874 let swc_type = package.create_application_sw_component_type("swc_type1").unwrap();
875
876 let comp_child_proto = comp_parent_type.create_component("comp2", &comp_child_type).unwrap();
877 let swc_proto = comp_parent_type.create_component("swc1", &swc_type).unwrap();
878
879 let port_interface_sr = package.create_sender_receiver_interface("sr").unwrap();
881 let port_interface_cs = package.create_client_server_interface("cs").unwrap();
882
883 let comp_parent_r_port = comp_parent_type.create_r_port("port_r", &port_interface_sr).unwrap();
888 let swc_r_port = swc_type.create_r_port("port_r", &port_interface_sr).unwrap();
889 let swc_p_port = swc_type.create_p_port("port_p", &port_interface_sr).unwrap();
890 let comp_child_r_port = comp_child_type.create_r_port("port_r", &port_interface_sr).unwrap();
891 let comp_child_p_port = comp_child_type.create_p_port("port_p", &port_interface_sr).unwrap();
892
893 comp_parent_type
894 .create_delegation_connector("sr_delegation", &swc_r_port, &swc_proto, &comp_parent_r_port)
895 .unwrap();
896 comp_parent_type
897 .create_assembly_connector(
898 "sr_assembly",
899 &swc_p_port,
900 &swc_proto,
901 &comp_child_r_port,
902 &comp_child_proto,
903 )
904 .unwrap();
905 comp_child_type
906 .create_pass_through_connector("sr_passthrough", &comp_child_r_port, &comp_child_p_port)
907 .unwrap();
908
909 let comp_parent_s_port = comp_parent_type.create_p_port("port_s", &port_interface_cs).unwrap();
914 let swc_s_port = swc_type.create_p_port("port_s", &port_interface_cs).unwrap();
915 let swc_c_port = swc_type.create_r_port("port_c", &port_interface_cs).unwrap();
916 let comp_child_s_port = comp_child_type.create_p_port("port_s", &port_interface_cs).unwrap();
917 let comp_child_c_port = comp_child_type.create_r_port("port_c", &port_interface_cs).unwrap();
918
919 comp_parent_type
920 .create_delegation_connector("cs_delegation", &swc_s_port, &swc_proto, &comp_parent_s_port)
921 .unwrap();
922 comp_parent_type
923 .create_assembly_connector(
924 "cs_assembly",
925 &swc_c_port,
926 &swc_proto,
927 &comp_child_s_port,
928 &comp_child_proto,
929 )
930 .unwrap();
931 comp_child_type
932 .create_pass_through_connector("cs_passthrough", &comp_child_s_port, &comp_child_c_port)
933 .unwrap();
934
935 let mut parent_connectors = comp_parent_type.connectors();
937 assert_eq!(parent_connectors.next().unwrap().name().unwrap(), "sr_delegation");
938 assert_eq!(parent_connectors.next().unwrap().name().unwrap(), "sr_assembly");
939 assert_eq!(parent_connectors.next().unwrap().name().unwrap(), "cs_delegation");
940 assert_eq!(parent_connectors.next().unwrap().name().unwrap(), "cs_assembly");
941 assert!(parent_connectors.next().is_none());
942
943 let mut child_connectors = comp_child_type.connectors();
944 assert_eq!(child_connectors.next().unwrap().name().unwrap(), "sr_passthrough");
945 assert_eq!(child_connectors.next().unwrap().name().unwrap(), "cs_passthrough");
946 assert!(child_connectors.next().is_none());
947
948 comp_parent_type.create_port_group("group").unwrap();
950 }
951}