graphql.schema.SchemaTraverser Maven / Gradle / Ivy
package graphql.schema;
import graphql.PublicApi;
import graphql.collect.ImmutableKit;
import graphql.util.TraversalControl;
import graphql.util.Traverser;
import graphql.util.TraverserContext;
import graphql.util.TraverserResult;
import graphql.util.TraverserVisitor;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import static graphql.util.TraversalControl.CONTINUE;
@PublicApi
public class SchemaTraverser {
private final Function super GraphQLSchemaElement, ? extends List> getChildren;
public SchemaTraverser(Function super GraphQLSchemaElement, ? extends List> getChildren) {
this.getChildren = getChildren;
}
public SchemaTraverser() {
this(GraphQLSchemaElement::getChildren);
}
/**
* This will visit all of the schema elements in the specified schema and invokes the visitor.
*
* @param typeVisitor a list of visitors to use
* @param schema the schema to visit
*
* @return a traversal result
*/
public TraverserResult depthFirstFullSchema(GraphQLTypeVisitor typeVisitor, GraphQLSchema schema) {
return depthFirstFullSchema(Collections.singletonList(typeVisitor), schema, ImmutableKit.emptyMap());
}
/**
* This will visit all of the schema elements in the specified schema, invoking each visitor in turn.
*
* @param typeVisitors a list of visitors to use
* @param schema the schema to visit
* @param rootVars this sets up variables to be made available to the {@link TraverserContext}. This can be empty but not null
*
* @return a traversal result
*/
public TraverserResult depthFirstFullSchema(List typeVisitors, GraphQLSchema schema, Map, Object> rootVars) {
Set roots = new LinkedHashSet<>();
roots.add(schema.getQueryType());
if (schema.isSupportingMutations()) {
roots.add(schema.getMutationType());
}
if (schema.isSupportingSubscriptions()) {
roots.add(schema.getSubscriptionType());
}
roots.addAll(schema.getAdditionalTypes());
roots.addAll(schema.getDirectives());
roots.addAll(schema.getSchemaDirectives());
roots.addAll(schema.getSchemaAppliedDirectives());
roots.add(schema.getIntrospectionSchemaType());
TraverserDelegateListVisitor traverserDelegateListVisitor = new TraverserDelegateListVisitor(typeVisitors);
Traverser traverser = initTraverser().rootVars(rootVars).rootVar(GraphQLSchema.class, schema);
return traverser.traverse(roots, traverserDelegateListVisitor);
}
public TraverserResult depthFirst(GraphQLTypeVisitor graphQLTypeVisitor, GraphQLSchemaElement root) {
return depthFirst(graphQLTypeVisitor, Collections.singletonList(root));
}
public TraverserResult depthFirst(final GraphQLTypeVisitor graphQLTypeVisitor, Collection extends GraphQLSchemaElement> roots) {
return depthFirst(initTraverser(), new TraverserDelegateVisitor(graphQLTypeVisitor), roots);
}
public TraverserResult depthFirst(final Traverser traverser,
final TraverserDelegateVisitor traverserDelegateVisitor,
Collection extends GraphQLSchemaElement> roots) {
return doTraverse(traverser, roots, traverserDelegateVisitor);
}
private Traverser initTraverser() {
return Traverser.depthFirst(getChildren);
}
private TraverserResult doTraverse(Traverser traverser,
Collection extends GraphQLSchemaElement> roots,
TraverserDelegateVisitor traverserDelegateVisitor) {
return traverser.traverse(roots, traverserDelegateVisitor);
}
private static class TraverserDelegateVisitor implements TraverserVisitor {
private final GraphQLTypeVisitor delegate;
TraverserDelegateVisitor(GraphQLTypeVisitor delegate) {
this.delegate = delegate;
}
@Override
public TraversalControl enter(TraverserContext context) {
return context.thisNode().accept(context, delegate);
}
@Override
public TraversalControl leave(TraverserContext context) {
return CONTINUE;
}
@Override
public TraversalControl backRef(TraverserContext context) {
return delegate.visitBackRef(context);
}
}
private static class TraverserDelegateListVisitor implements TraverserVisitor {
private final List typeVisitors;
TraverserDelegateListVisitor(List typeVisitors) {
this.typeVisitors = typeVisitors;
}
@Override
public TraversalControl enter(TraverserContext context) {
for (GraphQLTypeVisitor graphQLTypeVisitor : typeVisitors) {
TraversalControl control = context.thisNode().accept(context, graphQLTypeVisitor);
if (control != CONTINUE) {
return control;
}
}
return CONTINUE;
}
@Override
public TraversalControl leave(TraverserContext context) {
return CONTINUE;
}
@Override
public TraversalControl backRef(TraverserContext context) {
for (GraphQLTypeVisitor graphQLTypeVisitor : typeVisitors) {
graphQLTypeVisitor.visitBackRef(context);
}
return CONTINUE;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy