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

312 lines
8.5 KiB
Java
Raw Normal View History

2019-10-24 11:57:21 +02:00
package org.gcube.informationsystem.types.impl;
import java.lang.reflect.Method;
2019-11-04 18:06:46 +01:00
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.TypeVariable;
2020-12-11 17:28:56 +01:00
import java.util.HashMap;
import java.util.HashSet;
2023-04-27 16:30:10 +02:00
import java.util.List;
2020-12-11 17:28:56 +01:00
import java.util.Map;
import java.util.Set;
2023-01-20 16:46:22 +01:00
import java.util.TreeSet;
2023-04-18 17:51:23 +02:00
import java.util.UUID;
import org.gcube.com.fasterxml.jackson.annotation.JsonGetter;
import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore;
2020-07-07 17:04:25 +02:00
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;
2023-04-18 17:51:23 +02:00
import org.gcube.informationsystem.model.reference.properties.Metadata;
2020-02-04 09:30:19 +01:00
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;
2020-02-03 10:51:29 +01:00
import org.gcube.informationsystem.types.reference.Type;
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
import org.gcube.informationsystem.utils.TypeUtility;
2021-10-21 10:11:45 +02:00
import org.gcube.informationsystem.utils.Version;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
2020-02-03 10:51:29 +01:00
public class TypeImpl implements Type {
2020-02-03 10:51:29 +01:00
private static Logger logger = LoggerFactory.getLogger(TypeImpl.class);
2019-10-24 11:26:49 +02:00
/**
2020-02-03 10:51:29 +01:00
* Generated Serial version UID
2019-10-24 11:26:49 +02:00
*/
2020-02-03 10:51:29 +01:00
private static final long serialVersionUID = -4333954207969059451L;
2021-10-21 10:11:45 +02:00
public static final Map<Version, String> DEFAULT_CHANGELOG_MAP;
private static final Map<String, String> DEFAULT_CHANGELOG_MAP_KEY_AS_STRING;
2020-12-11 17:28:56 +01:00
static {
DEFAULT_CHANGELOG_MAP = new HashMap<>();
2021-10-21 10:11:45 +02:00
DEFAULT_CHANGELOG_MAP.put(new Version(Version.MINIMAL_VERSION_STRING), Version.MINIMAL_VERSION_DESCRIPTION);
DEFAULT_CHANGELOG_MAP_KEY_AS_STRING = new HashMap<>();
2021-10-21 10:11:45 +02:00
DEFAULT_CHANGELOG_MAP_KEY_AS_STRING.put(Version.MINIMAL_VERSION_STRING, Version.MINIMAL_VERSION_DESCRIPTION);
2020-12-11 17:28:56 +01:00
}
2023-04-18 17:51:23 +02:00
protected UUID uuid;
protected Metadata metadata;
protected List<String> supertypes;
protected String expectedtype;
2023-04-27 16:30:10 +02:00
protected String name;
protected String description;
2021-10-21 10:11:45 +02:00
protected Version version;
@JsonProperty(value = CHANGELOG_PROPERTY, required = false)
@JsonInclude(Include.NON_NULL)
2021-10-21 10:11:45 +02:00
protected Map<Version, String> changelog;
@JsonProperty(value = ABSTRACT_PROPERTY)
protected boolean abstractType;
@JsonProperty(value = FINAL_PROPERTY)
protected boolean finalClass;
2023-04-27 11:14:35 +02:00
protected Set<String> typeSuperTypes;
2020-01-23 17:14:44 +01:00
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;
2020-02-04 09:30:19 +01:00
interfaceList.add(TypeMapper.getType(clz));
}
return interfaceList;
}
protected Set<PropertyDefinition> retrieveListOfProperties(Class<?> clz) {
2023-01-20 16:46:22 +01:00
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) {
2019-11-04 18:06:46 +01:00
ParameterizedType parameterizedType = (ParameterizedType) t;
return (Class<?>) parameterizedType.getRawType();
}
return (Class<?>) t;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
2020-02-03 10:51:29 +01:00
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)) {
2020-02-03 10:51:29 +01:00
typeDefinition = new TypeImpl(clz);
return typeDefinition;
} else {
throw new RuntimeException("Serialization required");
}
} finally {
if (typeDefinition != null) {
logger.debug("{} : {} ", clz, typeDefinition);
}
2019-10-24 11:26:49 +02:00
}
}
protected TypeImpl() {
}
2020-02-03 10:51:29 +01:00
protected TypeImpl(Class<? extends Element> clz) {
2020-02-04 09:30:19 +01:00
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;
}
}
2023-04-18 17:51:23 +02:00
@Override
2023-04-28 11:33:29 +02:00
public UUID getID() {
2023-04-18 17:51:23 +02:00
return uuid;
}
2020-02-03 10:51:29 +01:00
@Override
2023-04-28 11:33:29 +02:00
public void setID(UUID uuid) {
2023-04-18 17:51:23 +02:00
this.uuid = uuid;
}
@Override
public Metadata getMetadata() {
return metadata;
2020-02-03 10:51:29 +01:00
}
2020-02-03 10:51:29 +01:00
@Override
2023-04-18 17:51:23 +02:00
public void setMetadata(Metadata metadata) {
this.metadata = metadata;
2020-02-03 10:51:29 +01:00
}
@Override
public String getName() {
return name;
}
2019-10-24 11:26:49 +02:00
@Override
public String getDescription() {
return description;
}
2020-12-11 09:47:14 +01:00
@Override
2021-10-21 10:11:45 +02:00
public Version getVersion() {
2020-12-11 09:47:14 +01:00
return version;
}
@JsonGetter(value = VERSION_PROPERTY)
2021-01-07 11:16:40 +01:00
public String getVersionAsString() {
return version.toString();
}
@JsonSetter(value = VERSION_PROPERTY)
2021-01-07 11:16:40 +01:00
public void setVersion(String version) {
2021-10-21 10:11:45 +02:00
this.version = new Version(version);
}
2020-12-11 17:28:56 +01:00
@Override
2021-10-21 10:11:45 +02:00
public Map<Version, String> getChangelog() {
2020-12-11 17:28:56 +01:00
return changelog;
}
@JsonGetter(value = CHANGELOG_PROPERTY)
@JsonInclude(Include.NON_NULL)
2021-01-15 17:57:06 +01:00
public Map<String, String> getChangelogWithVersionAsString() {
if(this.changelog==null) {
return DEFAULT_CHANGELOG_MAP_KEY_AS_STRING;
}
Map<String, String> map = new HashMap<>();
2021-10-21 10:11:45 +02:00
for (Version typeVersion : changelog.keySet()) {
2020-12-11 17:28:56 +01:00
map.put(typeVersion.toString(), changelog.get(typeVersion));
}
return map;
}
@JsonSetter(value=CHANGELOG_PROPERTY)
2020-12-11 17:28:56 +01:00
public void setChangelog(Map<String, String> changelog) {
if(changelog==null) {
this.changelog = DEFAULT_CHANGELOG_MAP;
return;
}
2020-12-11 17:28:56 +01:00
this.changelog = new HashMap<>();
for (String version : changelog.keySet()) {
2021-10-21 10:11:45 +02:00
this.changelog.put(new Version(version), changelog.get(version));
2020-12-11 17:28:56 +01:00
}
}
2019-10-24 11:26:49 +02:00
@Override
public boolean isAbstract() {
return abstractType;
}
@Override
public boolean isFinal() {
return finalClass;
}
2019-10-24 11:26:49 +02:00
@Override
2023-04-27 11:14:35 +02:00
public Set<String> getTypeSuperTypes() {
return typeSuperTypes;
}
2020-02-03 10:51:29 +01:00
@JsonInclude(Include.NON_EMPTY)
2020-01-23 17:14:44 +01:00
public Set<PropertyDefinition> getProperties() {
return properties;
}
@Override
@JsonIgnore
public AccessType getAccessType() {
return null;
}
@Override
public String getTypeName() {
return TypeUtility.getTypeName(this.getClass());
}
2020-12-11 09:47:14 +01:00
2023-04-27 16:30:10 +02:00
@Override
public List<String> getSupertypes() {
return this.supertypes;
}
@Override
public String getExpectedtype() {
return this.expectedtype;
}
}