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

graphql.introspection.IntrospectionQueryBuilder Maven / Gradle / Ivy

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

import com.google.common.collect.ImmutableList;
import graphql.PublicApi;
import graphql.language.AstPrinter;
import graphql.language.BooleanValue;
import graphql.language.Document;
import graphql.language.OperationDefinition;
import graphql.language.SelectionSet;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import static graphql.language.Argument.newArgument;
import static graphql.language.Document.newDocument;
import static graphql.language.Field.newField;
import static graphql.language.FragmentDefinition.newFragmentDefinition;
import static graphql.language.FragmentSpread.newFragmentSpread;
import static graphql.language.OperationDefinition.newOperationDefinition;
import static graphql.language.SelectionSet.newSelectionSet;
import static graphql.language.TypeName.newTypeName;
import static java.util.stream.Collectors.toList;

/**
 * {@link IntrospectionQueryBuilder} allows you to build introspection queries controlled
 * by the options you specify
 */
@PublicApi
public class IntrospectionQueryBuilder {
    public static class Options {

        private final boolean descriptions;

        private final boolean specifiedByUrl;
        private final boolean isOneOf;

        private final boolean directiveIsRepeatable;

        private final boolean schemaDescription;

        private final boolean inputValueDeprecation;

        private final int typeRefFragmentDepth;

        private Options(boolean descriptions,
                        boolean specifiedByUrl,
                        boolean isOneOf,
                        boolean directiveIsRepeatable,
                        boolean schemaDescription,
                        boolean inputValueDeprecation,
                        int typeRefFragmentDepth) {
            this.descriptions = descriptions;
            this.specifiedByUrl = specifiedByUrl;
            this.isOneOf = isOneOf;
            this.directiveIsRepeatable = directiveIsRepeatable;
            this.schemaDescription = schemaDescription;
            this.inputValueDeprecation = inputValueDeprecation;
            this.typeRefFragmentDepth = typeRefFragmentDepth;
        }

        public boolean isDescriptions() {
            return descriptions;
        }

        public boolean isSpecifiedByUrl() {
            return specifiedByUrl;
        }

        public boolean isOneOf() {
            return isOneOf;
        }

        public boolean isDirectiveIsRepeatable() {
            return directiveIsRepeatable;
        }

        public boolean isSchemaDescription() {
            return schemaDescription;
        }

        public boolean isInputValueDeprecation() {
            return inputValueDeprecation;
        }

        public int getTypeRefFragmentDepth() {
            return typeRefFragmentDepth;
        }

        public static Options defaultOptions() {
            return new Options(
                    true,
                    false,
                    true,
                    true,
                    false,
                    true,
                    7
            );
        }

        /**
         * This will allow you to include description fields in the introspection query
         *
         * @param flag whether to include them
         *
         * @return options
         */
        public Options descriptions(boolean flag) {
            return new Options(flag,
                    this.specifiedByUrl,
                    this.isOneOf,
                    this.directiveIsRepeatable,
                    this.schemaDescription,
                    this.inputValueDeprecation,
                    this.typeRefFragmentDepth);
        }

        /**
         * This will allow you to include the `specifiedByURL` field for scalar types in the introspection query.
         *
         * @param flag whether to include them
         *
         * @return options
         */
        public Options specifiedByUrl(boolean flag) {
            return new Options(this.descriptions,
                    flag,
                    this.isOneOf,
                    this.directiveIsRepeatable,
                    this.schemaDescription,
                    this.inputValueDeprecation,
                    this.typeRefFragmentDepth);
        }

