Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/main/java/graphql/execution/ExecutionStrategy.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
import graphql.execution.instrumentation.parameters.InstrumentationFieldParameters;
import graphql.introspection.Introspection;
import graphql.language.Directive;
import graphql.language.Field;
import graphql.schema.CoercingSerializeException;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.DataFetchingFieldSelectionSet;
import graphql.schema.DataFetchingFieldSelectionSetImpl;
import graphql.schema.GraphQLDirective;
import graphql.schema.GraphQLEnumType;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLInterfaceType;
Expand All @@ -37,6 +39,7 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand All @@ -45,6 +48,7 @@
import java.util.OptionalLong;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.stream.Collectors;

import static graphql.execution.Async.exceptionallyCompletedFuture;
import static graphql.execution.ExecutionTypeInfo.newTypeInfo;
Expand Down Expand Up @@ -228,6 +232,14 @@ protected CompletableFuture<Object> fetchField(ExecutionContext executionContext

GraphqlFieldVisibility fieldVisibility = executionContext.getGraphQLSchema().getFieldVisibility();
Map<String, Object> argumentValues = valuesResolver.getArgumentValues(fieldVisibility, fieldDef.getArguments(), field.getArguments(), executionContext.getVariables());
Map<String, Map<String, Object>> directiveArgumentValues = field.getDirectives().stream()
.collect(Collectors.toMap(Directive::getName, dir -> {
GraphQLDirective directive = executionContext.getGraphQLSchema().getDirective(dir.getName());
if (directive == null) {
return Collections.emptyMap();
}
return valuesResolver.getArgumentValues(fieldVisibility, directive.getArguments(), dir.getArguments(), executionContext.getVariables());
}));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make put this into a DirectivesUtil helper class so its simpler to read and easier to test

Map<String, Map<String, Object>> directiveArgumentValues = DirectivesUtil.readDirectiveValues(field)

See graphql.DirectivesUtil

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it would maybe be better to create a new type to represent this or are you ok with Map<String, Map<String, Object>>?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a Map<String,graphql.schema.GraphQLDirective>

That is a field has a map of named graphql.schema.GraphQLDirective objects. From that you can get the arguments and the values to this arguments.

We have other code somewhere (off hand) that helps create that

GraphQLOutputType fieldType = fieldDef.getType();
DataFetchingFieldSelectionSet fieldCollector = DataFetchingFieldSelectionSetImpl.newCollector(executionContext, fieldType, parameters.getField());
Expand All @@ -236,6 +248,7 @@ protected CompletableFuture<Object> fetchField(ExecutionContext executionContext
DataFetchingEnvironment environment = newDataFetchingEnvironment(executionContext)
.source(parameters.getSource())
.arguments(argumentValues)
.directiveArguments(directiveArgumentValues)
.fieldDefinition(fieldDef)
.fields(parameters.getField())
.fieldType(fieldType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
import graphql.execution.instrumentation.parameters.InstrumentationExecutionStrategyParameters;
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
import graphql.execution.instrumentation.parameters.InstrumentationFieldParameters;
import graphql.language.Directive;
import graphql.language.Field;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.DataFetchingFieldSelectionSet;
import graphql.schema.DataFetchingFieldSelectionSetImpl;
import graphql.schema.GraphQLDirective;
import graphql.schema.GraphQLEnumType;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLInterfaceType;
Expand All @@ -49,6 +51,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static graphql.execution.ExecutionTypeInfo.newTypeInfo;
Expand Down Expand Up @@ -235,19 +238,30 @@ private CompletableFuture<FetchedValues> fetchData(ExecutionContext executionCon
GraphQLFieldDefinition fieldDef) {
GraphQLObjectType parentType = node.getType();
List<Field> fields = node.getFields().get(fieldName);
Field field = fields.get(0);
List<MapOrList> parentResults = node.getParentResults();

GraphqlFieldVisibility fieldVisibility = executionContext.getGraphQLSchema().getFieldVisibility();
Map<String, Object> argumentValues = valuesResolver.getArgumentValues(
fieldVisibility,
fieldDef.getArguments(), fields.get(0).getArguments(), executionContext.getVariables());

Map<String, Map<String, Object>> directiveArgumentValues = field.getDirectives().stream()
.collect(Collectors.toMap(Directive::getName, dir -> {
GraphQLDirective directive = executionContext.getGraphQLSchema().getDirective(dir.getName());
if (directive == null) {
return Collections.emptyMap();
}
return valuesResolver.getArgumentValues(fieldVisibility, directive.getArguments(), dir.getArguments(), executionContext.getVariables());
}));

GraphQLOutputType fieldType = fieldDef.getType();
DataFetchingFieldSelectionSet fieldCollector = DataFetchingFieldSelectionSetImpl.newCollector(executionContext, fieldType, fields);

DataFetchingEnvironment environment = newDataFetchingEnvironment(executionContext)
.source(node.getSources())
.arguments(argumentValues)
.directiveArguments(directiveArgumentValues)
.fieldDefinition(fieldDef)
.fields(fields)
.fieldType(fieldDef.getType())
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/graphql/schema/DataFetchingEnvironment.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import java.util.List;
import java.util.Map;
import java.util.Optional;


/**
Expand Down Expand Up @@ -55,6 +56,12 @@ public interface DataFetchingEnvironment {
*/
<T> T getArgument(String name);

Map<String, Map<String, Object>> getDirectiveArguments();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JavaDoc please


Map<String, Object> getDirectiveArguments(String directiveName);

<T> Optional<T> getDirectiveArgument(String directiveName, String argumentName);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As much as Optional is a better pattern, its mixing styles on this class. We already use null via getArgument() (because it predates Java 8) so I think we should stay consistent to the other methods in this interface

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference between this and getArgument(argumentName) is that in this case even the directiveName might be wrong, before we even check the argumentName. But I get your point., it does look weird.


/**
* Returns a context argument that is set up when the {@link graphql.GraphQL#execute} method
* is invoked.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static DataFetchingEnvironmentBuilder newDataFetchingEnvironment(DataFetc
return new DataFetchingEnvironmentBuilder()
.source(environment.getSource())
.arguments(environment.getArguments())
.directiveArguments(environment.getDirectiveArguments())
.context(environment.getContext())
.root(environment.getRoot())
.fields(environment.getFields())
Expand Down Expand Up @@ -57,6 +58,7 @@ public static DataFetchingEnvironmentBuilder newDataFetchingEnvironment(Executio

private Object source;
private Map<String, Object> arguments = Collections.emptyMap();
private Map<String, Map<String, Object>> directiveArguments = Collections.emptyMap();
private Object context;
private Object root;
private GraphQLFieldDefinition fieldDefinition;
Expand All @@ -80,6 +82,11 @@ public DataFetchingEnvironmentBuilder arguments(Map<String, Object> arguments) {
return this;
}

public DataFetchingEnvironmentBuilder directiveArguments(Map<String, Map<String, Object>> directiveArguments) {
this.directiveArguments = directiveArguments;
return this;
}

public DataFetchingEnvironmentBuilder context(Object context) {
this.context = context;
return this;
Expand Down Expand Up @@ -141,7 +148,7 @@ public DataFetchingEnvironmentBuilder executionContext(ExecutionContext executio
}

public DataFetchingEnvironment build() {
return new DataFetchingEnvironmentImpl(source, arguments, context, root,
return new DataFetchingEnvironmentImpl(source, arguments, directiveArguments, context, root,
fieldDefinition, fields, fieldType, parentType, graphQLSchema, fragmentsByName, executionId, selectionSet,
typeInfo,
executionContext);
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/graphql/schema/DataFetchingEnvironmentImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static graphql.Assert.assertNotNull;
import static java.util.Collections.unmodifiableMap;
Expand All @@ -21,6 +22,7 @@
public class DataFetchingEnvironmentImpl implements DataFetchingEnvironment {
private final Object source;
private final Map<String, Object> arguments;
private final Map<String, Map<String, Object>> directiveArguments;
private final Object context;
private final Object root;
private final GraphQLFieldDefinition fieldDefinition;
Expand All @@ -36,6 +38,7 @@ public class DataFetchingEnvironmentImpl implements DataFetchingEnvironment {

public DataFetchingEnvironmentImpl(Object source,
Map<String, Object> arguments,
Map<String, Map<String, Object>> directiveArguments,
Object context,
Object root,
GraphQLFieldDefinition fieldDefinition,
Expand All @@ -50,6 +53,7 @@ public DataFetchingEnvironmentImpl(Object source,
ExecutionContext executionContext) {
this.source = source;
this.arguments = arguments == null ? Collections.emptyMap() : arguments;
this.directiveArguments = directiveArguments == null ? Collections.emptyMap() : Collections.unmodifiableMap(directiveArguments);
this.fragmentsByName = fragmentsByName == null ? Collections.emptyMap() : fragmentsByName;
this.context = context;
this.root = root;
Expand Down Expand Up @@ -84,6 +88,22 @@ public <T> T getArgument(String name) {
return (T) arguments.get(name);
}

@Override
public Map<String, Map<String, Object>> getDirectiveArguments() {
return directiveArguments;
}

@Override
public Map<String, Object> getDirectiveArguments(String directiveName) {
return directiveArguments.get(directiveName);
}

@Override
public <T> Optional<T> getDirectiveArgument(String directiveName, String argumentName) {
return Optional.ofNullable(directiveArguments.get(directiveName))
.map(arg -> (T) arg.get(argumentName));
}

@Override
public <T> T getContext() {
return (T) context;
Expand Down