293 lines
8.1 KiB
Java
293 lines
8.1 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.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.TreeSet;
|
|
import java.util.UUID;
|
|
|
|
import org.gcube.com.fasterxml.jackson.annotation.JsonGetter;
|
|
import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore;
|
|
import org.gcube.com.fasterxml.jackson.annotation.JsonInclude;
|
|
import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include;
|
|
import org.gcube.com.fasterxml.jackson.annotation.JsonProperty;
|
|
import org.gcube.com.fasterxml.jackson.annotation.JsonSetter;
|
|
import org.gcube.informationsystem.base.reference.AccessType;
|
|
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.properties.Metadata;
|
|
import org.gcube.informationsystem.types.TypeMapper;
|
|
import org.gcube.informationsystem.types.annotations.Abstract;
|
|
import org.gcube.informationsystem.types.annotations.Final;
|
|
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.Type;
|
|
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
|
|
import org.gcube.informationsystem.utils.Version;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
/**
|
|
* @author Luca Frosini (ISTI - CNR)
|
|
*/
|
|
public class TypeImpl implements Type {
|
|
|
|
private static Logger logger = LoggerFactory.getLogger(TypeImpl.class);
|
|
|
|
/**
|
|
* Generated Serial version UID
|
|
*/
|
|
private static final long serialVersionUID = -4333954207969059451L;
|
|
|
|
public static final Map<Version, String> DEFAULT_CHANGELOG_MAP;
|
|
private static final Map<String, String> DEFAULT_CHANGELOG_MAP_KEY_AS_STRING;
|
|
|
|
static {
|
|
DEFAULT_CHANGELOG_MAP = new HashMap<>();
|
|
DEFAULT_CHANGELOG_MAP.put(new Version(Version.MINIMAL_VERSION_STRING), Version.MINIMAL_VERSION_DESCRIPTION);
|
|
DEFAULT_CHANGELOG_MAP_KEY_AS_STRING = new HashMap<>();
|
|
DEFAULT_CHANGELOG_MAP_KEY_AS_STRING.put(Version.MINIMAL_VERSION_STRING, Version.MINIMAL_VERSION_DESCRIPTION);
|
|
}
|
|
|
|
protected UUID uuid;
|
|
protected Metadata metadata;
|
|
|
|
protected String name;
|
|
protected String description;
|
|
protected Version version;
|
|
@JsonProperty(value = CHANGELOG_PROPERTY, required = false)
|
|
@JsonInclude(Include.NON_NULL)
|
|
protected Map<Version, String> changelog;
|
|
|
|
@JsonProperty(value = ABSTRACT_PROPERTY)
|
|
protected boolean abstractType;
|
|
|
|
@JsonProperty(value = FINAL_PROPERTY)
|
|
protected boolean finalClass;
|
|
|
|
protected Set<String> superClasses;
|
|
|
|
protected Set<PropertyDefinition> properties;
|
|
|
|
protected <E extends Element> Set<String> retrieveSuperClasses(Class<? extends E> type, Class<E> 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(TypeMapper.getType(clz));
|
|
}
|
|
|
|
return interfaceList;
|
|
}
|
|
|
|
protected Set<PropertyDefinition> retrieveListOfProperties(Class<?> clz) {
|
|
Set<PropertyDefinition> properties = new TreeSet<>();
|
|
for (Method m : clz.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, clz.getSimpleName());
|
|
}
|
|
|
|
}
|
|
if(properties.size()==0) {
|
|
properties = null;
|
|
}
|
|
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 Type getInstance(Class<? extends Element> clz) {
|
|
Type 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 (Type.class.isAssignableFrom(clz)) {
|
|
typeDefinition = new TypeImpl(clz);
|
|
return typeDefinition;
|
|
} else {
|
|
throw new RuntimeException("Serialization required");
|
|
}
|
|
} finally {
|
|
if (typeDefinition != null) {
|
|
logger.debug("{} : {} ", clz, typeDefinition);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected TypeImpl() {
|
|
}
|
|
|
|
|
|
|
|
protected TypeImpl(Class<? extends Element> clz) {
|
|
this.name = TypeMapper.getType(clz);
|
|
this.description = TypeMapper.getTypeDescription(clz);
|
|
this.version = TypeMapper.getTypeVersion(clz);
|
|
|
|
this.changelog = TypeMapper.getTypeChangelog(clz);
|
|
|
|
this.abstractType = false;
|
|
|
|
if (clz.isAnnotationPresent(Abstract.class)) {
|
|
this.abstractType = true;
|
|
}
|
|
|
|
if(clz.isAnnotationPresent(Final.class)) {
|
|
this.finalClass = true;
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public UUID getUUID() {
|
|
return uuid;
|
|
}
|
|
|
|
@Override
|
|
public void setUUID(UUID uuid) {
|
|
this.uuid = uuid;
|
|
}
|
|
|
|
@Override
|
|
public Metadata getMetadata() {
|
|
return metadata;
|
|
}
|
|
|
|
@Override
|
|
public void setMetadata(Metadata metadata) {
|
|
this.metadata = metadata;
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
@Override
|
|
public String getDescription() {
|
|
return description;
|
|
}
|
|
|
|
@Override
|
|
public Version getVersion() {
|
|
return version;
|
|
}
|
|
|
|
@JsonGetter(value = VERSION_PROPERTY)
|
|
public String getVersionAsString() {
|
|
return version.toString();
|
|
}
|
|
|
|
@JsonSetter(value = VERSION_PROPERTY)
|
|
public void setVersion(String version) {
|
|
this.version = new Version(version);
|
|
}
|
|
|
|
@Override
|
|
public Map<Version, String> getChangelog() {
|
|
return changelog;
|
|
}
|
|
|
|
@JsonGetter(value = CHANGELOG_PROPERTY)
|
|
@JsonInclude(Include.NON_NULL)
|
|
public Map<String, String> getChangelogWithVersionAsString() {
|
|
if(this.changelog==null) {
|
|
return DEFAULT_CHANGELOG_MAP_KEY_AS_STRING;
|
|
}
|
|
Map<String, String> map = new HashMap<>();
|
|
for (Version typeVersion : changelog.keySet()) {
|
|
map.put(typeVersion.toString(), changelog.get(typeVersion));
|
|
}
|
|
return map;
|
|
}
|
|
|
|
@JsonSetter(value=CHANGELOG_PROPERTY)
|
|
public void setChangelog(Map<String, String> changelog) {
|
|
if(changelog==null) {
|
|
this.changelog = DEFAULT_CHANGELOG_MAP;
|
|
return;
|
|
}
|
|
this.changelog = new HashMap<>();
|
|
for (String version : changelog.keySet()) {
|
|
this.changelog.put(new Version(version), changelog.get(version));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isAbstract() {
|
|
return abstractType;
|
|
}
|
|
|
|
@Override
|
|
public boolean isFinal() {
|
|
return finalClass;
|
|
}
|
|
|
|
@Override
|
|
public Set<String> getSuperClasses() {
|
|
return superClasses;
|
|
}
|
|
|
|
@JsonInclude(Include.NON_EMPTY)
|
|
public Set<PropertyDefinition> getProperties() {
|
|
return properties;
|
|
}
|
|
|
|
@Override
|
|
@JsonIgnore
|
|
public AccessType getAccessType() {
|
|
return null;
|
|
}
|
|
|
|
}
|