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

152 lines
4.2 KiB
Java
Raw Normal View History

/**
*
*/
2023-02-03 14:39:25 +01:00
package org.gcube.informationsystem.discovery;
import java.lang.reflect.Method;
2019-10-30 09:57:14 +01:00
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
2023-02-06 18:52:08 +01:00
import java.util.ArrayList;
2023-02-03 19:13:04 +01:00
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
2019-10-30 09:57:14 +01:00
import java.util.Map;
import java.util.Set;
import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.base.reference.properties.PropertyElement;
import org.gcube.informationsystem.types.annotations.ISProperty;
2023-02-03 14:45:15 +01:00
import org.gcube.informationsystem.utils.ReflectionUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
2023-02-03 14:39:25 +01:00
public class Discovery<E extends Element> {
2019-10-24 19:50:43 +02:00
2023-02-03 14:39:25 +01:00
public static Logger logger = LoggerFactory.getLogger(Discovery.class);
2019-10-24 19:50:43 +02:00
2020-02-03 10:51:29 +01:00
protected final Class<E> root;
2023-02-03 19:13:04 +01:00
protected final Set<Package> packages;
2023-02-06 18:52:08 +01:00
protected final List<Class<E>> discoveredElement;
protected final List<DiscoveredElementAction<Element>> discoveredElementActions;
2023-02-03 17:53:42 +01:00
protected boolean discovered;
2019-10-24 19:50:43 +02:00
2023-02-03 17:53:42 +01:00
public Discovery(Class<E> root) throws Exception {
this.root = root;
2023-02-03 19:13:04 +01:00
this.packages = new HashSet<>();
2023-02-03 17:53:42 +01:00
this.discovered = false;
2023-02-06 18:52:08 +01:00
this.discoveredElement = new ArrayList<>();
this.discoveredElementActions = new ArrayList<>();
add(root);
}
2019-10-24 19:50:43 +02:00
2023-02-06 18:52:08 +01:00
public List<Class<E>> getDiscoveredElement() {
2023-02-03 17:53:42 +01:00
return discoveredElement;
}
2023-02-03 19:13:04 +01:00
@SuppressWarnings("unchecked")
public synchronized void addDiscoveredElementActions(DiscoveredElementAction<Element> discoveredElementAction) throws Exception {
2023-02-03 17:53:42 +01:00
discoveredElementActions.add(discoveredElementAction);
if(discovered) {
2023-02-03 19:13:04 +01:00
for(Class<E> clz : discoveredElement) {
discoveredElementAction.analizeElement((Class<Element>) clz);
2023-02-03 17:53:42 +01:00
}
}
}
public void addPackage(Package p) {
packages.add(p);
}
2019-10-24 19:50:43 +02:00
2023-02-03 19:13:04 +01:00
public void addPackages(Collection<Package> packages) {
for(Package p : packages) {
addPackage(p);
}
}
2023-02-06 16:35:30 +01:00
2023-02-03 19:13:47 +01:00
@SuppressWarnings("unchecked")
2023-02-03 19:13:04 +01:00
protected void add(Class<E> clz) throws Exception {
2023-02-03 17:53:42 +01:00
if(!discoveredElement.contains(clz)) {
discoveredElement.add(clz);
2023-02-03 19:13:47 +01:00
for(DiscoveredElementAction<Element> discoveredElementAction : discoveredElementActions) {
discoveredElementAction.analizeElement((Class<Element>) clz);
2023-02-03 17:53:42 +01:00
}
2019-11-08 12:29:05 +01:00
logger.info("+ Added {}.", clz);
}
}
2019-10-24 19:50:43 +02:00
2023-02-03 19:13:04 +01:00
protected void analizeElement(Class<E> clz) throws Exception {
logger.trace("Analizyng {}", clz);
2019-10-24 19:50:43 +02:00
if(!clz.isInterface()) {
2023-02-03 17:53:42 +01:00
logger.trace("- Discarding {} because 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
2023-02-03 17:53:42 +01:00
if(discoveredElement.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;
2023-02-03 15:57:31 +01:00
analizeElement(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;
2023-02-03 15:57:31 +01:00
analizeElement(type);
2019-10-30 09:57:14 +01:00
}
}
} else if(root.isAssignableFrom(m.getReturnType())) {
@SuppressWarnings("unchecked")
2023-02-03 17:53:42 +01:00
Class<E> eClz = (Class<E>) m.getReturnType();
analizeElement(eClz);
}
}
2019-10-24 19:50:43 +02:00
}
}
add(clz);
}
2019-10-24 19:50:43 +02:00
2023-02-03 17:53:42 +01:00
public synchronized void discover() throws Exception {
this.discovered = false;
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")
2023-02-03 17:53:42 +01:00
Class<E> eClz = (Class<E>) clz;
analizeElement(eClz);
}
}
2023-02-03 17:53:42 +01:00
this.discovered = true;
}
2019-10-24 19:50:43 +02:00
}