        /**
         * This will allow you to include the `isOneOf` field for one of input types in the introspection query.
         * 

* This option is only needed while `@oneOf` input types are new and in time the reason for this * option will go away. * * @param flag whether to include them * * @return options */ public Options isOneOf(boolean flag) { return new Options(this.descriptions, this.specifiedByUrl, flag, this.directiveIsRepeatable, this.schemaDescription, this.inputValueDeprecation, this.typeRefFragmentDepth); } /** * This will allow you to include the `isRepeatable` field for directives in the introspection query. * * @param flag whether to include them * * @return options */ public Options directiveIsRepeatable(boolean flag) { return new Options(this.descriptions, this.specifiedByUrl, this.isOneOf, flag, this.schemaDescription, this.inputValueDeprecation, this.typeRefFragmentDepth); } /** * This will allow you to include the `description` field for the schema type in the introspection query. * * @param flag whether to include them * * @return options */ public Options schemaDescription(boolean flag) { return new Options(this.descriptions, this.specifiedByUrl, this.isOneOf, this.directiveIsRepeatable, flag, this.inputValueDeprecation, this.typeRefFragmentDepth); } /** * This will allow you to include deprecated input fields in the introspection query. * * @param flag whether to include them * * @return options */ public Options inputValueDeprecation(boolean flag) { return new Options(this.descriptions, this.specifiedByUrl, this.isOneOf, this.directiveIsRepeatable, this.schemaDescription, flag, this.typeRefFragmentDepth); } /** * This will allow you to control the depth of the `TypeRef` fragment in the introspection query. * * @param typeRefFragmentDepth the depth of the `TypeRef` fragment. * * @return options */ public Options typeRefFragmentDepth(int typeRefFragmentDepth) { return new Options(this.descriptions, this.specifiedByUrl, this.isOneOf, this.directiveIsRepeatable, this.schemaDescription, this.inputValueDeprecation, typeRefFragmentDepth); } } @SafeVarargs private static List filter(T... args) { return Arrays.stream(args).filter(Objects::nonNull).collect(toList()); } /** * This will build an introspection query in {@link Document} form * * @param options the options to use * * @return an introspection query in document form */ public static Document buildDocument(Options options) { SelectionSet schemaSelectionSet = newSelectionSet().selections(filter( options.schemaDescription ? newField("description").build() : null, newField("queryType", newSelectionSet() .selection(newField("name").build()) .build() ) .build(), newField("mutationType", newSelectionSet() .selection(newField("name").build()) .build() ) .build(), newField("subscriptionType", newSelectionSet() .selection(newField("name").build()) .build() ) .build(), newField("types", newSelectionSet() .selection(newFragmentSpread("FullType").build()) .build() ) .build(), newField("directives", newSelectionSet().selections(filter( newField("name").build(), options.descriptions ? newField("description").build() : null, newField("locations").build(), newField("args") .arguments(filter( options.inputValueDeprecation ? newArgument("includeDeprecated", BooleanValue.of(true)).build() : null )) .selectionSet(newSelectionSet() .selection(newFragmentSpread("InputValue").build()) .build() ) .build(), options.directiveIsRepeatable ? newField("isRepeatable").build() : null )) .build() ) .build() ) ).build(); SelectionSet fullTypeSelectionSet = newSelectionSet().selections(filter( newField("kind").build(), newField("name").build(), options.descriptions ? newField("description").build() : null, options.specifiedByUrl ? newField("specifiedByURL").build() : null, options.isOneOf ? newField("isOneOf").build() : null, newField("fields") .arguments(ImmutableList.of( newArgument("includeDeprecated", BooleanValue.of(true)).build() )) .selectionSet(newSelectionSet().selections(filter( newField("name").build(), options.descriptions ? newField("description").build() : null, newField("args") .arguments(filter( options.inputValueDeprecation ? newArgument("includeDeprecated", BooleanValue.of(true)).build() : null )) .selectionSet(newSelectionSet() .selection(newFragmentSpread("InputValue").build()) .build() ) .build(), newField("type", newSelectionSet() .selection(newFragmentSpread("TypeRef").build()) .build() ) .build(), newField("isDeprecated").build(), newField("deprecationReason").build() )).build() ) .build(), newField("inputFields") .arguments(filter( options.inputValueDeprecation ? newArgument("includeDeprecated", BooleanValue.of(true)).build() : null )) .selectionSet(newSelectionSet() .selection(newFragmentSpread("InputValue").build()) .build() ) .build(), newField("interfaces", newSelectionSet() .selection(newFragmentSpread("TypeRef").build()) .build() ) .build(), newField("enumValues") .arguments(ImmutableList.of( newArgument("includeDeprecated", BooleanValue.of(true)).build() )) .selectionSet(newSelectionSet().selections(filter( newField("name").build(), options.descriptions ? newField("description").build() : null, newField("isDeprecated").build(), newField("deprecationReason").build() )) .build() ) .build(), newField("possibleTypes", newSelectionSet() .selection(newFragmentSpread("TypeRef").build()) .build() ) .build() )).build(); SelectionSet inputValueSelectionSet = newSelectionSet().selections(filter( newField("name").build(), options.descriptions ? newField("description").build() : null, newField("type", newSelectionSet() .selection(newFragmentSpread("TypeRef").build()) .build() ) .build(), newField("defaultValue").build(), options.inputValueDeprecation ? newField("isDeprecated").build() : null, options.inputValueDeprecation ? newField("deprecationReason").build() : null )).build(); SelectionSet typeRefSelectionSet = newSelectionSet().selections(filter( newField("kind").build(), newField("name").build() )).build(); for (int i = options.typeRefFragmentDepth; i > 0; i -= 1) { typeRefSelectionSet = newSelectionSet().selections(filter( newField("kind").build(), newField("name").build(), newField("ofType", typeRefSelectionSet).build() )).build(); } return newDocument() .definition(newOperationDefinition() .operation(OperationDefinition.Operation.QUERY) .name("IntrospectionQuery") .selectionSet(newSelectionSet() .selection(newField("__schema", schemaSelectionSet).build()) .build() ) .build() ) .definition(newFragmentDefinition() .name("FullType") .typeCondition(newTypeName().name("__Type").build()) .selectionSet(fullTypeSelectionSet) .build() ) .definition(newFragmentDefinition() .name("InputValue") .typeCondition(newTypeName().name("__InputValue").build()) .selectionSet(inputValueSelectionSet) .build() ) .definition(newFragmentDefinition() .name("TypeRef") .typeCondition(newTypeName().name("__Type").build()) .selectionSet(typeRefSelectionSet) .build() ) .build(); } /** * This will build an introspection query in {@link String} form based on the options you provide * * @param options the options to use * * @return an introspection query in string form */ public static String build(Options options) { return AstPrinter.printAst(buildDocument(options)); } /** * This will build a default introspection query in {@link String} form * * @return an introspection query in string form */ public static String build() { return build(Options.defaultOptions()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy