From dfaa85d1ec8fbc65734abb237fc7d9f0ff212024 Mon Sep 17 00:00:00 2001 From: Frank Schnicke Date: Thu, 16 Nov 2023 09:49:47 +0100 Subject: [PATCH 1/3] Extracts common JsonMapper/TypeResolver factories Signed-off-by: Frank Schnicke --- .../v3/dataformat/json/JsonDeserializer.java | 63 +++++------------- .../v3/dataformat/json/JsonMapperFactory.java | 64 +++++++++++++++++++ .../v3/dataformat/json/JsonSerializer.java | 48 +++----------- .../SimpleAbstractTypeResolverFactory.java | 37 +++++++++++ 4 files changed, 126 insertions(+), 86 deletions(-) create mode 100644 dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java create mode 100644 dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/SimpleAbstractTypeResolverFactory.java 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 bfefb16e2..ab6275d9e 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 @@ -16,20 +16,6 @@ */ package org.eclipse.digitaltwin.aas4j.v3.dataformat.json; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.json.JsonMapper; -import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; -import com.fasterxml.jackson.databind.module.SimpleModule; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.deserialization.EnumDeserializer; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.internal.ReflectionAnnotationIntrospector; -import org.eclipse.digitaltwin.aas4j.v3.model.Environment; -import org.eclipse.digitaltwin.aas4j.v3.model.Referable; - import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -41,6 +27,16 @@ import java.util.List; import java.util.stream.Collectors; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; +import org.eclipse.digitaltwin.aas4j.v3.model.Environment; +import org.eclipse.digitaltwin.aas4j.v3.model.Referable; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; + /** * Class for deserializing/parsing AAS JSON documents. @@ -49,43 +45,14 @@ public class JsonDeserializer { protected JsonMapper mapper; protected SimpleAbstractTypeResolver typeResolver; + private JsonMapperFactory jsonMapperFactory; private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; public JsonDeserializer() { - initTypeResolver(); - buildMapper(); - } - - protected void buildMapper() { - mapper = JsonMapper.builder() - .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - .annotationIntrospector(new ReflectionAnnotationIntrospector()) - .addModule(buildEnumModule()) - .addModule(buildImplementationModule()) - .build(); - ReflectionHelper.JSON_MIXINS.entrySet().forEach(x -> mapper.addMixIn(x.getKey(), x.getValue())); - } - - @SuppressWarnings("unchecked") - private void initTypeResolver() { - typeResolver = new SimpleAbstractTypeResolver(); - ReflectionHelper.DEFAULT_IMPLEMENTATIONS - .stream() - .forEach(x -> typeResolver.addMapping(x.getInterfaceType(), x.getImplementationType())); - } - - protected SimpleModule buildEnumModule() { - SimpleModule module = new SimpleModule(); - ReflectionHelper.ENUMS.forEach(x -> module.addDeserializer(x, new EnumDeserializer<>(x))); - return module; - } - - protected SimpleModule buildImplementationModule() { - SimpleModule module = new SimpleModule(); - module.setAbstractTypes(typeResolver); - return module; + typeResolver = new SimpleAbstractTypeResolverFactory().create(); + jsonMapperFactory = new JsonMapperFactory(); + mapper = jsonMapperFactory.create(typeResolver); } /** @@ -185,7 +152,7 @@ public Environment read(java.io.File file) throws FileNotFoundException, Deseria */ public void useImplementation(Class aasInterface, Class implementation) { typeResolver.addMapping(aasInterface, implementation); - buildMapper(); + mapper = jsonMapperFactory.create(typeResolver); } /** diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java new file mode 100644 index 000000000..67810f5ab --- /dev/null +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e. V. + * + * 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.json; + +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.deserialization.EnumDeserializer; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.serialization.EnumSerializer; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.internal.ReflectionAnnotationIntrospector; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; +import com.fasterxml.jackson.databind.module.SimpleModule; + +/** + * Factory for creating a {@link JsonMapper} configured to produce and consume AAS Version 3 conformant JSON serializations + * + * @author schnicke + * + */ +public class JsonMapperFactory { + + public JsonMapper create(SimpleAbstractTypeResolver typeResolver) { + final JsonMapper mapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) + .serializationInclusion(JsonInclude.Include.NON_NULL) + .addModule(buildEnumModule()) + .addModule(buildImplementationModule(typeResolver)) + .annotationIntrospector(new ReflectionAnnotationIntrospector()) + .build(); + ReflectionHelper.JSON_MIXINS.entrySet().forEach(x -> mapper.addMixIn(x.getKey(), x.getValue())); + + return mapper; + } + + protected SimpleModule buildImplementationModule(SimpleAbstractTypeResolver typeResolver) { + SimpleModule module = new SimpleModule(); + module.setAbstractTypes(typeResolver); + return module; + } + + protected SimpleModule buildEnumModule() { + SimpleModule module = new SimpleModule(); + module.addSerializer(Enum.class, new EnumSerializer()); + ReflectionHelper.ENUMS.forEach(x -> module.addDeserializer(x, new EnumDeserializer<>(x))); + return module; + } +} diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializer.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializer.java index f370de8c0..993ee925d 100644 --- a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializer.java +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializer.java @@ -16,21 +16,6 @@ */ package org.eclipse.digitaltwin.aas4j.v3.dataformat.json; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.json.JsonMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.serialization.EnumSerializer; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.internal.ReflectionAnnotationIntrospector; -import org.eclipse.digitaltwin.aas4j.v3.model.Environment; -import org.eclipse.digitaltwin.aas4j.v3.model.Referable; - import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -41,6 +26,15 @@ import java.util.Collection; import java.util.List; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; +import org.eclipse.digitaltwin.aas4j.v3.model.Environment; +import org.eclipse.digitaltwin.aas4j.v3.model.Referable; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.json.JsonMapper; + /** * Class for serializing an instance of AssetAdministrationShellEnvironment or Referables to * JSON. @@ -52,29 +46,7 @@ public class JsonSerializer { private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; public JsonSerializer() { - buildMapper(); - } - - protected void buildMapper() { - mapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT) - .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - .serializationInclusion(JsonInclude.Include.NON_NULL) - .addModule(buildEnumModule()) - .addModule(buildCustomSerializerModule()) - .annotationIntrospector(new ReflectionAnnotationIntrospector()) - .build(); - ReflectionHelper.JSON_MIXINS.entrySet().forEach(x -> mapper.addMixIn(x.getKey(), x.getValue())); - } - - protected SimpleModule buildCustomSerializerModule() { - SimpleModule module = new SimpleModule(); - return module; - } - - protected SimpleModule buildEnumModule() { - SimpleModule module = new SimpleModule(); - module.addSerializer(Enum.class, new EnumSerializer()); - return module; + mapper = new JsonMapperFactory().create(new SimpleAbstractTypeResolverFactory().create()); } /** diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/SimpleAbstractTypeResolverFactory.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/SimpleAbstractTypeResolverFactory.java new file mode 100644 index 000000000..742af85ab --- /dev/null +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/SimpleAbstractTypeResolverFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e. V. + * + * 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.json; + +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; + +import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; + +/** + * Factory for creating a {@link SimpleAbstractTypeResolver} configured with the + * Default Implementations of AAS4J + * + * @author schnicke + * + */ +public class SimpleAbstractTypeResolverFactory { + @SuppressWarnings("unchecked") + public SimpleAbstractTypeResolver create() { + SimpleAbstractTypeResolver typeResolver = new SimpleAbstractTypeResolver(); + ReflectionHelper.DEFAULT_IMPLEMENTATIONS.stream().forEach(x -> typeResolver.addMapping(x.getInterfaceType(), x.getImplementationType())); + return typeResolver; + } +} From 51169cb9af2cf76b9a06146cfe3c95b503deb8e3 Mon Sep 17 00:00:00 2001 From: Frank Schnicke Date: Thu, 16 Nov 2023 10:06:45 +0100 Subject: [PATCH 2/3] Ensures only AAS4J enums are custom-configured Signed-off-by: Frank Schnicke --- .../digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java index 67810f5ab..3d5601943 100644 --- a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java @@ -57,7 +57,7 @@ protected SimpleModule buildImplementationModule(SimpleAbstractTypeResolver type protected SimpleModule buildEnumModule() { SimpleModule module = new SimpleModule(); - module.addSerializer(Enum.class, new EnumSerializer()); + ReflectionHelper.ENUMS.forEach(x -> module.addSerializer(x, new EnumSerializer())); ReflectionHelper.ENUMS.forEach(x -> module.addDeserializer(x, new EnumDeserializer<>(x))); return module; } From 1e155e3ed9ff19717b1d9d36e5269b7c427a6a44 Mon Sep 17 00:00:00 2001 From: Frank Schnicke Date: Thu, 16 Nov 2023 10:23:12 +0100 Subject: [PATCH 3/3] Adds further function for configuration Signed-off-by: Frank Schnicke --- .../v3/dataformat/json/JsonMapperFactory.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java index 3d5601943..a849c7370 100644 --- a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java @@ -16,6 +16,9 @@ package org.eclipse.digitaltwin.aas4j.v3.dataformat.json; +import java.util.Arrays; +import java.util.List; + import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.deserialization.EnumDeserializer; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.serialization.EnumSerializer; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; @@ -25,6 +28,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.json.JsonMapper.Builder; import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -37,18 +41,23 @@ public class JsonMapperFactory { public JsonMapper create(SimpleAbstractTypeResolver typeResolver) { - final JsonMapper mapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + Builder builder = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - .serializationInclusion(JsonInclude.Include.NON_NULL) - .addModule(buildEnumModule()) - .addModule(buildImplementationModule(typeResolver)) .annotationIntrospector(new ReflectionAnnotationIntrospector()) - .build(); + .serializationInclusion(JsonInclude.Include.NON_NULL); + + getModulesToInstall(typeResolver).stream().forEach(m -> builder.addModule(m)); + + JsonMapper mapper = builder.build(); ReflectionHelper.JSON_MIXINS.entrySet().forEach(x -> mapper.addMixIn(x.getKey(), x.getValue())); return mapper; } + protected List getModulesToInstall(SimpleAbstractTypeResolver typeResolver) { + return Arrays.asList(buildEnumModule(), buildImplementationModule(typeResolver)); + } + protected SimpleModule buildImplementationModule(SimpleAbstractTypeResolver typeResolver) { SimpleModule module = new SimpleModule(); module.setAbstractTypes(typeResolver);