diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializer.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializer.java index 1f37cbdf..785769cd 100644 --- a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializer.java +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializer.java @@ -79,20 +79,19 @@ public T read(String value, Class valueType) throws DeserializationExcept } /** - * Generic method to deserialize a given JSON node into instance of an AAS type + * Generic method to deserialize a given string into a list of AAS instances * - * @param node the node to parse - * @param valueType the class type of the AAS instance. Not null. + * @param value a string representation of the AAS instances list + * @param valueType the class type of the instance. Not null. * @param the AAS type - * @return an AAS instance - * + * @return a list of AAS instances * @throws DeserializationException if deserialization fails */ - public T read(JsonNode node, Class valueType) throws DeserializationException { + public List readList(String value, Class valueType) throws DeserializationException { try { - return mapper.treeToValue(node, valueType); + return mapper.readValue(value, mapper.getTypeFactory().constructCollectionLikeType(List.class, valueType)); } catch (JsonProcessingException ex) { - throw new DeserializationException("error deserializing " + valueType.getSimpleName(), ex); + throw new DeserializationException("error deserializing list of " + valueType.getSimpleName(), ex); } } @@ -128,67 +127,68 @@ public T read(InputStream stream, Charset charset, Class valueType) throw } /** - * Generic method to deserialize a given string into a list of AAS instances + * Deserializes a given input stream into a list of AAS instances using the default UTF-8 charset * - * @param value a string representation of the AAS instances list - * @param valueType the class type of the instance. Not null. + * @param stream An InputStream containing the string representation of the AAS instances list + * @param valueType the class type of the AAS instance. Not null. * @param the AAS type * @return a list of AAS instances * @throws DeserializationException if deserialization fails */ - public List readList(String value, Class valueType) throws DeserializationException { - try { - return mapper.readValue(value, mapper.getTypeFactory().constructCollectionLikeType(List.class, valueType)); - } catch (JsonProcessingException ex) { - throw new DeserializationException("error deserializing list of " + valueType.getSimpleName(), ex); - } + public List readList(InputStream stream, Class valueType) throws DeserializationException { + return readList(stream, StandardCharsets.UTF_8, valueType); } /** - * Deserializes a given JsonArray into a list of AAS instances + * Deserializes a given input stream into a list of AAS instances * - * @param node a JsonArray representing the AAS instances list - * @param valueType the class type of the instance. Not null. + * @param stream An InputStream containing the string representation of the AAS instances list + * @param charset the charset to use for deserialization + * @param valueType the class type of the AAS instance. Not null. * @param the AAS type * @return a list of AAS instances * @throws DeserializationException if deserialization fails */ - public List readList(JsonNode node, Class valueType) throws DeserializationException { + public List readList(InputStream stream, Charset charset, Class valueType) throws DeserializationException { try { - return mapper.treeToValue(node, mapper.getTypeFactory().constructCollectionLikeType(List.class, valueType)); - } catch (JsonProcessingException ex) { + return mapper.readValue(new InputStreamReader(stream, charset), + mapper.getTypeFactory().constructCollectionLikeType(List.class, valueType)); + } catch (Exception ex) { throw new DeserializationException("error deserializing list of " + valueType.getSimpleName(), ex); } } /** - * Deserializes a given input stream into a list of AAS instances using the default UTF-8 charset + * Generic method to deserialize a given JSON node into instance of an AAS type * - * @param stream An InputStream containing the string representation of the AAS instances list + * @param node the node to parse * @param valueType the class type of the AAS instance. Not null. * @param the AAS type - * @return a list of AAS instances + * @return an AAS instance + * * @throws DeserializationException if deserialization fails */ - public List readList(InputStream stream, Class valueType) throws DeserializationException { - return readList(stream, StandardCharsets.UTF_8, valueType); + public T read(JsonNode node, Class valueType) throws DeserializationException { + try { + return mapper.treeToValue(node, valueType); + } catch (JsonProcessingException ex) { + throw new DeserializationException("error deserializing " + valueType.getSimpleName(), ex); + } } /** - * Deserializes a given input stream into a list of AAS instances + * Deserializes a given JsonArray into a list of AAS instances * - * @param stream An InputStream containing the string representation of the AAS instances list - * @param charset the charset to use for deserialization - * @param valueType the class type of the AAS instance. Not null. + * @param node a JsonArray representing the AAS instances list + * @param valueType the class type of the instance. Not null. * @param the AAS type * @return a list of AAS instances * @throws DeserializationException if deserialization fails */ - public List readList(InputStream stream, Charset charset, Class valueType) throws DeserializationException { + public List readList(JsonNode node, Class valueType) throws DeserializationException { try { - return mapper.readValue(new InputStreamReader(stream, charset), - mapper.getTypeFactory().constructCollectionLikeType(List.class, valueType)); - } catch (Exception ex) { + return mapper.treeToValue(node, mapper.getTypeFactory().constructCollectionLikeType(List.class, valueType)); + } catch (JsonProcessingException ex) { throw new DeserializationException("error deserializing list of " + valueType.getSimpleName(), ex); } } diff --git a/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializerTest.java b/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializerTest.java index d4f4351b..3bfe98b4 100644 --- a/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializerTest.java +++ b/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializerTest.java @@ -16,15 +16,11 @@ package org.eclipse.digitaltwin.aas4j.v3.dataformat.json; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; - import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.CustomProperty; @@ -33,24 +29,18 @@ import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.util.ExampleData; 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.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; import org.eclipse.digitaltwin.aas4j.v3.model.DataSpecificationContent; import org.eclipse.digitaltwin.aas4j.v3.model.DefaultDummyDataSpecification; import org.eclipse.digitaltwin.aas4j.v3.model.Environment; -import org.eclipse.digitaltwin.aas4j.v3.model.OperationRequest; import org.eclipse.digitaltwin.aas4j.v3.model.Property; import org.eclipse.digitaltwin.aas4j.v3.model.Referable; import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelDescriptor; -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.DefaultProperty; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodel; -import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; @@ -65,12 +55,6 @@ public static void initialize() { deserializerToTest = new JsonDeserializer(); } - @Test - public void testReadEnvironmentFromStream() throws DeserializationException { - Environment env = deserializerToTest.read(Examples.EXAMPLE_FULL.fileContentStream(), Environment.class); - assertEquals(Examples.EXAMPLE_FULL.getModel(), env); - } - /** * This test ensures that future DataSpecificationContents can be added without adjustments in the code. * @@ -87,80 +71,6 @@ public void testReadCustomDataSpecification() throws DeserializationException { assertEquals(Examples.ENVIRONMENT_CUSTOM_DATA.getModel(), env); } - @Test - public void testReadReferable() throws IOException, DeserializationException { - Submodel submodel = deserializerToTest.read(Examples.SUBMODEL.fileContent(), Submodel.class); - assertEquals(Examples.SUBMODEL.getModel(), submodel); - } - - @Test - public void testReadReferableFromStream() throws DeserializationException { - Submodel submodel = deserializerToTest.read(Examples.SUBMODEL.fileContentStream(), Submodel.class); - assertEquals(Examples.SUBMODEL.getModel(), submodel); - } - - @Test - public void testReadReferableFromNode() throws Exception { - JsonNode node = new ObjectMapper().readTree(Examples.SUBMODEL.fileContentStream()); - Submodel submodel = deserializerToTest.read(node, Submodel.class); - assertEquals(Examples.SUBMODEL.getModel(), submodel); - } - - @Test - public void testReadReferableFromStreamUsingCharset() throws Exception { - Submodel submodel = deserializerToTest.read(Examples.SUBMODEL.fileContentStream(), StandardCharsets.UTF_8, Submodel.class); - assertEquals(Examples.SUBMODEL.getModel(), submodel); - } - - @Test - public void testReadReferables() throws Exception { - List submodels = deserializerToTest.readList(Examples.SUBMODEL_LIST_OF.fileContent(), Submodel.class); - assertEquals(Examples.SUBMODEL_LIST_OF.getModel(), submodels); - } - - @Test - public void testReadReferablesFromNode() throws Exception { - JsonNode node = new ObjectMapper().readTree(Examples.SUBMODEL_LIST_OF.fileContentStream()); - List submodels = deserializerToTest.readList(node, Submodel.class); - assertEquals(Examples.SUBMODEL_LIST_OF.getModel(), submodels); - } - - @Test - public void testReadReferablesFromStream() throws Exception { - List submodels = deserializerToTest.readList( - Examples.SUBMODEL_LIST_OF.fileContentStream(), Submodel.class); - assertEquals(Examples.SUBMODEL_LIST_OF.getModel(), submodels); - } - - @Test - public void testReadReferablesFromStreamUsingUtf8Charset() throws Exception { - List submodels = deserializerToTest.readList( - Examples.SUBMODEL_LIST_OF.fileContentStream(), StandardCharsets.UTF_8, Submodel.class); - assertEquals(Examples.SUBMODEL_LIST_OF.getModel(), submodels); - } - - @Test - public void testReadSimpleExampleEnv() throws Exception { - Environment expected = Examples.EXAMPLE_SIMPLE.getModel(); - Environment actual = deserializerToTest.read(Examples.EXAMPLE_SIMPLE.fileContentStream(), Environment.class); - Assert.assertEquals(expected, actual); - } - - @Test - public void testReadFullExampleEnv() throws Exception { - Environment expected = Examples.EXAMPLE_FULL.getModel(); - Environment actual = deserializerToTest.read(Examples.EXAMPLE_FULL.fileContentStream(), Environment.class); - Assert.assertEquals(expected, actual); - } - - @Test - public void testReadFullExampleEnvFromNode() throws Exception { - Environment expected = Examples.EXAMPLE_FULL.getModel(); - JsonNode node = new ObjectMapper().readTree(Examples.EXAMPLE_FULL.fileContentStream()); - Environment actual = deserializerToTest.read(node, Environment.class); - Assert.assertEquals(expected, actual); - } - @Test public void testReadCustomImplementationClass() throws Exception { String json = Examples.EXAMPLE_SIMPLE.fileContent(); @@ -178,115 +88,85 @@ public void testReadCustomImplementationClass() throws Exception { } @Test - public void testReadShell() throws DeserializationException { - AssetAdministrationShell expected = Examples.ASSET_ADMINISTRATION_SHELL.getModel(); - AssetAdministrationShell actual = deserializerToTest.read(Examples.ASSET_ADMINISTRATION_SHELL.fileContentStream(), AssetAdministrationShell.class); + @Ignore("Physical Unit has been removed from the V3.0 metamodel. Might be added later again.") + public void testReadConceptDescriptionWithPhysicalUnit() throws IOException, DeserializationException { + ConceptDescription expected = Examples.CONCEPT_DESCRIPTION_DATA_SPECIFICATION_PHYSICAL_UNIT.getModel(); + ConceptDescription actual = deserializerToTest.read( + Examples.CONCEPT_DESCRIPTION_DATA_SPECIFICATION_PHYSICAL_UNIT.fileContentStream(), + ConceptDescription.class); assertEquals(expected, actual); } @Test - public void testReadShells() throws DeserializationException { - List expected = Examples.ASSET_ADMINISTRATION_SHELL_LIST_OF.getModel(); - List actual = deserializerToTest.readList(Examples.ASSET_ADMINISTRATION_SHELL_LIST_OF.fileContentStream(), AssetAdministrationShell.class); - assertEquals(expected, actual); + public void testReadEmptyReferableList() throws DeserializationException { + List emptyList = Collections.emptyList(); + List deserialized = deserializerToTest.readList("[]", Referable.class); + assertEquals(emptyList, deserialized); } @Test - public void testReadSubmodelUsingUtf8Charset() throws DeserializationException { - Submodel expected = Examples.SUBMODEL.getModel(); - Submodel actual = deserializerToTest.read(Examples.SUBMODEL.fileContentStream(), StandardCharsets.UTF_8, Submodel.class); - assertEquals(expected, actual); + public void testReadFullExampleEnv() { + readAndCompare(Examples.EXAMPLE_FULL); } @Test - public void testReadSubmodelsFromStreamUsingUtf8Charset() throws DeserializationException { - List expected = Examples.SUBMODEL_LIST_OF.getModel(); - List actual = deserializerToTest.readList( - Examples.SUBMODEL_LIST_OF.fileContentStream(), StandardCharsets.UTF_8, Submodel.class); - assertEquals(expected, actual); + public void testReadSimpleExampleEnv() { + readAndCompare(Examples.EXAMPLE_SIMPLE); } @Test - public void testReadSubmodel() throws DeserializationException { - Submodel expected = Examples.SUBMODEL.getModel(); - Submodel actual = deserializerToTest.read(Examples.SUBMODEL.fileContentStream(), Submodel.class); - assertEquals(expected, actual); + public void testReadShell() { + readAndCompare(Examples.ASSET_ADMINISTRATION_SHELL); } @Test - public void testReadSubmodels() throws DeserializationException { - List expected = Examples.SUBMODEL_LIST_OF.getModel(); - List actual = deserializerToTest.readList(Examples.SUBMODEL_LIST_OF.fileContentStream(), Submodel.class); - assertEquals(expected, actual); + public void testReadShells() { + readAndCompare(Examples.ASSET_ADMINISTRATION_SHELL_LIST_OF); } @Test - public void testReadSubmodelElement() throws DeserializationException { - SubmodelElement expected = Examples.SUBMODEL_ELEMENT.getModel(); - SubmodelElement actual = deserializerToTest.read(Examples.SUBMODEL_ELEMENT.fileContentStream(), SubmodelElement.class); - assertEquals(expected, actual); + public void testReadSubmodel() { + readAndCompare(Examples.SUBMODEL); } @Test - public void testReadSubmodelElements() throws DeserializationException { - List expected = Examples.SUBMODEL_ELEMENT_LIST_OF.getModel(); - List actual = deserializerToTest.readList( - Examples.SUBMODEL_ELEMENT_LIST_OF.fileContentStream(), SubmodelElement.class); - assertEquals(expected, actual); + public void testReadSubmodels() { + readAndCompare(Examples.SUBMODEL_LIST_OF); } @Test - public void testReadSubmodelElementList() throws DeserializationException { - SubmodelElement expected = Examples.SUBMODEL_ELEMENT_LIST.getModel(); - SubmodelElementList actual = deserializerToTest.read(Examples.SUBMODEL_ELEMENT_LIST.fileContentStream(), SubmodelElementList.class); - assertEquals(expected, actual); + public void testReadSubmodelElement() { + readAndCompare(Examples.SUBMODEL_ELEMENT); } @Test - public void testReadSubmodelElementCollection() throws DeserializationException { - SubmodelElement expected = Examples.SUBMODEL_ELEMENT_COLLECTION.getModel(); - SubmodelElementCollection actual = deserializerToTest.read(Examples.SUBMODEL_ELEMENT_COLLECTION.fileContentStream(), SubmodelElementCollection.class); - assertEquals(expected, actual); + public void testReadSubmodelElements() { + readAndCompare(Examples.SUBMODEL_ELEMENT_LIST_OF); } @Test - public void testReadEmptyReferableList() throws DeserializationException { - List emptyList = Collections.emptyList(); - List deserialized = deserializerToTest.readList("[]", Referable.class); - assertEquals(emptyList, deserialized); + public void testReadSubmodelElementList() { + readAndCompare(Examples.SUBMODEL_ELEMENT_LIST); } @Test - @Ignore("Physical Unit has been removed from the V3.0 metamodel. Might be added later again.") - public void testReadConceptDescriptionWithPhysicalUnit() throws IOException, DeserializationException { - ConceptDescription expected = Examples.CONCEPT_DESCRIPTION_DATA_SPECIFICATION_PHYSICAL_UNIT.getModel(); - ConceptDescription actual = deserializerToTest.read( - Examples.CONCEPT_DESCRIPTION_DATA_SPECIFICATION_PHYSICAL_UNIT.fileContentStream(), - ConceptDescription.class); - assertEquals(expected, actual); + public void testReadSubmodelElementCollection() { + readAndCompare(Examples.SUBMODEL_ELEMENT_COLLECTION); } @Test - public void testReadExtensionMinimalEnv() throws Exception { - Environment expected = Examples.EXTENSION_MINIMAL.getModel(); - Environment actual = deserializerToTest.read(Examples.EXTENSION_MINIMAL.fileContentStream(), Environment.class); - assertEquals(expected, actual); + public void testReadExtensionMinimalEnv() { + readAndCompare(Examples.EXTENSION_MINIMAL); } @Test public void testReadExtensionMaximalEnv() throws Exception { - Environment expected = Examples.EXTENSION_MAXIMAL.getModel(); - Environment actual = deserializerToTest.read(Examples.EXTENSION_MAXIMAL.fileContentStream(), Environment.class); - assertEquals(expected, actual); + readAndCompare(Examples.EXTENSION_MAXIMAL); } - - @Test - public void testReadShellDescriptor() throws IOException, DeserializationException { - AssetAdministrationShellDescriptor shellDescriptor = - deserializerToTest.read(Examples.SHELL_DESCRIPTOR.fileContent(), AssetAdministrationShellDescriptor.class); - assertEquals(Examples.SHELL_DESCRIPTOR.getModel(), shellDescriptor); + public void testReadShellDescriptor() { + readAndCompare(Examples.SHELL_DESCRIPTOR); } @Test @@ -298,21 +178,15 @@ public void testReadShellDescriptors() throws IOException, DeserializationExcept } @Test - public void testReadOperationRequest() throws DeserializationException, IOException { + public void testReadOperationRequest() { readAndCompare(Examples.OPERATION_REQUEST); - OperationRequest expected = Examples.OPERATION_REQUEST.getModel(); - OperationRequest actual = deserializerToTest.read(Examples.OPERATION_REQUEST.fileContent(), OperationRequest.class); - assertEquals(expected, actual); } @Test - public void testReadSubmodelDescriptor() throws IOException, DeserializationException { - SubmodelDescriptor submodelDescriptor = deserializerToTest.read( - Examples.SUBMODEL_DESCRIPTOR.fileContentStream(), SubmodelDescriptor.class); - assertEquals(Examples.SUBMODEL_DESCRIPTOR.getModel(), submodelDescriptor); + public void testReadSubmodelDescriptor() { + readAndCompare(Examples.SUBMODEL_DESCRIPTOR); } - @Test public void testReadSubmodelDescriptors() throws IOException, DeserializationException { String jsonString = "[" + Examples.SUBMODEL_DESCRIPTOR.fileContent() + "]"; @@ -321,8 +195,15 @@ public void testReadSubmodelDescriptors() throws IOException, DeserializationExc assertEquals(Examples.SUBMODEL_DESCRIPTOR.getModel(), submodelDescriptors.get(0)); } - private void readAndCompare(ExampleData exampleData) throws IOException, DeserializationException { - assertEquals(exampleData.getModel(), readFromString(exampleData)); + private void readAndCompare(ExampleData exampleData) { + try { + Object expected = exampleData.getModel(); + assertEquals(expected, readFromString(exampleData)); + assertEquals(expected, readFromNode(exampleData)); + assertEquals(expected, readFromStream(exampleData)); + } catch (Exception ex) { + throw new RuntimeException(ex); + } } private Object readFromString(ExampleData exampleData) throws IOException, DeserializationException { @@ -334,6 +215,24 @@ private Object readFromString(ExampleData exampleData) throws IOException, De return deserializerToTest.read(exampleData.fileContent(), model.getClass()); } + private Object readFromStream(ExampleData exampleData) throws DeserializationException { + Object model = exampleData.getModel(); + if(model instanceof Collection) { + Collection coll = (Collection) model; + return deserializerToTest.readList(exampleData.fileContentStream(), coll.iterator().next().getClass()); + } + return deserializerToTest.read(exampleData.fileContentStream(), model.getClass()); + } + + private Object readFromNode(ExampleData exampleData) throws IOException, DeserializationException { + Object model = exampleData.getModel(); + if(model instanceof Collection) { + Collection coll = (Collection) model; + return deserializerToTest.readList(exampleData.getJsonNode(), coll.iterator().next().getClass()); + } + return deserializerToTest.read(exampleData.getJsonNode(), model.getClass()); + } + private void checkImplementationClasses(Environment environment, Class submodelImpl, Class propertyImpl) { environment.getSubmodels().forEach(submodel -> {