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.ISManageableImpl; import org.gcube.informationsystem.base.reference.ISManageable; import org.gcube.informationsystem.base.reference.entities.BaseEntity; import org.gcube.informationsystem.base.reference.properties.BaseProperty; import org.gcube.informationsystem.base.reference.relations.BaseRelation; 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.EntityTypeDefinitionImpl; import org.gcube.informationsystem.types.impl.properties.PropertyDefinitionImpl; import org.gcube.informationsystem.types.impl.properties.PropertyTypeDefinitionImpl; import org.gcube.informationsystem.types.impl.relations.RelationTypeDefinitionImpl; 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 ISManageableImpl 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 superClasses; protected Set properties; protected static Set retrieveSuperClasses(Class type, Class baseClass, String topSuperClass){ Set 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 clz = (Class) interfaceClass; interfaceList.add(TypeBinder.getType(clz)); } return interfaceList; } private static Set retrieveListOfProperties(Class type){ Set 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 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]; if(t instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) t; return (Class) parameterizedType.getRawType(); } return (Class) t; } @SuppressWarnings({"rawtypes", "unchecked"}) public static TypeDefinition getInstance(Class clz) { if(BaseEntity.class.isAssignableFrom(clz)) { return new EntityTypeDefinitionImpl(clz); } else if(BaseRelation.class.isAssignableFrom(clz)){ return new RelationTypeDefinitionImpl(clz); } else if(BaseProperty.class.isAssignableFrom(clz)){ return new PropertyTypeDefinitionImpl(clz); } else if(TypeDefinition.class.isAssignableFrom(clz)) { return new TypeDefinitionImpl(clz); } else { throw new RuntimeException("Serialization required"); } } protected TypeDefinitionImpl() {} protected TypeDefinitionImpl(Class 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); } logger.trace("{} : {} ", clz, this); } @Override public String getName() { return name; } @Override public String getDescription() { return description; } @Override public boolean isAbstract() { return abstractType; } @Override public Set getSuperClasses() { return superClasses; } @Override public Set getProperties() { return properties; } }