2016-06-09 10:56:14 +02:00
package org.gcube.informationsystem.types ;
2020-02-03 10:51:29 +01:00
import java.util.ArrayList ;
2023-02-10 17:03:50 +01:00
import java.util.Comparator ;
2020-12-15 11:28:34 +01:00
import java.util.HashMap ;
2019-03-22 15:18:23 +01:00
import java.util.List ;
2020-12-15 11:28:34 +01:00
import java.util.Map ;
2019-03-22 15:18:23 +01:00
2020-07-07 17:04:25 +02:00
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 ;
2020-01-30 10:26:43 +01:00
import org.gcube.informationsystem.base.reference.Element ;
2020-02-03 10:51:29 +01:00
import org.gcube.informationsystem.types.impl.TypeImpl ;
2020-12-15 11:28:34 +01:00
import org.gcube.informationsystem.types.reference.Change ;
import org.gcube.informationsystem.types.reference.Changelog ;
2020-02-03 10:51:29 +01:00
import org.gcube.informationsystem.types.reference.Type ;
2020-12-15 11:28:34 +01:00
import org.gcube.informationsystem.types.reference.TypeMetadata ;
2020-02-03 10:51:29 +01:00
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 ;
2021-10-21 10:11:45 +02:00
import org.gcube.informationsystem.utils.Version ;
2020-02-03 10:51:29 +01:00
2019-03-22 15:18:23 +01:00
/ * *
* @author Luca Frosini ( ISTI - CNR )
* /
2020-02-04 09:30:19 +01:00
public class TypeMapper {
2016-06-09 10:56:14 +02:00
2020-02-03 10:51:29 +01:00
protected static final ObjectMapper mapper ;
static {
mapper = new ObjectMapper ( ) ;
mapper . configure ( DeserializationFeature . FAIL_ON_UNKNOWN_PROPERTIES , false ) ;
2020-12-14 10:10:49 +01:00
mapper . configure ( DeserializationFeature . FAIL_ON_MISSING_CREATOR_PROPERTIES , false ) ;
2020-02-03 10:51:29 +01:00
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 ) ;
2016-06-09 10:56:14 +02:00
}
2019-03-22 15:18:23 +01:00
2020-02-03 10:51:29 +01:00
public static String serializeTypeDefinition ( Type type ) throws Exception {
String json = mapper . writeValueAsString ( type ) ;
return json ;
2019-03-22 15:18:23 +01:00
}
2016-06-09 10:56:14 +02:00
2021-02-11 17:24:46 +01:00
public static Type deserializeTypeDefinition ( String json ) throws Exception {
2020-02-03 10:51:29 +01:00
Type type = mapper . readValue ( json , Type . class ) ;
return type ;
2019-03-22 15:18:23 +01:00
}
2020-02-03 10:51:29 +01:00
public static String serializeTypeDefinitions ( List < Type > typeDefinitions ) throws Exception {
JavaType javaType = mapper . getTypeFactory ( ) . constructCollectionType ( List . class , Type . class ) ;
return mapper . writerFor ( javaType ) . writeValueAsString ( typeDefinitions ) ;
}
public static List < Type > deserializeTypeDefinitions ( String json ) throws Exception {
JavaType javaType = mapper . getTypeFactory ( ) . constructCollectionType ( ArrayList . class , Type . class ) ;
return mapper . readValue ( json , javaType ) ;
2019-03-22 15:18:23 +01:00
}
2020-02-03 10:51:29 +01:00
// TODO move somewhere else, probably in Element
public static < E extends Element > Type createTypeDefinition ( Class < E > clz ) {
Type type = TypeImpl . getInstance ( clz ) ;
return type ;
2019-03-22 15:18:23 +01:00
}
2020-02-03 10:51:29 +01:00
public static < E extends Element > String serializeType ( Class < E > clz ) throws Exception {
Type type = createTypeDefinition ( clz ) ;
return serializeTypeDefinition ( type ) ;
2016-06-09 10:56:14 +02:00
}
2016-07-01 16:02:37 +02:00
2021-01-28 23:15:46 +01:00
public static < E extends Element > String getType ( E e ) {
return getType ( e . getClass ( ) ) ;
}
2020-01-30 10:26:43 +01:00
public static String getType ( Class < ? extends Element > clz ) {
2020-12-15 11:28:34 +01:00
String classSimpleName = clz . getSimpleName ( ) ;
String name = null ;
2021-01-27 11:57:16 +01:00
if ( ! clz . isInterface ( ) ) {
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 ) ;
}
return name ;
2020-12-15 11:28:34 +01:00
}
}
if ( clz . isAnnotationPresent ( TypeMetadata . class ) ) {
TypeMetadata typeMetadata = clz . getAnnotation ( TypeMetadata . class ) ;
String typeMetadataName = typeMetadata . name ( ) ;
if ( typeMetadataName ! = null & & typeMetadataName . compareTo ( " " ) ! = 0 ) {
2021-01-27 11:57:16 +01:00
/ *
2020-12-15 11:28:34 +01:00
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 " ) ;
}
2021-01-27 11:57:16 +01:00
* /
2020-12-15 17:38:06 +01:00
return typeMetadataName ;
2020-12-15 11:28:34 +01:00
} else {
throw new RuntimeException ( " Invalid Name in annotation @TypeMetadata for type " + classSimpleName ) ;
}
} else {
throw new RuntimeException ( " You must provide @TypeMetadata for " + classSimpleName ) ;
}
2021-01-27 11:57:16 +01:00
2020-12-15 11:28:34 +01:00
}
public static String getTypeDescription ( Class < ? extends Element > 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 ) ;
}
}
2021-10-21 10:11:45 +02:00
public static Version getTypeVersion ( Class < ? extends Element > clz ) {
2020-12-15 11:28:34 +01:00
String classSimpleName = clz . getSimpleName ( ) ;
if ( clz . isAnnotationPresent ( TypeMetadata . class ) ) {
TypeMetadata typeMetadata = clz . getAnnotation ( TypeMetadata . class ) ;
2021-10-21 10:11:45 +02:00
return new Version ( typeMetadata . version ( ) ) ;
2020-12-15 11:28:34 +01:00
} else {
throw new RuntimeException ( " You must provide @TypeMetadata for " + classSimpleName ) ;
2020-07-02 18:05:15 +02:00
}
2016-06-09 10:56:14 +02:00
}
2016-07-04 12:05:47 +02:00
2021-10-21 10:11:45 +02:00
public static Map < Version , String > getTypeChangelog ( Class < ? extends Element > clz ) {
Map < Version , String > map = new HashMap < > ( ) ;
2020-12-15 11:28:34 +01:00
if ( clz . isAnnotationPresent ( Changelog . class ) ) {
Changelog changelog = clz . getAnnotation ( Changelog . class ) ;
Change [ ] changes = changelog . value ( ) ;
for ( Change change : changes ) {
String version = change . version ( ) ;
2021-10-21 10:11:45 +02:00
Version typeVersion = new Version ( version ) ;
2020-12-15 11:28:34 +01:00
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 ) ;
}
}
2021-10-21 10:11:45 +02:00
if ( ! map . containsKey ( Version . MINIMAL_VERSION ) ) {
2020-12-15 11:28:34 +01:00
map . putAll ( TypeImpl . DEFAULT_CHANGELOG_MAP ) ;
}
2021-10-21 10:11:45 +02:00
Version typeVersion = getTypeVersion ( clz ) ;
2020-12-15 11:28:34 +01:00
if ( ! map . containsKey ( typeVersion ) ) {
throw new RuntimeException ( " The Type " + clz . getSimpleName ( ) + " does not provided the appropriated changelog Map " ) ;
}
2023-02-10 17:03:50 +01:00
List < Version > versions = new ArrayList < > ( map . keySet ( ) ) ;
versions . sort ( new Comparator < Version > ( ) {
@Override
public int compare ( Version o1 , Version o2 ) {
/ * o2 . compareTo ( o1 ) and not vice - versa
* because we want descending order
* /
return o2 . compareTo ( o1 ) ;
}
} ) ;
if ( versions . get ( 0 ) . compareTo ( typeVersion ) ! = 0 ) {
throw new RuntimeException ( " The Type declared version (i.e. " + typeVersion . toString ( ) + " ) does not match the highest version declared in changelog (i.e. " + versions . get ( 0 ) + " ). Please fix your type. " ) ;
}
2020-12-15 11:28:34 +01:00
return map ;
}
2016-06-09 10:56:14 +02:00
}