package org.gcube.informationsystem.types.impl.relations; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore; import org.gcube.com.fasterxml.jackson.annotation.JsonTypeName; import org.gcube.informationsystem.base.reference.AccessType; import org.gcube.informationsystem.base.reference.entities.EntityElement; import org.gcube.informationsystem.base.reference.relations.RelationElement; import org.gcube.informationsystem.context.reference.relations.IsParentOf; 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.types.impl.TypeImpl; import org.gcube.informationsystem.types.impl.entities.EntityTypeImpl; import org.gcube.informationsystem.types.reference.entities.EntityType; import org.gcube.informationsystem.types.reference.relations.ConsistsOfType; import org.gcube.informationsystem.types.reference.relations.IsRelatedToType; import org.gcube.informationsystem.types.reference.relations.RelationType; /** * @author Luca Frosini (ISTI - CNR) */ @JsonTypeName(value = RelationType.NAME) public class RelationTypeImpl extends TypeImpl implements RelationType { /** * Generated Serial Version UID */ private static final long serialVersionUID = 2221831081869571296L; protected RelationTypeImpl() { super(); } public static RelationType getRelationTypeDefinitionInstance( Class> clz) { if(IsRelatedTo.class.isAssignableFrom(clz)) { @SuppressWarnings("unchecked") Class> c = (Class>) clz; return new IsRelatedToTypeImpl(c); } else if(ConsistsOf.class.isAssignableFrom(clz)) { @SuppressWarnings("unchecked") Class> c = (Class>) clz; return new ConsistsOfTypeImpl(c); } return new RelationTypeImpl(clz); } public RelationTypeImpl(Class> clz) { super(clz); if(RelationType.class.isAssignableFrom(clz)) { @SuppressWarnings({"unchecked"}) Class> c = (Class>) clz; this.superClasses = retrieveSuperClasses(c, RelationType.class, RelationElement.NAME); } else if(IsParentOf.class.isAssignableFrom(clz)) { @SuppressWarnings("unchecked") Class c = (Class) clz; this.superClasses = retrieveSuperClasses(c, IsParentOf.class, RelationElement.NAME); } else if(RelationElement.class.isAssignableFrom(clz)) { this.superClasses = retrieveSuperClasses(clz, RelationElement.class, null); } else { throw new RuntimeException("Type Hierachy Error"); } this.properties = retrieveListOfProperties(clz); discoverSourceAndTarget(clz); } @SuppressWarnings("unchecked") protected Type[] getParametersFromSuperClasses(Class> clz) { for(Type t : clz.getGenericInterfaces()) { if(t instanceof ParameterizedType) { if(RelationElement.class.isAssignableFrom((Class) ((ParameterizedType) t).getRawType())) { return ((ParameterizedType) t).getActualTypeArguments(); } } else if(RelationElement.class.isAssignableFrom((Class) t)) { return getParametersFromSuperClasses((Class>) t); } } throw new RuntimeException("Unable to find Generic Parameters From SuperClasses to set source and target"); } @SuppressWarnings("unchecked") private void discoverSourceAndTarget(Class> clz) { Type[] typeParameters = clz.getTypeParameters(); Class sourceClass; Class targetClass; if(typeParameters.length == 0) { typeParameters = getParametersFromSuperClasses(clz); sourceClass = (Class) typeParameters[0]; targetClass = (Class) typeParameters[1]; } else { sourceClass = (Class) getGenericClass(typeParameters[0]); targetClass = (Class) getGenericClass(typeParameters[1]); } this.source = (S) new EntityTypeImpl(sourceClass); this.target = (T) new EntityTypeImpl(targetClass); } /* * Java does not support class multiple inheritance. * TypeDefinitionImpl is the superclass so that this class does not inherits the methods and field of BaseRelationImpl * We need to copy them. */ protected S source; protected T target; @Override public S getSource() { return source; } @Override public void setSource(S source) { this.source = source; } @Override public T getTarget() { return target; } @Override public void setTarget(T target) { this.target = target; } @Override @JsonIgnore public AccessType getAccessType() { if(name.compareTo(IsParentOf.NAME)==0) { return AccessType.IS_PARENT_OF; } if(name.compareTo(RelationElement.NAME)==0) { return AccessType.RELATION_ELEMENT; } if(name.compareTo(RelationType.NAME)==0 || name.compareTo(IsRelatedToType.NAME)==0 || name.compareTo(ConsistsOfType.NAME)==0) { return AccessType.RELATION_TYPE; } return AccessType.RELATION; } }