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

graphql.execution.nextgen.result.ResultNodesUtil Maven / Gradle / Ivy

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

import graphql.Assert;
import graphql.ExecutionResult;
import graphql.ExecutionResultImpl;
import graphql.GraphQLError;
import graphql.Internal;
import graphql.execution.ExecutionStepInfo;
import graphql.execution.NonNullableFieldWasNullError;
import graphql.execution.NonNullableFieldWasNullException;
import graphql.util.NodeLocation;
import graphql.util.NodeMultiZipper;
import graphql.util.NodeZipper;
import graphql.util.TraversalControl;
import graphql.util.TraverserContext;
import graphql.util.TraverserVisitorStub;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static graphql.collect.ImmutableKit.map;
import static graphql.execution.nextgen.result.ResultNodeAdapter.RESULT_NODE_ADAPTER;
import static java.util.Collections.emptyList;
import static java.util.Collections.singleton;

/**
 * @deprecated Jan 2022 - We have decided to deprecate the NextGen engine, and it will be removed in a future release.
 */
@Deprecated
@Internal
public class ResultNodesUtil {

    public static ExecutionResult toExecutionResult(RootExecutionResultNode root) {
        ExecutionResultData executionResultData = toDataImpl(root);
        return ExecutionResultImpl.newExecutionResult()
                .data(executionResultData.data)
                .errors(executionResultData.errors)
                .build();
    }

    private static class ExecutionResultData {
        Object data;
        List errors;


        public ExecutionResultData(Object data, List errors) {
            this.data = data;
            this.errors = errors;
        }
    }


    private static ExecutionResultData data(Object data, ExecutionResultNode executionResultNode) {
        List allErrors = new ArrayList<>();
        allErrors.addAll(executionResultNode.getResolvedValue().getErrors());
        allErrors.addAll(executionResultNode.getErrors());
        return new ExecutionResultData(data, allErrors);
    }

    private static ExecutionResultData data(Object data, List errors) {
        return new ExecutionResultData(data, errors);
    }

    private static ExecutionResultData data(Object data, NonNullableFieldWasNullException exception) {
        return new ExecutionResultData(data, Arrays.asList(new NonNullableFieldWasNullError(exception)));
    }

    private static ExecutionResultData toDataImpl(ExecutionResultNode root) {
        if (root instanceof LeafExecutionResultNode) {
            return root.getResolvedValue().isNullValue() ? data(null, root) : data(((LeafExecutionResultNode) root).getValue(), root);
        }
        if (root instanceof ListExecutionResultNode) {
            Optional childNonNullableException = root.getChildNonNullableException();
            if (childNonNullableException.isPresent()) {
                return data(null, childNonNullableException.get());
            }

            List errors = new ArrayList<>();
            List data = new ArrayList<>();
            for (ExecutionResultNode child : root.getChildren()) {
                ExecutionResultData erd = toDataImpl(child);
                data.add(erd.data);
                if (!erd.errors.isEmpty()) {
                    errors.addAll(erd.errors);
                }
            }
            if (!root.getErrors().isEmpty()) {
                errors.addAll(root.getErrors());
            }
            return data(data, errors);
        }

        if (root instanceof UnresolvedObjectResultNode) {
            ExecutionStepInfo executionStepInfo = root.getExecutionStepInfo();
            return data("Not resolved : " + executionStepInfo.getPath() + " with field " + executionStepInfo.getField(), emptyList());
        }
        if (root instanceof ObjectExecutionResultNode) {
            Optional childrenNonNullableException = root.getChildNonNullableException();
            if (childrenNonNullableException.isPresent()) {
                return data(null, childrenNonNullableException.get());
            }
            Map resultMap = new LinkedHashMap<>();
            List errors = new ArrayList<>();
            root.getChildren().forEach(child -> {
                ExecutionResultData executionResultData = toDataImpl(child);
                resultMap.put(child.getMergedField().getResultKey(), executionResultData.data);
                errors.addAll(executionResultData.errors);
            });
            errors.addAll(root.getErrors());
            return data(resultMap, errors);
        }
        return Assert.assertShouldNeverHappen("An unexpected root type %s", root.getClass());
    }


    public static Optional getFirstNonNullableException(Collection collection) {
        return collection.stream()
                .filter(executionResultNode -> executionResultNode.getNonNullableFieldWasNullException() != null)
                .map(ExecutionResultNode::getNonNullableFieldWasNullException)
                .findFirst();
    }

    public static NonNullableFieldWasNullException newNullableException(ExecutionStepInfo executionStepInfo, List children) {
        return newNullableException(executionStepInfo, map(children, NamedResultNode::getNode));
    }

    public static Map namedNodesToMap(List namedResultNodes) {
        Map result = new LinkedHashMap<>();
        for (NamedResultNode namedResultNode : namedResultNodes) {
            result.put(namedResultNode.getName(), namedResultNode.getNode());
        }
        return result;
    }

    public static NonNullableFieldWasNullException newNullableException(ExecutionStepInfo executionStepInfo, Collection children) {
        // can only happen for the root node
        if (executionStepInfo == null) {
            return null;
        }
        Assert.assertNotNull(children);
        boolean listIsNonNull = executionStepInfo.isNonNullType();
        if (listIsNonNull) {
            Optional firstNonNullableException = getFirstNonNullableException(children);
            if (firstNonNullableException.isPresent()) {
                return new NonNullableFieldWasNullException(firstNonNullableException.get());
            }
        }
        return null;
    }

    public static List> getUnresolvedNodes(Collection roots) {
        List> result = new ArrayList<>();

        ResultNodeTraverser traverser = ResultNodeTraverser.depthFirst();
        traverser.traverse(new TraverserVisitorStub() {
            @Override
            public TraversalControl enter(TraverserContext context) {
                if (context.thisNode() instanceof UnresolvedObjectResultNode) {
                    result.add(new NodeZipper<>(context.thisNode(), context.getBreadcrumbs(), RESULT_NODE_ADAPTER));
                }
                return TraversalControl.CONTINUE;
            }

        }, roots);
        return result;
    }

    public static NodeMultiZipper getUnresolvedNodes(ExecutionResultNode root) {
        List> unresolvedNodes = getUnresolvedNodes(singleton(root));
        return new NodeMultiZipper<>(root, unresolvedNodes, RESULT_NODE_ADAPTER);
    }


    public static NodeLocation key(String name) {
        return new NodeLocation(name, 0);
    }

    public static NodeLocation index(int index) {
        return new NodeLocation(null, index);
    }

}