Adding a way to support to specify which implementation to use

This commit is contained in:
Luca Frosini 2024-07-01 17:36:24 +02:00
parent bfeaeacc40
commit 0931af85ed
5 changed files with 94 additions and 18 deletions

View File

@ -0,0 +1,19 @@
package org.gcube.informationsystem.contexts.reference;
public enum ContextState {
CREATED("created"),
ACTIVE("active"),
DELETED("deleted");
protected String state;
ContextState(String state) {
this.state = state;
}
public String getState() {
return state;
}
}

View File

@ -13,7 +13,6 @@ import org.gcube.com.fasterxml.jackson.annotation.JsonGetter;
import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore; import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore;
import org.gcube.com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.gcube.com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.gcube.com.fasterxml.jackson.annotation.JsonPropertyOrder; import org.gcube.com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.gcube.com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.gcube.com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.gcube.com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.gcube.informationsystem.base.reference.Element; import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.base.reference.IdentifiableElement; import org.gcube.informationsystem.base.reference.IdentifiableElement;
@ -23,6 +22,7 @@ import org.gcube.informationsystem.contexts.impl.entities.ContextImpl;
import org.gcube.informationsystem.contexts.reference.relations.IsParentOf; import org.gcube.informationsystem.contexts.reference.relations.IsParentOf;
import org.gcube.informationsystem.model.reference.relations.Relation; import org.gcube.informationsystem.model.reference.relations.Relation;
import org.gcube.informationsystem.serialization.AdditionalPropertiesSerializer; import org.gcube.informationsystem.serialization.AdditionalPropertiesSerializer;
import org.gcube.informationsystem.types.annotations.Deserialize;
import org.gcube.informationsystem.types.annotations.Final; import org.gcube.informationsystem.types.annotations.Final;
import org.gcube.informationsystem.types.annotations.ISProperty; import org.gcube.informationsystem.types.annotations.ISProperty;
import org.gcube.informationsystem.types.reference.Change; import org.gcube.informationsystem.types.reference.Change;
@ -34,7 +34,8 @@ import org.gcube.informationsystem.utils.Version;
* *
* @author Luca Frosini (ISTI - CNR) * @author Luca Frosini (ISTI - CNR)
*/ */
@JsonDeserialize(as = ContextImpl.class) //@JsonDeserialize(as = ContextImpl.class)
@Deserialize(as = ContextImpl.class)
@JsonPropertyOrder({ Element.TYPE_PROPERTY, IdentifiableElement.ID_PROPERTY, IdentifiableElement.METADATA_PROPERTY}) @JsonPropertyOrder({ Element.TYPE_PROPERTY, IdentifiableElement.ID_PROPERTY, IdentifiableElement.METADATA_PROPERTY})
@TypeMetadata(name = Context.NAME, description = "This type is the used to define a Context", version = Version.MINIMAL_VERSION_STRING) @TypeMetadata(name = Context.NAME, description = "This type is the used to define a Context", version = Version.MINIMAL_VERSION_STRING)
@Change(version = Version.MINIMAL_VERSION_STRING, description = Version.MINIMAL_VERSION_DESCRIPTION) @Change(version = Version.MINIMAL_VERSION_STRING, description = Version.MINIMAL_VERSION_DESCRIPTION)

View File

