Adding a way to support to specify which implementation to use
This commit is contained in:
parent
bfeaeacc40
commit
0931af85ed
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
|
@ -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,15 +88,19 @@ 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<? extends Element> dynamicImplementationClz = TypeMapper.getDynamicImplementation(clz);
|
||||||
|
if(dynamicImplementationClz!=null) {
|
||||||
|
ElementMapper.addDynamicAssociation(clz, dynamicImplementationClz);
|
||||||
|
}else {
|
||||||
Class<Element> dummyClz = accessType.getDummyImplementationClass();
|
Class<Element> dummyClz = accessType.getDummyImplementationClass();
|
||||||
if(dummyClz != null) {
|
if(dummyClz != null) {
|
||||||
// ElementMapper.registerSubtypes(clz, dummyClz);
|
|
||||||
ElementMapper.registerSubtype(dummyClz);
|
ElementMapper.registerSubtype(dummyClz);
|
||||||
}else {
|
}else {
|
||||||
ElementMapper.registerSubtype(clz);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This add the ElementDeserializer which has been deprecated thank to the fix in
|
public static <El extends Element, ELImpl extends El> void addDynamicAssociation(Class<El> interfaceClz, Class<ELImpl> implementationClass) {
|
||||||
// public static <El extends Element> void registerSubtypes(Class<El> clz, Class<El> implementationClass) {
|
interfaceToImplementation.put(interfaceClz, implementationClass);
|
||||||
// String typeName = TypeMapper.getType(clz);
|
}
|
||||||
// SimpleModule isModule = new SimpleModule(typeName);
|
|
||||||
// isModule.addDeserializer(clz, new ElementDeserializer<>(clz, mapper));
|
protected static <El extends Element, ELImpl extends El> void registerSubtypes(Class<El> interfaceClz, Class<ELImpl> implementationClass) {
|
||||||
// mapper.registerModule(isModule);
|
String typeName = TypeMapper.getType(interfaceClz);
|
||||||
// registerSubtype(implementationClass);
|
|
||||||
// }
|
SimpleModule module = new SimpleModule(typeName);
|
||||||
|
SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver();
|
||||||
|
resolver.addMapping(interfaceClz, 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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue