diff --git a/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/core/Examples.java b/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/core/Examples.java new file mode 100644 index 000000000..72261ada7 --- /dev/null +++ b/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/core/Examples.java @@ -0,0 +1,80 @@ +/* + * Copyright 2023 jab. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.eclipse.digitaltwin.aas4j.v3.dataformat.core; + +import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind; +import org.eclipse.digitaltwin.aas4j.v3.model.DataTypeDefXSD; +import org.eclipse.digitaltwin.aas4j.v3.model.Environment; +import org.eclipse.digitaltwin.aas4j.v3.model.KeyTypes; +import org.eclipse.digitaltwin.aas4j.v3.model.ReferenceTypes; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetAdministrationShell; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetInformation; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultEnvironment; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultExtension; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultKey; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultReference; + +public class Examples { + + public static final Environment EXTENSION_MINIMAL = new DefaultEnvironment.Builder() + .assetAdministrationShells(new DefaultAssetAdministrationShell.Builder() + .id("something_142922d6") + .extensions(new DefaultExtension.Builder() + .name("something_aae6caf4") + .build()) + .assetInformation(new DefaultAssetInformation.Builder() + .assetKind(AssetKind.NOT_APPLICABLE) + .globalAssetID("something_eea66fa1") + .build()) + .build()) + .build(); + + public static final Environment EXTENSION_MAXIMAL = new DefaultEnvironment.Builder() + .assetAdministrationShells(new DefaultAssetAdministrationShell.Builder() + .id("something_142922d6") + .extensions(new DefaultExtension.Builder() + .name("something_aae6caf4") + .value("10233") + .valueType(DataTypeDefXSD.UNSIGNED_SHORT) + .refersTo(new DefaultReference.Builder() + .keys(new DefaultKey.Builder() + .type(KeyTypes.SUBMODEL) + .value("urn:another-example01:f7faa581") + .build()) + .type(ReferenceTypes.MODEL_REFERENCE) + .build()) + .semanticID(new DefaultReference.Builder() + .keys(new DefaultKey.Builder() + .type(KeyTypes.GLOBAL_REFERENCE) + .value("urn:another-company07:4d1bd2cb") + .build()) + .type(ReferenceTypes.EXTERNAL_REFERENCE) + .build()) + .supplementalSemanticIds(new DefaultReference.Builder() + .keys(new DefaultKey.Builder() + .type(KeyTypes.GLOBAL_REFERENCE) + .value("urn:an-example13:be48ff29") + .build()) + .type(ReferenceTypes.EXTERNAL_REFERENCE) + .build()) + .build()) + .assetInformation(new DefaultAssetInformation.Builder() + .assetKind(AssetKind.NOT_APPLICABLE) + .globalAssetID("something_eea66fa1") + .build()) + .build()) + .build(); +} diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/mixins/HasExtensionsMixin.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/mixins/HasExtensionsMixin.java index d97c658e3..73ee6b923 100644 --- a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/mixins/HasExtensionsMixin.java +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/mixins/HasExtensionsMixin.java @@ -23,9 +23,9 @@ public interface HasExtensionsMixin { - @JsonProperty("extension") + @JsonProperty("extensions") public List getExtensions(); - @JsonProperty("extension") + @JsonProperty("extensions") public void setExtensions(List extensions); } diff --git a/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonReferableDeserializerTest.java b/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonReferableDeserializerTest.java index 54e48e11d..363d9ada5 100644 --- a/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonReferableDeserializerTest.java +++ b/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonReferableDeserializerTest.java @@ -23,21 +23,25 @@ import java.util.Collections; import java.util.List; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.util.Examples; import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; +import org.eclipse.digitaltwin.aas4j.v3.model.Environment; +import org.eclipse.digitaltwin.aas4j.v3.model.Property; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultProperty; import org.eclipse.digitaltwin.aas4j.v3.model.Referable; import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement; -import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementList; import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementCollection; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementList; import org.junit.Test; import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.util.Examples; -import org.eclipse.digitaltwin.aas4j.v3.model.Environment; -import org.eclipse.digitaltwin.aas4j.v3.model.Property; -import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultProperty; + import org.junit.Assert; + public class JsonReferableDeserializerTest { @Test @@ -115,4 +119,18 @@ public void testPropertyFromNode() throws Exception { Property actual = new JsonDeserializer().readReferable(input, Property.class); assertEquals(expected, actual); } + + @Test + public void testExtensionMinimal() throws Exception { + Environment expected = Examples.EXTENSION_MINIMAL.getModel(); + Environment actual = new JsonDeserializer().read(Examples.EXTENSION_MINIMAL.fileContentStream()); + assertEquals(expected, actual); + } + + @Test + public void testExtensionMaximal() throws Exception { + Environment expected = Examples.EXTENSION_MAXIMAL.getModel(); + Environment actual = new JsonDeserializer().read(Examples.EXTENSION_MAXIMAL.fileContentStream()); + assertEquals(expected, actual); + } } diff --git a/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonReferableSerializerTest.java b/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonReferableSerializerTest.java index 82d209133..643677f4a 100644 --- a/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonReferableSerializerTest.java +++ b/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonReferableSerializerTest.java @@ -43,7 +43,7 @@ public void testSerializeAAS() throws IOException, SerializationException, JSONE } @Test - public void testSerializeWithAssetInformation() throws SerializationException, JSONException, IOException { + public void testSerializeAASWithAssetInformation() throws SerializationException, JSONException, IOException { compare(Examples.ASSET_ADMINISTRATION_SHELL_WITH_ASSET_INFORMATION); } @@ -105,6 +105,16 @@ public void testSerializePropertyToNode() throws IOException, SerializationExcep Assert.assertEquals(expected, actual); } + @Test + public void testSerializeExtensionMinimal() throws SerializationException, JSONException, IOException { + compare(Examples.EXTENSION_MINIMAL); + } + + @Test + public void testSerializeExtensionMaximal() throws SerializationException, JSONException, IOException { + compare(Examples.EXTENSION_MAXIMAL); + } + @SuppressWarnings("unchecked") private void compare(ExampleData exampleData) throws IOException, SerializationException, JSONException { String expected = exampleData.fileContent(); diff --git a/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/util/Examples.java b/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/util/Examples.java index 6297303af..6d35239d7 100644 --- a/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/util/Examples.java +++ b/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/util/Examples.java @@ -29,14 +29,22 @@ 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.digitaltwin.aas4j.v3.model.impl.*; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetAdministrationShell; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetInformation; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultConceptDescription; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultEmbeddedDataSpecification; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultEnvironment; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultKey; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultReference; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultResource; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSpecificAssetID; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodelElementList; public class Examples { - public static final ExampleData EXAMPLE_FULL = ExampleData.of(AASFull.createEnvironment(), "Example-Full.json"); + public static final ExampleData EXAMPLE_FULL = ExampleData.of(AASFull.createEnvironment(), "Example-Full.json"); - public static final ExampleData EXAMPLE_SIMPLE = ExampleData.of(AASSimple.createEnvironment(), "Example-Simple.json"); + public static final ExampleData EXAMPLE_SIMPLE = ExampleData.of(AASSimple.createEnvironment(), "Example-Simple.json"); public static final ExampleData ENVIRONMENT_EMPTY = ExampleData.of(new DefaultEnvironment.Builder().build(), "Environment-Empty.json"); @@ -70,8 +78,8 @@ public class Examples { .build(), "AssetAdministrationShell-WithAssetInformation.json"); - public static final ExampleData ASSET_ADMINISTRATION_SHELL = ExampleData.of(AASFull.createEnvironment().getAssetAdministrationShells().get(0), "AssetAdministrationShell.json"); - + public static final ExampleData ASSET_ADMINISTRATION_SHELL = ExampleData.of(AASFull.createEnvironment().getAssetAdministrationShells().get(0), "AssetAdministrationShell.json"); + public static final ExampleData CONCEPT_DESCRIPTION_DATA_SPECIFICATION_PHYSICAL_UNIT = ExampleData.of( new DefaultConceptDescription.Builder() .id("https://example.org/ConceptDescription") @@ -83,28 +91,28 @@ public class Examples { .value("https://admin-shell.io/DataSpecificationTemplates/DataSpecificationPhysicalUnit/3/0/RC02") .build()) .build()) -// .dataSpecificationContent(new DefaultDataSpecificationPhysicalUnit.Builder() -// .conversionFactor("1.0") -// .eceCode("ece-code") -// .eceName("ece-name") -// .definition(new DefaultLangString.Builder() -// .language("en") -// .text("definition-en") -// .build()) -// .definition(new DefaultLangString.Builder() -// .language("de") -// .text("definition-de") -// .build()) -// .nistName("nist-name") -// .dinNotation("din-notation") -// .siName("si-name") -// .registrationAuthorityId("registration-authority-id") -// .siNotation("si-notation") -// .sourceOfDefinition("source-of-definition") -// .supplier("supplier") -// .unitName("unit-name") -// .unitSymbol("unit-symbol") -// .build()) + // .dataSpecificationContent(new DefaultDataSpecificationPhysicalUnit.Builder() + // .conversionFactor("1.0") + // .eceCode("ece-code") + // .eceName("ece-name") + // .definition(new DefaultLangString.Builder() + // .language("en") + // .text("definition-en") + // .build()) + // .definition(new DefaultLangString.Builder() + // .language("de") + // .text("definition-de") + // .build()) + // .nistName("nist-name") + // .dinNotation("din-notation") + // .siName("si-name") + // .registrationAuthorityId("registration-authority-id") + // .siNotation("si-notation") + // .sourceOfDefinition("source-of-definition") + // .supplier("supplier") + // .unitName("unit-name") + // .unitSymbol("unit-symbol") + // .build()) .build()) .build(), "ConceptDescription-DataSpecificationPhysicalUnit.json"); @@ -113,24 +121,28 @@ public class Examples { List.of(AASFull.createEnvironment().getSubmodels().get(0).getSubmodelElements().get(0), AASFull.createEnvironment().getSubmodels().get(0).getSubmodelElements().get(1)), "SubmodelElement-List.json"); - + public static final ExampleData> SUBMODEL_LIST_OF = ExampleData.of( List.of(AASFull.createEnvironment().getSubmodels().get(0), AASFull.createEnvironment().getSubmodels().get(1)), "Submodel-List.json"); - public static final ExampleData SUBMODEL = ExampleData.of(AASFull.createEnvironment().getSubmodels().get(0), "Submodel.json"); + public static final ExampleData SUBMODEL = ExampleData.of(AASFull.createEnvironment().getSubmodels().get(0), "Submodel.json"); - public static final ExampleData SUBMODEL_ELEMENT = ExampleData.of(AASFull.createEnvironment().getSubmodels().get(0).getSubmodelElements().get(0), "SubmodelElement.json"); + public static final ExampleData SUBMODEL_ELEMENT = ExampleData.of(AASFull.createEnvironment().getSubmodels().get(0).getSubmodelElements().get(0), "SubmodelElement.json"); - public static final ExampleData SUBMODEL_ELEMENT_COLLECTION = ExampleData.of((SubmodelElementCollection) AASFull.createEnvironment().getSubmodels().get(6).getSubmodelElements().get(6), - "SubmodelElementCollection.json"); + public static final ExampleData SUBMODEL_ELEMENT_COLLECTION = ExampleData.of((SubmodelElementCollection) AASFull.createEnvironment().getSubmodels().get(6).getSubmodelElements().get(6), + "SubmodelElementCollection.json"); public static final ExampleData SUBMODEL_ELEMENT_LIST_EMPTY = ExampleData.of( new DefaultSubmodelElementList.Builder() .idShort("submodelElementList") .orderRelevant(true) .build(), "SubmodelElementList-Empty.json"); - - public static final ExampleData SUBMODEL_ELEMENT_LIST = ExampleData.of((SubmodelElementList) AASFull.createEnvironment().getSubmodels().get(6).getSubmodelElements().get(5), "SubmodelElementList.json"); + + public static final ExampleData SUBMODEL_ELEMENT_LIST = ExampleData.of((SubmodelElementList) AASFull.createEnvironment().getSubmodels().get(6).getSubmodelElements().get(5), "SubmodelElementList.json"); + + public static final ExampleData EXTENSION_MINIMAL = ExampleData.of(org.eclipse.digitaltwin.aas4j.v3.dataformat.core.Examples.EXTENSION_MINIMAL, "admin-shell-io/Extension/Minimal.json"); + + public static final ExampleData EXTENSION_MAXIMAL = ExampleData.of(org.eclipse.digitaltwin.aas4j.v3.dataformat.core.Examples.EXTENSION_MAXIMAL, "admin-shell-io/Extension/Maximal.json"); } diff --git a/dataformat-json/src/test/resources/admin-shell-io/Extension/Maximal.json b/dataformat-json/src/test/resources/admin-shell-io/Extension/Maximal.json new file mode 100644 index 000000000..436f81fc9 --- /dev/null +++ b/dataformat-json/src/test/resources/admin-shell-io/Extension/Maximal.json @@ -0,0 +1,50 @@ +{ + "assetAdministrationShells": [ + { + "assetInformation": { + "assetKind": "NotApplicable", + "globalAssetId": "something_eea66fa1" + }, + "extensions": [ + { + "name": "something_aae6caf4", + "refersTo": [ + { + "keys": [ + { + "type": "Submodel", + "value": "urn:another-example01:f7faa581" + } + ], + "type": "ModelReference" + } + ], + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "value": "urn:another-company07:4d1bd2cb" + } + ], + "type": "ExternalReference" + }, + "supplementalSemanticIds": [ + { + "keys": [ + { + "type": "GlobalReference", + "value": "urn:an-example13:be48ff29" + } + ], + "type": "ExternalReference" + } + ], + "value": "10233", + "valueType": "xs:unsignedShort" + } + ], + "id": "something_142922d6", + "modelType": "AssetAdministrationShell" + } + ] +} \ No newline at end of file diff --git a/dataformat-json/src/test/resources/admin-shell-io/Extension/Minimal.json b/dataformat-json/src/test/resources/admin-shell-io/Extension/Minimal.json new file mode 100644 index 000000000..831658174 --- /dev/null +++ b/dataformat-json/src/test/resources/admin-shell-io/Extension/Minimal.json @@ -0,0 +1,17 @@ +{ + "assetAdministrationShells": [ + { + "assetInformation": { + "assetKind": "NotApplicable", + "globalAssetId": "something_eea66fa1" + }, + "extensions": [ + { + "name": "something_aae6caf4" + } + ], + "id": "something_142922d6", + "modelType": "AssetAdministrationShell" + } + ] +} \ No newline at end of file diff --git a/dataformat-json/src/test/resources/admin-shell-io/License.md b/dataformat-json/src/test/resources/admin-shell-io/License.md new file mode 100644 index 000000000..ad5bff5c6 --- /dev/null +++ b/dataformat-json/src/test/resources/admin-shell-io/License.md @@ -0,0 +1 @@ +The files contained in this directory are taken without any modification from https://github.com/admin-shell-io/aas-specs/ where they are made available under the CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/). \ No newline at end of file diff --git a/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/mixins/AssetAdministrationShellMixin.java b/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/mixins/AssetAdministrationShellMixin.java index 1e2728ed4..fd7579737 100644 --- a/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/mixins/AssetAdministrationShellMixin.java +++ b/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/mixins/AssetAdministrationShellMixin.java @@ -24,12 +24,12 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; -@JsonPropertyOrder({ "hasExtension", "category", "idShort", "displayNames", "description", "checksum", "administration", "id", "dataSpecifications", "embeddedDataSpecifications", "derivedFrom", "assetInformation", "submodels"}) +@JsonPropertyOrder({ "extension", "category", "idShort", "displayNames", "description", "checksum", "administration", "id", "dataSpecifications", "embeddedDataSpecifications", "derivedFrom", "assetInformation", "submodels" }) public interface AssetAdministrationShellMixin { - @JacksonXmlProperty(namespace = AasXmlNamespaceContext.AAS_URI, localName = "id") - public String getID(); + @JacksonXmlProperty(namespace = AasXmlNamespaceContext.AAS_URI, localName = "id") + public String getID(); @JacksonXmlElementWrapper(namespace = AasXmlNamespaceContext.AAS_URI, localName = "submodels") diff --git a/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/mixins/ExtensionMixin.java b/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/mixins/ExtensionMixin.java index 141b8aa9a..21e27d0cb 100644 --- a/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/mixins/ExtensionMixin.java +++ b/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/mixins/ExtensionMixin.java @@ -15,8 +15,16 @@ */ package org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.mixins; +import java.util.List; + +import org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.serialization.RefersToSerializer; +import org.eclipse.digitaltwin.aas4j.v3.model.Reference; + import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; -@JsonPropertyOrder({"semanticId", "name", "valueType", "value", "refersTo"}) +@JsonPropertyOrder({ "semanticId", "supplementalSemanticIds", "name", "valueType", "value", "refersTo" }) public interface ExtensionMixin { + @JsonSerialize(using = RefersToSerializer.class) + List getRefersTo(); } diff --git a/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/serialization/RefersToSerializer.java b/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/serialization/RefersToSerializer.java new file mode 100644 index 000000000..be0acf819 --- /dev/null +++ b/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/serialization/RefersToSerializer.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (C) 2023 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.serialization; + +import java.io.IOException; +import java.util.List; + +import org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.mixins.HasSemanticsMixin; +import org.eclipse.digitaltwin.aas4j.v3.model.Extension; +import org.eclipse.digitaltwin.aas4j.v3.model.Reference; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; + +/** + * Serializes the RefersTo value of {@link Extension}.
+ * This class is needed since using the same approach as used in + * {@link HasSemanticsMixin} leads to a conflict for XMLPropertyName "reference" + * + * @author schnicke + * + */ +public class RefersToSerializer extends JsonSerializer> { + + @Override + public void serialize(List value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + if (value.isEmpty()) + return; + + ToXmlGenerator xgen = (ToXmlGenerator) gen; + + xgen.writeStartObject(); + + for (Reference ref : value) { + writeReference(xgen, ref); + } + + xgen.writeEndObject(); + } + + private void writeReference(ToXmlGenerator xgen, Reference ref) throws IOException { + xgen.writeFieldName("reference"); + xgen.writeObject(ref); + } + +} diff --git a/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XMLDeserializerTest.java b/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XMLDeserializerTest.java index 784f3f888..8da48bc62 100644 --- a/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XMLDeserializerTest.java +++ b/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XMLDeserializerTest.java @@ -19,8 +19,10 @@ import java.util.List; import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.AASFull; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.AASSimple; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.Examples; import org.eclipse.digitaltwin.aas4j.v3.model.Environment; import org.eclipse.digitaltwin.aas4j.v3.model.Operation; import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable; @@ -29,36 +31,37 @@ import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement; import org.junit.Assert; import org.junit.Test; +import org.xml.sax.SAXException; public class XMLDeserializerTest { - @Test - public void deserializeAASSimple() throws FileNotFoundException, DeserializationException { - Environment env = new XmlDeserializer().read(XmlSerializerTest.AASSIMPLE_FILE); + @Test + public void deserializeAASSimple() throws FileNotFoundException, DeserializationException { + Environment env = new XmlDeserializer().read(XmlSerializerTest.AASSIMPLE_FILE); - Assert.assertEquals(AASSimple.createEnvironment(), env); - } + Assert.assertEquals(AASSimple.createEnvironment(), env); + } @Test - public void deserializeAASSimpleAAS() throws Exception { + public void deserializeAASSimpleAAS() throws Exception { Environment env = new XmlDeserializer().read(XmlSerializerTest.AASSIMPLE_FILE); - Assert.assertEquals(AASSimple.createEnvironment().getAssetAdministrationShells(), env.getAssetAdministrationShells()); - } + Assert.assertEquals(AASSimple.createEnvironment().getAssetAdministrationShells(), env.getAssetAdministrationShells()); + } - @Test - public void deserializeAASSimpleSubmodel() throws Exception { - Environment env = new XmlDeserializer().read(XmlSerializerTest.AASSIMPLE_FILE); + @Test + public void deserializeAASSimpleSubmodel() throws Exception { + Environment env = new XmlDeserializer().read(XmlSerializerTest.AASSIMPLE_FILE); - Assert.assertEquals(AASSimple.createEnvironment().getSubmodels(), env.getSubmodels()); - } + Assert.assertEquals(AASSimple.createEnvironment().getSubmodels(), env.getSubmodels()); + } - @Test - public void deserializeAASSimpleConceptDescription() throws Exception { - Environment env = new XmlDeserializer().read(XmlSerializerTest.AASSIMPLE_FILE); - - Assert.assertEquals(AASSimple.createEnvironment().getConceptDescriptions(), env.getConceptDescriptions()); - } + @Test + public void deserializeAASSimpleConceptDescription() throws Exception { + Environment env = new XmlDeserializer().read(XmlSerializerTest.AASSIMPLE_FILE); + + Assert.assertEquals(AASSimple.createEnvironment().getConceptDescriptions(), env.getConceptDescriptions()); + } @Test public void deserializeAnnotedRelationshipElement() throws Exception { @@ -78,7 +81,7 @@ public void deserializeQualifier() throws Exception { @Test public void deserializeOperation() throws Exception { - Environment env = new XmlDeserializer().read(XmlSerializerTest.AASFULL_FILE_WITH_OPERATIONS); + Environment env = new XmlDeserializer().read(XmlSerializerTest.AASFULL_FILE_WITH_OPERATIONS); Assert.assertNotNull(env); OperationVariable inputVariable = ((Operation) env.getSubmodels().get(0).getSubmodelElements().get(0)).getInputVariables().get(0); @@ -94,26 +97,40 @@ public void deserializeOperation() throws Exception { @Test public void deserializeAASFull() throws FileNotFoundException, DeserializationException { Environment env = new XmlDeserializer().read(XmlSerializerTest.AASFULL_FILE); - Assert.assertEquals(AASFull.createEnvironment(), env); + Assert.assertEquals(AASFull.createEnvironment(), env); } - @Test - public void deserializeAASFullAAS() throws FileNotFoundException, DeserializationException { - Environment env = new XmlDeserializer().read(XmlSerializerTest.AASFULL_FILE); - Assert.assertEquals(AASFull.createEnvironment().getAssetAdministrationShells(), env.getAssetAdministrationShells()); - } + @Test + public void deserializeAASFullAAS() throws FileNotFoundException, DeserializationException { + Environment env = new XmlDeserializer().read(XmlSerializerTest.AASFULL_FILE); + Assert.assertEquals(AASFull.createEnvironment().getAssetAdministrationShells(), env.getAssetAdministrationShells()); + } - @Test - public void deserializeAASFullSubmodel() throws FileNotFoundException, DeserializationException { - Environment env = new XmlDeserializer().read(XmlSerializerTest.AASFULL_FILE); + @Test + public void deserializeAASFullSubmodel() throws FileNotFoundException, DeserializationException { + Environment env = new XmlDeserializer().read(XmlSerializerTest.AASFULL_FILE); - Assert.assertEquals(AASFull.createEnvironment().getSubmodels(), env.getSubmodels()); - } + Assert.assertEquals(AASFull.createEnvironment().getSubmodels(), env.getSubmodels()); + } - @Test - public void deserializeAASFullConceptDescription() throws FileNotFoundException, DeserializationException { - Environment env = new XmlDeserializer().read(XmlSerializerTest.AASFULL_FILE); + @Test + public void deserializeAASFullConceptDescription() throws FileNotFoundException, DeserializationException { + Environment env = new XmlDeserializer().read(XmlSerializerTest.AASFULL_FILE); - Assert.assertEquals(AASFull.createEnvironment().getConceptDescriptions(), env.getConceptDescriptions()); - } + Assert.assertEquals(AASFull.createEnvironment().getConceptDescriptions(), env.getConceptDescriptions()); + } + + @Test + public void deserializeAASWithExtensionMinimal() throws SerializationException, SAXException, FileNotFoundException, DeserializationException { + Environment env = new XmlDeserializer().read(XmlSerializerTest.AAS_WITH_EXTENSION_MINIMAL); + + Assert.assertEquals(Examples.EXTENSION_MINIMAL, env); + } + + @Test + public void deserializeAASWithExtensionMaximal() throws SerializationException, SAXException, FileNotFoundException, DeserializationException { + Environment env = new XmlDeserializer().read(XmlSerializerTest.AAS_WITH_EXTENSION_MAXIMAL); + + Assert.assertEquals(Examples.EXTENSION_MAXIMAL, env); + } } diff --git a/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlSerializerTest.java b/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlSerializerTest.java index 1e35f8981..c50574d3e 100644 --- a/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlSerializerTest.java +++ b/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlSerializerTest.java @@ -27,6 +27,7 @@ import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.AASFull; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.AASSimple; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.Examples; import org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.internal.AasXmlNamespaceContext; import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind; import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; @@ -61,6 +62,8 @@ public class XmlSerializerTest { public static final java.io.File AASFULL_FILE_WITH_ANNOTATED_RELATIONSHIP = new java.io.File("src/test/resources/annotated_relationship_example.xml"); public static final java.io.File AASFULL_FILE_WITH_QUALIFIERS = new java.io.File("src/test/resources/qualifier_example.xml"); public static final java.io.File AASFULL_FILE_WITH_OPERATIONS = new java.io.File("src/test/resources/operation_example.xml"); + public static final java.io.File AAS_WITH_EXTENSION_MINIMAL = new java.io.File("src/test/resources/admin-shell-io/Extension/minimal.xml"); + public static final java.io.File AAS_WITH_EXTENSION_MAXIMAL = new java.io.File("src/test/resources/admin-shell-io/Extension/maximal.xml"); private static final Logger logger = LoggerFactory.getLogger(XmlSerializerTest.class); @@ -68,14 +71,14 @@ public class XmlSerializerTest { public TemporaryFolder tempFolder = new TemporaryFolder(); @Test - public void testWriteToFile() throws IOException, SerializationException { + public void writeToFile() throws IOException, SerializationException { File file = tempFolder.newFile("output.xml"); - new XmlSerializer().write(file, AASSimple.createEnvironment()); + new XmlSerializer().write(file, AASSimple.createEnvironment()); assertTrue(file.exists()); } @Test - public void testSerializeMinimal() throws SerializationException, SAXException { + public void serializeMinimal() throws SerializationException, SAXException { File file = new File("src/test/resources/minimum.xml"); Environment environment = new DefaultEnvironment.Builder() .assetAdministrationShells(new DefaultAssetAdministrationShell.Builder() @@ -89,25 +92,25 @@ public void testSerializeMinimal() throws SerializationException, SAXException { } @Test - public void testSerializeSimpleWithTestNamespacePrefix() throws SerializationException, SAXException { + public void serializeSimpleWithTestNamespacePrefix() throws SerializationException, SAXException { Map nsPrefixes = new HashMap<>(AasXmlNamespaceContext.PREFERRED_PREFIX_CONTEXT); nsPrefixes.put("test", nsPrefixes.get("aas")); nsPrefixes.remove("aas"); - validateXmlSerializer(AASSIMPLE_FILE_WITH_TEST_NAMESPACE, AASSimple.createEnvironment(), new XmlSerializer(nsPrefixes)); + validateXmlSerializer(AASSIMPLE_FILE_WITH_TEST_NAMESPACE, AASSimple.createEnvironment(), new XmlSerializer(nsPrefixes)); } @Test - public void testSerializeSimple() throws SerializationException, SAXException { - validateXmlSerializer(AASSIMPLE_FILE, AASSimple.createEnvironment()); + public void serializeSimple() throws SerializationException, SAXException { + validateXmlSerializer(AASSIMPLE_FILE, AASSimple.createEnvironment()); } @Test - public void testSerializeFull() throws SerializationException, SAXException { - validateXmlSerializer(AASFULL_FILE, AASFull.createEnvironment()); + public void serializeFull() throws SerializationException, SAXException { + validateXmlSerializer(AASFULL_FILE, AASFull.createEnvironment()); } @Test - public void testConceptDescriptionAgainstXsdSchema() throws SerializationException, SAXException { + public void validateConceptDescriptionAgainstXsdSchema() throws SerializationException, SAXException { ConceptDescription object = AASSimple.createConceptDescriptionMaxRotationSpeed(); Set errors = validateAgainstXsdSchema( new XmlSerializer().write(new DefaultEnvironment.Builder().conceptDescriptions(object).build())); assertTrue(errors.isEmpty()); @@ -115,7 +118,7 @@ public void testConceptDescriptionAgainstXsdSchema() throws SerializationExcepti @Test - public void testMinimalOperationAgainstXsdSchema() throws SerializationException, SAXException { + public void validateMinimalOperationAgainstXsdSchema() throws SerializationException, SAXException { Submodel object = new DefaultSubmodel.Builder() .id("testSubmodel") .idShort("testSubmodel") @@ -135,17 +138,17 @@ public void testMinimalOperationAgainstXsdSchema() throws SerializationException assertTrue(errors.isEmpty()); } - @Test - public void testGYear() throws SerializationException, SAXException { - Submodel submodel = new DefaultSubmodel.Builder().id("yearTestSm").submodelElements(new DefaultProperty.Builder().idShort("yearTestProp").valueType(DataTypeDefXSD.GYEAR).build()).build(); - String xml = new XmlSerializer().write(new DefaultEnvironment.Builder().submodels(submodel).build()); - Set errors = validateAgainstXsdSchema(xml); - assertTrue(errors.isEmpty()); - } + @Test + public void validateGYearAgainstXsdSchema() throws SerializationException, SAXException { + Submodel submodel = new DefaultSubmodel.Builder().id("yearTestSm").submodelElements(new DefaultProperty.Builder().idShort("yearTestProp").valueType(DataTypeDefXSD.GYEAR).build()).build(); + String xml = new XmlSerializer().write(new DefaultEnvironment.Builder().submodels(submodel).build()); + Set errors = validateAgainstXsdSchema(xml); + assertTrue(errors.isEmpty()); + } @Test - public void testDocumentationSubmodelAgainstXsdSchema() throws SerializationException, SAXException { + public void validateDocumentationSubmodelAgainstXsdSchema() throws SerializationException, SAXException { Submodel object = AASSimple.createSubmodelDocumentation(); String xml = new XmlSerializer().write(new DefaultEnvironment.Builder().submodels(object).build()); Set errors = validateAgainstXsdSchema( xml ); @@ -154,14 +157,22 @@ public void testDocumentationSubmodelAgainstXsdSchema() throws SerializationExce @Test - public void testIsCaseOfAgainstXsdSchema() throws SerializationException, SAXException { - ConceptDescription object = AASFull.createEnvironment().getConceptDescriptions().get(0); + public void validateIsCaseOfAgainstXsdSchema() throws SerializationException, SAXException { + ConceptDescription object = AASFull.createEnvironment().getConceptDescriptions().get(0); String xml = new XmlSerializer().write(new DefaultEnvironment.Builder().conceptDescriptions(object).build()); Set errors = validateAgainstXsdSchema( xml ); assertTrue(errors.isEmpty()); } + @Test + public void serializeAASWithExtensionMinimal() throws SerializationException, SAXException { + validateXmlSerializer(AAS_WITH_EXTENSION_MINIMAL, Examples.EXTENSION_MINIMAL, new XmlSerializer()); + } + @Test + public void serializeAASWithExtensionMaximal() throws SerializationException, SAXException { + validateXmlSerializer(AAS_WITH_EXTENSION_MAXIMAL, Examples.EXTENSION_MAXIMAL, new XmlSerializer()); + } private Set validateAgainstXsdSchema(String xml) throws SAXException { return new XmlSchemaValidator().validateSchema(xml); @@ -176,7 +187,7 @@ private void validateXmlSerializer(File expectedFile, Environment environment, X throws SerializationException, SAXException { String actual = xmlSerializer.write(environment); Set errors = validateAgainstXsdSchema(actual); - logger.debug(actual); + logger.info(actual); logErrors(expectedFile.getName(), errors); assertTrue(errors.isEmpty()); CompareMatcher xmlTestMatcher = CompareMatcher @@ -218,18 +229,18 @@ private boolean ignoreDefaults(Node node) { return false; } - if (node.getLocalName() != null - && node.getLocalName().equals("category") - && node.getFirstChild().getNodeValue().equals("PROPERTY")) { // TODO: only for ConceptDescriptions - return false; - } - - if (node.getLocalName() != null - && node.getLocalName().equals("orderRelevant") - && node.getFirstChild().getNodeValue().equals("true")) { - return false; - } - + if (node.getLocalName() != null + && node.getLocalName().equals("category") + && node.getFirstChild().getNodeValue().equals("PROPERTY")) { // TODO: only for ConceptDescriptions + return false; + } + + if (node.getLocalName() != null + && node.getLocalName().equals("orderRelevant") + && node.getFirstChild().getNodeValue().equals("true")) { + return false; + } + return true; } diff --git a/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlValidationTest.java b/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlValidationTest.java index eff9fa49c..6db0f8f26 100644 --- a/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlValidationTest.java +++ b/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlValidationTest.java @@ -46,7 +46,7 @@ public static void prepareValidator() throws SAXException { } @Test - @Parameters({ "src/test/resources/minimum.xml", "src/test/resources/Example_AAS_ServoDCMotor - Simplified.xml", "src/test/resources/test_demo_full_example.xml" }) + @Parameters({ "src/test/resources/minimum.xml", "src/test/resources/Example_AAS_ServoDCMotor - Simplified.xml", "src/test/resources/test_demo_full_example.xml" }) // import from admin-shell.io -> is actually V3 // -> fix name, as soon as it is fixed externally public void validateValidXml(String file) throws IOException { @@ -56,7 +56,7 @@ public void validateValidXml(String file) throws IOException { } @Test - @Parameters({ "src/test/resources/invalidXmlExample.xml", "src/test/resources/ServoDCMotor_invalid.xml" }) + @Parameters({ "src/test/resources/invalidXmlExample.xml", "src/test/resources/ServoDCMotor_invalid.xml" }) public void validateInvalidXml(String file) throws IOException { Set errors = validateXmlFile(file); logErrors(file, errors); diff --git a/dataformat-xml/src/test/resources/admin-shell-io/Extension/maximal.xml b/dataformat-xml/src/test/resources/admin-shell-io/Extension/maximal.xml new file mode 100644 index 000000000..0283acaec --- /dev/null +++ b/dataformat-xml/src/test/resources/admin-shell-io/Extension/maximal.xml @@ -0,0 +1,52 @@ + + + + + + + + ExternalReference + + + GlobalReference + urn:another-company07:4d1bd2cb + + + + + + ExternalReference + + + GlobalReference + urn:an-example13:be48ff29 + + + + + something_aae6caf4 + xs:unsignedShort + 10233 + + + ModelReference + + + Submodel + urn:another-example01:f7faa581 + + + + + + + something_142922d6 + + NotApplicable + something_eea66fa1 + + + + diff --git a/dataformat-xml/src/test/resources/admin-shell-io/Extension/minimal.xml b/dataformat-xml/src/test/resources/admin-shell-io/Extension/minimal.xml new file mode 100644 index 000000000..cf753d6f1 --- /dev/null +++ b/dataformat-xml/src/test/resources/admin-shell-io/Extension/minimal.xml @@ -0,0 +1,19 @@ + + + + + + + something_aae6caf4 + + + something_142922d6 + + NotApplicable + something_eea66fa1 + + + + diff --git a/dataformat-xml/src/test/resources/admin-shell-io/License.md b/dataformat-xml/src/test/resources/admin-shell-io/License.md new file mode 100644 index 000000000..bc9888bb0 --- /dev/null +++ b/dataformat-xml/src/test/resources/admin-shell-io/License.md @@ -0,0 +1,5 @@ +The files contained in this directory are taken from https://github.com/admin-shell-io/aas-specs/ where they are made available under the CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/). + +They are modified in the following way: +- Added xml version tag +- Added namespaces \ No newline at end of file