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

304 lines
9.4 KiB
Java
Raw Normal View History

package org.gcube.informationsystem.types;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import org.gcube.informationsystem.model.annotations.Abstract;
import org.gcube.informationsystem.model.embedded.Embedded;
import org.gcube.informationsystem.model.entity.Entity;
import org.gcube.informationsystem.model.entity.Facet;
import org.gcube.informationsystem.model.entity.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.ObjectMapper;
public class TypeBinder {
private static Logger logger = LoggerFactory.getLogger(TypeBinder.class);
public final static String NAME = "NAME";
public final static String DESCRIPTION = "DESCRIPTION";
private static String getStaticStringFieldByName(Class<?> type, String fieldName, String defaultValue){
Field field;
try {
field = type.getDeclaredField(NAME);
return (String) field.get(null);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
return defaultValue;
}
}
public static String serializeType(Class<?> type) throws Exception{
TypeDefinition def = createTypeDefinition(type);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(def);
return json;
}
protected static TypeDefinition createTypeDefinition(Class<?> type) {
TypeDefinition typeDefinition = new TypeDefinition();
typeDefinition.name = getStaticStringFieldByName(type, NAME, type.getSimpleName());
typeDefinition.description = getStaticStringFieldByName(type, DESCRIPTION, "");
typeDefinition.abstractType = false;
if(type.isAnnotationPresent(Abstract.class)){
typeDefinition.abstractType = true;
}
if(Resource.class.isAssignableFrom(type)){
typeDefinition.superclasses = retrieveSuperClasses(type, Resource.class, Entity.class.getSimpleName());
}else{
// TODO
//typeDefinition.properties = retrieveListOfProperties(type);
if(Facet.class.isAssignableFrom(type)){
typeDefinition.superclasses = retrieveSuperClasses(type, Facet.class, Entity.class.getSimpleName());
}else if(Embedded.class.isAssignableFrom(type)){
typeDefinition.superclasses = retrieveSuperClasses(type, Embedded.class, null);
} else if(Entity.class.isAssignableFrom(type)){
typeDefinition.superclasses = retrieveSuperClasses(type, Entity.class, "V");
}
}
/*
if (typeDefinition.name.equals(DEFAULT_ENTITY_SUPERCLASS)) {
typeDefinition.superclasses = Collections.singletonList("V");
} else {
String superClassName = retrieveSuperClasses(type);
typeDefinition.superclasses = Collections.singletonList(superClassName.isEmpty()?DEFAULT_ENTITY_SUPERCLASS:superClassName);
}
if (typeDefinition.name.equals(DEFAULT_RESOURCE_SUPERCLASS)) {
typeDefinition.superclasses = Collections.singletonList(DEFAULT_ENTITY_SUPERCLASS);
} else {
String superClassName = retrieveSuperClasses(type);
typeDefinition.superclasses = Collections.singletonList(superClassName.isEmpty()?DEFAULT_RESOURCE_SUPERCLASS:superClassName);
}
if (typeDefinition.name.equals(DEFAULT_FACET_SUPERCLASS)) {
typeDefinition.superclasses = Collections.singletonList(DEFAULT_ENTITY_SUPERCLASS);
} else {
String superClassName = retrieveSuperClasses(type);
typeDefinition.superclasses = Collections.singletonList(superClassName.isEmpty()?DEFAULT_FACET_SUPERCLASS:superClassName);
}
*/
logger.trace("{} TypeDefinition {} ", type, typeDefinition);
return typeDefinition;
}
/*
private static List<Property> retrieveListOfProperties(Class<?> type){
List<Property> properties = new ArrayList<TypeBinder.Property>();
for (Field f:type.getDeclaredFields()){
f.setAccessible(true);
if (f.isAnnotationPresent(ISPropertyRef.class)){
ISPropertyRef refAnnotation = f.getAnnotation(ISPropertyRef.class);
Property prop = getProperty(refAnnotation, f);
properties.add(prop);
logger.trace("property {} retrieved in type {} ",prop, type.getSimpleName());
}else if (f.isAnnotationPresent(ISProperty.class)){
ISProperty propAnnotation = f.getAnnotation(ISProperty.class);
Property prop = getProperty(propAnnotation, f);
properties.add(prop);
logger.trace("property {} retrieved in type {} ",prop, type.getSimpleName());
}
}
return properties;
}
private static Property getProperty(ISPropertyRef refPropertyAnnotation, Field field){
if (!refPropertyAnnotation.ref().isAnnotationPresent(ISEmbeddedType.class))
throw new RuntimeException("class "+refPropertyAnnotation.ref().getSimpleName()+" must be annotated with @ISEmbeddedType");
ISEmbeddedType embeddedTypeAnn= refPropertyAnnotation.ref().getAnnotation(ISEmbeddedType.class);
String link = embeddedTypeAnn.name().isEmpty()?refPropertyAnnotation.ref().getSimpleName():embeddedTypeAnn.name();
String name = refPropertyAnnotation.name().isEmpty()?field.getName():refPropertyAnnotation.name();
Property prop = new Property();
prop.name = name;
prop.description = refPropertyAnnotation.description();
prop.mandatory= refPropertyAnnotation.mandatory();
prop.notnull = !refPropertyAnnotation.nullable();
prop.readonly = refPropertyAnnotation.readonly();
if(refPropertyAnnotation.max()>0) prop.max = refPropertyAnnotation.max();
if(refPropertyAnnotation.max()>=refPropertyAnnotation.min() && refPropertyAnnotation.min()>0) prop.min = refPropertyAnnotation.min();
if(!refPropertyAnnotation.regexpr().isEmpty()) prop.regexpr = refPropertyAnnotation.regexpr();
logger.trace("serching correspondance for type {}",field.getType());
if (Type.getTypeByClass(field.getType())!=null)
prop.type = Type.getTypeByClass(field.getType()).getIntValue();
prop.linkedClass = link;
if (prop.type==null)
prop.type = OType.EMBEDDED.getIntValue();
return prop;
}
private static Property getProperty(ISProperty propertyAnnotation, Field field){
String name = propertyAnnotation.name().isEmpty()?field.getName():propertyAnnotation.name();
Property prop = new Property();
prop.name = name;
prop.description = propertyAnnotation.description();
prop.mandatory= propertyAnnotation.mandatory();
prop.notnull = !propertyAnnotation.nullable();
prop.readonly = propertyAnnotation.readonly();
if(propertyAnnotation.max()>0) prop.max = propertyAnnotation.max();
if(propertyAnnotation.max()>=propertyAnnotation.min() && propertyAnnotation.min()>0) prop.min = propertyAnnotation.min();
if(!propertyAnnotation.regexpr().isEmpty()) prop.regexpr = propertyAnnotation.regexpr();
logger.trace("serching correspondance for type {}",field.getType());
if (Type.getTypeByClass(field.getType())!=null)
prop.type = Type.getTypeByClass(field.getType()).getIntValue();
else throw new RuntimeException("type "+field.getType().getSimpleName()+" not reconized");
return prop;
}
*/
private static Set<String> retrieveSuperClasses(Class<?> type, Class<?> 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(interfaceClass==Embedded.class){
continue;
}
if(!baseClass.isAssignableFrom(interfaceClass)){
continue;
}
interfaceList.add(getStaticStringFieldByName(interfaceClass, NAME, interfaceClass.getSimpleName()));
}
return interfaceList;
}
@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
public static class TypeDefinition{
protected String name;
protected String description;
protected boolean abstractType;
protected Set<String> superclasses;
protected Set<Property> properties;
@Override
public String toString() {
return "TypeDefinition [name=" + name +", description="
+ description + ", superclasses="
+ superclasses + ", properties=" + properties + "]";
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public boolean isAbstractType() {
return abstractType;
}
public Set<String> getSuperclasses() {
return superclasses;
}
public Set<Property> getProperties() {
return properties;
}
}
@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
public static class Property{
private String name= "";
private String description= "";
private boolean mandatory = false;
private boolean readonly = false;
private boolean notnull = false;
private Integer max= null;
private Integer min= null;
private String regexpr= null;
private String linkedClass = null;
private Integer type=null;
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public boolean isMandatory() {
return mandatory;
}
public boolean isReadonly() {
return readonly;
}
public boolean isNotnull() {
return notnull;
}
public Integer getMax() {
return max;
}
public Integer getMin() {
return min;
}
public String getRegexpr() {
return regexpr;
}
public String getLinkedClass() {
return linkedClass;
}
public Integer getType() {
return type;
}
@Override
public String toString() {
return "Property [name=" + name + ", description=" + description
+ ", mandatory=" + mandatory + ", readonly=" + readonly
+ ", notnull=" + notnull + ", max=" + max + ", min="
+ min + ", regexpr=" + regexpr + ", linkedClass = "+linkedClass+"]";
}
}
}