diff --git a/.github/workflows/gradle-publish-package.yml b/.github/workflows/gradle-publish-package.yml index 5d972d2..494a2cc 100644 --- a/.github/workflows/gradle-publish-package.yml +++ b/.github/workflows/gradle-publish-package.yml @@ -27,7 +27,7 @@ jobs: uses: actions/delete-package-versions@v4 continue-on-error: true with: - package-name: 'com.sap.dsc.aas.lib.aas-transformation-library' + package-name: 'org.eclipse.digitaltwin.aas4j.aas4j-transformation-library' - name: Publish package run: ./gradlew -i publish env: diff --git a/build.gradle b/build.gradle index 0123bb5..5e82d27 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - SPDX-FileCopyrightText: (C)2021 SAP SE or an affiliate company and aas-transformation-library contributors. All rights reserved. + SPDX-FileCopyrightText: (C)2021 SAP SE or an affiliate company and aas4j-transformation-library contributors. All rights reserved. SPDX-License-Identifier: Apache-2.0 */ @@ -17,7 +17,7 @@ plugins { } group = 'org.eclipse.digitaltwin.aas4j' -version = '0.1.2' +version = '0.1.3' application { group = group @@ -154,7 +154,7 @@ spotless { trimTrailingWhitespace() indentWithSpaces() endWithNewline() - licenseHeader('/* \n SPDX-FileCopyrightText: (C)$YEAR SAP SE or an affiliate company and aas-transformation-library contributors. All rights reserved. \n\n SPDX-License-Identifier: Apache-2.0 \n */','\\w') + licenseHeader('/* \n SPDX-FileCopyrightText: (C)$YEAR SAP SE or an affiliate company and aas4j-transformation-library contributors. All rights reserved. \n\n SPDX-License-Identifier: Apache-2.0 \n */','\\w') } // format 'xmlaml', { @@ -162,7 +162,7 @@ spotless { // trimTrailingWhitespace() // indentWithSpaces() // endWithNewline() - // licenseHeader('','<[^!]') + // licenseHeader('','<[^!]') // } java { @@ -172,7 +172,7 @@ spotless { endWithNewline() eclipse('4.12.0').configFile 'codestyle/EclipseFormatterProfile.xml' importOrderFile('codestyle/EclipseOrganizeImports.importorder') - licenseHeader('/* \n SPDX-FileCopyrightText: (C)$YEAR SAP SE or an affiliate company and aas-transformation-library contributors. All rights reserved. \n\n SPDX-License-Identifier: Apache-2.0 \n */') + licenseHeader('/* \n SPDX-FileCopyrightText: (C)$YEAR SAP SE or an affiliate company and aas4j-transformation-library contributors. All rights reserved. \n\n SPDX-License-Identifier: Apache-2.0 \n */') } } @@ -218,8 +218,8 @@ task buildJar (type: Jar) { exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/NOTICE', 'META-INF/LICENSE', 'META-INF/DEPENDENCIES' - archiveExtension.set('jar') with jar + archiveExtension.set('jar') } task build(overwrite: true) { @@ -228,12 +228,12 @@ task build(overwrite: true) { shadowJar { destinationDirectory = file("${buildDir}/distributions") - archiveClassifier.set("") exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/NOTICE', 'META-INF/LICENSE', 'META-INF/LICENSE' - archiveBaseName.set("aas-transformation-library") + archiveBaseName.set("aas4j-transformation-library") archiveAppendix.set("shadow") + archiveClassifier.set("shadedJar") archiveExtension.set("jar") } @@ -254,7 +254,7 @@ publishing { } publications { gpr(MavenPublication) { - artifact jar + from components.java } } } @@ -266,7 +266,7 @@ dependencies { def mockito_version = "3.2.4" def dom4j_version = "2.1.3" def apache_poi_version = "4.1.2" - def jackson_version = "2.11.3" + def jackson_version = "2.14.2" def truth_version = "1.1" def slf4j_version = "1.7.30" def json_schema_validator_version = "1.0.45" diff --git a/settings.gradle b/settings.gradle index 5b4144a..b8158c1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,4 +3,4 @@ SPDX-License-Identifier: Apache-2.0 */ -rootProject.name = 'aas-transformation-library' +rootProject.name = 'aas4j-transformation-library' diff --git a/src/main/java/org/eclipse/digitaltwin/aas4j/expressions/Expressions.java b/src/main/java/org/eclipse/digitaltwin/aas4j/expressions/Expressions.java index 1861512..4c1ec4d 100644 --- a/src/main/java/org/eclipse/digitaltwin/aas4j/expressions/Expressions.java +++ b/src/main/java/org/eclipse/digitaltwin/aas4j/expressions/Expressions.java @@ -6,13 +6,7 @@ package org.eclipse.digitaltwin.aas4j.expressions; import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -21,6 +15,7 @@ import org.dom4j.Node; import com.google.common.hash.Hashing; +import org.eclipse.digitaltwin.aas4j.exceptions.TransformationException; public class Expressions { @@ -135,6 +130,18 @@ public class Expressions { return Hashing.sha256().hashString(concatenated, StandardCharsets.UTF_8).toString(); }); + functions.put("generate_uuid", args -> + { + boolean isEmpty = Helpers.valueToStream(args).allMatch(element -> element.equals("")); + if (args == null || isEmpty) { + return UUID.randomUUID(); + } else { + String input = nodeListsToString(Helpers.valueToStream(args)).collect(Collectors.joining()); + return UUID.nameUUIDFromBytes(input.getBytes()); + } + } + ); + // string encoding functions.put("base64", args -> { Stream stream = (Stream) Helpers.valueToStream(args); diff --git a/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/TransformationContext.java b/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/TransformationContext.java index 4d59433..9dcf058 100644 --- a/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/TransformationContext.java +++ b/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/TransformationContext.java @@ -56,8 +56,8 @@ static TransformationContext buildContext(TransformationContext parentCtx, Objec } // add and/or override with template context if (template != null) { - if (template.getDefinitions() != null) { - build.definitions.putAll(template.getDefinitions()); + if (template.getTemplateDefinitions() != null) { + build.definitions.putAll(template.getTemplateDefinitions()); } if (template.getVariables() != null) { template.getVariables().forEach((key, expr) -> { diff --git a/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/LangStringTemplate.java b/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/LangStringTemplate.java index 42ac937..7722ebd 100644 --- a/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/LangStringTemplate.java +++ b/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/LangStringTemplate.java @@ -38,13 +38,13 @@ public void setForeachExpression(Expression expression) { } @Override - public Map getDefinitions() { - return template.getDefinitions(); + public Map getTemplateDefinitions() { + return template.getTemplateDefinitions(); } @Override - public void setDefinitions(Map definitions) { - template.setDefinitions(definitions); + public void setTemplateDefinitions(Map definitions) { + template.setTemplateDefinitions(definitions); } @Override diff --git a/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/Template.java b/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/Template.java index 3bd6170..c587c1e 100644 --- a/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/Template.java +++ b/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/Template.java @@ -24,10 +24,10 @@ public interface Template { @JsonProperty("@foreach") void setForeachExpression(Expression expression); - Map getDefinitions(); + Map getTemplateDefinitions(); @JsonProperty("@definitions") - void setDefinitions(Map definitions); + void setTemplateDefinitions(Map definitions); Map getVariables(); diff --git a/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/TemplateSupport.java b/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/TemplateSupport.java index ee7f7a7..2e3d2f5 100644 --- a/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/TemplateSupport.java +++ b/src/main/java/org/eclipse/digitaltwin/aas4j/mapping/model/TemplateSupport.java @@ -53,12 +53,12 @@ public void setForeachExpression(Expression foreachExpression) { } @Override - public Map getDefinitions() { + public Map getTemplateDefinitions() { return definitions; } @Override - public void setDefinitions(Map definitions) { + public void setTemplateDefinitions(Map definitions) { this.definitions = definitions; } diff --git a/src/test/java/org/eclipse/digitaltwin/aas4j/mapping/TransformationContextTest.java b/src/test/java/org/eclipse/digitaltwin/aas4j/mapping/TransformationContextTest.java index df4ebce..29ecc31 100644 --- a/src/test/java/org/eclipse/digitaltwin/aas4j/mapping/TransformationContextTest.java +++ b/src/test/java/org/eclipse/digitaltwin/aas4j/mapping/TransformationContextTest.java @@ -26,14 +26,14 @@ void setup() { mockDefs1.put("myDef", Expressions.getConstantByName("pi")); mockTemplate1 = Mockito.mock(Template.class); Mockito.when(mockTemplate1.getVariables()).thenReturn(null); - Mockito.when(mockTemplate1.getDefinitions()).thenReturn(mockDefs1); + Mockito.when(mockTemplate1.getTemplateDefinitions()).thenReturn(mockDefs1); HashMap mockDefs2 = new HashMap<>(); mockDefs2.put("myDef", Expressions.getConstantByName("NaN")); mockDefs2.put("myDef2", Expressions.getConstantByName("e")); mockTemplate2 = Mockito.mock(Template.class); Mockito.when(mockTemplate2.getVariables()).thenReturn(null); - Mockito.when(mockTemplate2.getDefinitions()).thenReturn(mockDefs2); + Mockito.when(mockTemplate2.getTemplateDefinitions()).thenReturn(mockDefs2); } diff --git a/src/test/java/org/eclipse/digitaltwin/aas4j/transform/GenericDocumentTransformerTest.java b/src/test/java/org/eclipse/digitaltwin/aas4j/transform/GenericDocumentTransformerTest.java index fc808b5..07de68f 100644 --- a/src/test/java/org/eclipse/digitaltwin/aas4j/transform/GenericDocumentTransformerTest.java +++ b/src/test/java/org/eclipse/digitaltwin/aas4j/transform/GenericDocumentTransformerTest.java @@ -23,10 +23,16 @@ import io.adminshell.aas.v3.model.AssetAdministrationShellEnvironment; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + class GenericDocumentTransformerTest { public static final String XML_INPUT = "src/test/resources/ua/aasfull.xml"; public static final String JSON_CONFIG = "src/test/resources/ua/genericSampleConfig.json"; + public static final String SPARQL_XML_INPUT = "src/test/resources/xml/groupable.xml"; + public static final String NESTED_FOR_EACH_JSON_CONFIG = "src/test/resources/mappings/generic/nestedForEach.json"; + private InputStream testInputStream; @@ -39,7 +45,6 @@ static void tearDownAfterClass() throws Exception {} @BeforeEach void setUp() throws Exception { TestUtils.resetBindings(); - testInputStream = Files.newInputStream(Paths.get(XML_INPUT)); } @AfterEach @@ -47,6 +52,7 @@ void tearDown() throws Exception {} @Test void testNsBindings() throws TransformationException, IOException { + testInputStream = Files.newInputStream(Paths.get(XML_INPUT)); DocumentTransformer transformer = new GenericDocumentTransformer(); MappingSpecification mapping = new MappingSpecificationParser().loadMappingSpecification(JSON_CONFIG); @@ -56,4 +62,17 @@ void testNsBindings() throws TransformationException, IOException { Assert.assertEquals(71, transform.getSubmodels().size()); } + @Test + void testNestedForEach() throws IOException, TransformationException { + testInputStream = Files.newInputStream(Paths.get(SPARQL_XML_INPUT)); + DocumentTransformer transformer = new GenericDocumentTransformer(); + + MappingSpecification mapping = new MappingSpecificationParser().loadMappingSpecification(NESTED_FOR_EACH_JSON_CONFIG); + + AssetAdministrationShellEnvironment transform = transformer.execute(testInputStream, mapping); + + assertEquals(2, transform.getSubmodels().size()); + assertTrue(transform.getSubmodels().stream().anyMatch(sm -> sm.getIdShort().equals("131"))); + } + } diff --git a/src/test/java/org/eclipse/digitaltwin/aas4j/ua/transform/UaIntegrationTest.java b/src/test/java/org/eclipse/digitaltwin/aas4j/ua/transform/UaIntegrationTest.java index fe65aeb..1e4ced1 100644 --- a/src/test/java/org/eclipse/digitaltwin/aas4j/ua/transform/UaIntegrationTest.java +++ b/src/test/java/org/eclipse/digitaltwin/aas4j/ua/transform/UaIntegrationTest.java @@ -50,6 +50,12 @@ void testIntegration() throws Exception { boolean idInEnv = shellEnv.getSubmodels().stream().map(s -> s.getIdentification().getIdentifier()) .collect(Collectors.toList()).contains("http://exp.organization.com/UA/BigMachine/ns=4;i=1281"); assertTrue(idInEnv); + + assertEquals("407ef772-7040-3b9e-b51a-80286d1c8e49", shellEnv.getAssetAdministrationShells().get(0).getIdentification().getIdentifier()); + + //this value was extracted from the first run. Since it should change + assertNotEquals("6b6dcb8f-352c-49f7-8267-e2586601e858", shellEnv.getAssetAdministrationShells().get(0).getIdShort()); + } @Test diff --git a/src/test/resources/mappings/generic/nestedForEach.json b/src/test/resources/mappings/generic/nestedForEach.json new file mode 100644 index 0000000..342602f --- /dev/null +++ b/src/test/resources/mappings/generic/nestedForEach.json @@ -0,0 +1,52 @@ +{ + "@header": { + "version": "1.0.0", + "aasVersion": "3.0RC01", + "@namespaces": { + "ns": "http://ns.org/" + } + }, + "aasEnvironmentMapping": { + "submodels": [ + { + "@foreach": { + "@xpath": "//ns:a/ns:c[not(.=../following::ns:c)]" + }, + "@variables": { + "here": { + "@xpath": "." + } + }, + "semanticId": { + "keys": [ + { + "@bind": { + "value": { + "@var": "here" + } + }, + "idType": "Iri", + "type": "Submodel" + } + ] + }, + "@bind": { + "idShort": { + "@concatenate": [ + { + "@xpath": { + "@concatenate": [ + "//ns:a[ns:c='", + { + "@var": "here" + }, + "']/ns:b[@name='prop_b']" + ] + } + }] + } + } + } + ] + } +} diff --git a/src/test/resources/ua/uaIntegrationTest.json b/src/test/resources/ua/uaIntegrationTest.json index 4e58242..cb0a0ad 100644 --- a/src/test/resources/ua/uaIntegrationTest.json +++ b/src/test/resources/ua/uaIntegrationTest.json @@ -11,10 +11,18 @@ "assets": [], "assetAdministrationShells": [ { - "idShort": "UaAdminShell", + "@bind": { + "idShort": { + "@generate_uuid": "" + } + }, "identification": { - "idType": "Custom", - "id": "UaAdminShellId" + "@bind": { + "idType": "Custom", + "id": { + "@generate_uuid": "someStringAsSeed" + } + } }, "assetInformation": { "@bind": { diff --git a/src/test/resources/xml/groupable.xml b/src/test/resources/xml/groupable.xml new file mode 100644 index 0000000..1e582c0 --- /dev/null +++ b/src/test/resources/xml/groupable.xml @@ -0,0 +1,27 @@ + + + foo + 1 + 2 + + + foo + 3 + 3 + + + foo + 1 + 2 + + + bar + 4 + 5 + + + bar + 4 + 8 + + \ No newline at end of file