Added support to specify property type
This commit is contained in:
parent
5abcb94c52
commit
8cea94d297
|
@ -122,6 +122,7 @@ public class PropertyTypeName {
|
||||||
|
|
||||||
protected static final Map<Class<?>,BaseType> BASE_PROPERTY_TYPES_BY_CLASS;
|
protected static final Map<Class<?>,BaseType> BASE_PROPERTY_TYPES_BY_CLASS;
|
||||||
protected static final Map<Class<?>,String> REGEX_BY_CLASS_MAPPED_AS_STRING;
|
protected static final Map<Class<?>,String> REGEX_BY_CLASS_MAPPED_AS_STRING;
|
||||||
|
protected static final Map<String,String> REGEX_BY_CLASS_MAPPED_AS_STRING_BY_CLASS_NAME;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
BASE_PROPERTY_TYPES_BY_CLASS = new HashMap<>();
|
BASE_PROPERTY_TYPES_BY_CLASS = new HashMap<>();
|
||||||
|
@ -180,6 +181,13 @@ public class PropertyTypeName {
|
||||||
REGEX_BY_CLASS_MAPPED_AS_STRING.put(UUID.class,PropertyTypeName.UUID_REGEX);
|
REGEX_BY_CLASS_MAPPED_AS_STRING.put(UUID.class,PropertyTypeName.UUID_REGEX);
|
||||||
REGEX_BY_CLASS_MAPPED_AS_STRING.put(Version.class, Version.VERSION_REGEX);
|
REGEX_BY_CLASS_MAPPED_AS_STRING.put(Version.class, Version.VERSION_REGEX);
|
||||||
|
|
||||||
|
REGEX_BY_CLASS_MAPPED_AS_STRING_BY_CLASS_NAME = new HashMap<>();
|
||||||
|
for(Class<?> clz : REGEX_BY_CLASS_MAPPED_AS_STRING.keySet()) {
|
||||||
|
String className = clz.getSimpleName();
|
||||||
|
String regex = REGEX_BY_CLASS_MAPPED_AS_STRING.get(clz);
|
||||||
|
REGEX_BY_CLASS_MAPPED_AS_STRING_BY_CLASS_NAME.put(className, regex);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static String URI_REGEX = null;
|
public final static String URI_REGEX = null;
|
||||||
|
@ -203,6 +211,10 @@ public class PropertyTypeName {
|
||||||
return REGEX_BY_CLASS_MAPPED_AS_STRING.get(clz);
|
return REGEX_BY_CLASS_MAPPED_AS_STRING.get(clz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getRegexByClassname(String className) {
|
||||||
|
return REGEX_BY_CLASS_MAPPED_AS_STRING_BY_CLASS_NAME.get(className);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the correspondent type by checking the "assignability" of the
|
* Return the correspondent type by checking the "assignability" of the
|
||||||
* class received as parameter.
|
* class received as parameter.
|
||||||
|
@ -235,10 +247,34 @@ public class PropertyTypeName {
|
||||||
protected BaseType genericBaseType;
|
protected BaseType genericBaseType;
|
||||||
protected String genericClassName;
|
protected String genericClassName;
|
||||||
|
|
||||||
|
protected Class<?> clz;
|
||||||
|
|
||||||
public PropertyTypeName(String type) {
|
public PropertyTypeName(String type) {
|
||||||
setType(type);
|
setType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PropertyTypeName(Class<?> clz) {
|
||||||
|
baseType = null;
|
||||||
|
genericType = false;
|
||||||
|
genericBaseType = null;
|
||||||
|
genericClassName = null;
|
||||||
|
|
||||||
|
logger.trace("The type is {}", clz);
|
||||||
|
|
||||||
|
baseType = PropertyTypeName.getBaseTypeByClass(clz);
|
||||||
|
|
||||||
|
if(baseType == BaseType.PROPERTY){
|
||||||
|
if(clz != PropertyElement.class){
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Class<? extends Element> type = (Class<? extends Element>) clz;
|
||||||
|
genericType = true;
|
||||||
|
genericClassName = TypeMapper.getType(type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public PropertyTypeName(Method method) {
|
public PropertyTypeName(Method method) {
|
||||||
baseType = null;
|
baseType = null;
|
||||||
genericType = false;
|
genericType = false;
|
||||||
|
@ -265,13 +301,13 @@ public class PropertyTypeName {
|
||||||
genericType = true;
|
genericType = true;
|
||||||
|
|
||||||
java.lang.reflect.Type genericReturnType = method.getGenericReturnType();
|
java.lang.reflect.Type genericReturnType = method.getGenericReturnType();
|
||||||
logger.trace("Generic Return Type for method {} is {}", method, genericReturnType);
|
logger.trace("Generic Type for method {} is {}", method, genericReturnType);
|
||||||
|
|
||||||
java.lang.reflect.Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
|
java.lang.reflect.Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
|
||||||
|
|
||||||
java.lang.reflect.Type genericType = null;
|
java.lang.reflect.Type genericType = null;
|
||||||
for(java.lang.reflect.Type t : actualTypeArguments){
|
for(java.lang.reflect.Type t : actualTypeArguments){
|
||||||
logger.trace("Generic Return Type {} for method {} - Actual Type Argument : {}", genericReturnType, method, t);
|
logger.trace("Generic Type {} for method {} - Actual Type Argument : {}", genericReturnType, method, t);
|
||||||
genericType = t;
|
genericType = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.gcube.informationsystem.types.annotations;
|
||||||
|
|
||||||
|
import org.gcube.informationsystem.types.PropertyTypeName.BaseType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a facade class.
|
||||||
|
* {@link ISProperty} has the possibility to specify the type.
|
||||||
|
* If we don't specify a default in the annotation definition the type is mandatory.
|
||||||
|
* We need a way to specify a default which means get the return of the annotated method.
|
||||||
|
* This avoid to the developer to specify something which can be get from the annotated method.
|
||||||
|
* We can't use Object as default because Object is mapped as {@link BaseType#ANY}
|
||||||
|
*
|
||||||
|
* This interface has been defined for this reason.
|
||||||
|
*/
|
||||||
|
public interface GetReturnType {
|
||||||
|
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import java.lang.annotation.Target;
|
||||||
|
|
||||||
import org.gcube.informationsystem.model.reference.entities.Entity;
|
import org.gcube.informationsystem.model.reference.entities.Entity;
|
||||||
import org.gcube.informationsystem.types.TypeMapper;
|
import org.gcube.informationsystem.types.TypeMapper;
|
||||||
|
import org.gcube.informationsystem.types.PropertyTypeName.BaseType;
|
||||||
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
|
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,6 +25,17 @@ import org.gcube.informationsystem.types.reference.properties.PropertyDefinition
|
||||||
public @interface ISProperty {
|
public @interface ISProperty {
|
||||||
|
|
||||||
String name() default "";
|
String name() default "";
|
||||||
|
/**
|
||||||
|
* If we don't specify a default in the annotation definition, the type becomes mandatory.
|
||||||
|
* We wanted a way to specify a default that means using the return type of the annotated method.
|
||||||
|
* This avoids the need for developers to specify something that can be obtained from the annotated method itself.
|
||||||
|
* We can't use Object as the default because Object is mapped as {@link BaseType#ANY}.
|
||||||
|
* For this reason, the type {@link GetReturnType} has been set as the default.
|
||||||
|
*
|
||||||
|
* Please note that you can't use this functionality for generic types
|
||||||
|
* like List<String> because it is not accepted by the annotation.
|
||||||
|
*/
|
||||||
|
Class<?> type() default GetReturnType.class;
|
||||||
String description() default "";
|
String description() default "";
|
||||||
boolean mandatory() default false;
|
boolean mandatory() default false;
|
||||||
boolean readonly() default false;
|
boolean readonly() default false;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.gcube.com.fasterxml.jackson.annotation.JsonTypeName;
|
||||||
import org.gcube.informationsystem.model.impl.properties.AttributeUtility;
|
import org.gcube.informationsystem.model.impl.properties.AttributeUtility;
|
||||||
import org.gcube.informationsystem.types.PropertyTypeName;
|
import org.gcube.informationsystem.types.PropertyTypeName;
|
||||||
import org.gcube.informationsystem.types.annotations.ISProperty;
|
import org.gcube.informationsystem.types.annotations.ISProperty;
|
||||||
|
import org.gcube.informationsystem.types.annotations.GetReturnType;
|
||||||
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
|
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
|
||||||
import org.gcube.informationsystem.utils.TypeUtility;
|
import org.gcube.informationsystem.utils.TypeUtility;
|
||||||
import org.gcube.informationsystem.utils.Version;
|
import org.gcube.informationsystem.utils.Version;
|
||||||
|
@ -82,19 +83,25 @@ public final class PropertyDefinitionImpl implements PropertyDefinition {
|
||||||
this.min = propertyAnnotation.min();
|
this.min = propertyAnnotation.min();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.propertyTypeName = new PropertyTypeName(method);
|
Class<?> clz = propertyAnnotation.type();
|
||||||
this.propertyTypeName = new PropertyTypeName(method);
|
if(clz==GetReturnType.class) {
|
||||||
|
// We have to read the return of the method
|
||||||
|
this.propertyTypeName = new PropertyTypeName(method);
|
||||||
|
clz = method.getReturnType();
|
||||||
|
logger.trace("Return Type for method {} is {}", method, clz);
|
||||||
|
}else {
|
||||||
|
this.propertyTypeName = new PropertyTypeName(clz);
|
||||||
|
}
|
||||||
|
|
||||||
String defaultValueAsString = propertyAnnotation.defaultValue();
|
String defaultValueAsString = propertyAnnotation.defaultValue();
|
||||||
defaultValueAsString = AttributeUtility.evaluateNullForDefaultValue(defaultValueAsString);
|
defaultValueAsString = AttributeUtility.evaluateNullForDefaultValue(defaultValueAsString);
|
||||||
|
|
||||||
// The default value is evaluated to test if compliant with the declared type
|
// The default value is evaluated to test if compliant with the declared type
|
||||||
this.defaultValue = AttributeUtility.evaluateDefaultValueStringAccordingBaseType(propertyTypeName.getBaseType(), defaultValueAsString);
|
this.defaultValue = AttributeUtility.evaluateDefaultValueStringAccordingBaseType(propertyTypeName.getBaseType(), defaultValueAsString);
|
||||||
|
|
||||||
Class<?> clz = method.getReturnType();
|
if(!propertyAnnotation.regexpr().isEmpty()) {
|
||||||
logger.trace("Return Type for method {} is {}", method, clz);
|
this.regexp = propertyAnnotation.regexpr();
|
||||||
|
}else {
|
||||||
if(!propertyAnnotation.regexpr().isEmpty()) this.regexp = propertyAnnotation.regexpr();
|
|
||||||
if(this.regexp==null || this.regexp.compareTo("")==0 ){
|
|
||||||
if(Enum.class.isAssignableFrom(clz)){
|
if(Enum.class.isAssignableFrom(clz)){
|
||||||
Object[] constants = clz.getEnumConstants();
|
Object[] constants = clz.getEnumConstants();
|
||||||
StringBuilder stringBuilder = new StringBuilder("^(");
|
StringBuilder stringBuilder = new StringBuilder("^(");
|
||||||
|
@ -119,7 +126,6 @@ public final class PropertyDefinitionImpl implements PropertyDefinition {
|
||||||
if(Version.class.isAssignableFrom(clz)){
|
if(Version.class.isAssignableFrom(clz)){
|
||||||
this.regexp = Version.VERSION_REGEX;
|
this.regexp = Version.VERSION_REGEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
*
|
*
|
||||||
* @author Luca Frosini (ISTI - CNR)
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
*/
|
*/
|
||||||
public class Version implements Comparable<Version> {
|
public final class Version implements Comparable<Version> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regex validating the version
|
* Regex validating the version
|
||||||
|
|
Loading…
Reference in New Issue