diff --git a/src/main/java/org/gcube/informationsystem/types/PropertyTypeName.java b/src/main/java/org/gcube/informationsystem/types/PropertyTypeName.java index 27d090e..eb87d7e 100644 --- a/src/main/java/org/gcube/informationsystem/types/PropertyTypeName.java +++ b/src/main/java/org/gcube/informationsystem/types/PropertyTypeName.java @@ -1,5 +1,7 @@ package org.gcube.informationsystem.types; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; import java.math.BigInteger; import java.net.URI; import java.net.URL; @@ -8,17 +10,23 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; +import org.gcube.informationsystem.base.reference.Element; import org.gcube.informationsystem.base.reference.properties.PropertyElement; import org.gcube.informationsystem.utils.TypeVersion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Luca Frosini (ISTI - CNR) */ public class PropertyTypeName { + private static Logger logger = LoggerFactory.getLogger(PropertyTypeName.class); + public enum BaseType { BOOLEAN("Boolean"), @@ -146,15 +154,18 @@ public class PropertyTypeName { BaseType type = BASE_PROPERTY_TYPES_BY_CLASS.get(clazz); - if(type == null && Enum.class.isAssignableFrom(clazz)) { - type = BASE_PROPERTY_TYPES_BY_CLASS.get(Enum.class); + if(type == null) { + for(Class c : BASE_PROPERTY_TYPES_BY_CLASS.keySet()) { + if(c.isAssignableFrom(clazz)) { + type = BASE_PROPERTY_TYPES_BY_CLASS.get(c); + } + } } return type; } protected BaseType baseType; - protected boolean genericType; protected BaseType genericBaseType; protected String genericClassName; @@ -163,6 +174,58 @@ public class PropertyTypeName { setType(type); } + public PropertyTypeName(Method method) { + baseType = null; + genericType = false; + genericBaseType = null; + genericClassName = null; + + Class clz = method.getReturnType(); + logger.trace("Return Type for method {} is {}", method, clz); + + baseType = PropertyTypeName.getBaseTypeByClass(clz); + + if(baseType == BaseType.PROPERTY){ + if(clz != PropertyElement.class){ + @SuppressWarnings("unchecked") + Class type = (Class) clz; + genericClassName = TypeMapper.getType(type); + return; + } + } + + if(baseType!=null) { + if(baseType.ordinal()>BaseType.PROPERTY.ordinal()){ + genericType = true; + + java.lang.reflect.Type genericReturnType = method.getGenericReturnType(); + logger.trace("Generic Return Type for method {} is {}", method, genericReturnType); + + java.lang.reflect.Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); + + java.lang.reflect.Type genericType = null; + for(java.lang.reflect.Type t : actualTypeArguments){ + logger.trace("Generic Return Type {} for method {} - Actual Type Argument : {}", genericReturnType, method, t); + genericType = t; + } + + genericBaseType = PropertyTypeName.getBaseTypeByClass((Class) genericType); + if(genericBaseType!= null && genericBaseType.ordinal()>BaseType.PROPERTY.ordinal()) { + throw new IllegalArgumentException("The generic of a " + baseType.toString() + " cannot be a Set, a List or a Map."); + } + + if(genericBaseType == BaseType.PROPERTY){ + @SuppressWarnings("unchecked") + Class genericElementType = (Class) genericType; + genericClassName = TypeMapper.getType(genericElementType); + } + + } + }else { + throw new IllegalArgumentException("Type " + clz.getSimpleName() + " not supported as property type"); + } + } + public void setType(String type) { int indexOfMinor = type.indexOf("<"); if(indexOfMinor == -1) { @@ -208,6 +271,7 @@ public class PropertyTypeName { genericBaseType = null; genericBaseType = BaseType.getBaseTypeFromString(generic); }catch (IllegalArgumentException e) { + genericBaseType = BaseType.PROPERTY; genericClassName = generic; } @@ -224,7 +288,11 @@ public class PropertyTypeName { switch (baseType) { case PROPERTY: - stringBuffer.append(genericClassName); + if(genericClassName != null) { + stringBuffer.append(genericClassName); + }else { + stringBuffer.append(baseType.toString()); + } break; case SET: case LIST: case MAP: @@ -272,4 +340,22 @@ public class PropertyTypeName { return genericClassName; } + @Override + public int hashCode() { + return Objects.hash(baseType, genericBaseType, genericClassName, genericType); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PropertyTypeName other = (PropertyTypeName) obj; + return baseType == other.baseType && genericBaseType == other.genericBaseType + && Objects.equals(genericClassName, other.genericClassName) && genericType == other.genericType; + } + } diff --git a/src/main/java/org/gcube/informationsystem/types/impl/TypeImpl.java b/src/main/java/org/gcube/informationsystem/types/impl/TypeImpl.java index d79ab58..a8da4b8 100644 --- a/src/main/java/org/gcube/informationsystem/types/impl/TypeImpl.java +++ b/src/main/java/org/gcube/informationsystem/types/impl/TypeImpl.java @@ -31,6 +31,9 @@ import org.gcube.informationsystem.utils.TypeVersion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * @author Luca Frosini (ISTI - CNR) + */ public class TypeImpl implements Type { private static Logger logger = LoggerFactory.getLogger(TypeImpl.class); @@ -114,6 +117,9 @@ public class TypeImpl implements Type { } } + if(properties.size()==0) { + properties = null; + } return properties; } diff --git a/src/main/java/org/gcube/informationsystem/types/impl/properties/PropertyDefinitionImpl.java b/src/main/java/org/gcube/informationsystem/types/impl/properties/PropertyDefinitionImpl.java index 448ffef..e24277b 100644 --- a/src/main/java/org/gcube/informationsystem/types/impl/properties/PropertyDefinitionImpl.java +++ b/src/main/java/org/gcube/informationsystem/types/impl/properties/PropertyDefinitionImpl.java @@ -1,21 +1,15 @@ package org.gcube.informationsystem.types.impl.properties; import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; import java.net.URI; import java.net.URL; import java.util.Objects; import java.util.UUID; -import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore; +import org.gcube.com.fasterxml.jackson.annotation.JsonSetter; import org.gcube.com.fasterxml.jackson.annotation.JsonTypeName; -import org.gcube.informationsystem.base.reference.Element; -import org.gcube.informationsystem.base.reference.properties.PropertyElement; -import org.gcube.informationsystem.types.OrientDBType; -import org.gcube.informationsystem.types.OrientDBType.OType; -import org.gcube.informationsystem.types.TypeMapper; +import org.gcube.informationsystem.types.PropertyTypeName; import org.gcube.informationsystem.types.annotations.ISProperty; -import org.gcube.informationsystem.types.impl.TypeImpl; import org.gcube.informationsystem.types.reference.properties.PropertyDefinition; import org.gcube.informationsystem.utils.TypeVersion; import org.slf4j.Logger; @@ -30,7 +24,7 @@ public final class PropertyDefinitionImpl implements PropertyDefinition { */ private static final long serialVersionUID = -5925314595659292025L; - private static Logger logger = LoggerFactory.getLogger(TypeImpl.class); + private static Logger logger = LoggerFactory.getLogger(PropertyDefinitionImpl.class); public final static String UUID_REGEX = "^([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}$"; public final static String URI_REGEX = null; @@ -44,12 +38,8 @@ public final class PropertyDefinitionImpl implements PropertyDefinition { private Integer max= null; private Integer min= null; private String regexp= null; - - - - private Integer linkedType = null; - private String linkedClass = null; - private Integer type=null; + + private PropertyTypeName propertyTypeName = null; private static String getPropertyNameFromMethodName(Method method){ String name = method.getName(); @@ -81,77 +71,41 @@ public final class PropertyDefinitionImpl implements PropertyDefinition { this.readonly = propertyAnnotation.readonly(); if(propertyAnnotation.max()>0) this.max = propertyAnnotation.max(); if(propertyAnnotation.max()>=propertyAnnotation.min() && propertyAnnotation.min()>0) this.min = propertyAnnotation.min(); + + this.propertyTypeName = new PropertyTypeName(method); + + Class clz = method.getReturnType(); + logger.trace("Return Type for method {} is {}", method, clz); + if(!propertyAnnotation.regexpr().isEmpty()) this.regexp = propertyAnnotation.regexpr(); - - logger.trace("Looking for property type {}", method.getReturnType()); - @SuppressWarnings("unchecked") - Class type = (Class) method.getReturnType(); - this.type = OType.PROPERTY.getIntValue(); - - if(PropertyElement.class.isAssignableFrom(type)){ - if(type != PropertyElement.class){ - this.linkedClass = TypeMapper.getType(type); - } - }else if (OrientDBType.getTypeByClass(type)!=null) { - this.type = OrientDBType.getTypeByClass(type).getIntValue(); - if(this.type > 9 && this.type <= 12){ - java.lang.reflect.Type genericReturnType = method.getGenericReturnType(); - logger.trace("Generic Return Type {} for method {}", genericReturnType, method); - - java.lang.reflect.Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); - - java.lang.reflect.Type genericType = null; - for(java.lang.reflect.Type t : actualTypeArguments){ - logger.trace("Generic Return Type {} for method {} - Actual Type Argument : {}", genericReturnType, method, t); - genericType = t; - } - - @SuppressWarnings("unchecked") - Class genericClass = (Class) genericType; - OType linkedOType = OrientDBType.getTypeByClass(genericClass); - if(linkedOType!=null){ - this.linkedType = linkedOType.getIntValue(); - }else{ - this.linkedClass = TypeMapper.getType(genericClass); - } - - } - - if((this.regexp==null || this.regexp.compareTo("")==0 )&& this.type==OType.STRING.getIntValue()){ - if(Enum.class.isAssignableFrom(type)){ - Object[] constants = type.getEnumConstants(); - StringBuilder stringBuilder = new StringBuilder("^("); - for(int i=0; i extends TypeImpl implements PropertyType

{ diff --git a/src/main/java/org/gcube/informationsystem/types/reference/properties/PropertyDefinition.java b/src/main/java/org/gcube/informationsystem/types/reference/properties/PropertyDefinition.java index 53596fb..6b2ad1b 100644 --- a/src/main/java/org/gcube/informationsystem/types/reference/properties/PropertyDefinition.java +++ b/src/main/java/org/gcube/informationsystem/types/reference/properties/PropertyDefinition.java @@ -29,8 +29,6 @@ public interface PropertyDefinition extends PropertyElement { public static final String MAX_PROPERTY = "max"; public static final String MIN_PROPERTY = "min"; public static final String REGEX_PROPERTY = "regexp"; - public static final String LINKED_TYPE_PROPERTY = "linkedType"; - public static final String LINKED_CLASS_PROPERTY = "linkedClass"; public static final String TYPE_PROPERTY = "type"; @ISProperty(name = NAME_PROPERTY, readonly = true, mandatory = true, nullable = false) @@ -57,13 +55,7 @@ public interface PropertyDefinition extends PropertyElement { @ISProperty(name = REGEX_PROPERTY, readonly = false, mandatory = true, nullable = false) public String getRegexp(); - @ISProperty(name = LINKED_TYPE_PROPERTY, readonly = false, mandatory = true, nullable = false) - public Integer getLinkedType(); - - @ISProperty(name = LINKED_CLASS_PROPERTY, readonly = false, mandatory = true, nullable = false) - public String getLinkedClass(); - @ISProperty(name = TYPE_PROPERTY, readonly = false, mandatory = true, nullable = false) - public Integer getType(); + public String getType(); } diff --git a/src/test/java/org/gcube/informationsystem/types/SerializationTest.java b/src/test/java/org/gcube/informationsystem/types/SerializationTest.java index 047934b..3b4e76e 100644 --- a/src/test/java/org/gcube/informationsystem/types/SerializationTest.java +++ b/src/test/java/org/gcube/informationsystem/types/SerializationTest.java @@ -29,6 +29,9 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * @author Luca Frosini (ISTI - CNR) + */ public class SerializationTest { private static Logger logger = LoggerFactory.getLogger(SerializationTest.class); diff --git a/src/test/java/org/gcube/informationsystem/types/TypeNameTest.java b/src/test/java/org/gcube/informationsystem/types/TypeNameTest.java index 70194fa..f414069 100644 --- a/src/test/java/org/gcube/informationsystem/types/TypeNameTest.java +++ b/src/test/java/org/gcube/informationsystem/types/TypeNameTest.java @@ -1,6 +1,7 @@ package org.gcube.informationsystem.types; import org.gcube.informationsystem.model.reference.properties.Encrypted; +import org.gcube.informationsystem.model.reference.properties.Header; import org.gcube.informationsystem.types.PropertyTypeName.BaseType; import org.junit.Assert; import org.junit.Test; @@ -11,6 +12,13 @@ public class TypeNameTest { private static Logger logger = LoggerFactory.getLogger(TypeNameTest.class); + @Test + public void getBaseType() throws Exception { + Class clz = Header.class; + BaseType baseType = PropertyTypeName.getBaseTypeByClass(clz); + logger.debug("{} for class {} is {}", BaseType.class.getSimpleName(), clz, baseType); + } + @Test public void testValidBaseType() throws Exception { for(BaseType baseType : BaseType.values()) { diff --git a/src/test/java/org/gcube/informationsystem/utils/discovery/ISMDiscoveryTest.java b/src/test/java/org/gcube/informationsystem/utils/discovery/ISMDiscoveryTest.java index 1ac9cfa..39a6cf7 100644 --- a/src/test/java/org/gcube/informationsystem/utils/discovery/ISMDiscoveryTest.java +++ b/src/test/java/org/gcube/informationsystem/utils/discovery/ISMDiscoveryTest.java @@ -2,6 +2,7 @@ package org.gcube.informationsystem.utils.discovery; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.ServiceLoader; import org.gcube.informationsystem.base.reference.AccessType; @@ -12,11 +13,15 @@ import org.gcube.informationsystem.base.reference.relations.RelationElement; import org.gcube.informationsystem.types.TypeMapper; import org.gcube.informationsystem.types.reference.Type; import org.gcube.informationsystem.types.reference.properties.PropertyType; +import org.gcube.informationsystem.utils.TypeVersion; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * @author Luca Frosini (ISTI - CNR) + */ public class ISMDiscoveryTest { private static final Logger logger = LoggerFactory.getLogger(ISMDiscoveryTest.class); @@ -27,6 +32,47 @@ public class ISMDiscoveryTest { propertyDiscovery.analizeISM(PropertyType.class); } + + private void checkType(Type type, Type expected) { + Assert.assertTrue(type.getName().compareTo(expected.getName())==0); + Assert.assertTrue(type.getVersion().compareTo(expected.getVersion())==0); + Assert.assertTrue(type.getDescription().compareTo(expected.getDescription())==0); + Assert.assertTrue(type.isAbstract() == expected.isAbstract()); + + Assert.assertTrue(type.getSuperClasses().containsAll(expected.getSuperClasses())); + Assert.assertTrue(expected.getSuperClasses().containsAll(type.getSuperClasses())); + + + Map typeChangelog = type.getChangelog(); + Map typeManagedChangelog = expected.getChangelog(); + + Assert.assertTrue(typeChangelog.keySet().containsAll(typeManagedChangelog.keySet())); + Assert.assertTrue(typeManagedChangelog.keySet().containsAll(typeChangelog.keySet())); + + for(TypeVersion typeVersion : typeChangelog.keySet()) { + Assert.assertTrue(typeChangelog.get(typeVersion).compareTo(typeManagedChangelog.get(typeVersion))==0); + } + + if(type.getProperties()!=null || expected.getProperties()!=null) { + Assert.assertTrue(type.getProperties().containsAll(expected.getProperties())); + Assert.assertTrue(expected.getProperties().containsAll(type.getProperties())); + } + } + + + @Test + public void testcheckType() throws Exception { + Class clz = PropertyType.class; + Type type = TypeMapper.createTypeDefinition(clz); + Type expected = TypeMapper.createTypeDefinition(PropertyType.class); + checkType(type, expected); + + String json = TypeMapper.serializeType(clz); + expected = TypeMapper.deserializeTypeDefinition(json); + + checkType(type, expected); + } + @Test public void test() throws Exception { @@ -54,25 +100,35 @@ public class ISMDiscoveryTest { Class r) throws Exception { Type type = TypeMapper.createTypeDefinition(r); Assert.assertTrue(type.getName().compareTo(r.getSimpleName())==0); - logger.debug("{} {}", r.getSimpleName(), TypeMapper.serializeTypeDefinition(type)); + String typeDefinitionJsonString = TypeMapper.serializeTypeDefinition(type); + logger.debug("{} {}", r.getSimpleName(), typeDefinitionJsonString); + Type expected = TypeMapper.deserializeTypeDefinition(typeDefinitionJsonString); + checkType(type, expected); } @Override public

void managePropertyClass(Class

p) throws Exception { Type type = TypeMapper.createTypeDefinition(p); Assert.assertTrue(type.getName().compareTo(p.getSimpleName())==0); - logger.debug("{} {}", p.getSimpleName(), TypeMapper.serializeTypeDefinition(type)); + String typeDefinitionJsonString = TypeMapper.serializeTypeDefinition(type); + logger.debug("{} {}", p.getSimpleName(), typeDefinitionJsonString); + Type expected = TypeMapper.deserializeTypeDefinition(typeDefinitionJsonString); + checkType(type, expected); } @Override public void manageEntityClass(Class e) throws Exception { Type type = TypeMapper.createTypeDefinition(e); Assert.assertTrue(type.getName().compareTo(e.getSimpleName())==0); - logger.debug("{} {}", e.getSimpleName(), TypeMapper.serializeTypeDefinition(type)); + String typeDefinitionJsonString = TypeMapper.serializeTypeDefinition(type); + logger.debug("{} {}", e.getSimpleName(), typeDefinitionJsonString); + Type expected = TypeMapper.deserializeTypeDefinition(typeDefinitionJsonString); + checkType(type, expected); } }; ElementSpecilizationDiscovery.manageISM(schemaAction , packages); } + } diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 6bbdacc..b0953a7 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -9,7 +9,7 @@ - +