1use crate::communication::{
2 CanCluster, CanFrame, CanTpConfig, Cluster, CommunicationDirection, ContainerIPdu, ContainerIPduHeaderType,
3 DcmIPdu, DiagPduType, DoIpTpConfig, EthernetCluster, EventGroupControlType, FlexrayArTpConfig, FlexrayCluster,
4 FlexrayClusterSettings, FlexrayFrame, FlexrayTpConfig, Frame, GeneralPurposeIPdu, GeneralPurposeIPduCategory,
5 GeneralPurposePdu, GeneralPurposePduCategory, ISignal, ISignalGroup, ISignalIPdu, ISignalIPduGroup, LinCluster,
6 LinEventTriggeredFrame, LinSporadicFrame, LinUnconditionalFrame, MultiplexedIPdu, NPdu, NmConfig, NmPdu, Pdu,
7 RxAcceptContainedIPdu, SecureCommunicationProps, SecuredIPdu, ServiceInstanceCollectionSet, SoAdRoutingGroup,
8 SocketConnectionIpduIdentifierSet, SomeipTpConfig, SystemSignal, SystemSignalGroup, UserDefinedPdu,
9};
10use crate::datatype::SwBaseType;
11use crate::software_component::{CompositionSwComponentType, RootSwCompositionPrototype};
12use crate::{
13 AbstractionElement, ArPackage, AutosarAbstractionError, EcuInstance, IdentifiableAbstractionElement,
14 abstraction_element,
15};
16use autosar_data::{AutosarModel, Element, ElementName, WeakElement};
17
18mod mapping;
19
20pub use mapping::*;
21
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
27pub struct System(Element);
28abstraction_element!(System, System);
29impl IdentifiableAbstractionElement for System {}
30
31impl System {
32 #[must_use]
34 pub(crate) fn find(model: &AutosarModel) -> Option<Self> {
35 let elem = model
36 .identifiable_elements()
37 .filter_map(|(_, weak)| weak.upgrade())
38 .find(|elem| elem.element_name() == ElementName::System)?;
39 Some(Self(elem))
40 }
41
42 pub(crate) fn new(
65 name: &str,
66 package: &ArPackage,
67 category: SystemCategory,
68 ) -> Result<Self, AutosarAbstractionError> {
69 let pkg_elem_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
70
71 let system_elem = pkg_elem_elements.create_named_sub_element(ElementName::System, name)?;
72 let system = System(system_elem);
73 system.set_category(category)?;
74
75 Ok(system)
76 }
77
78 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
80 for mapping in self
82 .0
83 .get_sub_element(ElementName::Mappings)
84 .into_iter()
85 .flat_map(|mappings| mappings.sub_elements())
86 .filter_map(|mapping| SystemMapping::try_from(mapping).ok())
87 {
88 mapping.remove(deep)?;
89 }
90
91 if let Some(root_sw_comp) = self.root_sw_composition() {
92 root_sw_comp.remove(deep)?;
93 }
94
95 if deep {
98 for cluster in self.clusters() {
99 cluster.remove(deep)?;
100 }
101
102 for frame in self.frames() {
103 frame.remove(deep)?;
104 }
105
106 for pdu in self.pdus() {
107 pdu.remove(deep)?;
108 }
109
110 for isignal_ipdu_group in self.isignal_ipdu_groups() {
111 isignal_ipdu_group.remove(deep)?;
112 }
113
114 for isignal in self.isignals() {
115 isignal.remove(deep)?;
116 }
117
118 for isignal_group in self.isignal_groups() {
119 isignal_group.remove(deep)?;
120 }
121
122 if let Some(nm_config) = self.nm_config() {
123 nm_config.remove(deep)?;
124 }
125
126 for ecu_instance in self.ecu_instances() {
127 ecu_instance.remove(deep)?;
128 }
129 }
130
131 AbstractionElement::remove(self, deep)
132 }
133
134 pub fn set_category(&self, category: SystemCategory) -> Result<(), AutosarAbstractionError> {
136 self.0
137 .get_or_create_sub_element(ElementName::Category)?
138 .set_character_data(category.to_string())?;
139 Ok(())
140 }
141
142 #[must_use]
144 pub fn category(&self) -> Option<SystemCategory> {
145 self.0
146 .get_sub_element(ElementName::Category)?
147 .character_data()?
148 .string_value()?
149 .parse()
150 .ok()
151 }
152
153 pub fn set_pnc_vector_length(&self, length: Option<u32>) -> Result<(), AutosarAbstractionError> {
155 if let Some(length) = length {
156 self.0
157 .get_or_create_sub_element(ElementName::PncVectorLength)?
158 .set_character_data(length as u64)?;
159 } else {
160 let _ = self.0.remove_sub_element_kind(ElementName::PncVectorLength);
161 }
162 Ok(())
163 }
164
165 #[must_use]
167 pub fn pnc_vector_length(&self) -> Option<u32> {
168 self.0
169 .get_sub_element(ElementName::PncVectorLength)?
170 .character_data()?
171 .parse_integer()
172 }
173
174 pub fn set_pnc_vector_offset(&self, offset: Option<u32>) -> Result<(), AutosarAbstractionError> {
176 if let Some(offset) = offset {
177 self.0
178 .get_or_create_sub_element(ElementName::PncVectorOffset)?
179 .set_character_data(offset as u64)?;
180 } else {
181 let _ = self.0.remove_sub_element_kind(ElementName::PncVectorOffset);
182 }
183 Ok(())
184 }
185
186 #[must_use]
188 pub fn pnc_vector_offset(&self) -> Option<u32> {
189 self.0
190 .get_sub_element(ElementName::PncVectorOffset)?
191 .character_data()?
192 .parse_integer()
193 }
194
195 pub fn create_ecu_instance(&self, name: &str, package: &ArPackage) -> Result<EcuInstance, AutosarAbstractionError> {
215 let ecu_instance = EcuInstance::new(name, package)?;
216 self.create_fibex_element_ref_unchecked(ecu_instance.element())?;
217
218 Ok(ecu_instance)
219 }
220
221 pub fn ecu_instances(&self) -> impl Iterator<Item = EcuInstance> + Send + use<> {
241 self.0
242 .get_sub_element(ElementName::FibexElements)
243 .into_iter()
244 .flat_map(|fibexelems| fibexelems.sub_elements())
245 .filter_map(|ferc| {
246 ferc.get_sub_element(ElementName::FibexElementRef)
247 .and_then(|fer| fer.get_reference_target().ok())
248 .and_then(|elem| EcuInstance::try_from(elem).ok())
249 })
250 }
251
252 pub fn create_can_cluster(
276 &self,
277 cluster_name: &str,
278 package: &ArPackage,
279 can_baudrate: Option<u32>,
280 ) -> Result<CanCluster, AutosarAbstractionError> {
281 let cluster = CanCluster::new(cluster_name, package, can_baudrate)?;
282 self.create_fibex_element_ref_unchecked(cluster.element())?;
283
284 Ok(cluster)
285 }
286
287 pub fn create_ethernet_cluster(
312 &self,
313 cluster_name: &str,
314 package: &ArPackage,
315 ) -> Result<EthernetCluster, AutosarAbstractionError> {
316 let cluster = EthernetCluster::new(cluster_name, package)?;
317 self.create_fibex_element_ref_unchecked(cluster.element())?;
318
319 Ok(cluster)
320 }
321
322 pub fn create_flexray_cluster(
348 &self,
349 cluster_name: &str,
350 package: &ArPackage,
351 settings: &FlexrayClusterSettings,
352 ) -> Result<FlexrayCluster, AutosarAbstractionError> {
353 let cluster = FlexrayCluster::new(cluster_name, package, settings)?;
354 self.create_fibex_element_ref_unchecked(cluster.element())?;
355
356 Ok(cluster)
357 }
358
359 pub fn create_lin_cluster(
383 &self,
384 cluster_name: &str,
385 package: &ArPackage,
386 ) -> Result<LinCluster, AutosarAbstractionError> {
387 let cluster = LinCluster::new(cluster_name, package)?;
388 self.create_fibex_element_ref_unchecked(cluster.element())?;
389
390 Ok(cluster)
391 }
392
393 pub fn clusters(&self) -> impl Iterator<Item = Cluster> + Send + use<> {
414 self.0
415 .get_sub_element(ElementName::FibexElements)
416 .into_iter()
417 .flat_map(|fibexelems| fibexelems.sub_elements())
418 .filter_map(|ferc| {
419 ferc.get_sub_element(ElementName::FibexElementRef)
420 .and_then(|fer| fer.get_reference_target().ok())
421 .and_then(|elem| Cluster::try_from(elem).ok())
422 })
423 }
424
425 pub fn create_can_frame(
429 &self,
430 name: &str,
431 package: &ArPackage,
432 byte_length: u64,
433 ) -> Result<CanFrame, AutosarAbstractionError> {
434 let can_frame = CanFrame::new(name, package, byte_length)?;
435 self.create_fibex_element_ref_unchecked(can_frame.element())?;
436
437 Ok(can_frame)
438 }
439
440 pub fn create_flexray_frame(
444 &self,
445 name: &str,
446 package: &ArPackage,
447 byte_length: u64,
448 ) -> Result<FlexrayFrame, AutosarAbstractionError> {
449 let flexray_frame = FlexrayFrame::new(name, package, byte_length)?;
450 self.create_fibex_element_ref_unchecked(flexray_frame.element())?;
451
452 Ok(flexray_frame)
453 }
454
455 pub fn create_lin_event_triggered_frame(
459 &self,
460 name: &str,
461 package: &ArPackage,
462 byte_length: u64,
463 ) -> Result<LinEventTriggeredFrame, AutosarAbstractionError> {
464 let lin_event_triggered_frame = LinEventTriggeredFrame::new(name, package, byte_length)?;
465 self.create_fibex_element_ref_unchecked(lin_event_triggered_frame.element())?;
466
467 Ok(lin_event_triggered_frame)
468 }
469
470 pub fn create_lin_sporadic_frame(
474 &self,
475 name: &str,
476 package: &ArPackage,
477 byte_length: u64,
478 ) -> Result<LinSporadicFrame, AutosarAbstractionError> {
479 let lin_sporadic_frame = LinSporadicFrame::new(name, package, byte_length)?;
480 self.create_fibex_element_ref_unchecked(lin_sporadic_frame.element())?;
481
482 Ok(lin_sporadic_frame)
483 }
484
485 pub fn create_lin_unconditional_frame(
489 &self,
490 name: &str,
491 package: &ArPackage,
492 byte_length: u64,
493 ) -> Result<LinUnconditionalFrame, AutosarAbstractionError> {
494 let lin_unconditional_frame = LinUnconditionalFrame::new(name, package, byte_length)?;
495 self.create_fibex_element_ref_unchecked(lin_unconditional_frame.element())?;
496
497 Ok(lin_unconditional_frame)
498 }
499
500 pub fn frames(&self) -> impl Iterator<Item = Frame> + Send + use<> {
504 self.0
505 .get_sub_element(ElementName::FibexElements)
506 .into_iter()
507 .flat_map(|fibexelems| fibexelems.sub_elements())
508 .filter_map(|ferc| {
509 ferc.get_sub_element(ElementName::FibexElementRef)
510 .and_then(|fer| fer.get_reference_target().ok())
511 .and_then(|elem| Frame::try_from(elem).ok())
512 })
513 }
514
515 pub fn create_isignal(
539 &self,
540 name: &str,
541 package: &ArPackage,
542 bit_length: u64,
543 syssignal: &SystemSignal,
544 datatype: Option<&SwBaseType>,
545 ) -> Result<ISignal, AutosarAbstractionError> {
546 let i_signal = ISignal::new(name, package, bit_length, syssignal, datatype)?;
547
548 self.create_fibex_element_ref_unchecked(i_signal.element())?;
549
550 Ok(i_signal)
551 }
552
553 pub fn isignals(&self) -> impl Iterator<Item = ISignal> + Send + use<> {
557 self.0
558 .get_sub_element(ElementName::FibexElements)
559 .into_iter()
560 .flat_map(|fibexelems| fibexelems.sub_elements())
561 .filter_map(|ferc| {
562 ferc.get_sub_element(ElementName::FibexElementRef)
563 .and_then(|fer| fer.get_reference_target().ok())
564 .and_then(|elem| ISignal::try_from(elem).ok())
565 })
566 }
567
568 pub fn create_isignal_group(
595 &self,
596 name: &str,
597 package: &ArPackage,
598 system_signal_group: &SystemSignalGroup,
599 ) -> Result<ISignalGroup, AutosarAbstractionError> {
600 let i_signal_group = ISignalGroup::new(name, package, system_signal_group)?;
601
602 self.create_fibex_element_ref_unchecked(i_signal_group.element())?;
603
604 Ok(i_signal_group)
605 }
606
607 pub fn isignal_groups(&self) -> impl Iterator<Item = ISignalGroup> + Send + use<> {
611 self.0
612 .get_sub_element(ElementName::FibexElements)
613 .into_iter()
614 .flat_map(|fibexelems| fibexelems.sub_elements())
615 .filter_map(|ferc| {
616 ferc.get_sub_element(ElementName::FibexElementRef)
617 .and_then(|fer| fer.get_reference_target().ok())
618 .and_then(|elem| ISignalGroup::try_from(elem).ok())
619 })
620 }
621
622 pub fn create_isignal_ipdu(
643 &self,
644 name: &str,
645 package: &ArPackage,
646 length: u32,
647 ) -> Result<ISignalIPdu, AutosarAbstractionError> {
648 let pdu = ISignalIPdu::new(name, package, length)?;
649 self.create_fibex_element_ref_unchecked(pdu.element())?;
650
651 Ok(pdu)
652 }
653
654 pub fn create_nm_pdu(
675 &self,
676 name: &str,
677 package: &ArPackage,
678 length: u32,
679 ) -> Result<NmPdu, AutosarAbstractionError> {
680 let pdu = NmPdu::new(name, package, length)?;
681 self.create_fibex_element_ref_unchecked(pdu.element())?;
682
683 Ok(pdu)
684 }
685
686 pub fn create_n_pdu(&self, name: &str, package: &ArPackage, length: u32) -> Result<NPdu, AutosarAbstractionError> {
707 let pdu = NPdu::new(name, package, length)?;
708 self.create_fibex_element_ref_unchecked(pdu.element())?;
709
710 Ok(pdu)
711 }
712
713 pub fn create_dcm_ipdu(
734 &self,
735 name: &str,
736 package: &ArPackage,
737 length: u32,
738 diag_pdu_type: DiagPduType,
739 ) -> Result<DcmIPdu, AutosarAbstractionError> {
740 let pdu = DcmIPdu::new(name, package, length, diag_pdu_type)?;
741 self.create_fibex_element_ref_unchecked(pdu.element())?;
742
743 Ok(pdu)
744 }
745
746 pub fn create_general_purpose_pdu(
767 &self,
768 name: &str,
769 package: &ArPackage,
770 length: u32,
771 category: GeneralPurposePduCategory,
772 ) -> Result<GeneralPurposePdu, AutosarAbstractionError> {
773 let pdu = GeneralPurposePdu::new(name, package, length, category)?;
774 self.create_fibex_element_ref_unchecked(pdu.element())?;
775
776 Ok(pdu)
777 }
778
779 pub fn create_general_purpose_ipdu(
800 &self,
801 name: &str,
802 package: &ArPackage,
803 length: u32,
804 category: GeneralPurposeIPduCategory,
805 ) -> Result<GeneralPurposeIPdu, AutosarAbstractionError> {
806 let pdu = GeneralPurposeIPdu::new(name, package, length, category)?;
807 self.create_fibex_element_ref_unchecked(pdu.element())?;
808
809 Ok(pdu)
810 }
811
812 pub fn create_container_ipdu(
833 &self,
834 name: &str,
835 package: &ArPackage,
836 length: u32,
837 header_type: ContainerIPduHeaderType,
838 rx_accept: RxAcceptContainedIPdu,
839 ) -> Result<ContainerIPdu, AutosarAbstractionError> {
840 let pdu = ContainerIPdu::new(name, package, length, header_type, rx_accept)?;
841 self.create_fibex_element_ref_unchecked(pdu.element())?;
842
843 Ok(pdu)
844 }
845
846 pub fn create_secured_ipdu(
868 &self,
869 name: &str,
870 package: &ArPackage,
871 length: u32,
872 secure_props: &SecureCommunicationProps,
873 ) -> Result<SecuredIPdu, AutosarAbstractionError> {
874 let pdu = SecuredIPdu::new(name, package, length, secure_props)?;
875 self.create_fibex_element_ref_unchecked(pdu.element())?;
876
877 Ok(pdu)
878 }
879
880 pub fn create_multiplexed_ipdu(
901 &self,
902 name: &str,
903 package: &ArPackage,
904 length: u32,
905 ) -> Result<MultiplexedIPdu, AutosarAbstractionError> {
906 let pdu = MultiplexedIPdu::new(name, package, length)?;
907 self.create_fibex_element_ref_unchecked(pdu.element())?;
908
909 Ok(pdu)
910 }
911
912 pub fn create_user_defined_pdu(
933 &self,
934 name: &str,
935 package: &ArPackage,
936 length: u32,
937 ) -> Result<UserDefinedPdu, AutosarAbstractionError> {
938 let pdu = UserDefinedPdu::new(name, package, length)?;
939 self.create_fibex_element_ref_unchecked(pdu.element())?;
940
941 Ok(pdu)
942 }
943
944 pub fn pdus(&self) -> impl Iterator<Item = Pdu> + Send + use<> {
948 self.0
949 .get_sub_element(ElementName::FibexElements)
950 .into_iter()
951 .flat_map(|fibexelems| fibexelems.sub_elements())
952 .filter_map(|ferc| {
953 ferc.get_sub_element(ElementName::FibexElementRef)
954 .and_then(|fer| fer.get_reference_target().ok())
955 .and_then(|elem| Pdu::try_from(elem).ok())
956 })
957 }
958
959 pub fn create_isignal_ipdu_group(
979 &self,
980 name: &str,
981 package: &ArPackage,
982 communication_direction: CommunicationDirection,
983 ) -> Result<ISignalIPduGroup, AutosarAbstractionError> {
984 let ipdu_group = ISignalIPduGroup::new(name, package, communication_direction)?;
985 self.create_fibex_element_ref_unchecked(ipdu_group.element())?;
986
987 Ok(ipdu_group)
988 }
989
990 pub fn isignal_ipdu_groups(&self) -> impl Iterator<Item = ISignalIPduGroup> + Send + use<> {
994 self.0
995 .get_sub_element(ElementName::FibexElements)
996 .into_iter()
997 .flat_map(|fibexelems| fibexelems.sub_elements())
998 .filter_map(|ferc| {
999 ferc.get_sub_element(ElementName::FibexElementRef)
1000 .and_then(|fer| fer.get_reference_target().ok())
1001 .and_then(|elem| ISignalIPduGroup::try_from(elem).ok())
1002 })
1003 }
1004
1005 pub fn create_socket_connection_ipdu_identifier_set(
1023 &self,
1024 name: &str,
1025 package: &ArPackage,
1026 ) -> Result<SocketConnectionIpduIdentifierSet, AutosarAbstractionError> {
1027 let set = SocketConnectionIpduIdentifierSet::new(name, package)?;
1028 self.create_fibex_element_ref_unchecked(set.element())?;
1029
1030 Ok(set)
1031 }
1032
1033 pub fn create_so_ad_routing_group(
1039 &self,
1040 name: &str,
1041 package: &ArPackage,
1042 control_type: Option<EventGroupControlType>,
1043 ) -> Result<SoAdRoutingGroup, AutosarAbstractionError> {
1044 let group = SoAdRoutingGroup::new(name, package, control_type)?;
1045 self.create_fibex_element_ref_unchecked(group.element())?;
1046
1047 Ok(group)
1048 }
1049
1050 pub fn create_service_instance_collection_set(
1054 &self,
1055 name: &str,
1056 package: &ArPackage,
1057 ) -> Result<ServiceInstanceCollectionSet, AutosarAbstractionError> {
1058 let set = ServiceInstanceCollectionSet::new(name, package)?;
1059 self.create_fibex_element_ref_unchecked(set.element())?;
1060
1061 Ok(set)
1062 }
1063
1064 pub fn create_someip_tp_config<T: Into<Cluster> + Clone>(
1068 &self,
1069 name: &str,
1070 package: &ArPackage,
1071 cluster: &T,
1072 ) -> Result<SomeipTpConfig, AutosarAbstractionError> {
1073 let config = SomeipTpConfig::new(name, package, &cluster.clone().into())?;
1074 self.create_fibex_element_ref_unchecked(config.element())?;
1075
1076 Ok(config)
1077 }
1078
1079 pub fn create_can_tp_config(
1083 &self,
1084 name: &str,
1085 package: &ArPackage,
1086 can_cluster: &CanCluster,
1087 ) -> Result<CanTpConfig, AutosarAbstractionError> {
1088 let config = CanTpConfig::new(name, package, can_cluster)?;
1089 self.create_fibex_element_ref_unchecked(config.element())?;
1090
1091 Ok(config)
1092 }
1093
1094 pub fn create_doip_tp_config(
1098 &self,
1099 name: &str,
1100 package: &ArPackage,
1101 eth_cluster: &EthernetCluster,
1102 ) -> Result<DoIpTpConfig, AutosarAbstractionError> {
1103 let config = DoIpTpConfig::new(name, package, eth_cluster)?;
1104 self.create_fibex_element_ref_unchecked(config.element())?;
1105
1106 Ok(config)
1107 }
1108
1109 pub fn create_flexray_tp_config(
1114 &self,
1115 name: &str,
1116 package: &ArPackage,
1117 flexray_cluster: &FlexrayCluster,
1118 ) -> Result<FlexrayTpConfig, AutosarAbstractionError> {
1119 let config = FlexrayTpConfig::new(name, package, flexray_cluster)?;
1120 self.create_fibex_element_ref_unchecked(config.element())?;
1121
1122 Ok(config)
1123 }
1124
1125 pub fn create_flexray_ar_tp_config(
1130 &self,
1131 name: &str,
1132 package: &ArPackage,
1133 flexray_cluster: &FlexrayCluster,
1134 ) -> Result<FlexrayArTpConfig, AutosarAbstractionError> {
1135 let config = FlexrayArTpConfig::new(name, package, flexray_cluster)?;
1136 self.create_fibex_element_ref_unchecked(config.element())?;
1137
1138 Ok(config)
1139 }
1140
1141 pub fn create_nm_config(&self, name: &str, package: &ArPackage) -> Result<NmConfig, AutosarAbstractionError> {
1146 let config = NmConfig::new(name, package)?;
1147 self.create_fibex_element_ref_unchecked(config.element())?;
1148
1149 Ok(config)
1150 }
1151
1152 #[must_use]
1156 pub fn nm_config(&self) -> Option<NmConfig> {
1157 self.0
1158 .get_sub_element(ElementName::FibexElements)
1159 .into_iter()
1160 .flat_map(|fibexelems| fibexelems.sub_elements())
1161 .find_map(|ferc| {
1162 ferc.get_sub_element(ElementName::FibexElementRef)
1163 .and_then(|fer| fer.get_reference_target().ok())
1164 .and_then(|elem| NmConfig::try_from(elem).ok())
1165 })
1166 }
1167
1168 pub fn create_fibex_element_ref(&self, elem: &Element) -> Result<(), AutosarAbstractionError> {
1192 let model = elem.model()?;
1193 let refs = model.get_references_to(&elem.path()?);
1194 for reference in refs.iter().filter_map(WeakElement::upgrade) {
1195 if reference.element_name() == ElementName::FibexElementRef {
1196 return Ok(());
1198 }
1199 }
1200 self.create_fibex_element_ref_unchecked(elem)
1201 }
1202
1203 fn create_fibex_element_ref_unchecked(&self, elem: &Element) -> Result<(), AutosarAbstractionError> {
1204 let fibex_elements = self.0.get_or_create_sub_element(ElementName::FibexElements)?;
1205 let fibex_element_ref = fibex_elements
1206 .create_sub_element(ElementName::FibexElementRefConditional)?
1207 .create_sub_element(ElementName::FibexElementRef)?;
1208 fibex_element_ref.set_reference_target(elem)?;
1209 Ok(())
1210 }
1211
1212 pub fn set_root_sw_composition(
1217 &self,
1218 name: &str,
1219 composition_type: &CompositionSwComponentType,
1220 ) -> Result<RootSwCompositionPrototype, AutosarAbstractionError> {
1221 let root_compositions = self
1222 .0
1223 .get_or_create_sub_element(ElementName::RootSoftwareCompositions)?;
1224
1225 if let Some(existing_composition) = root_compositions.get_sub_element(ElementName::RootSwCompositionPrototype) {
1226 root_compositions.remove_sub_element(existing_composition)?;
1227 }
1228 RootSwCompositionPrototype::new(name, &root_compositions, composition_type)
1229 }
1230
1231 #[must_use]
1233 pub fn root_sw_composition(&self) -> Option<RootSwCompositionPrototype> {
1234 let root_compositions = self.element().get_sub_element(ElementName::RootSoftwareCompositions)?;
1235 let root_composition = root_compositions.get_sub_element(ElementName::RootSwCompositionPrototype)?;
1236 RootSwCompositionPrototype::try_from(root_composition).ok()
1237 }
1238
1239 pub fn get_or_create_mapping(&self, name: &str) -> Result<SystemMapping, AutosarAbstractionError> {
1244 if let Some(mapping) = self.0.get_sub_element(ElementName::Mappings)
1245 && let Some(mapping) = mapping.get_sub_element(ElementName::SystemMapping)
1246 {
1247 return SystemMapping::try_from(mapping);
1248 }
1249 SystemMapping::new(name, self)
1250 }
1251}
1252
1253#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1257pub enum SystemCategory {
1258 SystemConstraints,
1260 SystemDescription,
1262 SystemExtract,
1264 EcuExtract,
1266 AbstractSystemDescription,
1268 EcuSystemDescription,
1270 SwClusterSystemDescription,
1272 RptSystem,
1274}
1275
1276impl std::fmt::Display for SystemCategory {
1277 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1278 match self {
1279 SystemCategory::SystemConstraints => f.write_str("SYSTEM_CONSTRAINTS"),
1280 SystemCategory::SystemDescription => f.write_str("SYSTEM_DESCRIPTION"),
1281 SystemCategory::SystemExtract => f.write_str("SYSTEM_EXTRACT"),
1282 SystemCategory::EcuExtract => f.write_str("ECU_EXTRACT"),
1283 SystemCategory::AbstractSystemDescription => f.write_str("ABSTRACT_SYSTEM_DESCRIPTION"),
1284 SystemCategory::EcuSystemDescription => f.write_str("ECU_SYSTEM_DESCRIPTION"),
1285 SystemCategory::SwClusterSystemDescription => f.write_str("SW_CLUSTER_SYSTEM_DESCRIPTION"),
1286 SystemCategory::RptSystem => f.write_str("RPT_SYSTEM"),
1287 }
1288 }
1289}
1290
1291impl std::str::FromStr for SystemCategory {
1292 type Err = AutosarAbstractionError;
1293
1294 fn from_str(s: &str) -> Result<Self, Self::Err> {
1295 match s {
1296 "SYSTEM_CONSTRAINTS" => Ok(SystemCategory::SystemConstraints),
1297 "SYSTEM_DESCRIPTION" => Ok(SystemCategory::SystemDescription),
1298 "SYSTEM_EXTRACT" => Ok(SystemCategory::SystemExtract),
1299 "ECU_EXTRACT" => Ok(SystemCategory::EcuExtract),
1300 "ABSTRACT_SYSTEM_DESCRIPTION" => Ok(SystemCategory::AbstractSystemDescription),
1301 "ECU_SYSTEM_DESCRIPTION" => Ok(SystemCategory::EcuSystemDescription),
1302 "SW_CLUSTER_SYSTEM_DESCRIPTION" => Ok(SystemCategory::SwClusterSystemDescription),
1303 "RPT_SYSTEM" => Ok(SystemCategory::RptSystem),
1304 _ => Err(AutosarAbstractionError::InvalidParameter(s.to_string())),
1305 }
1306 }
1307}
1308
1309pub(crate) fn is_used_system_element(element: &Element) -> bool {
1313 let Ok(model) = element.model() else {
1314 return false;
1316 };
1317 let Ok(path) = element.path() else {
1318 return false;
1321 };
1322 let references = model.get_references_to(&path);
1323
1324 if let [weak_elem] = references.as_slice()
1326 && weak_elem
1327 .upgrade()
1328 .is_none_or(|elem| elem.element_name() == ElementName::FibexElementRef)
1329 {
1330 false
1331 } else {
1332 !references.is_empty()
1333 }
1334}
1335
1336#[cfg(test)]
1339mod test {
1340 use crate::{
1341 AbstractionElement, AutosarModelAbstraction, IdentifiableAbstractionElement, System,
1342 communication::{
1343 ContainerIPduHeaderType, DiagPduType, FlexrayClusterSettings, GeneralPurposeIPduCategory,
1344 GeneralPurposePduCategory, RxAcceptContainedIPdu, SecureCommunicationProps,
1345 },
1346 software_component::CompositionSwComponentType,
1347 system::SystemCategory,
1348 };
1349 use autosar_data::{AutosarVersion, ElementName};
1350
1351 #[test]
1352 fn system() {
1353 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1354
1355 let result = model.find_system();
1357 assert!(result.is_none());
1358
1359 let package = model.get_or_create_package("/SYSTEM").unwrap();
1361 let system = package.create_system("System", SystemCategory::SystemExtract).unwrap();
1362
1363 let system_2 = model.find_system().unwrap();
1365 assert_eq!(system, system_2);
1366
1367 assert_eq!(system.name().unwrap(), "System");
1369 system.set_name("NewName").unwrap();
1370 assert_eq!(system.name().unwrap(), "NewName");
1371
1372 assert_eq!(system.category().unwrap(), SystemCategory::SystemExtract);
1374 system.set_category(SystemCategory::EcuExtract).unwrap();
1375 assert_eq!(system.category().unwrap(), SystemCategory::EcuExtract);
1376
1377 assert!(system.pnc_vector_length().is_none());
1379 system.set_pnc_vector_length(Some(42)).unwrap();
1380 assert_eq!(system.pnc_vector_length().unwrap(), 42);
1381 system.set_pnc_vector_length(None).unwrap();
1382 assert!(system.pnc_vector_length().is_none());
1383
1384 assert!(system.pnc_vector_offset().is_none());
1386 system.set_pnc_vector_offset(Some(42)).unwrap();
1387 assert_eq!(system.pnc_vector_offset().unwrap(), 42);
1388 system.set_pnc_vector_offset(None).unwrap();
1389 assert!(system.pnc_vector_offset().is_none());
1390 }
1391
1392 #[test]
1393 fn system_category() {
1394 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1395 let package = model.get_or_create_package("/SYSTEM").unwrap();
1396 System::new("System", &package, SystemCategory::AbstractSystemDescription).unwrap();
1397
1398 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1399 let package = model.get_or_create_package("/SYSTEM").unwrap();
1400 System::new("System", &package, SystemCategory::EcuExtract).unwrap();
1401
1402 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1403 let package = model.get_or_create_package("/SYSTEM").unwrap();
1404 System::new("System", &package, SystemCategory::EcuSystemDescription).unwrap();
1405
1406 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1407 let package = model.get_or_create_package("/SYSTEM").unwrap();
1408 System::new("System", &package, SystemCategory::RptSystem).unwrap();
1409
1410 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1411 let package = model.get_or_create_package("/SYSTEM").unwrap();
1412 System::new("System", &package, SystemCategory::SwClusterSystemDescription).unwrap();
1413
1414 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1415 let package = model.get_or_create_package("/SYSTEM").unwrap();
1416 System::new("System", &package, SystemCategory::SystemConstraints).unwrap();
1417
1418 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1419 let package = model.get_or_create_package("/SYSTEM").unwrap();
1420 System::new("System", &package, SystemCategory::SystemDescription).unwrap();
1421
1422 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1423 let package = model.get_or_create_package("/SYSTEM").unwrap();
1424 System::new("System", &package, SystemCategory::SystemExtract).unwrap();
1425 }
1426
1427 #[test]
1428 fn fibex_ref() {
1429 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1430 let package = model.get_or_create_package("/SYSTEM").unwrap();
1431 let system = package
1432 .create_system("System", SystemCategory::SystemDescription)
1433 .unwrap();
1434
1435 let el_elements = package
1436 .element()
1437 .get_or_create_sub_element(ElementName::Elements)
1438 .unwrap();
1439 let el_ecuinst = el_elements
1440 .create_named_sub_element(ElementName::EcuInstance, "Ecu")
1441 .unwrap();
1442
1443 let el_fibex_elements = system
1444 .element()
1445 .get_or_create_sub_element(ElementName::FibexElements)
1446 .unwrap();
1447 assert_eq!(el_fibex_elements.sub_elements().count(), 0);
1448
1449 system.create_fibex_element_ref(&el_ecuinst).unwrap();
1451 assert_eq!(el_fibex_elements.sub_elements().count(), 1);
1452 system.create_fibex_element_ref(&el_ecuinst).unwrap();
1454 assert_eq!(el_fibex_elements.sub_elements().count(), 1);
1455 }
1456
1457 #[test]
1458 fn ecu_instance_iterator() {
1459 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1460 let package_1 = model.get_or_create_package("/SYSTEM").unwrap();
1461 let system = package_1
1462 .create_system("System", SystemCategory::SystemExtract)
1463 .unwrap();
1464 let package_2 = model.get_or_create_package("/ECU").unwrap();
1465 system.create_ecu_instance("Ecu_1", &package_2).unwrap();
1466 system.create_ecu_instance("Ecu_2", &package_2).unwrap();
1467 system.create_ecu_instance("Ecu_3", &package_2).unwrap();
1468
1469 let mut iter = system.ecu_instances();
1470 let item = iter.next().unwrap();
1471 assert_eq!(item.name().unwrap(), "Ecu_1");
1472 assert_eq!(model.get_element_by_path("/ECU/Ecu_1").unwrap(), *item.element());
1473 let item = iter.next().unwrap();
1474 assert_eq!(item.name().unwrap(), "Ecu_2");
1475 assert_eq!(model.get_element_by_path("/ECU/Ecu_2").unwrap(), *item.element());
1476 let item = iter.next().unwrap();
1477 assert_eq!(item.name().unwrap(), "Ecu_3");
1478 assert_eq!(model.get_element_by_path("/ECU/Ecu_3").unwrap(), *item.element());
1479
1480 assert!(iter.next().is_none());
1481 assert!(iter.next().is_none());
1483 }
1484
1485 #[test]
1486 fn cluster_iterator() {
1487 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1488 let package_1 = model.get_or_create_package("/SYSTEM").unwrap();
1489 let system = package_1
1490 .create_system("System", SystemCategory::SystemExtract)
1491 .unwrap();
1492 let package_2 = model.get_or_create_package("/Clusters").unwrap();
1493
1494 system.create_can_cluster("CanCluster", &package_2, None).unwrap();
1495
1496 let settings = FlexrayClusterSettings::new();
1497 system
1498 .create_flexray_cluster("FlexrayCluster", &package_2, &settings)
1499 .unwrap();
1500
1501 system.create_ethernet_cluster("EthernetCluster", &package_2).unwrap();
1502 system.create_lin_cluster("LinCluster", &package_2).unwrap();
1503
1504 let package_3 = model.get_or_create_package("/ECU").unwrap();
1506 system.create_ecu_instance("Ecu_1", &package_3).unwrap();
1507
1508 assert_eq!(system.clusters().count(), 4);
1509 }
1510
1511 #[test]
1512 fn frames_iterator() {
1513 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1514 let package_1 = model.get_or_create_package("/SYSTEM").unwrap();
1515 let system = package_1
1516 .create_system("System", SystemCategory::SystemExtract)
1517 .unwrap();
1518 let package_2 = model.get_or_create_package("/Frames").unwrap();
1519
1520 system.create_can_frame("CanFrame", &package_2, 8).unwrap();
1521 system.create_flexray_frame("FlexrayFrame", &package_2, 8).unwrap();
1522 system
1523 .create_lin_event_triggered_frame("LinEventTriggeredFrame", &package_2, 8)
1524 .unwrap();
1525 system
1526 .create_lin_unconditional_frame("LinUnconditionalFrame", &package_2, 8)
1527 .unwrap();
1528 system
1529 .create_lin_sporadic_frame("LinSporadicFrame", &package_2, 8)
1530 .unwrap();
1531
1532 let package_3 = model.get_or_create_package("/ECU").unwrap();
1534 system.create_ecu_instance("Ecu_1", &package_3).unwrap();
1535
1536 assert_eq!(system.frames().count(), 5);
1537 }
1538
1539 #[test]
1540 fn signals_iterator() {
1541 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1542 let package_1 = model.get_or_create_package("/SYSTEM").unwrap();
1543 let system = package_1
1544 .create_system("System", SystemCategory::SystemExtract)
1545 .unwrap();
1546 let package_2 = model.get_or_create_package("/Signals").unwrap();
1547
1548 let syssig1 = package_2.create_system_signal("syssig1").unwrap();
1549 system.create_isignal("Sig1", &package_2, 8, &syssig1, None).unwrap();
1550 let syssig2 = package_2.create_system_signal("syssig2").unwrap();
1551 system.create_isignal("Sig2", &package_2, 8, &syssig2, None).unwrap();
1552
1553 let package_3 = model.get_or_create_package("/ECU").unwrap();
1555 system.create_ecu_instance("Ecu_1", &package_3).unwrap();
1556
1557 assert_eq!(system.isignals().count(), 2);
1558 }
1559
1560 #[test]
1561 fn isignal_groups_iterator() {
1562 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1563 let package_1 = model.get_or_create_package("/SYSTEM").unwrap();
1564 let system = package_1
1565 .create_system("System", SystemCategory::SystemExtract)
1566 .unwrap();
1567 let package_2 = model.get_or_create_package("/SignalGroups").unwrap();
1568
1569 let sysgroup1 = package_2.create_system_signal_group("sysgroup1").unwrap();
1570 system
1571 .create_isignal_group("siggroup1", &package_2, &sysgroup1)
1572 .unwrap();
1573 let sysgroup2 = package_2.create_system_signal_group("sysgroup2").unwrap();
1574 system
1575 .create_isignal_group("siggroup2", &package_2, &sysgroup2)
1576 .unwrap();
1577
1578 let package_3 = model.get_or_create_package("/ECU").unwrap();
1580 system.create_ecu_instance("Ecu_1", &package_3).unwrap();
1581
1582 assert_eq!(system.isignal_groups().count(), 2);
1583 }
1584
1585 #[test]
1586 fn pdus_iterator() {
1587 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1588 let package_1 = model.get_or_create_package("/SYSTEM").unwrap();
1589 let system = package_1
1590 .create_system("System", SystemCategory::SystemExtract)
1591 .unwrap();
1592 let package_2 = model.get_or_create_package("/Pdus").unwrap();
1593
1594 system
1595 .create_dcm_ipdu("DcmIpdu", &package_2, 8, DiagPduType::DiagRequest)
1596 .unwrap();
1597 system
1598 .create_general_purpose_pdu("GeneralPurposePdu", &package_2, 8, GeneralPurposePduCategory::DoIp)
1599 .unwrap();
1600 system
1601 .create_general_purpose_ipdu("GeneralPurposeIpdu", &package_2, 8, GeneralPurposeIPduCategory::Xcp)
1602 .unwrap();
1603 system
1604 .create_container_ipdu(
1605 "ContainerIpdu",
1606 &package_2,
1607 8,
1608 ContainerIPduHeaderType::NoHeader,
1609 RxAcceptContainedIPdu::AcceptAll,
1610 )
1611 .unwrap();
1612 system
1613 .create_secured_ipdu("SecuredIpdu", &package_2, 8, &SecureCommunicationProps::default())
1614 .unwrap();
1615 system
1616 .create_multiplexed_ipdu("MultiplexedIpdu", &package_2, 8)
1617 .unwrap();
1618
1619 let package_3 = model.get_or_create_package("/ECU").unwrap();
1621 system.create_ecu_instance("Ecu_1", &package_3).unwrap();
1622
1623 assert_eq!(system.pdus().count(), 6);
1624 }
1625
1626 #[test]
1627 fn nm_config() {
1628 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1629 let sys_package = model.get_or_create_package("/SYSTEM").unwrap();
1630 let system = sys_package
1631 .create_system("System", SystemCategory::SystemExtract)
1632 .unwrap();
1633
1634 assert!(system.nm_config().is_none());
1635
1636 let nm_package = model.get_or_create_package("/Nm").unwrap();
1637 let nm_config = system.create_nm_config("NmConfig", &nm_package).unwrap();
1638
1639 assert!(system.nm_config().is_some());
1640 assert_eq!(system.nm_config().unwrap(), nm_config);
1641 }
1642
1643 #[test]
1644 fn sw_mapping() {
1645 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1646 let package_1 = model.get_or_create_package("/SYSTEM").unwrap();
1647 let system = package_1
1648 .create_system("System", SystemCategory::SystemExtract)
1649 .unwrap();
1650 let package_2 = model.get_or_create_package("/SWC").unwrap();
1651 let package_3 = model.get_or_create_package("/ECU").unwrap();
1652
1653 let root_composition = CompositionSwComponentType::new("RootComposition", &package_2).unwrap();
1654 let context_composition = CompositionSwComponentType::new("ContextComposition", &package_2).unwrap();
1655 let ecu_composition = CompositionSwComponentType::new("EcuComposition", &package_2).unwrap();
1656 let _root_proto = system
1657 .set_root_sw_composition("RootComposition", &root_composition)
1658 .unwrap();
1659 assert_eq!(system.root_sw_composition().unwrap(), _root_proto);
1660
1661 let context_proto = root_composition
1662 .create_component("ContextComposition", &context_composition.clone())
1663 .unwrap();
1664 let ecu_proto = context_composition
1665 .create_component("EcuComposition", &ecu_composition)
1666 .unwrap();
1667 let ecu = system.create_ecu_instance("Ecu", &package_3).unwrap();
1668
1669 let mapping = system.get_or_create_mapping("Mapping").unwrap();
1670 mapping.map_swc_to_ecu("SwcToEcu1", &context_proto, &ecu).unwrap();
1671 let swc_to_ecu = mapping.map_swc_to_ecu("SwcToEcu2", &ecu_proto, &ecu).unwrap();
1672
1673 assert_eq!(swc_to_ecu.target_component().unwrap(), ecu_proto);
1674 assert_eq!(swc_to_ecu.ecu_instance().unwrap(), ecu);
1675
1676 }
1678}