org.fiolino.common.analyzing.ClassWalker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons Show documentation
Show all versions of commons Show documentation
General structure to easily create dynamic logic via MethodHandles and others.
package org.fiolino.common.analyzing;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* Analyzes classes to find annotated elements (fields or methods).
*/
public class ClassWalker {
private final List> visitors = new ArrayList<>();
public static final class ClassVisitor {
private final Predicate super Class>> classTest;
private final List> fieldActions = new ArrayList<>();
private final List> methodActions = new ArrayList<>();
private ClassVisitor(Predicate super Class>> classTest) {
this.classTest = classTest;
}
private ClassVisitor() {
this(c -> true);
}
private boolean startClass(Class> type) {
return classTest.test(type);
}
private void visitField(Field f) {
for (Consumer super Field> c : fieldActions) {
c.accept(f);
}
}
private void visitMethod(Method m) {
for (Consumer super Method> c : methodActions) {
c.accept(m);
}
}
public ClassVisitor onField(Consumer super Field> action) {
fieldActions.add(action);
return this;
}
public ClassVisitor onMethod(Consumer super Method> action) {
methodActions.add(action);
return this;
}
}
private ClassVisitor addVisitor(ClassVisitor visitor) {
visitors.add(visitor);
return visitor;
}
public ClassVisitor forClasses(Predicate super Class>> classTest) {
return addVisitor(new ClassVisitor(classTest));
}
public ClassVisitor onField(Consumer super Field> action) {
return addVisitor(new ClassVisitor()).onField(action);
}
public ClassVisitor onMethod(Consumer super Method> action) {
return addVisitor(new ClassVisitor()).onMethod(action);
}
public void analyze(Class> model) throws E {
for (ClassVisitor v : visitors) {
if (v.startClass(model)) {
analyzeUsing(model, v);
}
}
}
private void analyzeUsing(Class> modelClass, ClassVisitor visitor) throws E {
Class> supertype = modelClass.getSuperclass();
if (supertype != null && supertype != Object.class) {
analyzeUsing(supertype, visitor);
}
for (Field f : modelClass.getDeclaredFields()) {
visitor.visitField(f);
}
for (Method m : modelClass.getDeclaredMethods()) {
visitor.visitMethod(m);
}
}
@Override
public String toString() {
return getClass().getSimpleName() + " with " +
visitors.size() + " visitors.";
}
}