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

calculator.validation.Validator Maven / Gradle / Ivy

There is a newer version: 2.0.0-RC1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package calculator.validation;

import calculator.config.Config;
import calculator.engine.annotation.PublicApi;
import graphql.ExecutionInput;
import graphql.ParseAndValidate;
import graphql.ParseAndValidateResult;
import graphql.analysis.QueryTraverser;
import graphql.language.Document;
import graphql.language.OperationDefinition;
import graphql.language.VariableDefinition;
import graphql.parser.Parser;
import graphql.schema.GraphQLSchema;
import graphql.validation.ValidationError;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@PublicApi
public class Validator {

    public static ParseAndValidateResult validateQuery(String query, GraphQLSchema wrappedSchema, Config wrapperConfig) {

        ExecutionInput executionInput = ExecutionInput.newExecutionInput().query(query).build();
        ParseAndValidateResult origPVResult = ParseAndValidate.parseAndValidate(wrappedSchema, executionInput);
        if (origPVResult.isFailure()) {
            return origPVResult;
        }

        Document document = Parser.parse(query);
        QueryTraverser traverser = QueryTraverser.newQueryTraverser()
                .schema(wrappedSchema)
                .document(document)
                .variables(Collections.emptyMap()).build();

        BasicRule basicRule = new BasicRule(wrapperConfig.getScriptEvaluator());
        traverser.visitDepthFirst(basicRule);
        if (!basicRule.getErrors().isEmpty()) {
            return ParseAndValidateResult.newResult().validationErrors(basicRule.getErrors()).build();
        }


        OperationDefinition operationDefinition = (OperationDefinition) document.getDefinitions().get(0);
        List variableNames = operationDefinition.getVariableDefinitions().stream()
                .map(VariableDefinition::getName).collect(Collectors.toList());

        SourceRule nodeRule = new SourceRule(
                variableNames,
                wrapperConfig.getScriptEvaluator(),
                basicRule.getSourceWithAnnotatedField(),
                basicRule.getFieldWithTopTask(),
                basicRule.getSourceUsedByField(),
                basicRule.getFieldWithAncestorPath()
        );
        traverser.visitDepthFirst(nodeRule);
        // 不用在返回没有使用的节点,因为脏数据可能导致分析不够准确
        if (!nodeRule.getErrors().isEmpty()) {
            return ParseAndValidateResult.newResult().validationErrors(nodeRule.getErrors()).build();
        }

        // 是否有未使用的source节点
        if (!nodeRule.getUnusedSource().isEmpty()) {
            String errorMsg = String.format(" unused fetch source: %s.", nodeRule.getUnusedSource().toString());
            ValidationError error = ValidationError.newValidationError().description(errorMsg).build();
            return ParseAndValidateResult.newResult().validationErrors(Collections.singletonList(error)).build();
        }

        return ParseAndValidateResult.newResult().document(document).build();
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy