information-system-model/src/main/java/org/gcube/informationsystem/types/impl/properties/PropertyDefinitionImpl.java

253 lines
7.5 KiB
Java

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.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.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;
import org.slf4j.LoggerFactory;
// @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
@JsonTypeName(value=PropertyDefinition.NAME)
public final class PropertyDefinitionImpl implements PropertyDefinition {
/**
* Generated Serial Version UID
*/
private static final long serialVersionUID = -5925314595659292025L;
private static Logger logger = LoggerFactory.getLogger(TypeImpl.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;
public final static String URL_REGEX = null;
private String name= "";
private String description= "";
private boolean mandatory = false;
private boolean readonly = false;
private boolean notnull = false;
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 static String getPropertyNameFromMethodName(Method method){
String name = method.getName();
if(name.startsWith("get")){
name = name.replace("get", "");
}
if(name.startsWith("is")){
name = name.replace("is", "");
}
if(name.length() > 0){
name = Character.toLowerCase(name.charAt(0)) + (name.length() > 1 ? name.substring(1) : "");
}
return name;
}
protected PropertyDefinitionImpl() {
}
public PropertyDefinitionImpl(ISProperty propertyAnnotation, Method method) {
String name = propertyAnnotation.name().isEmpty()?getPropertyNameFromMethodName(method):propertyAnnotation.name();
this.name = name;
this.description = propertyAnnotation.description();
this.mandatory= propertyAnnotation.mandatory();
this.notnull = !propertyAnnotation.nullable();
this.readonly = propertyAnnotation.readonly();
if(propertyAnnotation.max()>0) this.max = propertyAnnotation.max();
if(propertyAnnotation.max()>=propertyAnnotation.min() && propertyAnnotation.min()>0) this.min = propertyAnnotation.min();
if(!propertyAnnotation.regexpr().isEmpty()) this.regexp = propertyAnnotation.regexpr();
logger.trace("Looking for property type {}", method.getReturnType());
@SuppressWarnings("unchecked")
Class<? extends Element> type = (Class<? extends Element>) 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<? extends Element> genericClass = (Class<? extends Element>) 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<constants.length; i++){
stringBuilder.append(constants[i].toString());
if(i<constants.length-1){
stringBuilder.append("|");
}
}
stringBuilder.append(")$");
this.regexp = stringBuilder.toString();
}
if(UUID.class.isAssignableFrom(type)){
this.regexp = UUID_REGEX;
}
if(URI.class.isAssignableFrom(type)){
this.regexp = URI_REGEX;
}
if(URL.class.isAssignableFrom(type)){
this.regexp = URL_REGEX;
}
if(TypeVersion.class.isAssignableFrom(type)){
this.regexp = TypeVersion.TYPE_VERSION_REGEX;
}
}
if(this.regexp!=null && this.regexp.compareTo("")==0){
this.regexp = null;
}
} else {
throw new RuntimeException("Type " + type.getSimpleName() + " not reconized");
}
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public boolean isMandatory() {
return mandatory;
}
@Override
public boolean isReadonly() {
return readonly;
}
@Override
public boolean isNotnull() {
return notnull;
}
@Override
public Integer getMax() {
return max;
}
@Override
public Integer getMin() {
return min;
}
@Override
public String getRegexp() {
return regexp;
}
@Override
public Integer getLinkedType() {
return linkedType;
}
@Override
public String getLinkedClass() {
return linkedClass;
}
@Override
public Integer getType() {
return type;
}
@JsonIgnore
public String getTypeStringValue() {
if(type==null){
return null;
}
return OType.values()[type].getStringValue();
}
@Override
public String toString() {
return "Property [name=" + name + ", description=" + description
+ ", mandatory=" + mandatory + ", readonly=" + readonly
+ ", notnull=" + notnull + ", max=" + max + ", min="
+ min + ", regexpr=" + regexp + ", type = " + type
+ " (" + getTypeStringValue() + "), linkedType = " + linkedType + ", linkedClass = "
+ linkedClass + "]";
}
@Override
public int hashCode() {
return Objects.hash(description, linkedClass, linkedType, mandatory, max, min, name, notnull, readonly, regexp,
type);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PropertyDefinitionImpl other = (PropertyDefinitionImpl) obj;
return Objects.equals(description, other.description) && Objects.equals(linkedClass, other.linkedClass)
&& Objects.equals(linkedType, other.linkedType) && mandatory == other.mandatory
&& Objects.equals(max, other.max) && Objects.equals(min, other.min) && Objects.equals(name, other.name)
&& notnull == other.notnull && readonly == other.readonly && Objects.equals(regexp, other.regexp)
&& Objects.equals(type, other.type);
}
}