@@ -3,19 +3,19 @@ use autosar_data::ElementName;
3
3
4
4
pub trait AbstractSwComponentType : AbstractionElement {
5
5
/// iterator over the instances of the component type
6
- fn instances ( & self ) -> SwComponentPrototypeIterator {
6
+ fn instances ( & self ) -> ComponentPrototypeIterator {
7
7
let model_result = self . element ( ) . model ( ) ;
8
8
let path_result = self . element ( ) . path ( ) ;
9
9
if let ( Ok ( model) , Ok ( path) ) = ( model_result, path_result) {
10
10
let reflist = model. get_references_to ( & path) ;
11
- SwComponentPrototypeIterator :: new ( reflist)
11
+ ComponentPrototypeIterator :: new ( reflist)
12
12
} else {
13
- SwComponentPrototypeIterator :: new ( vec ! [ ] )
13
+ ComponentPrototypeIterator :: new ( vec ! [ ] )
14
14
}
15
15
}
16
16
17
17
/// 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 > {
19
19
self . instances ( )
20
20
. filter_map ( |swcp| swcp. element ( ) . named_parent ( ) . ok ( ) . flatten ( ) )
21
21
. filter_map ( |elem| CompositionSwComponentType :: try_from ( elem) . ok ( ) )
@@ -40,7 +40,7 @@ impl CompositionSwComponentType {
40
40
pub fn is_parent_of < T : AbstractSwComponentType > ( & self , other : & T ) -> bool {
41
41
// the expectation is that in normal cases each component has only one parent
42
42
// 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 < _ > > ( ) ;
44
44
let mut counter = 1000 ; // just to prevent infinite loops, since I don't trust files generated by other tools
45
45
while !work_items. is_empty ( ) && counter > 0 {
46
46
counter -= 1 ;
@@ -49,7 +49,7 @@ impl CompositionSwComponentType {
49
49
}
50
50
// the uses of pop here makes this a depth-first search in the case where there are multiple parents
51
51
let item = work_items. pop ( ) . unwrap ( ) ;
52
- work_items. extend ( item. compositions ( ) ) ;
52
+ work_items. extend ( item. parent_compositions ( ) ) ;
53
53
}
54
54
55
55
false
@@ -58,7 +58,11 @@ impl CompositionSwComponentType {
58
58
/// add a component of type component_type to the composition
59
59
///
60
60
/// 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 > {
62
66
if let SwComponentType :: Composition ( composition_component) = component_type {
63
67
if composition_component. is_parent_of ( self ) {
64
68
return Err ( AutosarAbstractionError :: InvalidParameter (
@@ -68,11 +72,7 @@ impl CompositionSwComponentType {
68
72
}
69
73
70
74
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)
76
76
}
77
77
78
78
/// get an iterator over the components of the composition
@@ -257,13 +257,129 @@ impl AbstractSwComponentType for SwComponentType {}
257
257
pub struct SwComponentPrototype ( Element ) ;
258
258
abstraction_element ! ( SwComponentPrototype , SwComponentPrototype ) ;
259
259
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
+
260
376
//##################################################################
261
377
262
378
element_iterator ! ( CompositionComponentsIter , SwComponentType , Some ) ;
263
379
264
380
//##################################################################
265
381
266
- reflist_iterator ! ( SwComponentPrototypeIterator , SwComponentPrototype ) ;
382
+ reflist_iterator ! ( ComponentPrototypeIterator , ComponentPrototype ) ;
267
383
268
384
//##################################################################
269
385
@@ -309,4 +425,21 @@ mod test {
309
425
assert ! ( !comp4. is_parent_of( & comp2) ) ;
310
426
assert ! ( !comp4. is_parent_of( & comp3) ) ;
311
427
}
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
+ }
312
445
}
0 commit comments