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

150 lines
4.2 KiB
Java

/**
*
*/
package org.gcube.informationsystem.utils.discovery;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import org.gcube.informationsystem.base.reference.ISManageable;
import org.gcube.informationsystem.model.reference.entities.Entity;
import org.gcube.informationsystem.model.reference.properties.Property;
import org.gcube.informationsystem.model.reference.relations.Relation;
import org.gcube.informationsystem.types.annotations.ISProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class ISMDiscovery<ISM extends ISManageable> {
private static Logger logger = LoggerFactory.getLogger(ISMDiscovery.class);
protected final Class<ISM> root;
protected final List<Package> packages;
protected final List<Class<ISM>> discovered;
public List<Class<ISM>> getDiscovered() {
return discovered;
}
public ISMDiscovery(Class<ISM> root) {
this.root = root;
this.packages = new ArrayList<>();
addPackage(root.getPackage());
this.discovered = new ArrayList<>();
add(root);
}
public void addPackage(Package p) {
packages.add(p);
}
protected void add(Class<ISM> clz) {
discovered.add(clz);
logger.trace("+ Added {}.", clz);
}
protected void analizeISM(Class<ISM> clz) {
logger.trace("Analizyng {}", clz);
if (!clz.isInterface()) {
logger.trace("- Discarding {} that is not an interface", clz);
return;
}
if (!root.isAssignableFrom(clz)) {
logger.trace("- Discarding {} because is not a {}", clz, root.getSimpleName());
return;
}
if (discovered.contains(clz)) {
logger.trace("- Discarding {} because was already managed", clz);
return;
}
Class<?>[] interfaces = clz.getInterfaces();
for (Class<?> interfaceClass : interfaces) {
@SuppressWarnings("unchecked")
Class<ISM> parent = (Class<ISM>) interfaceClass;
analizeISM(parent);
}
if (root == Property.class) {
for (Method m : clz.getDeclaredMethods()) {
m.setAccessible(true);
if (m.isAnnotationPresent(ISProperty.class)) {
if (root.isAssignableFrom(m.getReturnType())) {
@SuppressWarnings("unchecked")
Class<ISM> type = (Class<ISM>) m.getReturnType();
analizeISM(type);
}
}
}
}
add(clz);
}
public void discover() throws Exception {
for (Package p : packages) {
List<Class<?>> classes = ReflectionUtility.getClassesForPackage(p);
for (Class<?> clz : classes) {
@SuppressWarnings("unchecked")
Class<ISM> ism = (Class<ISM>) clz;
analizeISM(ism);
}
}
}
public static void manageISM(SchemaAction schemaAction, List<Package> packages) throws Exception {
if (Objects.nonNull(packages) && packages.size() > 0) {
manageISM(schemaAction, packages.stream().toArray(Package[]::new));
} else {
manageISM(schemaAction);
}
}
@SuppressWarnings("unchecked")
public static void manageISM(SchemaAction schemaAction, Package... packages) throws Exception {
ISMDiscovery<Property> propertyDiscovery = new ISMDiscovery<>(Property.class);
if (Objects.nonNull(packages))
Arrays.stream(packages).forEach(p -> propertyDiscovery.addPackage(p));
propertyDiscovery.discover();
for (Class<Property> property : propertyDiscovery.getDiscovered()) {
logger.trace("Going to manage : {}", property);
schemaAction.managePropertyClass(property);
}
ISMDiscovery<Entity> entityDiscovery = new ISMDiscovery<>(Entity.class);
if (Objects.nonNull(packages))
Arrays.stream(packages).forEach(p -> entityDiscovery.addPackage(p));
entityDiscovery.discover();
for (Class<Entity> entity : entityDiscovery.getDiscovered()) {
logger.trace("Going to manage : {}", entity);
schemaAction.manageEntityClass(entity);
}
@SuppressWarnings("rawtypes")
ISMDiscovery<Relation> relationDiscovery = new ISMDiscovery<>(Relation.class);
if (Objects.nonNull(packages))
Arrays.stream(packages).forEach(p -> relationDiscovery.addPackage(p));
relationDiscovery.discover();
for (@SuppressWarnings("rawtypes")
Class<Relation> relation : relationDiscovery.getDiscovered()) {
logger.trace("Going to manage : {}", relation);
schemaAction.manageRelationClass(relation);
}
}
}