autosar_data_abstraction/communication/cluster/
mod.rs

1use crate::{AbstractionElement, AutosarAbstractionError, IdentifiableAbstractionElement, System};
2use autosar_data::{Element, ElementName};
3
4mod can;
5mod ethernet;
6mod flexray;
7mod lin;
8
9pub use can::*;
10pub use ethernet::*;
11pub use flexray::*;
12pub use lin::*;
13
14//##################################################################
15
16/// [`AbstractCluster`] defines the common interface for all supported communication clusters.
17pub trait AbstractCluster: AbstractionElement {
18    /// Returns the [`System`] the cluster is part of.
19    fn system(&self) -> Option<System> {
20        if let Ok(model) = self.element().model() {
21            let path = self.element().path().ok()?;
22            let refs = model.get_references_to(&path);
23
24            if let Some(system) = refs
25                .iter()
26                .filter_map(autosar_data::WeakElement::upgrade)
27                .filter(|elem| elem.element_name() == ElementName::FibexElementRef)
28                .filter_map(|elem| elem.named_parent().ok().flatten())
29                .find_map(|parent| System::try_from(parent).ok())
30            {
31                return Some(system);
32            }
33        }
34        None
35    }
36}
37
38//##################################################################
39
40/// A [`Cluster`] is returned by [`System::clusters`].
41/// It can contain any supported communication cluster.
42#[derive(Debug, Clone, PartialEq, Eq)]
43#[non_exhaustive]
44pub enum Cluster {
45    /// The Cluster is a [`CanCluster`]
46    Can(CanCluster),
47    /// The Cluster is an [`EthernetCluster`]
48    Ethernet(EthernetCluster),
49    /// The Cluster is a [`FlexrayCluster`]
50    FlexRay(FlexrayCluster),
51    /// The Cluster is a [`LinCluster`]
52    Lin(LinCluster),
53    // missing: TTCAN, J1939, CDD (aka user defined)
54}
55
56impl AbstractionElement for Cluster {
57    fn element(&self) -> &autosar_data::Element {
58        match self {
59            Cluster::Can(cancluster) => cancluster.element(),
60            Cluster::Ethernet(ethcluster) => ethcluster.element(),
61            Cluster::FlexRay(flxcluster) => flxcluster.element(),
62            Cluster::Lin(lincluster) => lincluster.element(),
63        }
64    }
65}
66
67impl IdentifiableAbstractionElement for Cluster {}
68impl AbstractCluster for Cluster {}
69
70impl TryFrom<Element> for Cluster {
71    type Error = AutosarAbstractionError;
72
73    fn try_from(element: Element) -> Result<Self, Self::Error> {
74        match element.element_name() {
75            ElementName::CanCluster => Ok(CanCluster::try_from(element)?.into()),
76            ElementName::EthernetCluster => Ok(EthernetCluster::try_from(element)?.into()),
77            ElementName::FlexrayCluster => Ok(FlexrayCluster::try_from(element)?.into()),
78            ElementName::LinCluster => Ok(LinCluster::try_from(element)?.into()),
79            _ => Err(AutosarAbstractionError::ConversionError {
80                element,
81                dest: "Cluster".to_string(),
82            }),
83        }
84    }
85}
86
87impl From<CanCluster> for Cluster {
88    fn from(value: CanCluster) -> Self {
89        Cluster::Can(value)
90    }
91}
92
93impl From<EthernetCluster> for Cluster {
94    fn from(value: EthernetCluster) -> Self {
95        Cluster::Ethernet(value)
96    }
97}
98
99impl From<FlexrayCluster> for Cluster {
100    fn from(value: FlexrayCluster) -> Self {
101        Cluster::FlexRay(value)
102    }
103}
104
105impl From<LinCluster> for Cluster {
106    fn from(value: LinCluster) -> Self {
107        Cluster::Lin(value)
108    }
109}
110
111impl Cluster {
112    /// remove this `Cluster` from the model
113    pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
114        match self {
115            Cluster::Can(can_cluster) => can_cluster.remove(deep),
116            Cluster::Ethernet(eth_cluster) => eth_cluster.remove(deep),
117            Cluster::FlexRay(flx_cluster) => flx_cluster.remove(deep),
118            Cluster::Lin(lin_cluster) => lin_cluster.remove(deep),
119        }
120    }
121}
122
123//##################################################################
124
125#[cfg(test)]
126mod tests {
127    use super::*;
128    use crate::AutosarModelAbstraction;
129    use autosar_data::AutosarVersion;
130
131    #[test]
132    fn cluster_system() {
133        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
134        let package = model.get_or_create_package("/Test").unwrap();
135        let system = package
136            .create_system("System", crate::SystemCategory::EcuExtract)
137            .unwrap();
138        let can_cluster = CanCluster::new("CanCluster", &package, None).unwrap();
139
140        assert!(can_cluster.system().is_none());
141        system.create_fibex_element_ref(can_cluster.element()).unwrap();
142        assert_eq!(can_cluster.system().unwrap(), system);
143    }
144
145    #[test]
146    fn cluster_conversion() {
147        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
148        let package = model.get_or_create_package("/Test").unwrap();
149        let can_cluster = CanCluster::new("CanCluster", &package, None).unwrap();
150        let ethernet_cluster = EthernetCluster::new("EthernetCluster", &package).unwrap();
151        let flexray_settings = FlexrayClusterSettings::default();
152        let flexray_cluster = FlexrayCluster::new("FlexrayCluster", &package, &flexray_settings).unwrap();
153
154        let can: Cluster = can_cluster.into();
155        let ethernet: Cluster = ethernet_cluster.into();
156        let flexray: Cluster = flexray_cluster.into();
157
158        assert_eq!(can.element().item_name().unwrap(), "CanCluster");
159        assert_eq!(ethernet.element().item_name().unwrap(), "EthernetCluster");
160        assert_eq!(flexray.element().item_name().unwrap(), "FlexrayCluster");
161    }
162
163    #[test]
164    fn remove_cluster() {
165        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
166        let package = model.get_or_create_package("/Test").unwrap();
167        let system = package
168            .create_system("System", crate::SystemCategory::EcuExtract)
169            .unwrap();
170        let can_cluster = system.create_can_cluster("CanCluster", &package, None).unwrap();
171        let flexray_cluster = system
172            .create_flexray_cluster("FlexrayCluster", &package, &FlexrayClusterSettings::default())
173            .unwrap();
174        let ethernet_cluster = system.create_ethernet_cluster("EthernetCluster", &package).unwrap();
175        let lin_cluster = system.create_lin_cluster("LinCluster", &package).unwrap();
176
177        assert_eq!(system.clusters().count(), 4);
178        let cluster: Cluster = can_cluster.into();
179        cluster.remove(true).unwrap();
180        let cluster: Cluster = flexray_cluster.into();
181        cluster.remove(true).unwrap();
182        let cluster: Cluster = ethernet_cluster.into();
183        cluster.remove(true).unwrap();
184        let cluster: Cluster = lin_cluster.into();
185        cluster.remove(true).unwrap();
186        assert_eq!(system.clusters().count(), 0);
187    }
188}