1515 */
1616package io .adminshell .aas .v3 .dataformat .aml .deserialization ;
1717
18- import io .adminshell .aas .v3 .dataformat .aml .model .caex .AttributeType ;
19- import io .adminshell .aas .v3 .dataformat .aml .model .caex .CAEXObject ;
20- import io .adminshell .aas .v3 .dataformat .aml .model .caex .InternalElementType ;
21- import io .adminshell .aas .v3 .dataformat .aml .model .caex .SystemUnitClassType ;
22- import io .adminshell .aas .v3 .dataformat .aml .model .caex .InterfaceClassType ;
18+ import io .adminshell .aas .v3 .dataformat .aml .model .caex .*;
2319import io .adminshell .aas .v3 .dataformat .core .ReflectionHelper ;
2420import io .adminshell .aas .v3 .dataformat .core .util .AasUtils ;
2521import io .adminshell .aas .v3 .dataformat .mapping .MappingException ;
@@ -67,6 +63,8 @@ public T map(AmlParser parser, MappingContext context) throws MappingException {
6763 return (T ) fromAttribute (parser , (AttributeType ) parser .getCurrent (), context );
6864 } else if (InternalElementType .class .isAssignableFrom (parser .getCurrent ().getClass ())) {
6965 return (T ) fromInternalElement (parser , (InternalElementType ) parser .getCurrent (), context );
66+ } else if (SystemUnitFamilyType .class .isAssignableFrom (parser .getCurrent ().getClass ())){
67+ return (T ) fromSystemUnitFamily (parser , (SystemUnitFamilyType ) parser .getCurrent (),context );
7068 }
7169 } else {
7270 if (Collection .class .isAssignableFrom (context .getProperty ().getReadMethod ().getReturnType ())) {
@@ -142,6 +140,25 @@ protected Object fromInternalElement(AmlParser parser, InternalElementType inter
142140 return result ;
143141 }
144142
143+ /**
144+ * Reads expected object from given SystemUnitFamily.
145+ *
146+ * @param parser the AML parser
147+ * @param systemUnitFamilyType the SystemUnitFamily to read from
148+ * @param context the mapping context
149+ * @return the read object or null if not present
150+ * @throws MappingException if reading object fails
151+ */
152+ protected Object fromSystemUnitFamily (AmlParser parser , SystemUnitFamilyType systemUnitFamilyType , MappingContext context ) throws MappingException {
153+ if (parser == null || systemUnitFamilyType == null || context == null ) {
154+ return null ;
155+ }
156+ Class <?> type = typeFromSystemUnit (systemUnitFamilyType );
157+ Object result = newInstance (type , context );
158+ mapProperties (result , parser , context );
159+ return result ;
160+ }
161+
145162 /**
146163 * Recursively calls context.map(...) on all properties except those
147164 * explicitely ignored and sets them on the parent.
@@ -285,6 +302,31 @@ protected Class<?> typeFromInternalElement(InternalElementType internalElement)
285302 return type .get ();
286303 }
287304
305+ /**
306+ * Extracts type information from a given SystemUnitFamily based on the
307+ * supportedRoleClass property
308+ *
309+ * @param systemUnitFamilyType The SystemUnitFamily to extract the type from
310+ * @return the type of the attribute
311+ * @throws MappingException if type information is missing or invalid or
312+ * type could not be resolved
313+ */
314+ protected Class <?> typeFromSystemUnit (SystemUnitFamilyType systemUnitFamilyType ) throws MappingException {
315+ if (systemUnitFamilyType .getSupportedRoleClass () == null || systemUnitFamilyType .getSupportedRoleClass ().get (0 ) == null ) {
316+ throw new MappingException (String .format ("missing required SupportedRoleClass with ID %s" , systemUnitFamilyType .getID ()));
317+ }
318+ String roleClassPath = systemUnitFamilyType .getSupportedRoleClass ().get (0 ).getRefRoleClassPath ();
319+ String className = roleClassPath .substring (roleClassPath .indexOf ("/" ) + 1 );
320+
321+ Optional <Class > type = ReflectionHelper .INTERFACES .stream ().filter (x -> x .getSimpleName ().equals (className )).findAny ();
322+ if (type .isEmpty ()) {
323+ throw new MappingException (String .format ("unkown type definition %s in role class path for systemUnitFamilyType with ID %s" ,
324+ className ,
325+ systemUnitFamilyType .getID ()));
326+ }
327+ return type .get ();
328+ }
329+
288330 protected Collection mapCollectionValueProperty (AmlParser parser , MappingContext context ) throws MappingException {
289331 if (parser == null || context == null || context .getProperty () == null ) {
290332 return null ;
@@ -419,7 +461,6 @@ protected AttributeType findAttribute(CAEXObject parent, PropertyDescriptor prop
419461 }
420462
421463
422-
423464 // TODO not working because of missing property renaming strategy
424465 protected List <AttributeType > findAttributes (CAEXObject parent , PropertyDescriptor property , MappingContext context ) {
425466 return findAttributes (parent , property ,context , AmlParser .DEFAULT_REFSEMANTIC_PREFIX );
@@ -443,17 +484,45 @@ protected List<AttributeType> findAttributes(CAEXObject parent, Predicate<Attrib
443484 return ((AttributeType ) parent ).getAttribute ().stream ().filter (filter ).collect (Collectors .toList ());
444485 } else if (InternalElementType .class .isAssignableFrom (parent .getClass ())) {
445486 return ((InternalElementType ) parent ).getAttribute ().stream ().filter (filter ).collect (Collectors .toList ());
487+ } else if (SystemUnitFamilyType .class .isAssignableFrom (parent .getClass ())) {
488+ return ((SystemUnitFamilyType ) parent ).getAttribute ().stream ().filter (filter ).collect (Collectors .toList ());
446489 }
447490 return List .of ();
448491 }
449492
450493 protected List <InternalElementType > findInternalElements (CAEXObject parent , Class desiredType , boolean acceptSubtypes , MappingContext context ) {
451- if (parent == null || !InternalElementType .class .isAssignableFrom (parent .getClass ())) {
494+ if (parent == null || !( InternalElementType .class .isAssignableFrom (parent .getClass ()) || SystemUnitFamilyType . class . isAssignableFrom ( parent . getClass () ))) {
452495 return List .of ();
453496 }
497+
498+ if (SystemUnitFamilyType .class .isAssignableFrom (parent .getClass ())){
499+ return findInternalElements ((SystemUnitFamilyType ) parent , desiredType ,acceptSubtypes ,context );
500+ }
501+
454502 return findInternalElements ((InternalElementType ) parent , desiredType , acceptSubtypes , context );
455503 }
456504
505+ protected List <InternalElementType > findInternalElements (SystemUnitFamilyType parent , Class desiredType , boolean acceptSubtypes , MappingContext context ) {
506+ if (desiredType == null || context == null || parent == null ) {
507+ return List .of ();
508+ }
509+ Predicate <InternalElementType > filter = x -> {
510+ String role = x .getRoleRequirements () != null ? x .getRoleRequirements ().getRefBaseRoleClassPath () : "" ;
511+ if (role .startsWith (context .getDocumentInfo ().getAssetAdministrationShellRoleClassLib ())) {
512+ String actualClassName = role .substring (context .getDocumentInfo ().getAssetAdministrationShellRoleClassLib ().length () + 1 );
513+ Optional <Class > actualType = ReflectionHelper .INTERFACES .stream ().filter (y -> y .getSimpleName ().equals (actualClassName )).findFirst ();
514+ if (actualType .isPresent ()) {
515+ if (acceptSubtypes ) {
516+ return desiredType .isAssignableFrom (actualType .get ());
517+ }
518+ return desiredType .equals (actualType .get ());
519+ }
520+ }
521+ return false ;
522+ };
523+ return parent .getInternalElement ().stream ().filter (filter ).collect (Collectors .toList ());
524+ }
525+
457526 protected List <InternalElementType > findInternalElements (InternalElementType parent , Class desiredType , boolean acceptSubtypes , MappingContext context ) {
458527 if (desiredType == null || context == null ) {
459528 return List .of ();
0 commit comments