package org.gcube.informationsystem.types; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.gcube.com.fasterxml.jackson.annotation.JsonTypeName; import org.gcube.com.fasterxml.jackson.databind.DeserializationFeature; import org.gcube.com.fasterxml.jackson.databind.JavaType; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.informationsystem.base.reference.Element; import org.gcube.informationsystem.types.impl.TypeImpl; import org.gcube.informationsystem.types.reference.Change; import org.gcube.informationsystem.types.reference.Changelog; import org.gcube.informationsystem.types.reference.Type; import org.gcube.informationsystem.types.reference.TypeMetadata; import org.gcube.informationsystem.types.reference.entities.EntityType; import org.gcube.informationsystem.types.reference.entities.FacetType; import org.gcube.informationsystem.types.reference.entities.ResourceType; import org.gcube.informationsystem.types.reference.properties.LinkedEntity; import org.gcube.informationsystem.types.reference.properties.PropertyDefinition; import org.gcube.informationsystem.types.reference.properties.PropertyType; import org.gcube.informationsystem.types.reference.relations.ConsistsOfType; import org.gcube.informationsystem.types.reference.relations.IsRelatedToType; import org.gcube.informationsystem.types.reference.relations.RelationType; import org.gcube.informationsystem.utils.TypeVersion; /** * @author Luca Frosini (ISTI - CNR) */ public class TypeMapper { protected static final ObjectMapper mapper; static { mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, false); mapper.registerSubtypes(Type.class); mapper.registerSubtypes(EntityType.class); mapper.registerSubtypes(ResourceType.class); mapper.registerSubtypes(FacetType.class); mapper.registerSubtypes(RelationType.class); mapper.registerSubtypes(IsRelatedToType.class); mapper.registerSubtypes(ConsistsOfType.class); mapper.registerSubtypes(PropertyType.class); mapper.registerSubtypes(PropertyDefinition.class); mapper.registerSubtypes(LinkedEntity.class); // TODO // mapper.registerSubtypes(LinkedResource.class); // mapper.registerSubtypes(LinkedFacet.class); } public static String serializeTypeDefinition(Type type) throws Exception{ String json = mapper.writeValueAsString(type); return json; } public static Type deserializeTypeDefinition(String json) throws Exception{ Type type = mapper.readValue(json, Type.class); return type; } public static String serializeTypeDefinitions(List typeDefinitions) throws Exception{ JavaType javaType = mapper.getTypeFactory().constructCollectionType(List.class, Type.class); return mapper.writerFor(javaType).writeValueAsString(typeDefinitions); } public static List deserializeTypeDefinitions(String json) throws Exception{ JavaType javaType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, Type.class); return mapper.readValue(json, javaType); } // TODO move somewhere else, probably in Element public static Type createTypeDefinition(Class clz) { Type type = TypeImpl.getInstance(clz); return type; } public static String serializeType(Class clz) throws Exception{ Type type = createTypeDefinition(clz); return serializeTypeDefinition(type); } public static String getType(Class clz){ String classSimpleName = clz.getSimpleName(); String name = null; if(clz.isAnnotationPresent(JsonTypeName.class)) { JsonTypeName jsonTypeName = clz.getAnnotation(JsonTypeName.class); name = jsonTypeName.value(); if(name==null || name.compareTo("")!=0) { throw new RuntimeException("Invalid annotation @JsonTypeName for type " + classSimpleName); } } if(clz.isAnnotationPresent(TypeMetadata.class)) { TypeMetadata typeMetadata = clz.getAnnotation(TypeMetadata.class); String typeMetadataName = typeMetadata.name(); if(typeMetadataName!=null && typeMetadataName.compareTo("")!=0) { if(name!=null && typeMetadataName.compareTo(name)!=0) { throw new RuntimeException("Name in annotation @TypeMetadata differ from annotation in @JsonTypeName for type " + classSimpleName + ". Please be coerent"); } return name; }else { throw new RuntimeException("Invalid Name in annotation @TypeMetadata for type " + classSimpleName); } }else { throw new RuntimeException("You must provide @TypeMetadata for " + classSimpleName); } } public static String getTypeDescription(Class clz){ String classSimpleName = clz.getSimpleName(); if(clz.isAnnotationPresent(TypeMetadata.class)) { TypeMetadata typeMetadata = clz.getAnnotation(TypeMetadata.class); String description = typeMetadata.description(); if(description!=null && description.compareTo("")!=0) { return description; }else { throw new RuntimeException("Invalid Description in annotation @TypeMetadata for type " + classSimpleName); } }else { throw new RuntimeException("You must provide @TypeMetadata for " + classSimpleName); } } public static TypeVersion getTypeVersion(Class clz){ String classSimpleName = clz.getSimpleName(); if(clz.isAnnotationPresent(TypeMetadata.class)) { TypeMetadata typeMetadata = clz.getAnnotation(TypeMetadata.class); return new TypeVersion(typeMetadata.version()); }else { throw new RuntimeException("You must provide @TypeMetadata for " + classSimpleName); } } public static Map getTypeChangelog(Class clz){ Map map = new HashMap<>(); if(clz.isAnnotationPresent(Changelog.class)) { Changelog changelog = clz.getAnnotation(Changelog.class); Change[] changes = changelog.value(); for(Change change : changes) { String version = change.version(); TypeVersion typeVersion = new TypeVersion(version); if(map.containsKey(typeVersion)) { throw new RuntimeException("Duplicated version " + version +" in @Change annotation"); } String description = change.description(); if(description==null || description.compareTo("")==0) { throw new RuntimeException("A valid description for version " + version +" must be provided in @Change annotation"); } map.put(typeVersion, description); } } if(!map.containsKey(TypeVersion.MINIMAL_VERSION)) { map.putAll(TypeImpl.DEFAULT_CHANGELOG_MAP); } TypeVersion typeVersion = getTypeVersion(clz); if (!map.containsKey(typeVersion)) { throw new RuntimeException("The Type " + clz.getSimpleName() + " does not provided the appropriated changelog Map"); } return map; } /* private final static String NAME = "NAME"; public static String getStaticStringFieldByName(Class clz, String fieldName, String defaultValue){ Field field; try { field = clz.getDeclaredField(fieldName); field.setAccessible(true); return (String) field.get(null); } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { return defaultValue; } } @SuppressWarnings("unchecked") public static O getStaticFieldByName(Class clz, String fieldName, O defaultValue){ Field field; try { field = clz.getDeclaredField(fieldName); field.setAccessible(true); return (O) field.get(null); } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { return defaultValue; } } */ }