Skip to content

Commit

Permalink
Extracts common JsonMapper/TypeResolver factories (#198)
Browse files Browse the repository at this point in the history

Signed-off-by: Frank Schnicke <frank.schnicke@iese.fraunhofer.de>
  • Loading branch information
FrankSchnicke authored Nov 16, 2023
1 parent 0ae35c2 commit dbab709
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -185,7 +152,7 @@ public Environment read(java.io.File file) throws FileNotFoundException, Deseria
*/
public <T> void useImplementation(Class<T> aasInterface, Class<? extends T> implementation) {
typeResolver.addMapping(aasInterface, implementation);
buildMapper();
mapper = jsonMapperFactory.create(typeResolver);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* 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 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;
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.json.JsonMapper.Builder;
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) {
Builder builder = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.annotationIntrospector(new ReflectionAnnotationIntrospector())
.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<SimpleModule> getModulesToInstall(SimpleAbstractTypeResolver typeResolver) {
return Arrays.asList(buildEnumModule(), buildImplementationModule(typeResolver));
}

protected SimpleModule buildImplementationModule(SimpleAbstractTypeResolver typeResolver) {
SimpleModule module = new SimpleModule();
module.setAbstractTypes(typeResolver);
return module;
}

protected SimpleModule buildEnumModule() {
SimpleModule module = new SimpleModule();
ReflectionHelper.ENUMS.forEach(x -> module.addSerializer(x, new EnumSerializer()));
ReflectionHelper.ENUMS.forEach(x -> module.addDeserializer(x, new EnumDeserializer<>(x)));
return module;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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());
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}

0 comments on commit dbab709

Please sign in to comment.