193 lines
6.3 KiB
Java
193 lines
6.3 KiB
Java
|
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;
|
||
|
}
|
||
|
|
||
|
}
|