All Downloads are FREE. Search and download functionalities are using the official Maven repository.

graphql.language.AstTransformer Maven / Gradle / Ivy

There is a newer version: 230521-nf-execution
Show newest version
package graphql.language;

import graphql.PublicApi;
import graphql.util.NodePosition;
import graphql.util.TraversalControl;
import graphql.util.Traverser;
import graphql.util.TraverserContext;
import graphql.util.TraverserVisitor;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;

import static graphql.Assert.assertNotNull;

/**
 * Allows for an easy way to "manipulate" the immutable Ast by changing specific nodes and getting back a new Ast
 * containing the changed nodes while everything else is the same.
 */
@PublicApi
public class AstTransformer {


    public Node transform(Node root, NodeVisitor nodeVisitor) {
        assertNotNull(root);
        assertNotNull(nodeVisitor);

        AstMultiZipper astMultiZipper = new AstMultiZipper(root, Collections.emptyList());

        Deque breadCrumbsStack = new ArrayDeque<>();
        TraverserVisitor nodeTraverserVisitor = new TraverserVisitor() {

            @Override
            public TraversalControl enter(TraverserContext context) {
                NodePosition generalNodePosition = context.getPosition();
                if (generalNodePosition != null) {
                    NodeLocation location = new NodeLocation(generalNodePosition.getName(), generalNodePosition.getIndex());
                    breadCrumbsStack.push(new AstBreadcrumb(context.getParentContext().thisNode(), location));
                }
                List breadcrumbs = new ArrayList<>(breadCrumbsStack);
                AstZipper astZipper = new AstZipper(context.thisNode(), breadcrumbs);
                context.setVar(AstZipper.class, astZipper);
                context.setVar(NodeTraverser.LeaveOrEnter.class, NodeTraverser.LeaveOrEnter.ENTER);
                return context.thisNode().accept(context, nodeVisitor);
            }

            @Override
            public TraversalControl leave(TraverserContext context) {
                if (!breadCrumbsStack.isEmpty()) {
                    breadCrumbsStack.pop();
                }
                return TraversalControl.CONTINUE;
            }

        };

        Traverser nodeTraverser = Traverser.depthFirstWithNamedChildren(node -> node.getNamedChildren().getChildren(), null, astMultiZipper);
        AstMultiZipper multiZipperResult = (AstMultiZipper) nodeTraverser.traverse(root, nodeTraverserVisitor).getAccumulatedResult();
        return multiZipperResult.toRootNode();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy