@@ -3,19 +3,19 @@ use autosar_data::ElementName;
33
44pub 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 {}
257257pub struct SwComponentPrototype ( Element ) ;
258258abstraction_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
262378element_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