Skip to content

Commit cfbdf03

Browse files
committed
Support mapping of software components to ECUs
1 parent 3348098 commit cfbdf03

File tree

2 files changed

+356
-24
lines changed

2 files changed

+356
-24
lines changed

autosar-data-abstraction/src/software_component/mod.rs

Lines changed: 146 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ use autosar_data::ElementName;
33

44
pub trait AbstractSwComponentType: AbstractionElement {
55
/// iterator over the instances of the component type
6-
fn instances(&self) -> SwComponentPrototypeIterator {
6+
fn instances(&self) -> ComponentPrototypeIterator {
77
let model_result = self.element().model();
88
let path_result = self.element().path();
99
if let (Ok(model), Ok(path)) = (model_result, path_result) {
1010
let reflist = model.get_references_to(&path);
11-
SwComponentPrototypeIterator::new(reflist)
11+
ComponentPrototypeIterator::new(reflist)
1212
} else {
13-
SwComponentPrototypeIterator::new(vec![])
13+
ComponentPrototypeIterator::new(vec![])
1414
}
1515
}
1616

1717
/// iterator over all compositions containing instances of the component type
18-
fn compositions(&self) -> impl Iterator<Item = CompositionSwComponentType> {
18+
fn parent_compositions(&self) -> impl Iterator<Item = CompositionSwComponentType> {
1919
self.instances()
2020
.filter_map(|swcp| swcp.element().named_parent().ok().flatten())
2121
.filter_map(|elem| CompositionSwComponentType::try_from(elem).ok())
@@ -40,7 +40,7 @@ impl CompositionSwComponentType {
4040
pub fn is_parent_of<T: AbstractSwComponentType>(&self, other: &T) -> bool {
4141
// the expectation is that in normal cases each component has only one parent
4242
// additionally there should never be any cycles in the composition hierarchy
43-
let mut work_items = other.compositions().collect::<Vec<_>>();
43+
let mut work_items = other.parent_compositions().collect::<Vec<_>>();
4444
let mut counter = 1000; // just to prevent infinite loops, since I don't trust files generated by other tools
4545
while !work_items.is_empty() && counter > 0 {
4646
counter -= 1;
@@ -49,7 +49,7 @@ impl CompositionSwComponentType {
4949
}
5050
// the uses of pop here makes this a depth-first search in the case where there are multiple parents
5151
let item = work_items.pop().unwrap();
52-
work_items.extend(item.compositions());
52+
work_items.extend(item.parent_compositions());
5353
}
5454

5555
false
@@ -58,7 +58,11 @@ impl CompositionSwComponentType {
5858
/// add a component of type component_type to the composition
5959
///
6060
/// It is not allowed to form cycles in the composition hierarchy, and this will return an error
61-
pub fn add_component(&self, name: &str, component_type: &SwComponentType) -> Result<(), AutosarAbstractionError> {
61+
pub fn add_component(
62+
&self,
63+
name: &str,
64+
component_type: &SwComponentType,
65+
) -> Result<SwComponentPrototype, AutosarAbstractionError> {
6266
if let SwComponentType::Composition(composition_component) = component_type {
6367
if composition_component.is_parent_of(self) {
6468
return Err(AutosarAbstractionError::InvalidParameter(
@@ -68,11 +72,7 @@ impl CompositionSwComponentType {
6872
}
6973

7074
let components = self.element().get_or_create_sub_element(ElementName::Components)?;
71-
let component = components.create_named_sub_element(ElementName::SwComponentPrototype, name)?;
72-
component
73-
.create_sub_element(ElementName::TypeTref)?
74-
.set_reference_target(&component_type.element())?;
75-
Ok(())
75+
SwComponentPrototype::new(name, &components, component_type)
7676
}
7777

7878
/// get an iterator over the components of the composition
@@ -257,13 +257,129 @@ impl AbstractSwComponentType for SwComponentType {}
257257
pub struct SwComponentPrototype(Element);
258258
abstraction_element!(SwComponentPrototype, SwComponentPrototype);
259259

260+
impl SwComponentPrototype {
261+
fn new(
262+
name: &str,
263+
components: &Element,
264+
component_type: &SwComponentType,
265+
) -> Result<Self, AutosarAbstractionError> {
266+
let component = components.create_named_sub_element(ElementName::SwComponentPrototype, name)?;
267+
component
268+
.create_sub_element(ElementName::TypeTref)?
269+
.set_reference_target(component_type.element())?;
270+
271+
Ok(Self(component))
272+
}
273+
274+
/// get the sw component type that this prototype is based on
275+
pub fn component_type(&self) -> Option<SwComponentType> {
276+
let component_elem = self
277+
.element()
278+
.get_sub_element(ElementName::TypeTref)?
279+
.get_reference_target()
280+
.ok()?;
281+
SwComponentType::try_from(component_elem).ok()
282+
}
283+
284+
/// get the composition containing this component
285+
pub fn parent_composition(&self) -> Result<CompositionSwComponentType, AutosarAbstractionError> {
286+
let parent = self.element().named_parent()?.unwrap();
287+
CompositionSwComponentType::try_from(parent)
288+
}
289+
}
290+
291+
//##################################################################
292+
293+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
294+
pub struct RootSwCompositionPrototype(Element);
295+
abstraction_element!(RootSwCompositionPrototype, RootSwCompositionPrototype);
296+
297+
impl RootSwCompositionPrototype {
298+
pub(crate) fn new(
299+
name: &str,
300+
root_compositions: &Element,
301+
composition_type: &CompositionSwComponentType,
302+
) -> Result<Self, AutosarAbstractionError> {
303+
let root_composition =
304+
root_compositions.create_named_sub_element(ElementName::RootSwCompositionPrototype, name)?;
305+
root_composition
306+
.create_sub_element(ElementName::SoftwareCompositionTref)?
307+
.set_reference_target(composition_type.element())?;
308+
309+
Ok(Self(root_composition))
310+
}
311+
312+
/// get the composition that this root component is based on
313+
pub fn composition(&self) -> Option<CompositionSwComponentType> {
314+
let composition_elem = self
315+
.element()
316+
.get_sub_element(ElementName::SoftwareCompositionTref)?
317+
.get_reference_target()
318+
.ok()?;
319+
CompositionSwComponentType::try_from(composition_elem).ok()
320+
}
321+
}
322+
323+
//##################################################################
324+
325+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
326+
pub enum ComponentPrototype {
327+
SwComponent(SwComponentPrototype),
328+
RootComposition(RootSwCompositionPrototype),
329+
}
330+
331+
impl AbstractionElement for ComponentPrototype {
332+
fn element(&self) -> &Element {
333+
match self {
334+
ComponentPrototype::SwComponent(swcp) => swcp.element(),
335+
ComponentPrototype::RootComposition(root) => root.element(),
336+
}
337+
}
338+
}
339+
340+
impl TryFrom<Element> for ComponentPrototype {
341+
type Error = AutosarAbstractionError;
342+
343+
fn try_from(element: Element) -> Result<Self, Self::Error> {
344+
match element.element_name() {
345+
ElementName::SwComponentPrototype => Ok(ComponentPrototype::SwComponent(SwComponentPrototype(element))),
346+
ElementName::RootSwCompositionPrototype => {
347+
Ok(ComponentPrototype::RootComposition(RootSwCompositionPrototype(element)))
348+
}
349+
_ => Err(AutosarAbstractionError::ConversionError {
350+
element,
351+
dest: "ComponentPrototype".to_string(),
352+
}),
353+
}
354+
}
355+
}
356+
357+
impl ComponentPrototype {
358+
pub fn component_type(&self) -> Option<SwComponentType> {
359+
match self {
360+
ComponentPrototype::SwComponent(swcp) => swcp.component_type(),
361+
ComponentPrototype::RootComposition(rc) => rc.composition().map(|composition| composition.into()),
362+
}
363+
}
364+
365+
/// get the composition containing this component
366+
///
367+
/// if the component is a root composition, this will always return None
368+
pub fn parent_composition(&self) -> Result<Option<CompositionSwComponentType>, AutosarAbstractionError> {
369+
match self {
370+
ComponentPrototype::SwComponent(swcp) => swcp.parent_composition().map(Some),
371+
ComponentPrototype::RootComposition(_) => Ok(None),
372+
}
373+
}
374+
}
375+
260376
//##################################################################
261377

262378
element_iterator!(CompositionComponentsIter, SwComponentType, Some);
263379

264380
//##################################################################
265381

266-
reflist_iterator!(SwComponentPrototypeIterator, SwComponentPrototype);
382+
reflist_iterator!(ComponentPrototypeIterator, ComponentPrototype);
267383

268384
//##################################################################
269385

@@ -309,4 +425,21 @@ mod test {
309425
assert!(!comp4.is_parent_of(&comp2));
310426
assert!(!comp4.is_parent_of(&comp3));
311427
}
428+
429+
#[test]
430+
fn root_composition() {
431+
let model = AutosarModel::new();
432+
let _file = model.create_file("filename", AutosarVersion::LATEST).unwrap();
433+
let package = ArPackage::get_or_create(&model, "/package").unwrap();
434+
435+
let system = System::new("system", &package, SystemCategory::EcuExtract).unwrap();
436+
let comp = CompositionSwComponentType::new("comp", &package).unwrap();
437+
let root_sw_component_prototype = system.set_root_sw_composition("root", &comp).unwrap();
438+
439+
assert_eq!(
440+
ComponentPrototype::RootComposition(root_sw_component_prototype),
441+
comp.instances().next().unwrap()
442+
);
443+
assert_eq!(comp.instances().count(), 1);
444+
}
312445
}

0 commit comments

Comments
 (0)