@ -8,6 +8,7 @@ import java.io.Writer;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
@ -24,6 +25,8 @@ import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.com.fasterxml.jackson.databind.SerializationFeature; import org.gcube.com.fasterxml.jackson.databind.SerializationFeature;
import org.gcube.com.fasterxml.jackson.databind.exc.InvalidTypeIdException; import org.gcube.com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
import org.gcube.com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver;
import org.gcube.com.fasterxml.jackson.databind.module.SimpleModule;
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
import org.gcube.com.fasterxml.jackson.databind.node.JsonNodeType; import org.gcube.com.fasterxml.jackson.databind.node.JsonNodeType;
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
@ -43,7 +46,7 @@ import org.slf4j.LoggerFactory;
* @author Luca Frosini (ISTI - CNR) * @author Luca Frosini (ISTI - CNR)
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public abstract class ElementMapper { public class ElementMapper {
private static Logger logger = LoggerFactory.getLogger(ElementMapper.class); private static Logger logger = LoggerFactory.getLogger(ElementMapper.class);
@ -51,6 +54,8 @@ public abstract class ElementMapper {
protected static final Map<String, Class<? extends Element>> knownTypes; protected static final Map<String, Class<? extends Element>> knownTypes;
protected static final Map<Class<? extends Element>, Class<? extends Element>> interfaceToImplementation;
/** /**
* @return the ObjectMapper * @return the ObjectMapper
*/ */
@ -70,8 +75,9 @@ public abstract class ElementMapper {
mapper.setDateFormat(sdf); mapper.setDateFormat(sdf);
knownTypes = new HashMap<>(); knownTypes = new HashMap<>();
interfaceToImplementation = new HashMap<>();
List<Package> packages = new ArrayList<Package>(); Set<Package> packages = new HashSet<Package>();
Class<Type> tdClz = Type.class; Class<Type> tdClz = Type.class;
ElementMapper.registerSubtype(tdClz); ElementMapper.registerSubtype(tdClz);
@ -82,14 +88,18 @@ public abstract class ElementMapper {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
Class clz = accessType.getTypeClass(); Class clz = accessType.getTypeClass();
if(!Type.class.isAssignableFrom(clz)) { if(!Type.class.isAssignableFrom(clz)) {
Class<Element> dummyClz = accessType.getDummyImplementationClass(); Class<? extends Element> dynamicImplementationClz = TypeMapper.getDynamicImplementation(clz);
if(dummyClz != null) { if(dynamicImplementationClz!=null) {
// ElementMapper.registerSubtypes(clz, dummyClz); ElementMapper.addDynamicAssociation(clz, dynamicImplementationClz);
ElementMapper.registerSubtype(dummyClz);
}else { }else {
ElementMapper.registerSubtype(clz); Class<Element> dummyClz = accessType.getDummyImplementationClass();
if(dummyClz != null) {
ElementMapper.registerSubtype(dummyClz);
}else {
ElementMapper.registerSubtype(clz);
}
packages.add(clz.getPackage());
} }
packages.add(clz.getPackage());
} }
} }
@ -117,16 +127,26 @@ public abstract class ElementMapper {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
for(@SuppressWarnings("rawtypes") Class clz : interfaceToImplementation.keySet()) {
Class<? extends Element> implClz = interfaceToImplementation.get(clz);
registerSubtypes(clz, implClz);
}
}
public static <El extends Element, ELImpl extends El> void addDynamicAssociation(Class<El> interfaceClz, Class<ELImpl> implementationClass) {
interfaceToImplementation.put(interfaceClz, implementationClass);
} }
// This add the ElementDeserializer which has been deprecated thank to the fix in protected static <El extends Element, ELImpl extends El> void registerSubtypes(Class<El> interfaceClz, Class<ELImpl> implementationClass) {
// public static <El extends Element> void registerSubtypes(Class<El> clz, Class<El> implementationClass) { String typeName = TypeMapper.getType(interfaceClz);
// String typeName = TypeMapper.getType(clz);
// SimpleModule isModule = new SimpleModule(typeName); SimpleModule module = new SimpleModule(typeName);
// isModule.addDeserializer(clz, new ElementDeserializer<>(clz, mapper)); SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver();
// mapper.registerModule(isModule); resolver.addMapping(interfaceClz, implementationClass);
// registerSubtype(implementationClass); module.setAbstractTypes(resolver);
// }
mapper.registerModule(module);
}
public static <El extends Element> void registerSubtype(Class<El> clz) { public static <El extends Element> void registerSubtype(Class<El> clz) {
String typeName = TypeMapper.getType(clz); String typeName = TypeMapper.getType(clz);

View File

@ -11,6 +11,7 @@ import org.gcube.com.fasterxml.jackson.databind.DeserializationFeature;
import org.gcube.com.fasterxml.jackson.databind.JavaType; import org.gcube.com.fasterxml.jackson.databind.JavaType;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.informationsystem.base.reference.Element; import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.types.annotations.Deserialize;
import org.gcube.informationsystem.types.impl.TypeImpl; import org.gcube.informationsystem.types.impl.TypeImpl;
import org.gcube.informationsystem.types.reference.Change; import org.gcube.informationsystem.types.reference.Change;
import org.gcube.informationsystem.types.reference.Changelog; import org.gcube.informationsystem.types.reference.Changelog;
@ -92,6 +93,19 @@ public class TypeMapper {
return getType(e.getClass()); return getType(e.getClass());
} }
public static <E extends Element, EImpl extends E> Class<EImpl> getDynamicImplementation(Class<E> clz){
if(clz.isInterface() && clz.isAnnotationPresent(Deserialize.class)) {
Deserialize deserialize = clz.getAnnotation(Deserialize.class);
Class<?> annotatedClass = deserialize.as();
if(clz.isAssignableFrom(annotatedClass) && !annotatedClass.isInterface()) {
@SuppressWarnings("unchecked")
Class<EImpl> implementationClz = (Class<EImpl>) annotatedClass;
return implementationClz;
}
}
return null;
}
public static String getType(Class<? extends Element> clz){ public static String getType(Class<? extends Element> clz){
String classSimpleName = clz.getSimpleName(); String classSimpleName = clz.getSimpleName();
String name = null; String name = null;

View File

@ -0,0 +1,22 @@
package org.gcube.informationsystem.types.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.gcube.informationsystem.base.reference.Element;
/**
* It indicates that the {@link Element} is final and cannot be extended/derived.
* This is needed because the type definition is made with interface.
* @author Luca Frosini (ISTI - CNR)
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Deserialize {
public Class<?> as() default Void.class;
}