graphql.execution.directives.QueryDirectivesImpl Maven / Gradle / Ivy
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 graphql.util.FpKit;
import graphql.util.LockKit;
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 final LockKit.ComputedOnce computedOnce = new LockKit.ComputedOnce();
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() {
computedOnce.runOnce(() -> {
final Map> byField = new LinkedHashMap<>();
final Map> byFieldApplied = new LinkedHashMap<>();
mergedField.getFields().forEach(field -> {
List directives = field.getDirectives();
ImmutableList resolvedDirectives = ImmutableList.copyOf(FpKit.flatList(
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());
}
}