1use crate::{
7 AbstractionElement, ArPackage, AutosarAbstractionError, Element, IdentifiableAbstractionElement, SwcToEcuMapping,
8 abstraction_element, get_reference_parents,
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 + use<Self> {
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 + use<Self> {
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 remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
150 for component in self.components() {
151 component.remove(deep)?;
152 }
153
154 for connector in self.connectors() {
155 connector.remove(deep)?;
156 }
157
158 let ref_parents = get_reference_parents(self.element())?;
159
160 AbstractionElement::remove(self, deep)?;
161
162 for (named_parent, _parent) in ref_parents {
163 match named_parent.element_name() {
164 ElementName::SwComponentPrototype => {
165 if let Ok(component) = SwComponentPrototype::try_from(named_parent) {
166 component.remove(deep)?;
167 }
168 }
169 ElementName::RootSwCompositionPrototype => {
170 if let Ok(composition) = RootSwCompositionPrototype::try_from(named_parent) {
171 composition.remove(deep)?;
172 }
173 }
174 _ => {}
175 }
176 }
177
178 Ok(())
179 }
180
181 pub fn is_parent_of<T: AbstractSwComponentType>(&self, other: &T) -> bool {
183 let mut work_items = other.parent_compositions();
186 let mut counter = 1000; while !work_items.is_empty() && counter > 0 {
188 counter -= 1;
189 if work_items.contains(self) {
190 return true;
191 }
192 let item = work_items.pop().unwrap();
194 work_items.extend(item.parent_compositions());
195 }
196
197 false
198 }
199
200 pub fn create_component<T: Into<SwComponentType> + Clone>(
204 &self,
205 name: &str,
206 component_type: &T,
207 ) -> Result<SwComponentPrototype, AutosarAbstractionError> {
208 let component_type = component_type.clone().into();
209 if let SwComponentType::Composition(composition_component) = &component_type
210 && composition_component.is_parent_of(self)
211 {
212 return Err(AutosarAbstractionError::InvalidParameter(
213 "Creating a cycle in the composition hierarchy".to_string(),
214 ));
215 }
216
217 let components = self.element().get_or_create_sub_element(ElementName::Components)?;
218 SwComponentPrototype::new(name, &components, &component_type)
219 }
220
221 pub fn components(&self) -> impl Iterator<Item = SwComponentPrototype> + Send + use<> {
223 self.element()
224 .get_sub_element(ElementName::Components)
225 .into_iter()
226 .flat_map(|components| components.sub_elements())
227 .filter_map(|elem| SwComponentPrototype::try_from(elem).ok())
228 }
229
230 pub fn create_delegation_connector<T1: Into<PortPrototype> + Clone, T2: Into<PortPrototype> + Clone>(
234 &self,
235 name: &str,
236 inner_port: &T1,
237 inner_sw_prototype: &SwComponentPrototype,
238 outer_port: &T2,
239 ) -> Result<DelegationSwConnector, AutosarAbstractionError> {
240 self.create_delegation_connector_internal(
241 name,
242 &inner_port.clone().into(),
243 inner_sw_prototype,
244 &outer_port.clone().into(),
245 )
246 }
247
248 fn create_delegation_connector_internal(
251 &self,
252 name: &str,
253 inner_port: &PortPrototype,
254 inner_sw_prototype: &SwComponentPrototype,
255 outer_port: &PortPrototype,
256 ) -> Result<DelegationSwConnector, AutosarAbstractionError> {
257 let interface_1 = inner_port
259 .port_interface()
260 .ok_or(AutosarAbstractionError::InvalidParameter(
261 "Invalid port lacks a port interface".to_string(),
262 ))?;
263 let interface_2 = outer_port
264 .port_interface()
265 .ok_or(AutosarAbstractionError::InvalidParameter(
266 "Invalid port lacks a port interface".to_string(),
267 ))?;
268 if std::mem::discriminant(&interface_1) != std::mem::discriminant(&interface_2) {
269 return Err(AutosarAbstractionError::InvalidParameter(
270 "The interfaces of the two ports are not compatible".to_string(),
271 ));
272 }
273
274 let inner_swc_from_port = SwComponentType::try_from(inner_port.element().named_parent()?.unwrap())?;
276 let inner_swc_from_component =
277 inner_sw_prototype
278 .component_type()
279 .ok_or(AutosarAbstractionError::InvalidParameter(
280 "The inner component is incomplete and lacks a type reference".to_string(),
281 ))?;
282 if inner_swc_from_port != inner_swc_from_component {
283 return Err(AutosarAbstractionError::InvalidParameter(
284 "The inner port must be part of the inner component".to_string(),
285 ));
286 }
287
288 let swc_self = self.clone().into();
289 let outer_swc_from_port = SwComponentType::try_from(outer_port.element().named_parent()?.unwrap())?;
290 if outer_swc_from_port != swc_self {
291 return Err(AutosarAbstractionError::InvalidParameter(
292 "The outer port must be part of the composition".to_string(),
293 ));
294 }
295
296 let connectors = self.element().get_or_create_sub_element(ElementName::Connectors)?;
298
299 DelegationSwConnector::new(
300 name,
301 &connectors,
302 inner_port, inner_sw_prototype,
304 outer_port, )
306 }
307
308 pub fn create_assembly_connector<T1: Into<PortPrototype> + Clone, T2: Into<PortPrototype> + Clone>(
312 &self,
313 name: &str,
314 port_1: &T1,
315 sw_prototype_1: &SwComponentPrototype,
316 port_2: &T2,
317 sw_prototype_2: &SwComponentPrototype,
318 ) -> Result<AssemblySwConnector, AutosarAbstractionError> {
319 self.create_assembly_connector_internal(
320 name,
321 &port_1.clone().into(),
322 sw_prototype_1,
323 &port_2.clone().into(),
324 sw_prototype_2,
325 )
326 }
327
328 fn create_assembly_connector_internal(
329 &self,
330 name: &str,
331 port_1: &PortPrototype,
332 sw_prototype_1: &SwComponentPrototype,
333 port_2: &PortPrototype,
334 sw_prototype_2: &SwComponentPrototype,
335 ) -> Result<AssemblySwConnector, AutosarAbstractionError> {
336 let interface_1 = port_1
338 .port_interface()
339 .ok_or(AutosarAbstractionError::InvalidParameter(
340 "Invalid port lacks a port interface".to_string(),
341 ))?;
342 let interface_2 = port_2
343 .port_interface()
344 .ok_or(AutosarAbstractionError::InvalidParameter(
345 "Invalid port lacks a port interface".to_string(),
346 ))?;
347 if std::mem::discriminant(&interface_1) != std::mem::discriminant(&interface_2) {
348 return Err(AutosarAbstractionError::InvalidParameter(
349 "The interfaces of the two ports are not compatible".to_string(),
350 ));
351 }
352
353 let swc_1_from_port = SwComponentType::try_from(port_1.element().named_parent()?.unwrap())?;
355 let swc_1_from_component = sw_prototype_1
356 .component_type()
357 .ok_or(AutosarAbstractionError::InvalidParameter(
358 "SW component prototype 1 is incomplete and lacks a type reference".to_string(),
359 ))?;
360 if swc_1_from_port != swc_1_from_component {
361 return Err(AutosarAbstractionError::InvalidParameter(
362 "The first port must be part of the first software component".to_string(),
363 ));
364 }
365
366 let swc_2_from_port = SwComponentType::try_from(port_2.element().named_parent()?.unwrap())?;
367 let swc_2_from_component = sw_prototype_2
368 .component_type()
369 .ok_or(AutosarAbstractionError::InvalidParameter(
370 "SW component prototype 2 is incomplete and lacks a type reference".to_string(),
371 ))?;
372 if swc_2_from_port != swc_2_from_component {
373 return Err(AutosarAbstractionError::InvalidParameter(
374 "The second port must be part of the second software component".to_string(),
375 ));
376 }
377
378 if &sw_prototype_1.parent_composition()? != self {
380 return Err(AutosarAbstractionError::InvalidParameter(
381 "The first software component must be part of the composition".to_string(),
382 ));
383 }
384 if &sw_prototype_2.parent_composition()? != self {
385 return Err(AutosarAbstractionError::InvalidParameter(
386 "The second software component must be part of the composition".to_string(),
387 ));
388 }
389
390 let connectors = self.element().get_or_create_sub_element(ElementName::Connectors)?;
392 AssemblySwConnector::new(name, &connectors, port_1, sw_prototype_1, port_2, sw_prototype_2)
393 }
394
395 pub fn create_pass_through_connector<T1: Into<PortPrototype> + Clone, T2: Into<PortPrototype> + Clone>(
399 &self,
400 name: &str,
401 port_1: &T1,
402 port_2: &T2,
403 ) -> Result<PassThroughSwConnector, AutosarAbstractionError> {
404 self.create_pass_through_connector_internal(name, &port_1.clone().into(), &port_2.clone().into())
405 }
406
407 fn create_pass_through_connector_internal(
408 &self,
409 name: &str,
410 port_1: &PortPrototype,
411 port_2: &PortPrototype,
412 ) -> Result<PassThroughSwConnector, AutosarAbstractionError> {
413 let interface_1 = port_1
415 .port_interface()
416 .ok_or(AutosarAbstractionError::InvalidParameter(
417 "Invalid port lacks a port interface".to_string(),
418 ))?;
419 let interface_2 = port_2
420 .port_interface()
421 .ok_or(AutosarAbstractionError::InvalidParameter(
422 "Invalid port lacks a port interface".to_string(),
423 ))?;
424 if std::mem::discriminant(&interface_1) != std::mem::discriminant(&interface_2) {
425 return Err(AutosarAbstractionError::InvalidParameter(
426 "The interfaces of the two ports are not compatible".to_string(),
427 ));
428 }
429
430 let swc_1 = SwComponentType::try_from(port_1.element().named_parent()?.unwrap())?;
432 let swc_2 = SwComponentType::try_from(port_2.element().named_parent()?.unwrap())?;
433 let swc_self = self.clone().into();
434
435 if swc_1 != swc_self || swc_2 != swc_self {
437 return Err(AutosarAbstractionError::InvalidParameter(
438 "The ports must be part of the composition".to_string(),
439 ));
440 }
441
442 let connectors = self.element().get_or_create_sub_element(ElementName::Connectors)?;
443 PassThroughSwConnector::new(name, &connectors, port_1, port_2)
444 }
445
446 pub fn connectors(&self) -> impl Iterator<Item = SwConnector> + Send + use<> {
448 self.element()
449 .get_sub_element(ElementName::Connectors)
450 .into_iter()
451 .flat_map(|connectors| connectors.sub_elements())
452 .filter_map(|elem| SwConnector::try_from(elem).ok())
453 }
454}
455
456impl AbstractSwComponentType for CompositionSwComponentType {}
457
458#[derive(Debug, Clone, PartialEq, Eq, Hash)]
464pub struct ApplicationSwComponentType(Element);
465abstraction_element!(ApplicationSwComponentType, ApplicationSwComponentType);
466impl IdentifiableAbstractionElement for ApplicationSwComponentType {}
467
468impl ApplicationSwComponentType {
469 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
471 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
472 let application = elements.create_named_sub_element(ElementName::ApplicationSwComponentType, name)?;
473 Ok(Self(application))
474 }
475
476 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
478 for swc_internal_behavior in self.swc_internal_behaviors() {
479 swc_internal_behavior.remove(deep)?;
480 }
481 let ref_parents = get_reference_parents(self.element())?;
482
483 AbstractionElement::remove(self, deep)?;
484
485 for (named_parent, _parent) in ref_parents {
486 if named_parent.element_name() == ElementName::SwComponentPrototype
487 && let Ok(component) = SwComponentPrototype::try_from(named_parent)
488 {
489 component.remove(deep)?;
490 }
491 }
492
493 Ok(())
494 }
495}
496
497impl AbstractSwComponentType for ApplicationSwComponentType {}
498impl AtomicSwComponentType for ApplicationSwComponentType {}
499
500#[derive(Debug, Clone, PartialEq, Eq, Hash)]
506pub struct ComplexDeviceDriverSwComponentType(Element);
507abstraction_element!(ComplexDeviceDriverSwComponentType, ComplexDeviceDriverSwComponentType);
508impl IdentifiableAbstractionElement for ComplexDeviceDriverSwComponentType {}
509
510impl ComplexDeviceDriverSwComponentType {
511 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
513 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
514 let cdd = elements.create_named_sub_element(ElementName::ComplexDeviceDriverSwComponentType, name)?;
515 Ok(Self(cdd))
516 }
517}
518
519impl AbstractSwComponentType for ComplexDeviceDriverSwComponentType {}
520impl AtomicSwComponentType for ComplexDeviceDriverSwComponentType {}
521
522#[derive(Debug, Clone, PartialEq, Eq, Hash)]
529pub struct ServiceSwComponentType(Element);
530abstraction_element!(ServiceSwComponentType, ServiceSwComponentType);
531impl IdentifiableAbstractionElement for ServiceSwComponentType {}
532
533impl ServiceSwComponentType {
534 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
536 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
537 let service = elements.create_named_sub_element(ElementName::ServiceSwComponentType, name)?;
538 Ok(Self(service))
539 }
540}
541
542impl AbstractSwComponentType for ServiceSwComponentType {}
543impl AtomicSwComponentType for ServiceSwComponentType {}
544
545#[derive(Debug, Clone, PartialEq, Eq, Hash)]
551pub struct SensorActuatorSwComponentType(Element);
552abstraction_element!(SensorActuatorSwComponentType, SensorActuatorSwComponentType);
553impl IdentifiableAbstractionElement for SensorActuatorSwComponentType {}
554
555impl SensorActuatorSwComponentType {
556 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
558 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
559 let sensor_actuator = elements.create_named_sub_element(ElementName::SensorActuatorSwComponentType, name)?;
560 Ok(Self(sensor_actuator))
561 }
562}
563
564impl AbstractSwComponentType for SensorActuatorSwComponentType {}
565impl AtomicSwComponentType for SensorActuatorSwComponentType {}
566
567#[derive(Debug, Clone, PartialEq, Eq, Hash)]
574pub struct EcuAbstractionSwComponentType(Element);
575abstraction_element!(EcuAbstractionSwComponentType, EcuAbstractionSwComponentType);
576impl IdentifiableAbstractionElement for EcuAbstractionSwComponentType {}
577
578impl EcuAbstractionSwComponentType {
579 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
581 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
582 let ecu_abstraction = elements.create_named_sub_element(ElementName::EcuAbstractionSwComponentType, name)?;
583 Ok(Self(ecu_abstraction))
584 }
585}
586
587impl AbstractSwComponentType for EcuAbstractionSwComponentType {}
588impl AtomicSwComponentType for EcuAbstractionSwComponentType {}
589
590#[derive(Debug, Clone, PartialEq, Eq, Hash)]
594pub enum SwComponentType {
595 Composition(CompositionSwComponentType),
597 Application(ApplicationSwComponentType),
599 ComplexDeviceDriver(ComplexDeviceDriverSwComponentType),
601 Service(ServiceSwComponentType),
603 SensorActuator(SensorActuatorSwComponentType),
605 EcuAbstraction(EcuAbstractionSwComponentType),
607}
608
609impl AbstractionElement for SwComponentType {
610 fn element(&self) -> &Element {
611 match self {
612 SwComponentType::Composition(comp) => comp.element(),
613 SwComponentType::Application(app) => app.element(),
614 SwComponentType::ComplexDeviceDriver(cdd) => cdd.element(),
615 SwComponentType::Service(service) => service.element(),
616 SwComponentType::SensorActuator(sensor_actuator) => sensor_actuator.element(),
617 SwComponentType::EcuAbstraction(ecu_abstraction) => ecu_abstraction.element(),
618 }
619 }
620}
621
622impl IdentifiableAbstractionElement for SwComponentType {}
623
624impl TryFrom<Element> for SwComponentType {
625 type Error = AutosarAbstractionError;
626
627 fn try_from(element: Element) -> Result<Self, Self::Error> {
628 match element.element_name() {
629 ElementName::CompositionSwComponentType => {
630 Ok(SwComponentType::Composition(CompositionSwComponentType(element)))
631 }
632 ElementName::ApplicationSwComponentType => {
633 Ok(SwComponentType::Application(ApplicationSwComponentType(element)))
634 }
635 ElementName::ComplexDeviceDriverSwComponentType => Ok(SwComponentType::ComplexDeviceDriver(
636 ComplexDeviceDriverSwComponentType(element),
637 )),
638 ElementName::ServiceSwComponentType => Ok(SwComponentType::Service(ServiceSwComponentType(element))),
639 ElementName::SensorActuatorSwComponentType => {
640 Ok(SwComponentType::SensorActuator(SensorActuatorSwComponentType(element)))
641 }
642 ElementName::EcuAbstractionSwComponentType => {
643 Ok(SwComponentType::EcuAbstraction(EcuAbstractionSwComponentType(element)))
644 }
645 _ => Err(AutosarAbstractionError::ConversionError {
646 element,
647 dest: "SwComponentType".to_string(),
648 }),
649 }
650 }
651}
652
653impl From<CompositionSwComponentType> for SwComponentType {
654 fn from(comp: CompositionSwComponentType) -> Self {
655 SwComponentType::Composition(comp)
656 }
657}
658
659impl From<ApplicationSwComponentType> for SwComponentType {
660 fn from(app: ApplicationSwComponentType) -> Self {
661 SwComponentType::Application(app)
662 }
663}
664
665impl From<ComplexDeviceDriverSwComponentType> for SwComponentType {
666 fn from(cdd: ComplexDeviceDriverSwComponentType) -> Self {
667 SwComponentType::ComplexDeviceDriver(cdd)
668 }
669}
670
671impl From<ServiceSwComponentType> for SwComponentType {
672 fn from(service: ServiceSwComponentType) -> Self {
673 SwComponentType::Service(service)
674 }
675}
676
677impl From<SensorActuatorSwComponentType> for SwComponentType {
678 fn from(sensor_actuator: SensorActuatorSwComponentType) -> Self {
679 SwComponentType::SensorActuator(sensor_actuator)
680 }
681}
682
683impl From<EcuAbstractionSwComponentType> for SwComponentType {
684 fn from(ecu_abstraction: EcuAbstractionSwComponentType) -> Self {
685 SwComponentType::EcuAbstraction(ecu_abstraction)
686 }
687}
688
689impl AbstractSwComponentType for SwComponentType {}
690
691impl SwComponentType {
692 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
694 match self {
695 SwComponentType::Composition(comp) => comp.remove(deep),
696 SwComponentType::Application(app) => app.remove(deep),
697 SwComponentType::ComplexDeviceDriver(cdd) => cdd.remove(deep),
698 SwComponentType::Service(service) => service.remove(deep),
699 SwComponentType::SensorActuator(sensor_actuator) => sensor_actuator.remove(deep),
700 SwComponentType::EcuAbstraction(ecu_abstraction) => ecu_abstraction.remove(deep),
701 }
702 }
703}
704
705#[derive(Debug, Clone, PartialEq, Eq, Hash)]
709pub struct SwComponentPrototype(Element);
710abstraction_element!(SwComponentPrototype, SwComponentPrototype);
711impl IdentifiableAbstractionElement for SwComponentPrototype {}
712
713impl SwComponentPrototype {
714 fn new(
715 name: &str,
716 components: &Element,
717 component_type: &SwComponentType,
718 ) -> Result<Self, AutosarAbstractionError> {
719 let component = components.create_named_sub_element(ElementName::SwComponentPrototype, name)?;
720 component
721 .create_sub_element(ElementName::TypeTref)?
722 .set_reference_target(component_type.element())?;
723
724 Ok(Self(component))
725 }
726
727 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
729 let ref_parents = get_reference_parents(self.element())?;
730
731 AbstractionElement::remove(self, deep)?;
732
733 for (named_parent, _parent) in ref_parents {
734 if named_parent.element_name() == ElementName::SwcToEcuMapping
735 && let Ok(swc_mapping) = SwcToEcuMapping::try_from(named_parent)
736 {
737 swc_mapping.remove(deep)?;
738 }
739 }
740
741 Ok(())
742 }
743
744 #[must_use]
746 pub fn component_type(&self) -> Option<SwComponentType> {
747 let component_elem = self
748 .element()
749 .get_sub_element(ElementName::TypeTref)?
750 .get_reference_target()
751 .ok()?;
752 SwComponentType::try_from(component_elem).ok()
753 }
754
755 pub fn parent_composition(&self) -> Result<CompositionSwComponentType, AutosarAbstractionError> {
757 let parent = self.element().named_parent()?.unwrap();
758 CompositionSwComponentType::try_from(parent)
759 }
760}
761
762#[derive(Debug, Clone, PartialEq, Eq, Hash)]
766pub struct RootSwCompositionPrototype(Element);
767abstraction_element!(RootSwCompositionPrototype, RootSwCompositionPrototype);
768impl IdentifiableAbstractionElement for RootSwCompositionPrototype {}
769
770impl RootSwCompositionPrototype {
771 pub(crate) fn new(
772 name: &str,
773 root_compositions: &Element,
774 composition_type: &CompositionSwComponentType,
775 ) -> Result<Self, AutosarAbstractionError> {
776 let root_composition =
777 root_compositions.create_named_sub_element(ElementName::RootSwCompositionPrototype, name)?;
778 root_composition
779 .create_sub_element(ElementName::SoftwareCompositionTref)?
780 .set_reference_target(composition_type.element())?;
781
782 Ok(Self(root_composition))
783 }
784
785 #[must_use]
787 pub fn composition(&self) -> Option<CompositionSwComponentType> {
788 let composition_elem = self
789 .element()
790 .get_sub_element(ElementName::SoftwareCompositionTref)?
791 .get_reference_target()
792 .ok()?;
793 CompositionSwComponentType::try_from(composition_elem).ok()
794 }
795}
796
797#[derive(Debug, Clone, PartialEq, Eq, Hash)]
801pub enum ComponentPrototype {
802 SwComponent(SwComponentPrototype),
804 RootComposition(RootSwCompositionPrototype),
806}
807
808impl AbstractionElement for ComponentPrototype {
809 fn element(&self) -> &Element {
810 match self {
811 ComponentPrototype::SwComponent(swcp) => swcp.element(),
812 ComponentPrototype::RootComposition(root) => root.element(),
813 }
814 }
815}
816
817impl TryFrom<Element> for ComponentPrototype {
818 type Error = AutosarAbstractionError;
819
820 fn try_from(element: Element) -> Result<Self, Self::Error> {
821 match element.element_name() {
822 ElementName::SwComponentPrototype => Ok(ComponentPrototype::SwComponent(SwComponentPrototype(element))),
823 ElementName::RootSwCompositionPrototype => {
824 Ok(ComponentPrototype::RootComposition(RootSwCompositionPrototype(element)))
825 }
826 _ => Err(AutosarAbstractionError::ConversionError {
827 element,
828 dest: "ComponentPrototype".to_string(),
829 }),
830 }
831 }
832}
833
834impl IdentifiableAbstractionElement for ComponentPrototype {}
835
836impl ComponentPrototype {
837 #[must_use]
838 pub fn component_type(&self) -> Option<SwComponentType> {
840 match self {
841 ComponentPrototype::SwComponent(swcp) => swcp.component_type(),
842 ComponentPrototype::RootComposition(rc) => rc.composition().map(std::convert::Into::into),
843 }
844 }
845
846 pub fn parent_composition(&self) -> Result<Option<CompositionSwComponentType>, AutosarAbstractionError> {
850 match self {
851 ComponentPrototype::SwComponent(swcp) => swcp.parent_composition().map(Some),
852 ComponentPrototype::RootComposition(_) => Ok(None),
853 }
854 }
855}
856
857#[cfg(test)]
860mod test {
861 use super::*;
862 use crate::{AutosarModelAbstraction, SystemCategory};
863 use autosar_data::AutosarVersion;
864
865 #[test]
866 fn software_compositions() {
867 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
868 let package = model.get_or_create_package("/package").unwrap();
869
870 let comp1 = CompositionSwComponentType::new("comp1", &package).unwrap();
871 let comp2 = CompositionSwComponentType::new("comp2", &package).unwrap();
872 let comp3 = CompositionSwComponentType::new("comp3", &package).unwrap();
873 let comp4 = CompositionSwComponentType::new("comp4", &package).unwrap();
874
875 comp1.create_component("comp2", &comp2.clone()).unwrap();
876 comp2.create_component("comp3", &comp3.clone()).unwrap();
877 comp3.create_component("comp4", &comp4.clone()).unwrap();
878
879 assert_eq!(comp1.instances().len(), 0);
880 assert_eq!(comp2.instances().len(), 1);
881 assert_eq!(comp3.instances().len(), 1);
882 assert_eq!(comp4.instances().len(), 1);
883
884 assert!(comp1.is_parent_of(&comp2));
885 assert!(comp1.is_parent_of(&comp3));
886 assert!(comp1.is_parent_of(&comp4));
887
888 assert!(!comp2.is_parent_of(&comp1));
889 assert!(comp2.is_parent_of(&comp3));
890 assert!(comp2.is_parent_of(&comp4));
891
892 assert!(!comp3.is_parent_of(&comp1));
893 assert!(!comp3.is_parent_of(&comp2));
894 assert!(comp3.is_parent_of(&comp4));
895
896 assert!(!comp4.is_parent_of(&comp1));
897 assert!(!comp4.is_parent_of(&comp2));
898 assert!(!comp4.is_parent_of(&comp3));
899 }
900
901 #[test]
902 fn root_composition() {
903 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
904 let package = model.get_or_create_package("/package").unwrap();
905
906 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
907 let comp = CompositionSwComponentType::new("comp", &package).unwrap();
908 let root_sw_component_prototype = system.set_root_sw_composition("root", &comp).unwrap();
909
910 assert_eq!(
911 ComponentPrototype::RootComposition(root_sw_component_prototype),
912 comp.instances()[0]
913 );
914 assert_eq!(comp.instances().len(), 1);
915 }
916
917 #[test]
918 fn components() {
919 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
920 let package = model.get_or_create_package("/package").unwrap();
921
922 let comp = CompositionSwComponentType::new("comp", &package).unwrap();
923 let app = ApplicationSwComponentType::new("app", &package).unwrap();
924 let cdd = ComplexDeviceDriverSwComponentType::new("cdd", &package).unwrap();
925 let service = ServiceSwComponentType::new("service", &package).unwrap();
926 let sensor_actuator = SensorActuatorSwComponentType::new("sensor_actuator", &package).unwrap();
927 let ecu_abstraction = EcuAbstractionSwComponentType::new("ecu_abstraction", &package).unwrap();
928
929 let container_comp = CompositionSwComponentType::new("container_comp", &package).unwrap();
930 let comp_prototype = container_comp.create_component("comp", &comp.clone()).unwrap();
931 let _app_prototype = container_comp.create_component("app", &app.clone()).unwrap();
932 let _cdd_prototype = container_comp.create_component("cdd", &cdd.clone()).unwrap();
933 let _service_prototype = container_comp.create_component("service", &service.clone()).unwrap();
934 let _sensor_actuator_prototype = container_comp
935 .create_component("sensor_actuator", &sensor_actuator.clone())
936 .unwrap();
937 let _ecu_abstraction_prototype = container_comp
938 .create_component("ecu_abstraction", &ecu_abstraction.clone())
939 .unwrap();
940
941 assert_eq!(container_comp.components().count(), 6);
942 let mut comp_prototype_iter = container_comp.components();
943 assert_eq!(
944 comp_prototype_iter.next().unwrap().component_type().unwrap(),
945 comp.clone().into()
946 );
947 assert_eq!(
948 comp_prototype_iter.next().unwrap().component_type().unwrap(),
949 app.into()
950 );
951 assert_eq!(
952 comp_prototype_iter.next().unwrap().component_type().unwrap(),
953 cdd.into()
954 );
955 assert_eq!(
956 comp_prototype_iter.next().unwrap().component_type().unwrap(),
957 service.into()
958 );
959 assert_eq!(
960 comp_prototype_iter.next().unwrap().component_type().unwrap(),
961 sensor_actuator.into()
962 );
963 assert_eq!(
964 comp_prototype_iter.next().unwrap().component_type().unwrap(),
965 ecu_abstraction.into()
966 );
967 assert!(comp_prototype_iter.next().is_none());
968
969 let component_prototype = ComponentPrototype::SwComponent(comp_prototype);
970 assert_eq!(component_prototype.component_type().unwrap(), comp.into());
971 }
972
973 #[test]
974 fn ports_and_connectors() {
975 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
976 let package = model.get_or_create_package("/package").unwrap();
977
978 let comp_parent_type = package.create_composition_sw_component_type("comp_parent").unwrap();
981 let comp_child_type = package.create_composition_sw_component_type("comp_child").unwrap();
982 let swc_type = package.create_application_sw_component_type("swc_type1").unwrap();
983
984 let comp_child_proto = comp_parent_type.create_component("comp2", &comp_child_type).unwrap();
985 let swc_proto = comp_parent_type.create_component("swc1", &swc_type).unwrap();
986
987 let port_interface_sr = package.create_sender_receiver_interface("sr").unwrap();
989 let port_interface_cs = package.create_client_server_interface("cs").unwrap();
990
991 let comp_parent_r_port = comp_parent_type.create_r_port("port_r", &port_interface_sr).unwrap();
996 let swc_r_port = swc_type.create_r_port("port_r", &port_interface_sr).unwrap();
997 let swc_p_port = swc_type.create_p_port("port_p", &port_interface_sr).unwrap();
998 let comp_child_r_port = comp_child_type.create_r_port("port_r", &port_interface_sr).unwrap();
999 let comp_child_p_port = comp_child_type.create_p_port("port_p", &port_interface_sr).unwrap();
1000
1001 comp_parent_type
1002 .create_delegation_connector("sr_delegation", &swc_r_port, &swc_proto, &comp_parent_r_port)
1003 .unwrap();
1004 comp_parent_type
1005 .create_assembly_connector(
1006 "sr_assembly",
1007 &swc_p_port,
1008 &swc_proto,
1009 &comp_child_r_port,
1010 &comp_child_proto,
1011 )
1012 .unwrap();
1013 comp_child_type
1014 .create_pass_through_connector("sr_passthrough", &comp_child_r_port, &comp_child_p_port)
1015 .unwrap();
1016
1017 let comp_parent_s_port = comp_parent_type.create_p_port("port_s", &port_interface_cs).unwrap();
1022 let swc_s_port = swc_type.create_p_port("port_s", &port_interface_cs).unwrap();
1023 let swc_c_port = swc_type.create_r_port("port_c", &port_interface_cs).unwrap();
1024 let comp_child_s_port = comp_child_type.create_p_port("port_s", &port_interface_cs).unwrap();
1025 let comp_child_c_port = comp_child_type.create_r_port("port_c", &port_interface_cs).unwrap();
1026
1027 comp_parent_type
1028 .create_delegation_connector("cs_delegation", &swc_s_port, &swc_proto, &comp_parent_s_port)
1029 .unwrap();
1030 comp_parent_type
1031 .create_assembly_connector(
1032 "cs_assembly",
1033 &swc_c_port,
1034 &swc_proto,
1035 &comp_child_s_port,
1036 &comp_child_proto,
1037 )
1038 .unwrap();
1039 comp_child_type
1040 .create_pass_through_connector("cs_passthrough", &comp_child_s_port, &comp_child_c_port)
1041 .unwrap();
1042
1043 let mut parent_connectors = comp_parent_type.connectors();
1045 assert_eq!(parent_connectors.next().unwrap().name().unwrap(), "sr_delegation");
1046 assert_eq!(parent_connectors.next().unwrap().name().unwrap(), "sr_assembly");
1047 assert_eq!(parent_connectors.next().unwrap().name().unwrap(), "cs_delegation");
1048 assert_eq!(parent_connectors.next().unwrap().name().unwrap(), "cs_assembly");
1049 assert!(parent_connectors.next().is_none());
1050
1051 let mut child_connectors = comp_child_type.connectors();
1052 assert_eq!(child_connectors.next().unwrap().name().unwrap(), "sr_passthrough");
1053 assert_eq!(child_connectors.next().unwrap().name().unwrap(), "cs_passthrough");
1054 assert!(child_connectors.next().is_none());
1055
1056 comp_parent_type.create_port_group("group").unwrap();
1058 }
1059
1060 #[test]
1061 fn remove_swc_type() {
1062 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1063 let package = model.get_or_create_package("/package").unwrap();
1064
1065 let comp_swc_type = CompositionSwComponentType::new("comp", &package).unwrap();
1066 let app_swc_type = ApplicationSwComponentType::new("app", &package).unwrap();
1067 let app_prototype = comp_swc_type.create_component("app", &app_swc_type.clone()).unwrap();
1068
1069 assert_eq!(comp_swc_type.components().count(), 1);
1070
1071 app_swc_type.remove(true).unwrap();
1072
1073 assert_eq!(comp_swc_type.components().count(), 0);
1074 assert!(app_prototype.element().path().is_err());
1075 }
1076}