io.kroxylicious.proxy.config.model.Visitable Maven / Gradle / Ivy
package io.kroxylicious.proxy.config.model;
import java.util.AbstractMap;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.ArrayList;
import java.lang.Class;
import java.lang.Object;
import java.util.List;
import java.lang.String;
import java.util.Collections;
public interface Visitable{
default T accept(Class type,Visitor visitor) {
return accept(Collections.emptyList(), new Visitor() {
@Override
public Class getType() {
return type;
}
@Override
public void visit(List> path, V element) {
visitor.visit(path, element);
}
@Override
public void visit(V element) {
visitor.visit(element);
}
});
}
default T accept(io.kroxylicious.proxy.config.model.Visitor... visitors) {
return accept(Collections.emptyList(), visitors);
}
default T accept(List> path,io.kroxylicious.proxy.config.model.Visitor... visitors) {
return accept(path, "", visitors);
}
default T accept(List> path,String currentKey,io.kroxylicious.proxy.config.model.Visitor... visitors) {
List sortedVisitor = new ArrayList<>();
for (Visitor visitor : visitors) {
visitor = VisitorListener.wrap(visitor);
if (!visitor.canVisit(path, this)) {
continue;
}
sortedVisitor.add(visitor);
}
sortedVisitor.sort((l, r) -> ((Visitor) r).order() - ((Visitor) l).order());
for (Visitor visitor : sortedVisitor) {
visitor.visit(path, this);
}
List> copyOfPath = path != null ? new ArrayList(path) : new ArrayList<>();
copyOfPath.add(new AbstractMap.SimpleEntry<>(currentKey, this));
getVisitableMap().ifPresent(vm -> {
for (Entry entry : vm.entrySet()) {
List> newPath = Collections.unmodifiableList(copyOfPath);
// Copy visitables to avoid ConcurrentModificationException when Visitors add/remove Visitables
for (Visitable visitable : new ArrayList<>((List>) entry.getValue())) {
for (Visitor visitor : visitors) {
if (visitor.getType() != null && visitor.getType().isAssignableFrom(visitable.getClass())) {
visitable.accept(newPath, entry.getKey(), visitor);
}
}
for (Visitor visitor : visitors) {
if (visitor.getType() == null || !visitor.getType().isAssignableFrom(visitable.getClass())) {
visitable.accept(newPath, entry.getKey(), visitor);
}
}
}
}
});
return (T) this;
}
default T getTarget(Visitable visitable) {
return (T) visitable;
}
default Optional getVisitableMap() {
return Optional.empty();
}
}