io.kroxylicious.proxy.config.model.Visitor Maven / Gradle / Ivy
package io.kroxylicious.proxy.config.model;
import java.util.Map.Entry;
import java.lang.Class;
import java.lang.FunctionalInterface;
import java.lang.Object;
import java.util.List;
import java.lang.String;
import java.lang.reflect.Method;
import java.lang.Boolean;
import java.util.function.Predicate;
@FunctionalInterface
public interface Visitor{
default Class getType() {
List args = Visitors.getTypeArguments(Visitor.class, getClass());
if (args == null || args.isEmpty()) {
return null;
}
return (Class) args.get(0);
}
void visit(T element);
default int order() {
return 0;
}
default void visit(List> path,T element) {
visit(element);
}
default Boolean canVisit(List> path,F target) {
if (target == null) {
return false;
}
if (getType() == null) {
return hasVisitMethodMatching(target);
} else if (!getType().isAssignableFrom(target.getClass())) {
return false;
}
try {
return getRequirement().test(path);
} catch (ClassCastException e) {
// This will happen if predicte does not match the Object.
// So, instead of using reflection to determine that, let's just catch the error
return false;
}
}
default Boolean hasVisitMethodMatching(F target) {
for (Method method : getClass().getMethods()) {
if (!method.getName().equals("visit") || method.getParameterTypes().length != 1) {
continue;
}
Class> visitorType = method.getParameterTypes()[0];
if (visitorType.isAssignableFrom(target.getClass())) {
return true;
} else {
return false;
}
}
return false;
}
default Predicate>> getRequirement() {
return p -> true;
}
default Predicate>> hasItem(Class type,Predicate predicate) {
Predicate>> result = l -> l.stream().map(Entry::getValue).filter(i -> type.isInstance(i))
.map(i -> type.cast(i)).anyMatch(predicate);
return result;
}
default Visitor addRequirement(Class type,Predicate
predicate) {
return addRequirement(predicate);
}
default Visitor addRequirement(Predicate predicate) {
return new DelegatingVisitor(getType(), this) {
@Override
public Predicate> getRequirement() {
return Visitor.this.getRequirement().and(predicate);
}
};
}
}