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

175 lines
5.4 KiB
Java

package org.gcube.informationsystem.types.impl;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.TypeVariable;
import java.util.HashSet;
import java.util.Set;
import org.gcube.informationsystem.base.impl.ERImpl;
import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.base.reference.entities.EntityElement;
import org.gcube.informationsystem.base.reference.properties.PropertyElement;
import org.gcube.informationsystem.base.reference.relations.RelationElement;
import org.gcube.informationsystem.model.reference.entities.Resource;
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.entities.EntityTypeImpl;
import org.gcube.informationsystem.types.impl.properties.PropertyDefinitionImpl;
import org.gcube.informationsystem.types.impl.properties.PropertyTypeImpl;
import org.gcube.informationsystem.types.impl.relations.RelationTypeImpl;
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.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
// @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
@JsonTypeName(value=TypeDefinition.NAME)
public class TypeDefinitionImpl extends ERImpl implements TypeDefinition {
/**
* Generated Serial Version UID
*/
private static final long serialVersionUID = 2698204820689338513L;
private static Logger logger = LoggerFactory.getLogger(TypeDefinitionImpl.class);
public 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;
protected <ISM extends Element> Set<String> retrieveSuperClasses(Class<? extends ISM> type, Class<ISM> baseClass, String topSuperClass){
Set<String> interfaceList = new HashSet<>();
if(type==baseClass){
if(topSuperClass!=null) {
interfaceList.add(topSuperClass);
}
return interfaceList;
}
Class<?>[] interfaces = type.getInterfaces();
for (Class<?> interfaceClass : interfaces) {
if(!baseClass.isAssignableFrom(interfaceClass)){
continue;
}
@SuppressWarnings("unchecked")
Class<? extends Element> clz = (Class<? extends Element>) interfaceClass;
interfaceList.add(TypeBinder.getType(clz));
}
return interfaceList;
}
protected 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;
}
protected 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];
if(t instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) t;
return (Class<?>) parameterizedType.getRawType();
}
return (Class<?>) t;
}
@SuppressWarnings({"rawtypes", "unchecked"})
public static TypeDefinition getInstance(Class<? extends Element> clz) {
TypeDefinition typeDefinition = null;
try {
if(EntityElement.class.isAssignableFrom(clz)) {
typeDefinition = EntityTypeImpl.getEntityTypeDefinitionInstance((Class<? extends EntityElement>) clz);
return typeDefinition;
} else if(RelationElement.class.isAssignableFrom(clz)){
typeDefinition = RelationTypeImpl.getRelationTypeDefinitionInstance((Class<? extends RelationElement<?,?>>) clz);
return typeDefinition;
} else if(PropertyElement.class.isAssignableFrom(clz)){
typeDefinition = new PropertyTypeImpl(clz);
return typeDefinition;
} else if(TypeDefinition.class.isAssignableFrom(clz)) {
typeDefinition = new TypeDefinitionImpl(clz);
return typeDefinition;
} else {
throw new RuntimeException("Serialization required");
}
} finally {
if(typeDefinition!=null) {
logger.debug("{} : {} ", clz, typeDefinition);
}
}
}
protected TypeDefinitionImpl() {}
protected TypeDefinitionImpl(Class<? extends Element> clz) {
this.name = TypeBinder.getType(clz);
this.description = TypeBinder.getStaticStringFieldByName(clz, DESCRIPTION, "");
this.abstractType = false;
if(clz.isAnnotationPresent(Abstract.class)){
this.abstractType = true;
}
if(!Resource.class.isAssignableFrom(clz)) {
this.properties = retrieveListOfProperties(clz);
}
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public boolean isAbstract() {
return abstractType;
}
@Override
public Set<String> getSuperClasses() {
return superClasses;
}
@Override
public Set<PropertyDefinition> getProperties() {
return properties;
}
}