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

graphql.execution.directives.QueryDirectivesImpl Maven / Gradle / Ivy

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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import graphql.GraphQLContext;
import graphql.Internal;
import graphql.collect.ImmutableKit;
import graphql.execution.MergedField;
import graphql.language.Directive;
import graphql.language.Field;
import graphql.schema.GraphQLArgument;
import graphql.schema.GraphQLDirective;
import graphql.schema.GraphQLSchema;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import static graphql.collect.ImmutableKit.emptyList;

/**
 * These objects are ALWAYS in the context of a single MergedField
 *
 * Also note we compute these values lazily
 */
@Internal
public class QueryDirectivesImpl implements QueryDirectives {

    private final DirectivesResolver directivesResolver = new DirectivesResolver();
    private final MergedField mergedField;
    private final GraphQLSchema schema;
    private final Map variables;
    private final GraphQLContext graphQLContext;
    private final Locale locale;
    private volatile ImmutableMap> fieldDirectivesByField;
    private volatile ImmutableMap> fieldDirectivesByName;
    private volatile ImmutableMap> fieldAppliedDirectivesByField;
    private volatile ImmutableMap> fieldAppliedDirectivesByName;

    public QueryDirectivesImpl(MergedField mergedField, GraphQLSchema schema, Map variables, GraphQLContext graphQLContext, Locale locale) {
        this.mergedField = mergedField;
        this.schema = schema;
        this.variables = variables;
        this.graphQLContext = graphQLContext;
        this.locale = locale;
    }

    private void computeValuesLazily() {
        synchronized (this) {
            if (fieldDirectivesByField != null) {
                return;
            }

            final Map> byField = new LinkedHashMap<>();
            final Map> byFieldApplied = new LinkedHashMap<>();
            mergedField.getFields().forEach(field -> {
                List directives = field.getDirectives();
                ImmutableList resolvedDirectives = ImmutableList.copyOf(
                        directivesResolver
                                .resolveDirectives(directives, schema, variables, graphQLContext, locale)
                                .values()
                );
                byField.put(field, resolvedDirectives);
                // at some point we will only use applied
                byFieldApplied.put(field, ImmutableKit.map(resolvedDirectives, this::toAppliedDirective));
            });

            Map> byName = new LinkedHashMap<>();
            Map> byNameApplied = new LinkedHashMap<>();
            byField.forEach((field, directiveList) -> directiveList.forEach(directive -> {
                String name = directive.getName();
                byName.computeIfAbsent(name, k -> new ArrayList<>()).add(directive);
                // at some point we will only use applied
                byNameApplied.computeIfAbsent(name, k -> new ArrayList<>()).add(toAppliedDirective(directive));
            }));

            this.fieldDirectivesByName = ImmutableMap.copyOf(byName);
            this.fieldDirectivesByField = ImmutableMap.copyOf(byField);
            this.fieldAppliedDirectivesByName = ImmutableMap.copyOf(byNameApplied);
            this.fieldAppliedDirectivesByField = ImmutableMap.copyOf(byFieldApplied);
        }
    }

    private QueryAppliedDirective toAppliedDirective(GraphQLDirective directive) {
        QueryAppliedDirective.Builder builder = QueryAppliedDirective.newDirective();
        builder.name(directive.getName());
        for (GraphQLArgument argument : directive.getArguments()) {
            builder.argument(toAppliedArgument(argument));
        }
        return builder.build();
    }

    private QueryAppliedDirectiveArgument toAppliedArgument(GraphQLArgument argument) {
        return QueryAppliedDirectiveArgument.newArgument()
                .name(argument.getName())
                .type(argument.getType())
                .inputValueWithState(argument.getArgumentValue())
                .build();
    }


    @Override
    public Map> getImmediateDirectivesByField() {
        computeValuesLazily();
        return fieldDirectivesByField;
    }

    @Override
    public Map> getImmediateAppliedDirectivesByField() {
        computeValuesLazily();
        return fieldAppliedDirectivesByField;
    }

    @Override
    public Map> getImmediateDirectivesByName() {
        computeValuesLazily();
        return fieldDirectivesByName;
    }

    @Override
    public Map> getImmediateAppliedDirectivesByName() {
        computeValuesLazily();
        return fieldAppliedDirectivesByName;
    }

    @Override
    public List getImmediateDirective(String directiveName) {
        computeValuesLazily();
        return getImmediateDirectivesByName().getOrDefault(directiveName, emptyList());
    }

    @Override
    public List getImmediateAppliedDirective(String directiveName) {
        computeValuesLazily();
        return getImmediateAppliedDirectivesByName().getOrDefault(directiveName, emptyList());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy