From 7252502b5e5a2085541be5df4a072cbd267dbb95 Mon Sep 17 00:00:00 2001 From: Johannes Kristan Date: Thu, 19 Oct 2023 22:02:44 +0200 Subject: [PATCH 01/14] Remove id_ prefix from aas idshort Signed-off-by: Johannes Kristan --- .../esmf/aspectmodel/aas/AspectModelAASVisitor.java | 2 +- .../aspectmodel/aas/AspectModelAASGeneratorTest.java | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java index 81c6e5f4d..3c17ee552 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java @@ -105,7 +105,7 @@ public class AspectModelAASVisitor implements AspectVisitor testValues = Set.of( "id_RightEntity", "id_LeftEntity" ); + final Set testValues = Set.of( "RightEntity", "LeftEntity" ); assertTrue( elementCollection.getValue().stream().anyMatch( x -> testValues.contains( x.getIdShort() ) ), "Neither left nor right entity contained." ); final Set semanticIds = @@ -291,7 +291,7 @@ void testGenerateAasxFromBammAspectWithEnumeration() throws IOException, Deseria final DataSpecificationIec61360 dataSpecificationContent = (DataSpecificationIec61360) env.getConceptDescriptions().stream() - .filter( x -> x.getIdShort().equals( "id_TestEnumeration" ) ) + .filter( x -> x.getIdShort().equals( "TestEnumeration" ) ) .findFirst() .get() .getEmbeddedDataSpecifications() From ace6640cd21705c65f1c503c79c29d977994101f Mon Sep 17 00:00:00 2001 From: Johannes Kristan Date: Thu, 19 Oct 2023 22:04:52 +0200 Subject: [PATCH 02/14] Removes constant holding id_ prefix Signed-off-by: Johannes Kristan --- .../aspectmodel/aas/AspectModelAASVisitor.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java index 3c17ee552..094cd8e00 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java @@ -105,7 +105,6 @@ public class AspectModelAASVisitor implements AspectVisitor submodelElements = visitProperties( entity.getAllProperties(), context ); return new DefaultSubmodelElementCollection.Builder() - .idShort( ID_PREFIX + entity.getName() ) + .idShort( entity.getName() ) .displayName( LangStringMapper.NAME.map( entity.getPreferredNames() ) ) .description( LangStringMapper.TEXT.map( entity.getDescriptions() ) ) .value( submodelElements ) @@ -291,7 +290,7 @@ private Operation mapText( final org.eclipse.esmf.metamodel.Operation operation, return new DefaultOperation.Builder() .displayName( LangStringMapper.NAME.map( operation.getPreferredNames() ) ) .description( LangStringMapper.TEXT.map( operation.getDescriptions() ) ) - .idShort( ID_PREFIX + operation.getName() ) + .idShort( operation.getName() ) .inputVariables( operation.getInput().stream() .map( i -> mapOperationVariable( i, context ) ) @@ -350,7 +349,7 @@ private void createConceptDescription( final Property property, final Context co if ( !context.hasEnvironmentConceptDescription( property.getAspectModelUrn().toString() ) ) { final ConceptDescription conceptDescription = new DefaultConceptDescription.Builder() - .idShort( ID_PREFIX + characteristic.getName() ) + .idShort( characteristic.getName() ) .displayName( LangStringMapper.NAME.map( characteristic.getPreferredNames() ) ) .embeddedDataSpecifications( extractEmbeddedDataSpecification( property ) ) .id( DEFAULT_MAPPER.determineIdentifierFor( property ) ) @@ -364,7 +363,7 @@ private void createConceptDescription( final Aspect aspect, final Context contex if ( !context.hasEnvironmentConceptDescription( aspect.getAspectModelUrn().toString() ) ) { final ConceptDescription conceptDescription = new DefaultConceptDescription.Builder() - .idShort( ID_PREFIX + aspect.getName() ) + .idShort( aspect.getName() ) .displayName( LangStringMapper.NAME.map( aspect.getPreferredNames() ) ) .embeddedDataSpecifications( extractEmbeddedDataSpecification( aspect ) ) .id( DEFAULT_MAPPER.determineIdentifierFor( aspect ) ) @@ -478,7 +477,7 @@ private Environment visitCollectionProperty( final SubmodelElementBuilder builder = ( property ) -> new DefaultSubmodelElementList.Builder() - .idShort( ID_PREFIX + property.getName() ) + .idShort( property.getName() ) .typeValueListElement( AASSubmodelElements.DATA_ELEMENT ) .displayName( LangStringMapper.NAME.map( property.getPreferredNames() ) ) .description( LangStringMapper.TEXT.map( property.getDescriptions() ) ) @@ -548,7 +547,7 @@ public Environment visitEither( final SubmodelElementList eitherSubModelElements = new DefaultSubmodelElementList.Builder() - .idShort( ID_PREFIX + either.getName() ) + .idShort( either.getName() ) .typeValueListElement( AASSubmodelElements.DATA_ELEMENT ) .displayName( LangStringMapper.NAME.map( either.getPreferredNames() ) ) .description( LangStringMapper.TEXT.map( either.getDescriptions() ) ) From 462ffd9400bf0372b8c0c628b49d6a3edecf6b0b Mon Sep 17 00:00:00 2001 From: Johannes Kristan Date: Thu, 19 Oct 2023 22:08:21 +0200 Subject: [PATCH 03/14] Removes embeddedDataSpecification for Aspect Signed-off-by: Johannes Kristan --- .../org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java index 094cd8e00..576945075 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java @@ -195,7 +195,6 @@ public Environment visitAspect( final Aspect aspect, final Context context ) { .assetInformation( new DefaultAssetInformation.Builder() .assetKind( usedContext.getAssetKind() ) .build() ) - .embeddedDataSpecifications( extractEmbeddedDataSpecification( aspect ) ) .build(); usedContext.getEnvironment() .setAssetAdministrationShells( Collections.singletonList( administrationShell ) ); From f0cda919c41bbba9ed106729a5c7b8a1fcc5c390 Mon Sep 17 00:00:00 2001 From: Johannes Kristan Date: Thu, 19 Oct 2023 22:25:12 +0200 Subject: [PATCH 04/14] Replace Urn of element with static url as reference to DataSpecification Signed-off-by: Johannes Kristan --- .../eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java index 576945075..ac8ffaa9c 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java @@ -105,6 +105,8 @@ public class AspectModelAASVisitor implements AspectVisitor Date: Thu, 19 Oct 2023 23:05:17 +0200 Subject: [PATCH 05/14] Fixes writing of default language code from EN to en Signed-off-by: Johannes Kristan --- .../org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java index ac8ffaa9c..c0ac3a2a0 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java @@ -103,7 +103,7 @@ public class AspectModelAASVisitor implements AspectVisitor Date: Fri, 20 Oct 2023 00:07:26 +0200 Subject: [PATCH 06/14] Adds reference to submodel to AAS Signed-off-by: Johannes Kristan --- .../aspectmodel/aas/AspectModelAASVisitor.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java index c0ac3a2a0..a750b7e07 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java @@ -178,9 +178,11 @@ public Environment visitAspect( final Aspect aspect, final Context context ) { usedContext.setEnvironment( environment ); } + String submodelId = aspect.getAspectModelUrn().toString() + "/submodel"; + final Submodel submodel = usedContext.getSubmodel(); submodel.setIdShort( aspect.getName() ); - submodel.setId( aspect.getAspectModelUrn().toString() + "/submodel" ); + submodel.setId( submodelId ); submodel.setSemanticID( buildReferenceToConceptDescription( aspect ) ); submodel.setDescription( LangStringMapper.TEXT.map( aspect.getDescriptions() ) ); submodel.setKind( usedContext.getModelingKind() ); @@ -197,6 +199,7 @@ public Environment visitAspect( final Aspect aspect, final Context context ) { .assetInformation( new DefaultAssetInformation.Builder() .assetKind( usedContext.getAssetKind() ) .build() ) + .submodels( buildReferenceForSubmodel( submodelId ) ) .build(); usedContext.getEnvironment() .setAssetAdministrationShells( Collections.singletonList( administrationShell ) ); @@ -337,6 +340,18 @@ private Reference buildReferenceForSeeElement( final String seeReference ) { .build(); } + private Reference buildReferenceForSubmodel( final String submodelId ) { + final Key key = + new DefaultKey.Builder() + .type( KeyTypes.SUBMODEL ) + .value( submodelId ) + .build(); + return new DefaultReference.Builder() + .type( ReferenceTypes.MODEL_REFERENCE ) + .keys( key ) + .build(); + } + private List buildReferencesForSeeElements( final List seeReferences ) { return seeReferences.stream().map( this::buildReferenceForSeeElement ).collect( Collectors.toList() ); } From dea72d9917d00d3bb395764a72be57b17ad61a11 Mon Sep 17 00:00:00 2001 From: Johannes Kristan Date: Fri, 20 Oct 2023 00:31:46 +0200 Subject: [PATCH 07/14] Fixes further places with id_ prefix of idShort Signed-off-by: Johannes Kristan --- .../java/org/eclipse/esmf/aspectmodel/aas/Context.java | 2 +- .../esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/Context.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/Context.java index f661415e2..718b7451a 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/Context.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/Context.java @@ -166,7 +166,7 @@ public String getPropertyShortId() { .collect( Collectors.joining( "_" ) ); } - return "id_" + shortId; + return shortId; } /** diff --git a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java index 099166bdb..619a7905f 100644 --- a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java +++ b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java @@ -159,7 +159,7 @@ void testGenerateAasxFromBammAspectWithEntity() throws IOException, Deserializat "SubmodelElement is not a SubmodelElementCollection." ); final SubmodelElementCollection collection = (SubmodelElementCollection) env.getSubmodels().get( 0 ).getSubmodelElements().get( 0 ); assertEquals( 1, collection.getValue().size(), "Not exactly one Element in SubmodelElementCollection" ); - assertEquals( "id_entityProperty", collection.getValue().stream().findFirst().get().getIdShort() ); + assertEquals( "entityProperty", collection.getValue().stream().findFirst().get().getIdShort() ); getDataSpecificationIEC61360( "urn:samm:org.eclipse.esmf.test:1.0.0#testProperty", env ); } @@ -234,7 +234,7 @@ void testGenerateAasxFromBammAspectWithQuantifiable() throws IOException, Deseri assertEquals( 1, env.getSubmodels().size(), "Not exactly one Submodel in AAS." ); assertEquals( 1, env.getSubmodels().get( 0 ).getSubmodelElements().size(), 1, "Not exactly one Element in SubmodelElements." ); final SubmodelElement element = env.getSubmodels().get( 0 ).getSubmodelElements().get( 0 ); - assertEquals( "id_testProperty", element.getIdShort() ); + assertEquals( "testProperty", element.getIdShort() ); final DataSpecificationContent dataSpecificationContent = getDataSpecificationIEC61360( "urn:samm:org.eclipse.esmf.test:1.0.0#testProperty", env ); @@ -248,10 +248,10 @@ void testGenerateAasxFromBammWithConstraint() throws IOException, Deserializatio assertEquals( 1, env.getSubmodels().get( 0 ).getSubmodelElements().size(), 6, "Not exactly six Elements in SubmodelElements." ); final SubmodelElement submodelElement = env.getSubmodels().get( 0 ).getSubmodelElements().stream() - .filter( x -> x.getIdShort().equals( "id_stringLcProperty" ) ) + .filter( x -> x.getIdShort().equals( "stringLcProperty" ) ) .findFirst() .orElseThrow(); - assertEquals( "id_stringLcProperty", submodelElement.getIdShort() ); + assertEquals( "stringLcProperty", submodelElement.getIdShort() ); final Set semanticIds = Set.of( "urn:samm:org.eclipse.esmf.test:1.0.0#stringLcProperty", From d704dcca4d4fdc4babaf9b63f4a6d9b8fd32c095 Mon Sep 17 00:00:00 2001 From: Johannes Kristan Date: Fri, 20 Oct 2023 00:33:02 +0200 Subject: [PATCH 08/14] Removes Optional from urn Signed-off-by: Johannes Kristan --- .../org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java index a750b7e07..c46b9cf29 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java @@ -178,7 +178,7 @@ public Environment visitAspect( final Aspect aspect, final Context context ) { usedContext.setEnvironment( environment ); } - String submodelId = aspect.getAspectModelUrn().toString() + "/submodel"; + String submodelId = aspect.getAspectModelUrn().get().getUrn().toString() + "/submodel"; final Submodel submodel = usedContext.getSubmodel(); submodel.setIdShort( aspect.getName() ); From b10d1c4ad93ecd034b1a065aec70ba991c265fce Mon Sep 17 00:00:00 2001 From: Johannes Kristan Date: Fri, 20 Oct 2023 21:14:20 +0200 Subject: [PATCH 09/14] Adds quickfix for schemaLocation bug, which needs to be removed if fixed in AAS4j Signed-off-by: Johannes Kristan --- .../aas/AspectModelAASGenerator.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java index 2a48ff671..b63558da9 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java @@ -15,6 +15,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Map; import java.util.function.Function; @@ -106,7 +107,7 @@ protected ByteArrayOutputStream generateXmlOutput( final Map a try ( final ByteArrayOutputStream out = new ByteArrayOutputStream() ) { final XmlSerializer serializer = new XmlSerializer(); serializer.write( out, mergedEnvironment ); - return out; + return fixSchemaLocation( out ); } catch ( final SerializationException e ) { throw new IOException( e ); } @@ -148,9 +149,25 @@ protected ByteArrayOutputStream generate( Serializer serializer, Aspect aspect ) try ( final ByteArrayOutputStream out = new ByteArrayOutputStream() ) { serializer.write( out, environment ); + // TODO must be removed as soon as https://github.com/eclipse-esmf/esmf-sdk/issues/461 is fixed + if(serializer instanceof XmlSerializer) { + return fixSchemaLocation( out ); + } return out; } catch ( final SerializationException e ) { throw new IOException( e ); } } + + // TODO must be removed as soon as https://github.com/eclipse-esmf/esmf-sdk/issues/461 is fixed + private ByteArrayOutputStream fixSchemaLocation(ByteArrayOutputStream out) throws IOException { + String document = out.toString( StandardCharsets.UTF_8 ); + String result = document.replace( + "https://admin-shell.io/aas/3/0 AAS.xsd", + "https://admin-shell.io/aas/3/0/AAS.xsd" ); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + baos.write( result.getBytes( StandardCharsets.UTF_8 ) ); + return baos; + + } } From dac5297c95a68364132d18f865792b21d2300e9b Mon Sep 17 00:00:00 2001 From: Johannes Kristan Date: Sat, 21 Oct 2023 01:25:12 +0200 Subject: [PATCH 10/14] Removes string "unknown" in case example value not present Signed-off-by: Johannes Kristan --- .../java/org/eclipse/esmf/aspectmodel/aas/PropertyMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/PropertyMapper.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/PropertyMapper.java index 546097bc3..b5b02f57b 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/PropertyMapper.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/PropertyMapper.java @@ -40,7 +40,7 @@ public interface PropertyMapper { static String UNKNOWN_TYPE = "Unknown"; - static String UNKNOWN_EXAMPLE = UNKNOWN_TYPE; + static String UNKNOWN_EXAMPLE = ""; /** * Maps Aspect types to DataTypeDefXSD Schema types, with no explicit mapping defaulting to From 43c4475afdaeea41ba2bd3ed6200326f6b6f79b9 Mon Sep 17 00:00:00 2001 From: "Textor Andreas (BCI/ESW17)" Date: Wed, 8 Nov 2023 11:51:29 +0100 Subject: [PATCH 11/14] Address code smells --- .../aas/AspectModelAASGenerator.java | 23 +-- .../aas/AspectModelAASVisitor.java | 150 ++++++++---------- .../aas/AspectModelAASGeneratorTest.java | 97 +++++------ 3 files changed, 128 insertions(+), 142 deletions(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java index b63558da9..492bbd35b 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java @@ -21,6 +21,9 @@ import java.util.function.Function; import java.util.stream.Collectors; +import org.eclipse.esmf.metamodel.Aspect; + +import com.fasterxml.jackson.databind.JsonNode; import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.Serializer; import org.eclipse.digitaltwin.aas4j.v3.dataformat.aasx.AASXSerializer; @@ -30,9 +33,6 @@ import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultEnvironment; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodel; -import org.eclipse.esmf.metamodel.Aspect; - -import com.fasterxml.jackson.databind.JsonNode; /** * Generator that generates an AASX file containing an AAS submodel for a given Aspect model @@ -40,7 +40,7 @@ public class AspectModelAASGenerator { /** - * Generates an AASX archive file for a given Aspect and writes it to a given OutputStream provided by nameMapper + * Generates an AASX archive file for a given Aspect and writes it to a given OutputStream provided by {@code nameMapper} * * @param aspect the Aspect for which an AASX archive shall be generated * @param nameMapper a Name Mapper implementation, which provides an OutputStream for a given filename @@ -54,7 +54,7 @@ public void generateAASXFile( final Aspect aspect, final FunctionnameMapper + * Generates an AAS XML archive file for a given Aspect and writes it to a given OutputStream provided by {@code nameMapper} * * @param aspect the Aspect for which an xml file shall be generated * @param nameMapper a Name Mapper implementation, which provides an OutputStream for a given filename @@ -75,7 +75,7 @@ public void generateAasXmlFile( } /** - * Generates an AAS JSON file for a given Aspect and writes it to a given OutputStream provided by nameMapper + * Generates an AAS JSON file for a given Aspect and writes it to a given OutputStream provided by {@code nameMapper} * * @param aspect the Aspect for which an JSON shall be generated * @param nameMapper a Name Mapper implementation, which provides an OutputStream for a given filename @@ -95,7 +95,8 @@ protected ByteArrayOutputStream generateXmlOutput( final Map a aspectsWithData.entrySet().stream() .map( aspectWithData -> { final Submodel submodel = new DefaultSubmodel.Builder().build(); - final Environment environment = new DefaultEnvironment.Builder().submodels( Collections.singletonList( submodel ) ).build(); + final Environment environment = new DefaultEnvironment.Builder().submodels( Collections.singletonList( submodel ) ) + .build(); final Context context = new Context( environment, submodel ); context.setEnvironment( environment ); context.setAspectData( aspectWithData.getValue() ); @@ -114,9 +115,9 @@ protected ByteArrayOutputStream generateXmlOutput( final Map a } private Environment mergeEnvironments( final Map aspectEnvironments ) { - final Submodel submodel = new DefaultSubmodel.Builder().build(); return new DefaultEnvironment.Builder() - .assetAdministrationShells( aspectEnvironments.values().stream().flatMap( e -> e.getAssetAdministrationShells().stream() ).toList() ) + .assetAdministrationShells( + aspectEnvironments.values().stream().flatMap( e -> e.getAssetAdministrationShells().stream() ).toList() ) .submodels( aspectEnvironments.values().stream().flatMap( e -> e.getSubmodels().stream() ).toList() ) .conceptDescriptions( aspectEnvironments.values().stream().flatMap( e -> e.getConceptDescriptions().stream() ).toList() ) .build(); @@ -139,11 +140,11 @@ protected ByteArrayOutputStream generateXmlOutput( final Aspect aspect ) throws return generate( new XmlSerializer(), aspect ); } - protected ByteArrayOutputStream generateJsonOutput( Aspect aspect ) throws IOException { + protected ByteArrayOutputStream generateJsonOutput( final Aspect aspect ) throws IOException { return generate( new JsonSerializer(), aspect ); } - protected ByteArrayOutputStream generate( Serializer serializer, Aspect aspect ) throws IOException { + protected ByteArrayOutputStream generate( final Serializer serializer, final Aspect aspect ) throws IOException { final AspectModelAASVisitor visitor = new AspectModelAASVisitor(); final Environment environment = visitor.visitAspect( aspect, null ); diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java index c771222bc..5138e5f4f 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java @@ -178,7 +178,7 @@ public Environment visitAspect( final Aspect aspect, final Context context ) { usedContext.setEnvironment( environment ); } - String submodelId = aspect.getAspectModelUrn().get().getUrn().toString() + "/submodel"; + final String submodelId = aspect.getAspectModelUrn().get().getUrn().toString() + "/submodel"; final Submodel submodel = usedContext.getSubmodel(); submodel.setIdShort( aspect.getName() ); @@ -238,7 +238,8 @@ private Optional mapText( final Property property, final Contex return defaultResultForProperty; } else { LOG.error( String.format( - "Having a recursive property: %s which is not optional is not valid. Check the model. Property will be excluded from AAS mapping.", + "Having a recursive property: %s which is not optional is not valid. Check the model. Property will be excluded from " + + "AAS mapping.", property.getAspectModelUrn().map( AspectModelUrn::toString ).orElse( "(unknown)" ) ) ); } return defaultResultForProperty; @@ -273,13 +274,13 @@ private SubmodelElement decideOnMapping( final Property property, final Context private SubmodelElement decideOnMapping( final Type type, final Property property, final Context context ) { if ( type instanceof Entity ) { - return mapToAasSubModelElementCollection( (Entity) type, property.getName(), context ); + return mapToAasSubModelElementCollection( (Entity) type, context ); } else { return findPropertyMapper( property ).mapToAasProperty( type, property, context ); } } - private SubmodelElementCollection mapToAasSubModelElementCollection( final Entity entity, final String name, final Context context ) { + private SubmodelElementCollection mapToAasSubModelElementCollection( final Entity entity, final Context context ) { final List submodelElements = visitProperties( entity.getAllProperties(), context ); return new DefaultSubmodelElementCollection.Builder() @@ -295,14 +296,12 @@ private Operation mapText( final org.eclipse.esmf.metamodel.Operation operation, .displayName( LangStringMapper.NAME.map( operation.getPreferredNames() ) ) .description( LangStringMapper.TEXT.map( operation.getDescriptions() ) ) .idShort( operation.getName() ) - .inputVariables( - operation.getInput().stream() - .map( i -> mapOperationVariable( i, context ) ) - .collect( Collectors.toList() ) ) - .outputVariables( - operation.getOutput().stream() - .map( i -> mapOperationVariable( i, context ) ) - .collect( Collectors.toList() ) ) + .inputVariables( operation.getInput().stream() + .map( i -> mapOperationVariable( i, context ) ) + .collect( Collectors.toList() ) ) + .outputVariables( operation.getOutput().stream() + .map( i -> mapOperationVariable( i, context ) ) + .collect( Collectors.toList() ) ) .build(); } @@ -310,30 +309,27 @@ private OperationVariable mapOperationVariable( final Property property, final C return new DefaultOperationVariable.Builder().value( mapText( property, context ).orElseThrow() ).build(); } - private Reference buildReferenceToEnumValue( final Enumeration enumeration, final Object value ) { - final Key key = - new DefaultKey.Builder() - .type( KeyTypes.DATA_ELEMENT ) - .value( DEFAULT_MAPPER.determineIdentifierFor( enumeration ) + ":" + value.toString() ) - .build(); + private Reference buildReferenceToEnumValue( final Enumeration enumeration, final String value ) { + final Key key = new DefaultKey.Builder() + .type( KeyTypes.DATA_ELEMENT ) + .value( DEFAULT_MAPPER.determineIdentifierFor( enumeration ) + ":" + value ) + .build(); return new DefaultReference.Builder().type( ReferenceTypes.MODEL_REFERENCE ).keys( key ).build(); } private Reference buildReferenceToConceptDescription( final Aspect aspect ) { - final Key key = - new DefaultKey.Builder() - .type( KeyTypes.CONCEPT_DESCRIPTION ) - .value( DEFAULT_MAPPER.determineIdentifierFor( aspect ) ) - .build(); + final Key key = new DefaultKey.Builder() + .type( KeyTypes.CONCEPT_DESCRIPTION ) + .value( DEFAULT_MAPPER.determineIdentifierFor( aspect ) ) + .build(); return new DefaultReference.Builder().type( ReferenceTypes.MODEL_REFERENCE ).keys( key ).build(); } private Reference buildReferenceForSeeElement( final String seeReference ) { - final Key key = - new DefaultKey.Builder() - .type( KeyTypes.GLOBAL_REFERENCE ) - .value( seeReference ) - .build(); + final Key key = new DefaultKey.Builder() + .type( KeyTypes.GLOBAL_REFERENCE ) + .value( seeReference ) + .build(); return new DefaultReference.Builder() .type( ReferenceTypes.EXTERNAL_REFERENCE ) .keys( key ) @@ -341,11 +337,10 @@ private Reference buildReferenceForSeeElement( final String seeReference ) { } private Reference buildReferenceForSubmodel( final String submodelId ) { - final Key key = - new DefaultKey.Builder() - .type( KeyTypes.SUBMODEL ) - .value( submodelId ) - .build(); + final Key key = new DefaultKey.Builder() + .type( KeyTypes.SUBMODEL ) + .value( submodelId ) + .build(); return new DefaultReference.Builder() .type( ReferenceTypes.MODEL_REFERENCE ) .keys( key ) @@ -433,11 +428,11 @@ private DataSpecificationIec61360 extractDataSpecificationContent( final Aspect .preferredName( preferredNames ) .shortName( LangStringMapper.SHORT_NAME.createLangString( aspect.getName(), DEFAULT_LOCALE ) ) .build(); - } private DataTypeIec61360 mapIEC61360DataType( final Optional characteristic ) { - return mapIEC61360DataType( characteristic.flatMap( Characteristic::getDataType ).map( Type::getUrn ).orElse( RDF.langString.getURI() ) ); + return mapIEC61360DataType( + characteristic.flatMap( Characteristic::getDataType ).map( Type::getUrn ).orElse( RDF.langString.getURI() ) ); } private DataTypeIec61360 mapIEC61360DataType( final Characteristic characteristic ) { @@ -457,27 +452,23 @@ private void createSubmodelElement( final SubmodelElementBuilder op, final Conte } @Override - public Environment visitCharacteristic( - final Characteristic characteristic, final Context context ) { + public Environment visitCharacteristic( final Characteristic characteristic, final Context context ) { createSubmodelElement( ( property ) -> decideOnMapping( property, context ), context ); return context.getEnvironment(); } @Override - public Environment visitCollection( - final Collection collection, final Context context ) { + public Environment visitCollection( final Collection collection, final Context context ) { return visitCollectionProperty( collection, context ); } @Override - public Environment visitList( - final org.eclipse.esmf.characteristic.List list, final Context context ) { + public Environment visitList( final org.eclipse.esmf.characteristic.List list, final Context context ) { return visitCollectionProperty( list, context ); } @Override - public Environment visitSet( - final org.eclipse.esmf.characteristic.Set set, final Context context ) { + public Environment visitSet( final org.eclipse.esmf.characteristic.Set set, final Context context ) { return visitCollectionProperty( set, context ); // this type is not available in AAS4J } @@ -490,28 +481,26 @@ public Environment visitSortedSet( private Environment visitCollectionProperty( final T collection, final Context context ) { - final SubmodelElementBuilder builder = - ( property ) -> - new DefaultSubmodelElementList.Builder() - .idShort( property.getName() ) - .typeValueListElement( AASSubmodelElements.DATA_ELEMENT ) - .displayName( LangStringMapper.NAME.map( property.getPreferredNames() ) ) - .description( LangStringMapper.TEXT.map( property.getDescriptions() ) ) - .value( List.of( decideOnMapping( property, context ) ) ) - .build(); + final SubmodelElementBuilder builder = property -> + new DefaultSubmodelElementList.Builder() + .idShort( property.getName() ) + .typeValueListElement( AASSubmodelElements.DATA_ELEMENT ) + .displayName( LangStringMapper.NAME.map( property.getPreferredNames() ) ) + .description( LangStringMapper.TEXT.map( property.getDescriptions() ) ) + .value( List.of( decideOnMapping( property, context ) ) ) + .build(); final Optional rawValue = context.getRawPropertyValue(); return rawValue.map( node -> { if ( node instanceof final ArrayNode arrayNode ) { - final SubmodelElementBuilder listBuilder = - ( property ) -> { - final var values = getValues( collection, property, context, arrayNode ); - return new DefaultSubmodelElementList.Builder() - .idShort( property.getName() ) - .displayName( LangStringMapper.NAME.map( property.getPreferredNames() ) ) - .description( LangStringMapper.TEXT.map( property.getDescriptions() ) ) - .value( values ) - .build(); - }; + final SubmodelElementBuilder listBuilder = property -> { + final List values = getValues( collection, property, context, arrayNode ); + return new DefaultSubmodelElementList.Builder() + .idShort( property.getName() ) + .displayName( LangStringMapper.NAME.map( property.getPreferredNames() ) ) + .description( LangStringMapper.TEXT.map( property.getDescriptions() ) ) + .value( values ) + .build(); + }; createSubmodelElement( listBuilder, context ); return context.getEnvironment(); } @@ -533,7 +522,7 @@ private List getValues( final T collecti .collect( Collectors.joining( "," ) ) .getBytes( StandardCharsets.UTF_8 ) ).build() ); } else { - final var values = StreamSupport.stream( arrayNode.spliterator(), false ) + final List values = StreamSupport.stream( arrayNode.spliterator(), false ) .map( n -> { context.iterate( property ); return decideOnMapping( property, context ); @@ -550,10 +539,9 @@ private List getValues( final T collecti // in the result and have to be manually selected. // When generating Submodels where data is given however only the present side is added. @Override - public Environment visitEither( - final Either either, final Context context ) { + public Environment visitEither( final Either either, final Context context ) { final List submodelElements = new ArrayList<>(); - final var property = context.getProperty(); + final Property property = context.getProperty(); either.getLeft().getDataType() .flatMap( dataType -> handleEitherField( "left", either.getLeft(), property, context ) ) .ifPresent( submodelElements::add ); @@ -575,7 +563,7 @@ public Environment visitEither( /** * Handles one {@code Either} field depending on whether a submodel template or a submodel is generated. - * + *

* In the latter case, a synthetic property is used to access the serialized data and retrieve the value to be added. * * @param field the name of the {@code Either} field ({@code left} or {@code right}) @@ -588,7 +576,7 @@ private Optional handleEitherField( final String field, final C final Property eitherProperty, final Context context ) { Optional result = Optional.empty(); if ( context.getModelingKind().equals( ModellingKind.INSTANCE ) ) { - final var fieldProperty = createProperty( eitherProperty.getMetaModelVersion(), field, fieldCharacteristic ); + final Property fieldProperty = createProperty( eitherProperty.getMetaModelVersion(), field, fieldCharacteristic ); context.setProperty( fieldProperty ); if ( context.getRawPropertyValue().isPresent() ) { result = fieldCharacteristic.getDataType().map( dataType -> decideOnMapping( dataType, context.getProperty(), context ) ); @@ -603,14 +591,15 @@ private Optional handleEitherField( final String field, final C private Property createProperty( final KnownVersion modelVersion, final String propertyName, final Characteristic characteristic ) { final MetaModelBaseAttributes propertyAttributes = - MetaModelBaseAttributes.from( modelVersion, AspectModelUrn.fromUrn( new SAMM( modelVersion ).Property().getURI() ), propertyName ); - return new org.eclipse.esmf.metamodel.impl.DefaultProperty( propertyAttributes, Optional.of( characteristic ), Optional.empty(), true, false, + MetaModelBaseAttributes.from( modelVersion, AspectModelUrn.fromUrn( new SAMM( modelVersion ).Property().getURI() ), + propertyName ); + return new org.eclipse.esmf.metamodel.impl.DefaultProperty( propertyAttributes, Optional.of( characteristic ), Optional.empty(), true, + false, Optional.empty(), false, Optional.empty() ); } @Override - public Environment visitQuantifiable( - final Quantifiable quantifiable, final Context context ) { + public Environment visitQuantifiable( final Quantifiable quantifiable, final Context context ) { createSubmodelElement( ( property ) -> decideOnMapping( property, context ), context ); if ( quantifiable.getUnit().isPresent() ) { @@ -628,22 +617,19 @@ public Environment visitQuantifiable( } @Override - public Environment visitMeasurement( - final Measurement measurement, final Context context ) { + public Environment visitMeasurement( final Measurement measurement, final Context context ) { // No special handling required can use Quantifiable mapping implementation return visitQuantifiable( measurement, context ); } @Override - public Environment visitDuration( - final Duration duration, final Context context ) { + public Environment visitDuration( final Duration duration, final Context context ) { // No special handling required can use Quantifiable mapping implementation return visitQuantifiable( duration, context ); } @Override - public Environment visitEnumeration( - final Enumeration enumeration, final Context context ) { + public Environment visitEnumeration( final Enumeration enumeration, final Context context ) { createSubmodelElement( ( property ) -> decideOnMapping( property, context ), context ); final ConceptDescription conceptDescription = @@ -680,16 +666,14 @@ public Environment visitState( final State state, final Context context ) { } @Override - public Environment visitSingleEntity( - final SingleEntity singleEntity, final Context context ) { + public Environment visitSingleEntity( final SingleEntity singleEntity, final Context context ) { // Same handling as characteristics return visitCharacteristic( singleEntity, context ); } @Override - public Environment visitStructuredValue( - final StructuredValue structuredValue, final Context context ) { - // https://openmanufacturingplatform.github.io/sds-documentation/bamm-specification/v1.0.0/modeling-guidelines.html#declaring-structured-value + public Environment visitStructuredValue( final StructuredValue structuredValue, final Context context ) { + // https://eclipse-esmf.github.io/samm-specification/snapshot/characteristics.html#structured-value-characteristic // AAS cannot handle structuredValues, so we can handle them as ordinary Characteristics return visitCharacteristic( structuredValue, context ); } diff --git a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java index bd041bf87..7e2bd0bc3 100644 --- a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java +++ b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java @@ -13,7 +13,9 @@ package org.eclipse.esmf.aspectmodel.aas; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.InstanceOfAssertFactories.type; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; @@ -23,7 +25,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import javax.xml.XMLConstants; import javax.xml.transform.stream.StreamSource; @@ -31,7 +32,14 @@ import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; -import org.assertj.core.api.InstanceOfAssertFactories; +import org.eclipse.esmf.aspectmodel.resolver.services.VersionedModel; +import org.eclipse.esmf.metamodel.Aspect; +import org.eclipse.esmf.metamodel.loader.AspectModelLoader; +import org.eclipse.esmf.samm.KnownVersion; +import org.eclipse.esmf.test.TestAspect; +import org.eclipse.esmf.test.TestResources; + +import com.fasterxml.jackson.databind.JsonNode; import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.XmlDeserializer; import org.eclipse.digitaltwin.aas4j.v3.model.AbstractLangString; @@ -46,20 +54,12 @@ import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement; import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementCollection; import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementList; -import org.eclipse.esmf.aspectmodel.resolver.services.VersionedModel; -import org.eclipse.esmf.metamodel.Aspect; -import org.eclipse.esmf.metamodel.loader.AspectModelLoader; -import org.eclipse.esmf.samm.KnownVersion; -import org.eclipse.esmf.test.TestAspect; -import org.eclipse.esmf.test.TestResources; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; -import com.fasterxml.jackson.databind.JsonNode; - class AspectModelAASGeneratorTest { // The AAS XML Schema is also present in the AAS4j library for testing purposes. So we can read @@ -77,34 +77,34 @@ void generateAasxWithAspectDataForMultilanguageText() throws IOException, Deseri assertThat( subModel.getSubmodelElements() ) .singleElement() .satisfies( property -> { - assertThat( property ).asInstanceOf( InstanceOfAssertFactories.type( MultiLanguageProperty.class ) ) - .extracting( mlp -> mlp.getValue() ) + assertThat( property ).asInstanceOf( type( MultiLanguageProperty.class ) ) + .extracting( MultiLanguageProperty::getValue ) .asList() .hasSize( 2 ) .allSatisfy( langString -> { - List.of( "en", "de" ).contains( ((AbstractLangString) langString).getLanguage() ); + assertThat( List.of( "en", "de" ) ).contains( ((AbstractLangString) langString).getLanguage() ); } ); } ); } ); } @Test - void generateAasxWithAspectDataForEitherWithEntity() throws IOException, DeserializationException, SAXException { + void generateAasxWithAspectDataForEitherWithEntity() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspectWithData( TestAspect.ASPECT_WITH_EITHER_WITH_COMPLEX_TYPES ); assertThat( env.getSubmodels() ) .singleElement() .satisfies( subModel -> { assertThat( subModel.getSubmodelElements() ) .anySatisfy( sme -> { - assertThat( sme ).asInstanceOf( InstanceOfAssertFactories.type( SubmodelElementList.class ) ) - .extracting( smel -> smel.getValue() ) + assertThat( sme ).asInstanceOf( type( SubmodelElementList.class ) ) + .extracting( SubmodelElementList::getValue ) .asList() .anySatisfy( entity -> { - assertThat( entity ).asInstanceOf( InstanceOfAssertFactories.type( SubmodelElementCollection.class ) ) - .extracting( smec -> smec.getValue() ) + assertThat( entity ).asInstanceOf( type( SubmodelElementCollection.class ) ) + .extracting( SubmodelElementCollection::getValue ) .asList() - .singleElement( InstanceOfAssertFactories.type( Property.class ) ) - .extracting( entityProperty -> entityProperty.getValue() ) + .singleElement( type( Property.class ) ) + .extracting( Property::getValue ) .isEqualTo( "The result" ); } ); } ); @@ -112,22 +112,22 @@ void generateAasxWithAspectDataForEitherWithEntity() throws IOException, Deseria } @Test - void generateAasxWithAspectDataForNestedEntityLists() throws IOException, DeserializationException, SAXException { + void generateAasxWithAspectDataForNestedEntityLists() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspectWithData( TestAspect.ASPECT_WITH_NESTED_ENTITY_LIST ); assertThat( env.getSubmodels() ) .singleElement() .satisfies( subModel -> { assertThat( subModel.getSubmodelElements() ) .anySatisfy( sme -> { - assertThat( sme ).asInstanceOf( InstanceOfAssertFactories.type( SubmodelElementList.class ) ) - .extracting( smel -> smel.getValue() ) + assertThat( sme ).asInstanceOf( type( SubmodelElementList.class ) ) + .extracting( SubmodelElementList::getValue ) .asList() .anySatisfy( entity -> { - assertThat( entity ).asInstanceOf( InstanceOfAssertFactories.type( SubmodelElementCollection.class ) ) - .extracting( smec -> smec.getValue() ) + assertThat( entity ).asInstanceOf( type( SubmodelElementCollection.class ) ) + .extracting( SubmodelElementCollection::getValue ) .asList() .anySatisfy( property -> { - assertThat( property ).asInstanceOf( InstanceOfAssertFactories.type( Property.class ) ) + assertThat( property ).asInstanceOf( type( Property.class ) ) .extracting( Property::getValue ) .isEqualTo( "2.25" ); } ); @@ -137,7 +137,7 @@ void generateAasxWithAspectDataForNestedEntityLists() throws IOException, Deseri } @Test - void testGenerateAasxFromBammAspectWithListAndAdditionalProperty() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithListAndAdditionalProperty() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_LIST_AND_ADDITIONAL_PROPERTY ); assertEquals( 3, env.getConceptDescriptions().size() ); assertEquals( 1, env.getSubmodels().size() ); @@ -151,7 +151,7 @@ void testGenerateAasxFromBammAspectWithListAndAdditionalProperty() throws IOExce } @Test - void testGenerateAasxFromBammAspectWithEntity() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithEntity() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_ENTITY ); assertEquals( 1, env.getSubmodels().size(), "Not exactly one Submodel in AAS." ); assertEquals( 1, env.getSubmodels().get( 0 ).getSubmodelElements().size(), "Not exactly one SubmodelElement in Submodel." ); @@ -165,7 +165,7 @@ void testGenerateAasxFromBammAspectWithEntity() throws IOException, Deserializat } @Test - void testGenerateAasxFromBammAspectWithCollection() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithCollection() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_COLLECTION ); assertEquals( 1, env.getSubmodels().size(), "Not exactly one Submodel in AAS." ); assertEquals( 1, env.getSubmodels().get( 0 ).getSubmodelElements().size(), "Not exactly one SubmodelElement in AAS." ); @@ -177,7 +177,7 @@ void testGenerateAasxFromBammAspectWithCollection() throws IOException, Deserial } @Test - void testGenerateAasxFromBammAspectWithList() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithList() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_LIST ); assertEquals( 1, env.getSubmodels().size(), "Not exactly one Submodel in AAS." ); assertEquals( 1, env.getSubmodels().get( 0 ).getSubmodelElements().size(), "Not exactly one SubmodelElement in AAS." ); @@ -189,7 +189,7 @@ void testGenerateAasxFromBammAspectWithList() throws IOException, Deserializatio } @Test - void testGenerateAasxFromBammAspectWithSet() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithSet() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_SET ); assertEquals( 1, env.getSubmodels().size(), "Not exactly one Submodel in AAS." ); assertEquals( 1, env.getSubmodels().get( 0 ).getSubmodelElements().size(), "Not exactly one SubmodelElement in AAS." ); @@ -201,7 +201,7 @@ void testGenerateAasxFromBammAspectWithSet() throws IOException, Deserialization } @Test - void testGenerateAasxFromBammAspectWithSortedSet() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithSortedSet() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_SORTED_SET ); assertEquals( 1, env.getSubmodels().size(), "Not exactly one Submodel in AAS." ); assertEquals( 1, env.getSubmodels().get( 0 ).getSubmodelElements().size(), "Not exactly one SubmodelElement in AAS." ); @@ -213,13 +213,14 @@ void testGenerateAasxFromBammAspectWithSortedSet() throws IOException, Deseriali } @Test - void testGenerateAasxFromBammAspectWithEitherWithComplexTypes() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithEitherWithComplexTypes() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_EITHER_WITH_COMPLEX_TYPES ); assertEquals( 1, env.getSubmodels().size(), "Not exactly one Submodel in AAS." ); assertEquals( 1, env.getSubmodels().get( 0 ).getSubmodelElements().size(), 1, "Not exactly one Element in SubmodelElements." ); final SubmodelElementList elementCollection = ((SubmodelElementList) env.getSubmodels().get( 0 ).getSubmodelElements().get( 0 )); final Set testValues = Set.of( "RightEntity", "LeftEntity" ); - assertTrue( elementCollection.getValue().stream().anyMatch( x -> testValues.contains( x.getIdShort() ) ), "Neither left nor right entity contained." ); + assertTrue( elementCollection.getValue().stream().anyMatch( x -> testValues.contains( x.getIdShort() ) ), + "Neither left nor right entity contained." ); final Set semanticIds = Set.of( "urn:samm:org.eclipse.esmf.test:1.0.0#result", @@ -229,14 +230,15 @@ void testGenerateAasxFromBammAspectWithEitherWithComplexTypes() throws IOExcepti } @Test - void testGenerateAasxFromBammAspectWithQuantifiable() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithQuantifiable() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_QUANTIFIABLE_WITH_UNIT ); assertEquals( 1, env.getSubmodels().size(), "Not exactly one Submodel in AAS." ); assertEquals( 1, env.getSubmodels().get( 0 ).getSubmodelElements().size(), 1, "Not exactly one Element in SubmodelElements." ); final SubmodelElement element = env.getSubmodels().get( 0 ).getSubmodelElements().get( 0 ); assertEquals( "testProperty", element.getIdShort() ); - final DataSpecificationContent dataSpecificationContent = getDataSpecificationIEC61360( "urn:samm:org.eclipse.esmf.test:1.0.0#testProperty", env ); + final DataSpecificationContent dataSpecificationContent = getDataSpecificationIEC61360( + "urn:samm:org.eclipse.esmf.test:1.0.0#testProperty", env ); assertEquals( "percent", ((DataSpecificationIec61360) dataSpecificationContent).getUnit(), "Unit is not percent" ); } @@ -265,13 +267,13 @@ void testGenerateAasxFromBammWithConstraint() throws IOException, Deserializatio } @Test - void testGenerateAasxFromBammAspectWithRecursivePropertyWithOptional() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithRecursivePropertyWithOptional() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_RECURSIVE_PROPERTY_WITH_OPTIONAL ); assertEquals( 1, env.getSubmodels().size(), "Not exactly one Submodel in AAS." ); } @Test - void testGenerateAasxFromBammAspectWithCode() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithCode() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_CODE ); assertEquals( 2, env.getConceptDescriptions().size() ); assertEquals( 1, env.getSubmodels().size() ); @@ -283,7 +285,7 @@ void testGenerateAasxFromBammAspectWithCode() throws IOException, Deserializatio } @Test - void testGenerateAasxFromBammAspectWithEnumeration() throws IOException, DeserializationException { + void testGenerateAasxFromAspectModelWithEnumeration() throws IOException, DeserializationException { final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_ENUMERATION ); assertEquals( 2, env.getConceptDescriptions().size() ); @@ -320,7 +322,7 @@ public void testGeneration( final TestAspect testAspect ) throws IOException, De final ByteArrayOutputStream baos = getByteArrayOutputStreamFromAspect( testAspect ); final byte[] xmlFile = baos.toByteArray(); final Environment env = loadAASX( new ByteArrayInputStream( xmlFile ) ); - assertTrue( env.getSubmodels().size() >= 1, "No Submodel in AAS present." ); + assertFalse( env.getSubmodels().isEmpty(), "No Submodel in AAS present." ); try { validate( new ByteArrayInputStream( xmlFile ) ); } catch ( final SAXException e ) { @@ -330,7 +332,6 @@ public void testGeneration( final TestAspect testAspect ) throws IOException, De final String model = "AAS XML file causing the Exception. \nProblem within line " + line + ": " + faultyLine + "\n" + xmlContent; throw new SAXException( model, e ); } - } private void checkDataSpecificationIEC61360( final Set semanticIds, final Environment env ) { @@ -342,10 +343,11 @@ private DataSpecificationContent getDataSpecificationIEC61360( final String sema final List filteredConceptDescriptions = conceptDescriptions.stream() .filter( x -> x.getId().equals( semanticId ) ) - .collect( Collectors.toList() ); + .toList(); assertEquals( 1, filteredConceptDescriptions.size(), "Not exactly 1 ConceptDescription for semanticId. " + semanticId ); - final List embeddedDataSpecifications = filteredConceptDescriptions.get( 0 ).getEmbeddedDataSpecifications(); + final List embeddedDataSpecifications = filteredConceptDescriptions.get( 0 ) + .getEmbeddedDataSpecifications(); assertEquals( 1, embeddedDataSpecifications.size(), "Not exactly 1 EmbeddedDataSpecification for semanticId. " + semanticId ); assertTrue( embeddedDataSpecifications.stream().findFirst().isPresent(), "There is no EmbeddedDataSpecification" ); @@ -356,7 +358,7 @@ private Environment getAssetAdministrationShellFromAspect( final TestAspect test throws DeserializationException, IOException { final Aspect aspect = loadAspect( testAspect ); final ByteArrayOutputStream out = generator.generateXmlOutput( aspect ); - return loadAASX( out.toByteArray(), testAspect ); + return loadAASX( out.toByteArray() ); } private Environment getAssetAdministrationShellFromAspectWithData( final TestAspect testAspect ) @@ -365,7 +367,7 @@ private Environment getAssetAdministrationShellFromAspectWithData( final TestAsp final JsonNode aspectData = loadPayload( testAspect ); final ByteArrayOutputStream out = generator.generateXmlOutput( Map.of( aspect, aspectData ) ); final var data = out.toByteArray(); - return loadAASX( data, testAspect ); + return loadAASX( data ); } private ByteArrayOutputStream getByteArrayOutputStreamFromAspect( final TestAspect testAspect ) @@ -374,7 +376,7 @@ private ByteArrayOutputStream getByteArrayOutputStreamFromAspect( final TestAspe return generator.generateXmlOutput( aspect ); } - private void validate( ByteArrayInputStream xmlStream ) throws IOException, SAXException { + private void validate( final ByteArrayInputStream xmlStream ) throws IOException, SAXException { final SchemaFactory factory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); @@ -382,7 +384,6 @@ private void validate( ByteArrayInputStream xmlStream ) throws IOException, SAXE new StreamSource( getClass().getResourceAsStream( XML_XSD_AAS_SCHEMA_LOCATION ) ) ); final Validator validator = schema.newValidator(); validator.validate( new StreamSource( xmlStream ), null ); - } private Aspect loadAspect( final TestAspect testAspect ) { @@ -399,7 +400,7 @@ private Environment loadAASX( final ByteArrayInputStream byteStream ) throws Des return deserializer.read( byteStream ); } - private Environment loadAASX( final byte[] data, final TestAspect testAspect ) throws DeserializationException { + private Environment loadAASX( final byte[] data ) throws DeserializationException { final XmlDeserializer deserializer = new XmlDeserializer(); return deserializer.read( new ByteArrayInputStream( data ) ); } From 605e74dba03779e661070d412f39d537ce125f5e Mon Sep 17 00:00:00 2001 From: "Textor Andreas (BCI/ESW17)" Date: Thu, 9 Nov 2023 10:27:43 +0100 Subject: [PATCH 12/14] Remove unnecessary rewriting of XML schema location --- .../aas/AspectModelAASGenerator.java | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java index 492bbd35b..499c6cff1 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGenerator.java @@ -15,7 +15,6 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Map; import java.util.function.Function; @@ -108,7 +107,7 @@ protected ByteArrayOutputStream generateXmlOutput( final Map a try ( final ByteArrayOutputStream out = new ByteArrayOutputStream() ) { final XmlSerializer serializer = new XmlSerializer(); serializer.write( out, mergedEnvironment ); - return fixSchemaLocation( out ); + return out; } catch ( final SerializationException e ) { throw new IOException( e ); } @@ -150,25 +149,9 @@ protected ByteArrayOutputStream generate( final Serializer serializer, final Asp try ( final ByteArrayOutputStream out = new ByteArrayOutputStream() ) { serializer.write( out, environment ); - // TODO must be removed as soon as https://github.com/eclipse-esmf/esmf-sdk/issues/461 is fixed - if(serializer instanceof XmlSerializer) { - return fixSchemaLocation( out ); - } return out; } catch ( final SerializationException e ) { throw new IOException( e ); } } - - // TODO must be removed as soon as https://github.com/eclipse-esmf/esmf-sdk/issues/461 is fixed - private ByteArrayOutputStream fixSchemaLocation(ByteArrayOutputStream out) throws IOException { - String document = out.toString( StandardCharsets.UTF_8 ); - String result = document.replace( - "https://admin-shell.io/aas/3/0 AAS.xsd", - "https://admin-shell.io/aas/3/0/AAS.xsd" ); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write( result.getBytes( StandardCharsets.UTF_8 ) ); - return baos; - - } } From 12537b9b7c4a9b422c9edd1aeeec551f9b98667a Mon Sep 17 00:00:00 2001 From: "Textor Andreas (BCI/ESW17)" Date: Thu, 9 Nov 2023 10:35:29 +0100 Subject: [PATCH 13/14] Properly serialize enumeration values --- .../aas/AspectModelAASVisitor.java | 106 +++++++++++------- .../aas/AspectModelAASGeneratorTest.java | 6 + 2 files changed, 74 insertions(+), 38 deletions(-) diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java index 5138e5f4f..781ae2168 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASVisitor.java @@ -23,6 +23,37 @@ import java.util.stream.Collectors; import java.util.stream.StreamSupport; +import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; +import org.eclipse.esmf.aspectmodel.vocabulary.SAMM; +import org.eclipse.esmf.characteristic.Code; +import org.eclipse.esmf.characteristic.Collection; +import org.eclipse.esmf.characteristic.Duration; +import org.eclipse.esmf.characteristic.Either; +import org.eclipse.esmf.characteristic.Enumeration; +import org.eclipse.esmf.characteristic.Measurement; +import org.eclipse.esmf.characteristic.Quantifiable; +import org.eclipse.esmf.characteristic.SingleEntity; +import org.eclipse.esmf.characteristic.SortedSet; +import org.eclipse.esmf.characteristic.State; +import org.eclipse.esmf.characteristic.StructuredValue; +import org.eclipse.esmf.characteristic.Trait; +import org.eclipse.esmf.metamodel.Aspect; +import org.eclipse.esmf.metamodel.Characteristic; +import org.eclipse.esmf.metamodel.CollectionValue; +import org.eclipse.esmf.metamodel.Entity; +import org.eclipse.esmf.metamodel.EntityInstance; +import org.eclipse.esmf.metamodel.ModelElement; +import org.eclipse.esmf.metamodel.Property; +import org.eclipse.esmf.metamodel.Scalar; +import org.eclipse.esmf.metamodel.ScalarValue; +import org.eclipse.esmf.metamodel.Type; +import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; +import org.eclipse.esmf.metamodel.visitor.AspectVisitor; +import org.eclipse.esmf.samm.KnownVersion; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.google.common.collect.ImmutableMap; import org.apache.jena.rdf.model.Resource; import org.apache.jena.rdf.model.ResourceFactory; import org.apache.jena.vocabulary.RDF; @@ -67,40 +98,12 @@ import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodelElementList; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultValueList; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultValueReferencePair; -import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; -import org.eclipse.esmf.aspectmodel.vocabulary.SAMM; -import org.eclipse.esmf.characteristic.Code; -import org.eclipse.esmf.characteristic.Collection; -import org.eclipse.esmf.characteristic.Duration; -import org.eclipse.esmf.characteristic.Either; -import org.eclipse.esmf.characteristic.Enumeration; -import org.eclipse.esmf.characteristic.Measurement; -import org.eclipse.esmf.characteristic.Quantifiable; -import org.eclipse.esmf.characteristic.SingleEntity; -import org.eclipse.esmf.characteristic.SortedSet; -import org.eclipse.esmf.characteristic.State; -import org.eclipse.esmf.characteristic.StructuredValue; -import org.eclipse.esmf.characteristic.Trait; -import org.eclipse.esmf.metamodel.Aspect; -import org.eclipse.esmf.metamodel.Characteristic; -import org.eclipse.esmf.metamodel.Entity; -import org.eclipse.esmf.metamodel.ModelElement; -import org.eclipse.esmf.metamodel.Property; -import org.eclipse.esmf.metamodel.Scalar; -import org.eclipse.esmf.metamodel.Type; -import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; -import org.eclipse.esmf.metamodel.visitor.AspectVisitor; -import org.eclipse.esmf.samm.KnownVersion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.google.common.collect.ImmutableMap; - public class AspectModelAASVisitor implements AspectVisitor { - private static final Logger LOG = LoggerFactory.getLogger( AspectModelAASVisitor.class ); + private static final ValueSerializer VALUE_SERIALIZER = new ValueSerializer(); public static final String ADMIN_SHELL_NAME = "defaultAdminShell"; public static final String DEFAULT_LOCALE = "en"; @@ -642,17 +645,16 @@ public Environment visitEnumeration( final Enumeration enumeration, final Contex dataSpecificationContent.setDataType( mapIEC61360DataType( enumeration ) ); final List valueReferencePairs = enumeration.getValues().stream() - .map( - x -> - new DefaultValueReferencePair.Builder() - .value( x.toString() ) - .valueID( buildReferenceToEnumValue( enumeration, x ) ) - .build() ) + .map( enumerationValue -> { + final String value = enumerationValue.accept( VALUE_SERIALIZER, enumeration ); + return new DefaultValueReferencePair.Builder() + .value( value ) + .valueID( buildReferenceToEnumValue( enumeration, value ) ) + .build(); + } ) .collect( Collectors.toList() ); - final ValueList valueList = - new DefaultValueList.Builder().valueReferencePairs( valueReferencePairs ).build(); - + final ValueList valueList = new DefaultValueList.Builder().valueReferencePairs( valueReferencePairs ).build(); dataSpecificationContent.setValueList( valueList ); } @@ -691,4 +693,32 @@ public Environment visitTrait( final Trait trait, final Context context ) { // ignored and have to be deduced by resolving a SAMM model referenced by its semanticID return visitCharacteristic( trait.getBaseCharacteristic(), context ); } + + public static class ValueSerializer implements AspectVisitor { + @Override + public String visitBase( final ModelElement modelElement, final ModelElement context ) { + throw new UnsupportedOperationException(); + } + + @Override + public String visitScalarValue( final ScalarValue value, final ModelElement context ) { + return context.is( Characteristic.class ) + ? value.getValue().toString() + : "\"" + value.getValue().toString() + "\""; + } + + @Override + public String visitEntityInstance( final EntityInstance instance, final ModelElement context ) { + return instance.getAssertions().entrySet().stream().map( entry -> + String.format( "\"%s\":%s", entry.getKey().getName(), entry.getValue().accept( this, instance ) ) ) + .collect( Collectors.joining( ",", "{", "}" ) ); + } + + @Override + public String visitCollectionValue( final CollectionValue value, final ModelElement context ) { + return value.getValues().stream().map( collectionValue -> + collectionValue.accept( this, value ) ) + .collect( Collectors.joining( ",", "[", "]" ) ); + } + } } diff --git a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java index 7e2bd0bc3..b69592fc5 100644 --- a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java +++ b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java @@ -321,6 +321,12 @@ void testGenerateAasxFromAspectModelWithEnumeration() throws IOException, Deseri public void testGeneration( final TestAspect testAspect ) throws IOException, DeserializationException, SAXException { final ByteArrayOutputStream baos = getByteArrayOutputStreamFromAspect( testAspect ); final byte[] xmlFile = baos.toByteArray(); + + final String aasXml = new String( xmlFile ); + assertThat( aasXml ).doesNotContain( "DefaultScalarValue[" ); + assertThat( aasXml ).doesNotContain( "DefaultEntity[" ); + assertThat( aasXml ).doesNotContain( "Optional[" ); + final Environment env = loadAASX( new ByteArrayInputStream( xmlFile ) ); assertFalse( env.getSubmodels().isEmpty(), "No Submodel in AAS present." ); try { From 647dc6ee33bd9baa3c60d94471fa85abe8a14145 Mon Sep 17 00:00:00 2001 From: "Textor Andreas (BCI/ESW17)" Date: Thu, 9 Nov 2023 10:36:45 +0100 Subject: [PATCH 14/14] Clean up AspectModelAASGeneratorTest --- .../aas/AspectModelAASGeneratorTest.java | 62 +++++++------------ 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java index b69592fc5..9dd6db755 100644 --- a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java +++ b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAASGeneratorTest.java @@ -17,11 +17,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import java.util.Set; @@ -58,7 +58,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; class AspectModelAASGeneratorTest { @@ -290,17 +289,15 @@ void testGenerateAasxFromAspectModelWithEnumeration() throws IOException, Deseri assertEquals( 2, env.getConceptDescriptions().size() ); - final DataSpecificationIec61360 dataSpecificationContent = - (DataSpecificationIec61360) - env.getConceptDescriptions().stream() - .filter( x -> x.getIdShort().equals( "TestEnumeration" ) ) - .findFirst() - .get() - .getEmbeddedDataSpecifications() - .stream() - .findFirst() - .get() - .getDataSpecificationContent(); + final DataSpecificationIec61360 dataSpecificationContent = (DataSpecificationIec61360) env.getConceptDescriptions().stream() + .filter( conceptDescription -> conceptDescription.getIdShort().equals( "TestEnumeration" ) ) + .findFirst() + .get() + .getEmbeddedDataSpecifications() + .stream() + .findFirst() + .get() + .getDataSpecificationContent(); assertEquals( 3, dataSpecificationContent.getValueList().getValueReferencePairs().size() ); assertEquals( 1, env.getSubmodels().size() ); @@ -310,15 +307,10 @@ void testGenerateAasxFromAspectModelWithEnumeration() throws IOException, Deseri } @ParameterizedTest - @EnumSource( - value = TestAspect.class, - mode = EnumSource.Mode.EXCLUDE, - names = { - "ASPECT_WITH_STRING_ENUMERATION" - } ) + @EnumSource( value = TestAspect.class ) // anonymous enumeration in test has no urn for enum values but is required for Concept // Description referencing - public void testGeneration( final TestAspect testAspect ) throws IOException, DeserializationException, SAXException { + public void testGeneration( final TestAspect testAspect ) throws IOException, DeserializationException { final ByteArrayOutputStream baos = getByteArrayOutputStreamFromAspect( testAspect ); final byte[] xmlFile = baos.toByteArray(); @@ -329,15 +321,7 @@ public void testGeneration( final TestAspect testAspect ) throws IOException, De final Environment env = loadAASX( new ByteArrayInputStream( xmlFile ) ); assertFalse( env.getSubmodels().isEmpty(), "No Submodel in AAS present." ); - try { - validate( new ByteArrayInputStream( xmlFile ) ); - } catch ( final SAXException e ) { - final String xmlContent = new String( xmlFile, StandardCharsets.UTF_8 ); - final int line = ((SAXParseException) e).getLineNumber(); - final String faultyLine = xmlContent.lines().skip( line - 1 ).findFirst().orElse( "" ); - final String model = "AAS XML file causing the Exception. \nProblem within line " + line + ": " + faultyLine + "\n" + xmlContent; - throw new SAXException( model, e ); - } + validate( new ByteArrayInputStream( xmlFile ) ); } private void checkDataSpecificationIEC61360( final Set semanticIds, final Environment env ) { @@ -376,20 +360,20 @@ private Environment getAssetAdministrationShellFromAspectWithData( final TestAsp return loadAASX( data ); } - private ByteArrayOutputStream getByteArrayOutputStreamFromAspect( final TestAspect testAspect ) - throws IOException { + private ByteArrayOutputStream getByteArrayOutputStreamFromAspect( final TestAspect testAspect ) throws IOException { final Aspect aspect = loadAspect( testAspect ); return generator.generateXmlOutput( aspect ); } - private void validate( final ByteArrayInputStream xmlStream ) throws IOException, SAXException { - final SchemaFactory factory = - SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); - - final Schema schema = factory.newSchema( - new StreamSource( getClass().getResourceAsStream( XML_XSD_AAS_SCHEMA_LOCATION ) ) ); - final Validator validator = schema.newValidator(); - validator.validate( new StreamSource( xmlStream ), null ); + private void validate( final ByteArrayInputStream xmlStream ) { + try { + final SchemaFactory factory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); + final Schema schema = factory.newSchema( new StreamSource( getClass().getResourceAsStream( XML_XSD_AAS_SCHEMA_LOCATION ) ) ); + final Validator validator = schema.newValidator(); + validator.validate( new StreamSource( xmlStream ), null ); + } catch ( final SAXException | IOException e ) { + fail( e ); + } } private Aspect loadAspect( final TestAspect testAspect ) {