graphql.execution.directives.QueryAppliedDirective Maven / Gradle / Ivy
package graphql.execution.directives;
import com.google.common.collect.ImmutableList;
import graphql.PublicApi;
import graphql.language.Directive;
import graphql.schema.GraphQLArgument;
import graphql.schema.GraphQLDirective;
import graphql.schema.GraphqlTypeBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import static graphql.Assert.assertNotNull;
import static graphql.Assert.assertValidName;
import static graphql.util.FpKit.getByName;
/**
* An applied directive represents the instance of a directive that is applied to a query element such as a field or fragment.
*
* Originally graphql-java re-used the {@link GraphQLDirective} and {@link GraphQLArgument}
* classes to do both purposes. This was a modelling mistake. New {@link QueryAppliedDirective} and {@link QueryAppliedDirectiveArgument}
* classes have been introduced to better model when a directive is applied to a query element,
* as opposed to its schema definition itself.
*
* See https://graphql.org/learn/queries/#directives for more details on the concept.
*/
@PublicApi
public class QueryAppliedDirective {
private final String name;
private final ImmutableList arguments;
private final Directive definition;
private QueryAppliedDirective(String name, Directive definition, Collection arguments) {
assertValidName(name);
assertNotNull(arguments, () -> "arguments can't be null");
this.name = name;
this.arguments = ImmutableList.copyOf(arguments);
this.definition = definition;
}
@NotNull
public String getName() {
return name;
}
@Nullable
public String getDescription() {
return null;
}
public List getArguments() {
return arguments;
}
@Nullable
public QueryAppliedDirectiveArgument getArgument(String name) {
for (QueryAppliedDirectiveArgument argument : arguments) {
if (argument.getName().equals(name)) {
return argument;
}
}
return null;
}
@Nullable
public Directive getDefinition() {
return definition;
}
@Override
public String toString() {
return new StringJoiner(", ", QueryAppliedDirective.class.getSimpleName() + "[", "]")
.add("name='" + name + "'")
.add("arguments=" + arguments)
.add("definition=" + definition)
.toString();
}
/**
* This helps you transform the current GraphQLDirective into another one by starting a builder with all
* the current values and allows you to transform it how you want.
*
* @param builderConsumer the consumer code that will be given a builder to transform
*
* @return a new field based on calling build on that builder
*/
public QueryAppliedDirective transform(Consumer builderConsumer) {
Builder builder = newDirective(this);
builderConsumer.accept(builder);
return builder.build();
}
public static Builder newDirective() {
return new Builder();
}
public static Builder newDirective(QueryAppliedDirective existing) {
return new Builder(existing);
}
public static class Builder extends GraphqlTypeBuilder {
private final Map arguments = new LinkedHashMap<>();
private Directive definition;
public Builder() {
}
public Builder(QueryAppliedDirective existing) {
this.name = existing.getName();
this.description = existing.getDescription();
this.arguments.putAll(getByName(existing.getArguments(), QueryAppliedDirectiveArgument::getName));
}
public Builder argument(QueryAppliedDirectiveArgument argument) {
assertNotNull(argument, () -> "argument must not be null");
arguments.put(argument.getName(), argument);
return this;
}
public Builder replaceArguments(List arguments) {
assertNotNull(arguments, () -> "arguments must not be null");
this.arguments.clear();
for (QueryAppliedDirectiveArgument argument : arguments) {
this.arguments.put(argument.getName(), argument);
}
return this;
}
/**
* Take an argument builder in a function definition and apply. Can be used in a jdk8 lambda
* e.g.:
*
* {@code
* argument(a -> a.name("argumentName"))
* }
*
*
* @param builderFunction a supplier for the builder impl
*
* @return this
*/
public Builder argument(UnaryOperator builderFunction) {
QueryAppliedDirectiveArgument.Builder builder = QueryAppliedDirectiveArgument.newArgument();
builder = builderFunction.apply(builder);
return argument(builder);
}
/**
* Same effect as the argument(GraphQLAppliedDirectiveArgument). Builder.build() is called
* from within
*
* @param builder an un-built/incomplete GraphQLAppliedDirectiveArgument
*
* @return this
*/
public Builder argument(QueryAppliedDirectiveArgument.Builder builder) {
return argument(builder.build());
}
/**
* This is used to clear all the arguments in the builder so far.
*
* @return the builder
*/
public Builder clearArguments() {
arguments.clear();
return this;
}
public Builder definition(Directive definition) {
this.definition = definition;
return this;
}
public QueryAppliedDirective build() {
return new QueryAppliedDirective(name, this.definition, arguments.values());
}
}
}