information-system-model/src/main/java/org/gcube/informationsystem/types/impl/entities/TypeDefinitionImpl.java

193 lines
6.3 KiB
Java
Raw Normal View History

package org.gcube.informationsystem.types.impl.entities;
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
import java.util.HashSet;
import java.util.Set;
import org.gcube.informationsystem.base.reference.ISManageable;
import org.gcube.informationsystem.base.reference.properties.Property;
import org.gcube.informationsystem.model.reference.entities.Entity;
import org.gcube.informationsystem.model.reference.entities.Facet;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
import org.gcube.informationsystem.model.reference.relations.IsRelatedTo;
import org.gcube.informationsystem.model.reference.relations.Relation;
import org.gcube.informationsystem.types.TypeBinder;
import org.gcube.informationsystem.types.annotations.Abstract;
import org.gcube.informationsystem.types.annotations.ISProperty;
import org.gcube.informationsystem.types.impl.properties.PropertyDefinitionImpl;
import org.gcube.informationsystem.types.reference.TypeDefinition;
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
@JsonIgnoreProperties(ignoreUnknown=true)
public class TypeDefinitionImpl implements TypeDefinition {
private static Logger logger = LoggerFactory.getLogger(TypeDefinitionImpl.class);
private static final String EDGE_CLASS_NAME = "E";
private static final String VERTEX_CLASS_NAME = "V";
private final static String DESCRIPTION = "DESCRIPTION";
protected String name;
protected String description;
@JsonProperty(value="abstract")
protected boolean abstractType;
protected Set<String> superClasses;
protected Set<PropertyDefinition> properties;
@JsonInclude(JsonInclude.Include.NON_NULL)
protected String sourceType;
@JsonInclude(JsonInclude.Include.NON_NULL)
protected String targetType;
private static Set<String> retrieveSuperClasses(Class<? extends ISManageable> type, Class<? extends ISManageable> baseClass, String topSuperClass){
Set<String> interfaceList = new HashSet<>();
if(type==baseClass){
interfaceList.add(topSuperClass);
return interfaceList;
}
Class<?>[] interfaces = type.getInterfaces();
for (Class<?> interfaceClass : interfaces) {
if(!baseClass.isAssignableFrom(interfaceClass)){
continue;
}
@SuppressWarnings("unchecked")
Class<? extends ISManageable> clz = (Class<? extends ISManageable>) interfaceClass;
interfaceList.add(TypeBinder.getType(clz));
}
return interfaceList;
}
private static Set<PropertyDefinition> retrieveListOfProperties(Class<?> type){
Set<PropertyDefinition> properties = new HashSet<>();
for (Method m : type.getDeclaredMethods()){
m.setAccessible(true);
if(m.isAnnotationPresent(ISProperty.class)){
if(m.isBridge()) {
continue;
}
ISProperty propAnnotation = m.getAnnotation(ISProperty.class);
PropertyDefinition prop = new PropertyDefinitionImpl(propAnnotation, m);
properties.add(prop);
logger.trace("Property {} retrieved in type {} ", prop, type.getSimpleName());
}
}
return properties;
}
private static Class<?> getGenericClass(java.lang.reflect.Type type){
TypeVariable<?> typeVariable = (TypeVariable<?>) type;
java.lang.reflect.Type[] bounds = typeVariable.getBounds();
java.lang.reflect.Type t = bounds[0];
return (Class<?>) t;
}
public TypeDefinitionImpl(Class<? extends ISManageable> clz) {
this.name = TypeBinder.getType(clz);
this.description = TypeBinder.getStaticStringFieldByName(clz, DESCRIPTION, "");
this.abstractType = false;
if(clz.isAnnotationPresent(Abstract.class)){
this.abstractType = true;
}
if(Entity.class.isAssignableFrom(clz)) {
if(Resource.class.isAssignableFrom(clz)){
this.superClasses = retrieveSuperClasses(clz, Resource.class, Entity.NAME);
}else{
if(Facet.class.isAssignableFrom(clz)){
this.superClasses = retrieveSuperClasses(clz, Facet.class, Entity.NAME);
} else {
this.superClasses = retrieveSuperClasses(clz, Entity.class, VERTEX_CLASS_NAME);
}
}
} else if(Relation.class.isAssignableFrom(clz)){
if(IsRelatedTo.class.isAssignableFrom(clz)){
this.superClasses = retrieveSuperClasses(clz, IsRelatedTo.class, Relation.NAME);
} else if(ConsistsOf.class.isAssignableFrom(clz)) {
this.superClasses = retrieveSuperClasses(clz, ConsistsOf.class, Relation.NAME);
} else {
this.superClasses = retrieveSuperClasses(clz, Relation.class, EDGE_CLASS_NAME);
}
java.lang.reflect.Type[] typeParameters = clz.getTypeParameters();
@SuppressWarnings("unchecked")
Class<? extends ISManageable> sourceClass = (Class<? extends ISManageable>) getGenericClass(typeParameters[0]);
@SuppressWarnings("unchecked")
Class<? extends ISManageable> targetClass = (Class<? extends ISManageable>) getGenericClass(typeParameters[1]);
this.sourceType = TypeBinder.getType(sourceClass);
this.targetType = TypeBinder.getType(targetClass);
} else if(Property.class.isAssignableFrom(clz)){
this.superClasses = retrieveSuperClasses(clz, Property.class, clz == Property.class ? null : Property.NAME);
} else {
throw new RuntimeException("Serialization required");
}
if(!Resource.class.isAssignableFrom(clz)){
this.properties = retrieveListOfProperties(clz);
}
logger.trace("{} : {} ", clz, this);
}
@Override
public String toString() {
return "TypeDefinition ["
+ "name=" + name
+ (sourceType==null ? "" : "(" + sourceType + "->" + targetType + ")")
+ ", description=" + description
+ ", abstract=" + abstractType
+ ", superClasses=" + superClasses
+ ", properties=" + properties
+ "]";
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public boolean isAbstract() {
return abstractType;
}
public Set<String> getSuperClasses() {
return superClasses;
}
public Set<PropertyDefinition> getProperties() {
return properties;
}
public String getSourceType() {
return sourceType;
}
public String getTargetType() {
return targetType;
}
}