information-system-model/src/main/java/org/gcube/informationsystem/utils/discovery/ElementSpecilizationDiscove...

183 lines
5.5 KiB
Java
Raw Normal View History

/**
*
*/
package org.gcube.informationsystem.utils.discovery;
import java.lang.reflect.Method;
2019-10-30 09:57:14 +01:00
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
2019-10-30 09:57:14 +01:00
import java.util.Map;
import java.util.Objects;
2019-10-30 09:57:14 +01:00
import java.util.Set;
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.types.annotations.ISProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
2020-02-03 10:51:29 +01:00
public class ElementSpecilizationDiscovery<E extends Element> {
2019-10-24 19:50:43 +02:00
2020-02-03 10:51:29 +01:00
private static Logger logger = LoggerFactory.getLogger(ElementSpecilizationDiscovery.class);
2019-10-24 19:50:43 +02:00
2020-02-03 10:51:29 +01:00
protected final Class<E> root;
protected final List<Package> packages;
2020-02-03 10:51:29 +01:00
protected final List<Class<? extends E>> discovered;
protected final boolean includeRootPackage;
2019-10-24 19:50:43 +02:00
2020-02-03 10:51:29 +01:00
public List<Class<? extends E>> getDiscovered() {
return discovered;
}
2019-10-24 19:50:43 +02:00
2020-02-03 10:51:29 +01:00
public ElementSpecilizationDiscovery(Class<E> root) {
this(root, true);
}
public ElementSpecilizationDiscovery(Class<E> root, boolean includeRootPackage) {
this.root = root;
this.packages = new ArrayList<>();
this.includeRootPackage = includeRootPackage;
if(includeRootPackage) {
addPackage(root.getPackage());
}
this.discovered = new ArrayList<>();
add(root);
}
2019-10-24 19:50:43 +02:00
public void addPackage(Package p) {
if(!includeRootPackage && p==root.getPackage()) {
return;
}
packages.add(p);
}
2019-10-24 19:50:43 +02:00
2020-02-03 10:51:29 +01:00
protected void add(Class<? extends E> clz) {
2019-11-08 12:29:05 +01:00
if(!discovered.contains(clz)) {
discovered.add(clz);
logger.info("+ Added {}.", clz);
}
}
2019-10-24 19:50:43 +02:00
2020-02-03 10:51:29 +01:00
protected void analizeISM(Class<? extends E> clz) {
logger.trace("Analizyng {}", clz);
2019-10-24 19:50:43 +02:00
if(!clz.isInterface()) {
logger.trace("- Discarding {} that is not an interface", clz);
return;
}
2019-10-24 19:50:43 +02:00
if(!root.isAssignableFrom(clz)) {
logger.trace("- Discarding {} because is not a {}", clz, root.getSimpleName());
return;
}
2019-10-24 19:50:43 +02:00
if(discovered.contains(clz)) {
logger.trace("- Discarding {} because was already managed", clz);
return;
}
2019-10-24 19:50:43 +02:00
Class<?>[] interfaces = clz.getInterfaces();
2019-10-24 19:50:43 +02:00
for(Class<?> interfaceClass : interfaces) {
@SuppressWarnings("unchecked")
2020-02-03 10:51:29 +01:00
Class<E> parent = (Class<E>) interfaceClass;
analizeISM(parent);
}
2019-10-24 19:50:43 +02:00
if(root == PropertyElement.class) {
2019-10-24 19:50:43 +02:00
for(Method m : clz.getDeclaredMethods()) {
m.setAccessible(true);
2019-10-24 19:50:43 +02:00
if(m.isAnnotationPresent(ISProperty.class)) {
2019-10-30 09:57:14 +01:00
if(Map.class.isAssignableFrom(m.getReturnType()) || Set.class.isAssignableFrom(m.getReturnType())
|| List.class.isAssignableFrom(m.getReturnType())) {
Type[] typeArguments = ((ParameterizedType) m.getGenericReturnType()).getActualTypeArguments();
for(Type t : typeArguments) {
@SuppressWarnings("unchecked")
Class<? extends PropertyElement> tClass = (Class<? extends PropertyElement>) t;
2019-10-30 09:57:14 +01:00
if(root.isAssignableFrom(tClass)) {
@SuppressWarnings("unchecked")
2020-02-03 10:51:29 +01:00
Class<E> type = (Class<E>) tClass;
2019-10-30 09:57:14 +01:00
analizeISM(type);
}
}
} else if(root.isAssignableFrom(m.getReturnType())) {
@SuppressWarnings("unchecked")
2020-02-03 10:51:29 +01:00
Class<E> type = (Class<E>) m.getReturnType();
analizeISM(type);
}
}
2019-10-24 19:50:43 +02:00
}
}
add(clz);
}
2019-10-24 19:50:43 +02:00
public void discover() throws Exception {
2019-10-24 19:50:43 +02:00
for(Package p : packages) {
List<Class<?>> classes = ReflectionUtility.getClassesForPackage(p);
2019-10-24 19:50:43 +02:00
for(Class<?> clz : classes) {
@SuppressWarnings("unchecked")
2020-02-03 10:51:29 +01:00
Class<E> ism = (Class<E>) clz;
analizeISM(ism);
}
}
2019-10-24 19:50:43 +02:00
}
2019-10-24 19:50:43 +02:00
public static void manageISM(SchemaAction schemaAction, List<Package> packages) throws Exception {
2019-10-24 19:50:43 +02:00
if(Objects.nonNull(packages) && packages.size() > 0) {
manageISM(schemaAction, packages.stream().toArray(Package[]::new));
} else {
manageISM(schemaAction);
}
}
2019-10-24 19:50:43 +02:00
@SuppressWarnings("unchecked")
public static void manageISM(SchemaAction schemaAction, Package... packages) throws Exception {
2020-02-03 10:51:29 +01:00
ElementSpecilizationDiscovery<PropertyElement> propertyDiscovery = new ElementSpecilizationDiscovery<>(PropertyElement.class);
if(Objects.nonNull(packages)) {
Arrays.stream(packages).forEach(p -> propertyDiscovery.addPackage(p));
}
propertyDiscovery.discover();
for(Class<? extends PropertyElement> property : propertyDiscovery.getDiscovered()) {
logger.trace("Going to manage : {}", property);
schemaAction.managePropertyClass(property);
}
2019-10-24 19:50:43 +02:00
2020-02-03 10:51:29 +01:00
ElementSpecilizationDiscovery<EntityElement> entityDiscovery = new ElementSpecilizationDiscovery<>(EntityElement.class);
if(Objects.nonNull(packages)) {
Arrays.stream(packages).forEach(p -> entityDiscovery.addPackage(p));
}
entityDiscovery.discover();
2019-10-24 19:50:43 +02:00
for(Class<? extends EntityElement> entity : entityDiscovery.getDiscovered()) {
logger.trace("Going to manage : {}", entity);
schemaAction.manageEntityClass(entity);
}
2019-10-24 19:50:43 +02:00
@SuppressWarnings("rawtypes")
2020-02-03 10:51:29 +01:00
ElementSpecilizationDiscovery<RelationElement> relationDiscovery = new ElementSpecilizationDiscovery<RelationElement>(RelationElement.class);
2019-10-24 19:50:43 +02:00
if(Objects.nonNull(packages))
Arrays.stream(packages).forEach(p -> relationDiscovery.addPackage(p));
relationDiscovery.discover();
2019-10-24 19:50:43 +02:00
for(@SuppressWarnings("rawtypes")
Class<? extends RelationElement> relation : relationDiscovery.getDiscovered()) {
logger.trace("Going to manage : {}", relation);
schemaAction.manageRelationClass(relation);
}
}
2019-10-24 19:50:43 +02:00
}