autosar_data_abstraction/ecu_configuration/definition/
container.rs

1use crate::{
2    AbstractionElement, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
3    ecu_configuration::{
4        EcucAddInfoParamDef, EcucAnyReferenceDef, EcucBooleanParamDef, EcucChoiceReferenceDef, EcucDefinitionElement,
5        EcucEnumerationParamDef, EcucFloatParamDef, EcucForeignReferenceDef, EcucFunctionNameDef,
6        EcucInstanceReferenceDef, EcucIntegerParamDef, EcucLinkerSymbolDef, EcucMultilineStringParamDef,
7        EcucParameterDef, EcucReferenceDef, EcucStringParamDef, EcucUriReferenceDef,
8    },
9};
10use autosar_data::{Element, ElementName};
11
12//#########################################################
13
14/// Marker trait for container definitions
15pub trait AbstractEcucContainerDef: EcucDefinitionElement {}
16
17//#########################################################
18
19/// The `EcucChoiceContainerDef` is used to define configuration containers
20/// that provide a choice between several `EcucParamConfContainerDef`
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22pub struct EcucChoiceContainerDef(Element);
23abstraction_element!(EcucChoiceContainerDef, EcucChoiceContainerDef);
24impl IdentifiableAbstractionElement for EcucChoiceContainerDef {}
25impl EcucDefinitionElement for EcucChoiceContainerDef {}
26impl AbstractEcucContainerDef for EcucChoiceContainerDef {}
27
28impl EcucChoiceContainerDef {
29    pub(crate) fn new(name: &str, containers_elem: &Element) -> Result<Self, AutosarAbstractionError> {
30        let choice_container_def_elem =
31            containers_elem.create_named_sub_element(ElementName::EcucChoiceContainerDef, name)?;
32
33        Ok(Self(choice_container_def_elem))
34    }
35
36    /// create a new `EcucParamConfContainerDef` as one of the choices in this choice container
37    pub fn create_param_conf_container_def(
38        &self,
39        name: &str,
40    ) -> Result<EcucParamConfContainerDef, AutosarAbstractionError> {
41        let containers_elem = self.element().get_or_create_sub_element(ElementName::Choices)?;
42        EcucParamConfContainerDef::new(name, &containers_elem)
43    }
44
45    /// iterate over the choices in the container
46    pub fn choices(&self) -> impl Iterator<Item = EcucParamConfContainerDef> + Send + use<> {
47        self.element()
48            .get_sub_element(ElementName::Choices)
49            .into_iter()
50            .flat_map(|elem| elem.sub_elements())
51            .filter_map(|elem| EcucParamConfContainerDef::try_from(elem).ok())
52    }
53}
54
55//#########################################################
56
57/// The `EcucParamConfContainerDef` is used to define configuration containers
58#[derive(Debug, Clone, PartialEq, Eq, Hash)]
59pub struct EcucParamConfContainerDef(Element);
60abstraction_element!(EcucParamConfContainerDef, EcucParamConfContainerDef);
61impl IdentifiableAbstractionElement for EcucParamConfContainerDef {}
62impl EcucDefinitionElement for EcucParamConfContainerDef {}
63impl AbstractEcucContainerDef for EcucParamConfContainerDef {}
64
65impl EcucParamConfContainerDef {
66    pub(crate) fn new(name: &str, containers_elem: &Element) -> Result<Self, AutosarAbstractionError> {
67        let param_conf_container_def_elem =
68            containers_elem.create_named_sub_element(ElementName::EcucParamConfContainerDef, name)?;
69
70        Ok(Self(param_conf_container_def_elem))
71    }
72
73    /// create a new `EcucChoiceContainerDef` as a sub-container
74    pub fn create_choice_container_def(&self, name: &str) -> Result<EcucChoiceContainerDef, AutosarAbstractionError> {
75        let containers_elem = self.element().get_or_create_sub_element(ElementName::SubContainers)?;
76        EcucChoiceContainerDef::new(name, &containers_elem)
77    }
78
79    /// create a new `EcucParamConfContainerDef` as a sub-container
80    pub fn create_param_conf_container_def(
81        &self,
82        name: &str,
83    ) -> Result<EcucParamConfContainerDef, AutosarAbstractionError> {
84        let containers_elem = self.element().get_or_create_sub_element(ElementName::SubContainers)?;
85        EcucParamConfContainerDef::new(name, &containers_elem)
86    }
87
88    /// iterate over the sub-containers
89    pub fn sub_containers(&self) -> impl Iterator<Item = EcucContainerDef> + Send + use<> {
90        self.element()
91            .get_sub_element(ElementName::SubContainers)
92            .into_iter()
93            .flat_map(|elem| elem.sub_elements())
94            .filter_map(|elem| EcucContainerDef::try_from(elem).ok())
95    }
96
97    /// create a new `EcucAddInfoParamDef` in the container
98    pub fn create_add_info_param_def(
99        &self,
100        name: &str,
101        origin: &str,
102    ) -> Result<EcucAddInfoParamDef, AutosarAbstractionError> {
103        let parameters_elem = self.element().get_or_create_sub_element(ElementName::Parameters)?;
104        EcucAddInfoParamDef::new(name, &parameters_elem, origin)
105    }
106
107    /// create a new `EcucBooleanParamDef` in the container
108    pub fn create_boolean_param_def(
109        &self,
110        name: &str,
111        origin: &str,
112    ) -> Result<EcucBooleanParamDef, AutosarAbstractionError> {
113        let parameters_elem = self.element().get_or_create_sub_element(ElementName::Parameters)?;
114        EcucBooleanParamDef::new(name, &parameters_elem, origin)
115    }
116
117    /// create a new `EcucEnumerationParamDef` in the container
118    pub fn create_enumeration_param_def(
119        &self,
120        name: &str,
121        origin: &str,
122    ) -> Result<EcucEnumerationParamDef, AutosarAbstractionError> {
123        let parameters_elem = self.element().get_or_create_sub_element(ElementName::Parameters)?;
124        EcucEnumerationParamDef::new(name, &parameters_elem, origin)
125    }
126
127    /// create a new `EcucFloatParamDef` in the container
128    pub fn create_float_param_def(
129        &self,
130        name: &str,
131        origin: &str,
132    ) -> Result<EcucFloatParamDef, AutosarAbstractionError> {
133        let parameters_elem = self.element().get_or_create_sub_element(ElementName::Parameters)?;
134        EcucFloatParamDef::new(name, &parameters_elem, origin)
135    }
136
137    /// create a new `EcucIntegerParamDef` in the container
138    pub fn create_integer_param_def(
139        &self,
140        name: &str,
141        origin: &str,
142    ) -> Result<EcucIntegerParamDef, AutosarAbstractionError> {
143        let parameters_elem = self.element().get_or_create_sub_element(ElementName::Parameters)?;
144        EcucIntegerParamDef::new(name, &parameters_elem, origin)
145    }
146
147    /// create a new `EcucFunctionNameDef` in the container
148    pub fn create_function_name_param_def(
149        &self,
150        name: &str,
151        origin: &str,
152    ) -> Result<EcucFunctionNameDef, AutosarAbstractionError> {
153        let parameters_elem = self.element().get_or_create_sub_element(ElementName::Parameters)?;
154        EcucFunctionNameDef::new(name, &parameters_elem, origin)
155    }
156
157    /// create a new `EcucLinkerSymbolDef` in the container
158    pub fn create_linker_symbol_param_def(
159        &self,
160        name: &str,
161        origin: &str,
162    ) -> Result<EcucLinkerSymbolDef, AutosarAbstractionError> {
163        let parameters_elem = self.element().get_or_create_sub_element(ElementName::Parameters)?;
164        EcucLinkerSymbolDef::new(name, &parameters_elem, origin)
165    }
166
167    /// create a new `EcucMultilineStringParamDef` in the container
168    pub fn create_multiline_string_param_def(
169        &self,
170        name: &str,
171        origin: &str,
172    ) -> Result<EcucMultilineStringParamDef, AutosarAbstractionError> {
173        let parameters_elem = self.element().get_or_create_sub_element(ElementName::Parameters)?;
174        EcucMultilineStringParamDef::new(name, &parameters_elem, origin)
175    }
176
177    /// create a new `EcucStringParamDef` in the container
178    pub fn create_string_param_def(
179        &self,
180        name: &str,
181        origin: &str,
182    ) -> Result<EcucStringParamDef, AutosarAbstractionError> {
183        let parameters_elem = self.element().get_or_create_sub_element(ElementName::Parameters)?;
184        EcucStringParamDef::new(name, &parameters_elem, origin)
185    }
186
187    /// get the parameters in the container
188    pub fn parameters(&self) -> impl Iterator<Item = EcucParameterDef> + Send + use<> {
189        self.element()
190            .get_sub_element(ElementName::Parameters)
191            .into_iter()
192            .flat_map(|elem| elem.sub_elements())
193            .filter_map(|elem| EcucParameterDef::try_from(elem).ok())
194    }
195
196    /// create a new `EcucForeignReferenceDef` in the container
197    pub fn create_foreign_reference_def(
198        &self,
199        name: &str,
200        origin: &str,
201    ) -> Result<EcucForeignReferenceDef, AutosarAbstractionError> {
202        let foreign_references_elem = self.element().get_or_create_sub_element(ElementName::References)?;
203        EcucForeignReferenceDef::new(name, &foreign_references_elem, origin)
204    }
205
206    /// create a new `EcucInstanceReferenceDef` in the container
207    pub fn create_instance_reference_def(
208        &self,
209        name: &str,
210        origin: &str,
211    ) -> Result<EcucInstanceReferenceDef, AutosarAbstractionError> {
212        let instance_references_elem = self.element().get_or_create_sub_element(ElementName::References)?;
213        EcucInstanceReferenceDef::new(name, &instance_references_elem, origin)
214    }
215
216    /// create a new `EcucChoiceReferenceDef` in the container
217    pub fn create_choice_reference_def(
218        &self,
219        name: &str,
220        origin: &str,
221    ) -> Result<EcucChoiceReferenceDef, AutosarAbstractionError> {
222        let choice_references_elem = self.element().get_or_create_sub_element(ElementName::References)?;
223        EcucChoiceReferenceDef::new(name, &choice_references_elem, origin)
224    }
225
226    /// create a new `EcucReferenceDef` in the container
227    pub fn create_reference_def(&self, name: &str, origin: &str) -> Result<EcucReferenceDef, AutosarAbstractionError> {
228        let references_elem = self.element().get_or_create_sub_element(ElementName::References)?;
229        EcucReferenceDef::new(name, &references_elem, origin)
230    }
231
232    /// create a new `EcucUriReferenceDef` in the container
233    pub fn create_uri_reference_def(
234        &self,
235        name: &str,
236        origin: &str,
237    ) -> Result<EcucUriReferenceDef, AutosarAbstractionError> {
238        let uri_references_elem = self.element().get_or_create_sub_element(ElementName::References)?;
239        EcucUriReferenceDef::new(name, &uri_references_elem, origin)
240    }
241
242    /// get the references in the container
243    pub fn references(&self) -> impl Iterator<Item = EcucAnyReferenceDef> + Send + use<> {
244        self.element()
245            .get_sub_element(ElementName::References)
246            .into_iter()
247            .flat_map(|elem| elem.sub_elements())
248            .filter_map(|elem| EcucAnyReferenceDef::try_from(elem).ok())
249    }
250}
251
252//#########################################################
253
254/// `EcucContainerDef` is an enum of both container definitions, which is used as a return type by iterators
255#[derive(Debug, Clone, PartialEq, Eq, Hash)]
256pub enum EcucContainerDef {
257    /// the container is a choice container
258    Choice(EcucChoiceContainerDef),
259    /// the container is a parameter container
260    ParamConf(EcucParamConfContainerDef),
261}
262
263impl AbstractionElement for EcucContainerDef {
264    fn element(&self) -> &Element {
265        match self {
266            EcucContainerDef::Choice(elem) => elem.element(),
267            EcucContainerDef::ParamConf(elem) => elem.element(),
268        }
269    }
270}
271
272impl TryFrom<Element> for EcucContainerDef {
273    type Error = AutosarAbstractionError;
274
275    fn try_from(element: Element) -> Result<Self, Self::Error> {
276        match element.element_name() {
277            ElementName::EcucChoiceContainerDef => Ok(EcucContainerDef::Choice(element.try_into()?)),
278            ElementName::EcucParamConfContainerDef => Ok(EcucContainerDef::ParamConf(element.try_into()?)),
279            _ => Err(AutosarAbstractionError::ConversionError {
280                element,
281                dest: "EcucContainerDef".to_string(),
282            }),
283        }
284    }
285}
286
287impl IdentifiableAbstractionElement for EcucContainerDef {}
288impl EcucDefinitionElement for EcucContainerDef {}
289impl AbstractEcucContainerDef for EcucContainerDef {}
290
291//#########################################################
292
293#[cfg(test)]
294mod test {
295    use crate::{AbstractionElement, AutosarModelAbstraction};
296    use autosar_data::AutosarVersion;
297
298    #[test]
299    fn container() {
300        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
301        let package = model.get_or_create_package("/pkg1").unwrap();
302        let ecuc_module = package.create_ecuc_module_def("ecuc_module").unwrap();
303        assert_eq!(ecuc_module.containers().count(), 0);
304
305        let choice_container = ecuc_module.create_choice_container_def("ChoiceContainer").unwrap();
306        assert_eq!(choice_container.choices().count(), 0);
307        choice_container
308            .create_param_conf_container_def("ParamConfContainerChoice1")
309            .unwrap();
310        choice_container
311            .create_param_conf_container_def("ParamConfContainerChoice2")
312            .unwrap();
313        assert_eq!(choice_container.choices().count(), 2);
314
315        let param_conf_container = ecuc_module
316            .create_param_conf_container_def("ParamConfContainer")
317            .unwrap();
318        assert_eq!(param_conf_container.sub_containers().count(), 0);
319        param_conf_container
320            .create_choice_container_def("ChoiceContainer")
321            .unwrap();
322        assert_eq!(param_conf_container.sub_containers().count(), 1);
323
324        assert_eq!(param_conf_container.parameters().count(), 0);
325        param_conf_container
326            .create_add_info_param_def("AddInfoParam", "origin")
327            .unwrap();
328        param_conf_container
329            .create_boolean_param_def("BooleanParam", "origin")
330            .unwrap();
331        param_conf_container
332            .create_enumeration_param_def("EnumerationParam", "origin")
333            .unwrap();
334        param_conf_container
335            .create_float_param_def("FloatParam", "origin")
336            .unwrap();
337        param_conf_container
338            .create_integer_param_def("IntegerParam", "origin")
339            .unwrap();
340        param_conf_container
341            .create_function_name_param_def("FunctionName", "origin")
342            .unwrap();
343        param_conf_container
344            .create_linker_symbol_param_def("LinkerSymbol", "origin")
345            .unwrap();
346        param_conf_container
347            .create_multiline_string_param_def("MultilineStringParam", "origin")
348            .unwrap();
349        param_conf_container
350            .create_string_param_def("StringParam", "origin")
351            .unwrap();
352        assert_eq!(param_conf_container.parameters().count(), 9);
353
354        assert_eq!(param_conf_container.references().count(), 0);
355        param_conf_container
356            .create_foreign_reference_def("ForeignReference", "origin")
357            .unwrap();
358        param_conf_container
359            .create_instance_reference_def("InstanceReference", "origin")
360            .unwrap();
361        param_conf_container
362            .create_choice_reference_def("ChoiceReference", "origin")
363            .unwrap();
364        param_conf_container
365            .create_reference_def("Reference", "origin")
366            .unwrap();
367        param_conf_container
368            .create_uri_reference_def("UriReference", "origin")
369            .unwrap();
370        assert_eq!(param_conf_container.references().count(), 5);
371
372        assert_eq!(ecuc_module.containers().count(), 2);
373        let mut containers_iter = ecuc_module.containers();
374        assert_eq!(containers_iter.next().unwrap().element(), choice_container.element());
375        assert_eq!(
376            containers_iter.next().unwrap().element(),
377            param_conf_container.element()
378        );
379    }
380}