Type deserialization is compliant with old version without CHANGELOG
This commit is contained in:
parent
745bb9eb3e
commit
21fcb502f2
|
@ -34,6 +34,7 @@ public class TypeMapper {
|
||||||
static {
|
static {
|
||||||
mapper = new ObjectMapper();
|
mapper = new ObjectMapper();
|
||||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
mapper.configure(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, false);
|
||||||
|
|
||||||
mapper.registerSubtypes(Type.class);
|
mapper.registerSubtypes(Type.class);
|
||||||
|
|
||||||
|
|
|
@ -32,151 +32,159 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class TypeImpl implements Type {
|
public class TypeImpl implements Type {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(TypeImpl.class);
|
private static Logger logger = LoggerFactory.getLogger(TypeImpl.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generated Serial version UID
|
* Generated Serial version UID
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -4333954207969059451L;
|
private static final long serialVersionUID = -4333954207969059451L;
|
||||||
|
|
||||||
public final static String DESCRIPTION = "DESCRIPTION";
|
public final static String DESCRIPTION = "DESCRIPTION";
|
||||||
public final static String VERSION = "VERSION";
|
public final static String VERSION = "VERSION";
|
||||||
public final static String CHANGELOG = "CHANGELOG";
|
public final static String CHANGELOG = "CHANGELOG";
|
||||||
|
|
||||||
public static final Map<TypeVersion, String> DEFAULT_CHANGELOG_MAP;
|
public static final Map<TypeVersion, String> DEFAULT_CHANGELOG_MAP;
|
||||||
|
private static final Map<String, String> DEFAULT_CHANGELOG_MAP_KEY_AS_STRING;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
DEFAULT_CHANGELOG_MAP = new HashMap<>();
|
DEFAULT_CHANGELOG_MAP = new HashMap<>();
|
||||||
DEFAULT_CHANGELOG_MAP.put(new TypeVersion(TypeVersion.MINIMAL_VERSION_STRING), "First Version");
|
DEFAULT_CHANGELOG_MAP.put(new TypeVersion(TypeVersion.MINIMAL_VERSION_STRING), TypeVersion.MINIMAL_VERSION_DESCRIPTION);
|
||||||
|
DEFAULT_CHANGELOG_MAP_KEY_AS_STRING = new HashMap<>();
|
||||||
|
DEFAULT_CHANGELOG_MAP_KEY_AS_STRING.put(TypeVersion.MINIMAL_VERSION_STRING, TypeVersion.MINIMAL_VERSION_DESCRIPTION);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Header header;
|
protected Header header;
|
||||||
|
|
||||||
protected String name;
|
protected String name;
|
||||||
protected String description;
|
protected String description;
|
||||||
protected TypeVersion version;
|
protected TypeVersion version;
|
||||||
|
@JsonProperty(value = CHANGELOG_PROPERTY, required = false)
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
protected Map<TypeVersion, String> changelog;
|
protected Map<TypeVersion, String> changelog;
|
||||||
|
|
||||||
@JsonProperty(value="abstract")
|
@JsonProperty(value = "abstract")
|
||||||
protected boolean abstractType;
|
protected boolean abstractType;
|
||||||
protected Set<String> superClasses;
|
protected Set<String> superClasses;
|
||||||
|
|
||||||
protected Set<PropertyDefinition> properties;
|
protected Set<PropertyDefinition> properties;
|
||||||
|
|
||||||
protected <E extends Element> Set<String> retrieveSuperClasses(Class<? extends E> type, Class<E> baseClass, String topSuperClass){
|
protected <E extends Element> Set<String> retrieveSuperClasses(Class<? extends E> type, Class<E> baseClass,
|
||||||
|
String topSuperClass) {
|
||||||
Set<String> interfaceList = new HashSet<>();
|
Set<String> interfaceList = new HashSet<>();
|
||||||
|
|
||||||
if(type==baseClass){
|
if (type == baseClass) {
|
||||||
if(topSuperClass!=null) {
|
if (topSuperClass != null) {
|
||||||
interfaceList.add(topSuperClass);
|
interfaceList.add(topSuperClass);
|
||||||
}
|
}
|
||||||
return interfaceList;
|
return interfaceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?>[] interfaces = type.getInterfaces();
|
Class<?>[] interfaces = type.getInterfaces();
|
||||||
|
|
||||||
for (Class<?> interfaceClass : interfaces) {
|
for (Class<?> interfaceClass : interfaces) {
|
||||||
|
|
||||||
if(!baseClass.isAssignableFrom(interfaceClass)){
|
if (!baseClass.isAssignableFrom(interfaceClass)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<? extends Element> clz = (Class<? extends Element>) interfaceClass;
|
Class<? extends Element> clz = (Class<? extends Element>) interfaceClass;
|
||||||
interfaceList.add(TypeMapper.getType(clz));
|
interfaceList.add(TypeMapper.getType(clz));
|
||||||
}
|
}
|
||||||
|
|
||||||
return interfaceList;
|
return interfaceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<PropertyDefinition> retrieveListOfProperties(Class<?> type){
|
protected Set<PropertyDefinition> retrieveListOfProperties(Class<?> type) {
|
||||||
Set<PropertyDefinition> properties = new HashSet<>();
|
Set<PropertyDefinition> properties = new HashSet<>();
|
||||||
for (Method m : type.getDeclaredMethods()){
|
for (Method m : type.getDeclaredMethods()) {
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
if(m.isAnnotationPresent(ISProperty.class)){
|
if (m.isAnnotationPresent(ISProperty.class)) {
|
||||||
if(m.isBridge()) {
|
if (m.isBridge()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ISProperty propAnnotation = m.getAnnotation(ISProperty.class);
|
ISProperty propAnnotation = m.getAnnotation(ISProperty.class);
|
||||||
PropertyDefinition prop = new PropertyDefinitionImpl(propAnnotation, m);
|
PropertyDefinition prop = new PropertyDefinitionImpl(propAnnotation, m);
|
||||||
properties.add(prop);
|
properties.add(prop);
|
||||||
logger.trace("Property {} retrieved in type {} ", prop, type.getSimpleName());
|
logger.trace("Property {} retrieved in type {} ", prop, type.getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Class<?> getGenericClass(java.lang.reflect.Type type){
|
protected Class<?> getGenericClass(java.lang.reflect.Type type) {
|
||||||
TypeVariable<?> typeVariable = (TypeVariable<?>) type;
|
TypeVariable<?> typeVariable = (TypeVariable<?>) type;
|
||||||
java.lang.reflect.Type[] bounds = typeVariable.getBounds();
|
java.lang.reflect.Type[] bounds = typeVariable.getBounds();
|
||||||
java.lang.reflect.Type t = bounds[0];
|
java.lang.reflect.Type t = bounds[0];
|
||||||
if(t instanceof ParameterizedType) {
|
if (t instanceof ParameterizedType) {
|
||||||
ParameterizedType parameterizedType = (ParameterizedType) t;
|
ParameterizedType parameterizedType = (ParameterizedType) t;
|
||||||
return (Class<?>) parameterizedType.getRawType();
|
return (Class<?>) parameterizedType.getRawType();
|
||||||
}
|
}
|
||||||
return (Class<?>) t;
|
return (Class<?>) t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public static Type getInstance(Class<? extends Element> clz) {
|
public static Type getInstance(Class<? extends Element> clz) {
|
||||||
Type typeDefinition = null;
|
Type typeDefinition = null;
|
||||||
try {
|
try {
|
||||||
if(EntityElement.class.isAssignableFrom(clz)) {
|
if (EntityElement.class.isAssignableFrom(clz)) {
|
||||||
typeDefinition = EntityTypeImpl.getEntityTypeDefinitionInstance((Class<? extends EntityElement>) clz);
|
typeDefinition = EntityTypeImpl.getEntityTypeDefinitionInstance((Class<? extends EntityElement>) clz);
|
||||||
return typeDefinition;
|
return typeDefinition;
|
||||||
} else if(RelationElement.class.isAssignableFrom(clz)){
|
} else if (RelationElement.class.isAssignableFrom(clz)) {
|
||||||
typeDefinition = RelationTypeImpl.getRelationTypeDefinitionInstance((Class<? extends RelationElement<?,?>>) clz);
|
typeDefinition = RelationTypeImpl
|
||||||
|
.getRelationTypeDefinitionInstance((Class<? extends RelationElement<?, ?>>) clz);
|
||||||
return typeDefinition;
|
return typeDefinition;
|
||||||
} else if(PropertyElement.class.isAssignableFrom(clz)){
|
} else if (PropertyElement.class.isAssignableFrom(clz)) {
|
||||||
typeDefinition = new PropertyTypeImpl(clz);
|
typeDefinition = new PropertyTypeImpl(clz);
|
||||||
return typeDefinition;
|
return typeDefinition;
|
||||||
} else if(Type.class.isAssignableFrom(clz)) {
|
} else if (Type.class.isAssignableFrom(clz)) {
|
||||||
typeDefinition = new TypeImpl(clz);
|
typeDefinition = new TypeImpl(clz);
|
||||||
return typeDefinition;
|
return typeDefinition;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Serialization required");
|
throw new RuntimeException("Serialization required");
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if(typeDefinition!=null) {
|
if (typeDefinition != null) {
|
||||||
logger.debug("{} : {} ", clz, typeDefinition);
|
logger.debug("{} : {} ", clz, typeDefinition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TypeImpl() {}
|
protected TypeImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
protected TypeImpl(Class<? extends Element> clz) {
|
protected TypeImpl(Class<? extends Element> clz) {
|
||||||
this.name = TypeMapper.getType(clz);
|
this.name = TypeMapper.getType(clz);
|
||||||
this.description = TypeMapper.getStaticStringFieldByName(clz, DESCRIPTION, "");
|
this.description = TypeMapper.getStaticStringFieldByName(clz, DESCRIPTION, "");
|
||||||
String versionString = TypeMapper.getStaticStringFieldByName(clz, VERSION, TypeVersion.MINIMAL_VERSION_STRING);
|
String versionString = TypeMapper.getStaticStringFieldByName(clz, VERSION, TypeVersion.MINIMAL_VERSION_STRING);
|
||||||
this.version = new TypeVersion(versionString);
|
this.version = new TypeVersion(versionString);
|
||||||
|
|
||||||
this.changelog = TypeMapper.getStaticFieldByName(clz, CHANGELOG, DEFAULT_CHANGELOG_MAP);
|
this.changelog = TypeMapper.getStaticFieldByName(clz, CHANGELOG, DEFAULT_CHANGELOG_MAP);
|
||||||
if(!changelog.containsKey(version)) {
|
if (!changelog.containsKey(version)) {
|
||||||
throw new RuntimeException("The Type " + name + " does not provided the appropriated changelog Map");
|
throw new RuntimeException("The Type " + name + " does not provided the appropriated changelog Map");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.abstractType = false;
|
this.abstractType = false;
|
||||||
|
|
||||||
if(clz.isAnnotationPresent(Abstract.class)){
|
if (clz.isAnnotationPresent(Abstract.class)) {
|
||||||
this.abstractType = true;
|
this.abstractType = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Header getHeader() {
|
public Header getHeader() {
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHeader(Header header){
|
public void setHeader(Header header) {
|
||||||
this.header = header;
|
this.header = header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -186,17 +194,17 @@ public class TypeImpl implements Type {
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeVersion getVersion() {
|
public TypeVersion getVersion() {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonGetter(value=VERSION_PROPERTY)
|
@JsonGetter(value = VERSION_PROPERTY)
|
||||||
protected String getVersionAsString() {
|
protected String getVersionAsString() {
|
||||||
return version.toString();
|
return version.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonSetter(value = VERSION_PROPERTY)
|
@JsonSetter(value = VERSION_PROPERTY)
|
||||||
protected void setVersion(String version) {
|
protected void setVersion(String version) {
|
||||||
this.version = new TypeVersion(version);
|
this.version = new TypeVersion(version);
|
||||||
|
@ -206,24 +214,32 @@ public class TypeImpl implements Type {
|
||||||
public Map<TypeVersion, String> getChangelog() {
|
public Map<TypeVersion, String> getChangelog() {
|
||||||
return changelog;
|
return changelog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonGetter(value=CHANGELOG_PROPERTY)
|
@JsonGetter(value = CHANGELOG_PROPERTY)
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
public Map<String, String> getChangelogwithVersionAsString() {
|
public Map<String, String> getChangelogwithVersionAsString() {
|
||||||
Map<String,String> map = new HashMap<>();
|
if(this.changelog==null) {
|
||||||
for(TypeVersion typeVersion : changelog.keySet()) {
|
return DEFAULT_CHANGELOG_MAP_KEY_AS_STRING;
|
||||||
|
}
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
for (TypeVersion typeVersion : changelog.keySet()) {
|
||||||
map.put(typeVersion.toString(), changelog.get(typeVersion));
|
map.put(typeVersion.toString(), changelog.get(typeVersion));
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonSetter(value = CHANGELOG_PROPERTY)
|
@JsonSetter(value=CHANGELOG_PROPERTY)
|
||||||
public void setChangelog(Map<String, String> changelog) {
|
public void setChangelog(Map<String, String> changelog) {
|
||||||
|
if(changelog==null) {
|
||||||
|
this.changelog = DEFAULT_CHANGELOG_MAP;
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.changelog = new HashMap<>();
|
this.changelog = new HashMap<>();
|
||||||
for(String version : changelog.keySet()) {
|
for (String version : changelog.keySet()) {
|
||||||
this.changelog.put(new TypeVersion(version), changelog.get(version));
|
this.changelog.put(new TypeVersion(version), changelog.get(version));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAbstract() {
|
public boolean isAbstract() {
|
||||||
return abstractType;
|
return abstractType;
|
||||||
|
@ -233,12 +249,10 @@ public class TypeImpl implements Type {
|
||||||
public Set<String> getSuperClasses() {
|
public Set<String> getSuperClasses() {
|
||||||
return superClasses;
|
return superClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonInclude(Include.NON_EMPTY)
|
@JsonInclude(Include.NON_EMPTY)
|
||||||
public Set<PropertyDefinition> getProperties() {
|
public Set<PropertyDefinition> getProperties() {
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,12 @@ public class SerializationTest {
|
||||||
TypeVersion typeVersion = propertyType.getVersion();
|
TypeVersion typeVersion = propertyType.getVersion();
|
||||||
logger.debug("Version {}", typeVersion.toString());
|
logger.debug("Version {}", typeVersion.toString());
|
||||||
logger.info(ElementMapper.marshal(propertyType));
|
logger.info(ElementMapper.marshal(propertyType));
|
||||||
|
|
||||||
|
String json = "{\"@class\":\"PropertyType\",\"header\":null,\"name\":\"Header\",\"description\":\"\",\"superClasses\":[\"Property\"],\"properties\":[{\"@class\":\"PropertyDefinition\",\"name\":\"lastUpdateTime\",\"description\":\"\",\"mandatory\":true,\"readonly\":false,\"notnull\":true,\"max\":null,\"min\":null,\"regexp\":null,\"linkedType\":null,\"linkedClass\":null,\"type\":6},{\"@class\":\"PropertyDefinition\",\"name\":\"modifiedBy\",\"description\":\"\",\"mandatory\":true,\"readonly\":false,\"notnull\":true,\"max\":null,\"min\":null,\"regexp\":null,\"linkedType\":null,\"linkedClass\":null,\"type\":7},{\"@class\":\"PropertyDefinition\",\"name\":\"creator\",\"description\":\"\",\"mandatory\":true,\"readonly\":true,\"notnull\":true,\"max\":null,\"min\":null,\"regexp\":null,\"linkedType\":null,\"linkedClass\":null,\"type\":7},{\"@class\":\"PropertyDefinition\",\"name\":\"creationTime\",\"description\":\"\",\"mandatory\":true,\"readonly\":true,\"notnull\":true,\"max\":null,\"min\":null,\"regexp\":null,\"linkedType\":null,\"linkedClass\":null,\"type\":6},{\"@class\":\"PropertyDefinition\",\"name\":\"uuid\",\"description\":\"\",\"mandatory\":true,\"readonly\":true,\"notnull\":true,\"max\":null,\"min\":null,\"regexp\":\"^([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}){1}$\",\"linkedType\":null,\"linkedClass\":null,\"type\":7}],\"abstract\":false,\"version\":\"1.0.0\"}";
|
||||||
|
logger.info(json);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
PropertyType<Header> headerType = (PropertyType<Header>) TypeMapper.deserializeTypeDefinition(json);
|
||||||
|
logger.info(ElementMapper.marshal(headerType));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue