All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
graphql.util.Traverser Maven / Gradle / Ivy
package graphql.util;
import graphql.Internal;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import static graphql.Assert.assertNotNull;
import static graphql.Assert.assertShouldNeverHappen;
import static graphql.Assert.assertTrue;
import static graphql.util.TraversalControl.CONTINUE;
import static graphql.util.TraversalControl.QUIT;
@Internal
public class Traverser {
private final TraverserState traverserState;
private final Function super T, ? extends List> getChildren;
private final Map, Object> rootVars = new ConcurrentHashMap<>();
private final TraverserContext BARRIER = new SimpleTraverserContext<>(null);
private static final List CONTINUE_OR_QUIT = Arrays.asList(CONTINUE, QUIT);
private Traverser(TraverserState traverserState, Function super T, ? extends List> getChildren) {
this.traverserState = assertNotNull(traverserState);
this.getChildren = assertNotNull(getChildren);
}
public Traverser rootVars(Map, Object> rootVars) {
this.rootVars.putAll(assertNotNull(rootVars));
return this;
}
public Traverser rootVar(Class> key, Object value) {
rootVars.put(key, value);
return this;
}
public static Traverser depthFirst(Function super T, ? extends List> getChildren) {
return depthFirst(getChildren, null);
}
public static Traverser depthFirst(Function super T, ? extends List> getChildren, Object initialData) {
return new Traverser<>(TraverserState.newStackState(initialData), getChildren);
}
public static Traverser breadthFirst(Function super T, ? extends List> getChildren) {
return breadthFirst(getChildren, null);
}
public static Traverser breadthFirst(Function super T, ? extends List> getChildren, Object initialData) {
return new Traverser<>(TraverserState.newQueueState(initialData), getChildren);
}
public TraverserResult traverse(T root, TraverserVisitor super T> visitor) {
return traverse(Collections.singleton(root), visitor);
}
public TraverserResult traverse(Collection extends T> roots, TraverserVisitor super T> visitor) {
assertNotNull(roots);
assertNotNull(visitor);
traverserState.addNewContexts(roots, traverserState.newContext(null, null, rootVars));
TraverserContext currentContext = BARRIER;
traverseLoop:
while (!traverserState.isEmpty()) {
Object top = traverserState.pop();
if (top == TraverserState.Marker.END_LIST) {
// end-of-list marker, we are done recursing children,
// mark the current node as fully visited
TraverserContext contextForLeave = (TraverserContext) traverserState.pop();
currentContext = contextForLeave;
TraversalControl traversalControl = visitor.leave(contextForLeave);
assertNotNull(traversalControl, "result of leave must not be null");
assertTrue(CONTINUE_OR_QUIT.contains(traversalControl), "result can only return CONTINUE or QUIT");
switch (traversalControl) {
case QUIT:
break traverseLoop;
case CONTINUE:
continue;
default:
assertShouldNeverHappen();
}
}
currentContext = (TraverserContext) top;
if (currentContext.isVisited()) {
TraversalControl traversalControl = visitor.backRef(currentContext);
assertNotNull(traversalControl, "result of backRef must not be null");
assertTrue(CONTINUE_OR_QUIT.contains(traversalControl), "backRef can only return CONTINUE or QUIT");
if (traversalControl == QUIT) {
break traverseLoop;
}
} else {
TraversalControl traversalControl = visitor.enter(currentContext);
assertNotNull(traversalControl, "result of enter must not be null");
this.traverserState.addVisited((T) currentContext.thisNode());
switch (traversalControl) {
case QUIT:
break traverseLoop;
case ABORT:
continue;
case CONTINUE:
traverserState.pushAll(currentContext, getChildren);
continue;
default:
assertShouldNeverHappen();
}
}
}
TraverserResult traverserResult = new TraverserResult(currentContext.getResult());
return traverserResult;
}
}