Skip to content

Commit 4510275

Browse files
committed
Adding extra data to type resolver
Merge branch '122TypeResolver' of git://github.com/kaqqao/graphql-java into kaqqao-122TypeResolver # Conflicts: # src/main/java/graphql/execution/ExecutionStrategy.java # src/test/groovy/graphql/RelaySchema.java # src/test/groovy/graphql/validation/SpecValidationSchema.java # src/test/groovy/graphql/validation/rules/Harness.java This addresses graphql-java#122 and graphql-java#205. We had clashing parameters in place. I fix this up and removed one set of them from the original PR
2 parents 7bd01a5 + 6e6f1dd commit 4510275

13 files changed

+324
-99
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package graphql;
2+
3+
import java.util.Map;
4+
5+
import graphql.language.Field;
6+
import graphql.schema.GraphQLSchema;
7+
import graphql.schema.GraphQLType;
8+
9+
public class TypeResolutionEnvironment {
10+
11+
private final Object object;
12+
private final Map<String, Object> arguments;
13+
private final Field field;
14+
private final GraphQLType fieldType;
15+
private final GraphQLSchema schema;
16+
17+
public TypeResolutionEnvironment(Object object, Map<String, Object> arguments, Field field, GraphQLType fieldType, GraphQLSchema schema) {
18+
this.object = object;
19+
this.arguments = arguments;
20+
this.field = field;
21+
this.fieldType = fieldType;
22+
this.schema = schema;
23+
}
24+
25+
public Object getObject() {
26+
return object;
27+
}
28+
29+
public Map<String, Object> getArguments() {
30+
return arguments;
31+
}
32+
33+
public Field getField() {
34+
return field;
35+
}
36+
37+
public GraphQLType getFieldType() {
38+
return fieldType;
39+
}
40+
41+
public GraphQLSchema getSchema() {
42+
return schema;
43+
}
44+
}

src/main/java/graphql/execution/ExecutionStrategy.java

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import graphql.ExecutionResult;
55
import graphql.ExecutionResultImpl;
66
import graphql.GraphQLException;
7+
import graphql.TypeResolutionEnvironment;
78
import graphql.execution.instrumentation.Instrumentation;
89
import graphql.execution.instrumentation.InstrumentationContext;
910
import graphql.execution.instrumentation.parameters.FieldFetchParameters;
@@ -132,19 +133,31 @@ protected ExecutionResult completeValue(ExecutionContext executionContext, Execu
132133

133134

134135
GraphQLObjectType resolvedType;
135-
if (fieldType instanceof GraphQLInterfaceType) {
136-
resolvedType = resolveType((GraphQLInterfaceType) fieldType, result);
137-
} else if (fieldType instanceof GraphQLUnionType) {
138-
resolvedType = resolveType((GraphQLUnionType) fieldType, result);
136+
if (params.getFieldType() instanceof GraphQLInterfaceType) {
137+
TypeResolutionParameters resolutionParams = TypeResolutionParameters.newParameters()
138+
.graphQLInterfaceType(params.getFieldType())
139+
.field(params.getFields().get(0))
140+
.value(params.getResult())
141+
.argumentValues(params.getArgumentValues())
142+
.schema(params.getExecutionContext().getGraphQLSchema()).build();
143+
resolvedType = resolveTypeForInterface(resolutionParams);
144+
} else if (params.getFieldType() instanceof GraphQLUnionType) {
145+
TypeResolutionParameters resolutionParams = TypeResolutionParameters.newParameters()
146+
.graphQLUnionType(params.getFieldType())
147+
.field(params.getFields().get(0))
148+
.value(params.getResult())
149+
.argumentValues(params.getArgumentValues())
150+
.schema(params.getExecutionContext().getGraphQLSchema()).build();
151+
resolvedType = resolveTypeForUnion(resolutionParams);
139152
} else {
140-
resolvedType = (GraphQLObjectType) fieldType;
153+
resolvedType = params.getFieldType();
141154
}
142155

143156
Map<String, List<Field>> subFields = new LinkedHashMap<>();
144157
List<String> visitedFragments = new ArrayList<>();
145-
for (Field field : fields) {
158+
for (Field field : params.getFields()) {
146159
if (field.getSelectionSet() == null) continue;
147-
fieldCollector.collectFields(executionContext, resolvedType, field.getSelectionSet(), visitedFragments, subFields);
160+
fieldCollector.collectFields(params.getExecutionContext(), resolvedType, field.getSelectionSet(), visitedFragments, subFields);
148161
}
149162

150163
ExecutionParameters newParameters = ExecutionParameters.newParameters()
@@ -165,18 +178,36 @@ private Iterable<Object> toIterable(Object result) {
165178
return (Iterable<Object>) result;
166179
}
167180

181+
/**
182+
* @deprecated Use {@link #resolveTypeForInterface(TypeResolutionParameters)}
183+
*/
184+
@Deprecated
168185
protected GraphQLObjectType resolveType(GraphQLInterfaceType graphQLInterfaceType, Object value) {
169-
GraphQLObjectType result = graphQLInterfaceType.getTypeResolver().getType(value);
186+
return resolveTypeForInterface(TypeResolutionParameters.newParameters().graphQLInterfaceType(graphQLInterfaceType).value(value).build());
187+
}
188+
189+
protected GraphQLObjectType resolveTypeForInterface(TypeResolutionParameters params) {
190+
TypeResolutionEnvironment env = new TypeResolutionEnvironment(params.getValue(), params.getArgumentValues(), params.getField(), params.getGraphQLInterfaceType(), params.getSchema());
191+
GraphQLObjectType result = params.getGraphQLInterfaceType().getTypeResolver().getType(env);
170192
if (result == null) {
171-
throw new GraphQLException("could not determine type");
193+
throw new GraphQLException("Could not determine the exact type of " + params.getGraphQLInterfaceType().getName());
172194
}
173195
return result;
174196
}
175197

198+
/**
199+
* @deprecated Use {@link #resolveTypeForUnion(TypeResolutionParameters)}
200+
*/
201+
@Deprecated
176202
protected GraphQLObjectType resolveType(GraphQLUnionType graphQLUnionType, Object value) {
177-
GraphQLObjectType result = graphQLUnionType.getTypeResolver().getType(value);
203+
return resolveTypeForUnion(TypeResolutionParameters.newParameters().graphQLUnionType(graphQLUnionType).value(value).build());
204+
}
205+
206+
protected GraphQLObjectType resolveTypeForUnion(TypeResolutionParameters params) {
207+
TypeResolutionEnvironment env = new TypeResolutionEnvironment(params.getValue(), params.getArgumentValues(), params.getField(), params.getGraphQLUnionType(), params.getSchema());
208+
GraphQLObjectType result = params.getGraphQLUnionType().getTypeResolver().getType(env);
178209
if (result == null) {
179-
throw new GraphQLException("could not determine type");
210+
throw new GraphQLException("Could not determine the exact type of " + params.getGraphQLUnionType().getName());
180211
}
181212
return result;
182213
}
@@ -226,10 +257,19 @@ protected GraphQLFieldDefinition getFieldDef(GraphQLSchema schema, GraphQLObject
226257

227258
GraphQLFieldDefinition fieldDefinition = parentType.getFieldDefinition(field.getName());
228259
if (fieldDefinition == null) {
229-
throw new GraphQLException("unknown field " + field.getName());
260+
throw new GraphQLException("Unknown field " + field.getName());
230261
}
231262
return fieldDefinition;
232263
}
233264

234-
265+
private ValueCompletionParameters createCompletionParams(ExecutionContext executionContext, GraphQLType fieldType,
266+
List<Field> fields, Object result, Map<String, Object> argumentValues) {
267+
return ValueCompletionParameters.newParameters()
268+
.executionContext(executionContext)
269+
.fieldType(fieldType)
270+
.fields(fields)
271+
.result(result)
272+
.argumentValues(argumentValues)
273+
.build();
274+
}
235275
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package graphql.execution;
2+
3+
import java.util.Map;
4+
5+
import graphql.language.Field;
6+
import graphql.schema.GraphQLInterfaceType;
7+
import graphql.schema.GraphQLSchema;
8+
import graphql.schema.GraphQLUnionType;
9+
10+
public class TypeResolutionParameters {
11+
12+
private final GraphQLInterfaceType graphQLInterfaceType;
13+
private final GraphQLUnionType graphQLUnionType;
14+
private final Field field;
15+
private final Object value;
16+
private final Map<String, Object> argumentValues;
17+
private final GraphQLSchema schema;
18+
19+
private TypeResolutionParameters(GraphQLInterfaceType graphQLInterfaceType, GraphQLUnionType graphQLUnionType,
20+
Field field, Object value, Map<String, Object> argumentValues, GraphQLSchema schema) {
21+
this.graphQLInterfaceType = graphQLInterfaceType;
22+
this.graphQLUnionType = graphQLUnionType;
23+
this.field = field;
24+
this.value = value;
25+
this.argumentValues = argumentValues;
26+
this.schema = schema;
27+
}
28+
29+
public GraphQLInterfaceType getGraphQLInterfaceType() {
30+
return graphQLInterfaceType;
31+
}
32+
33+
public GraphQLUnionType getGraphQLUnionType() {
34+
return graphQLUnionType;
35+
}
36+
37+
public Field getField() {
38+
return field;
39+
}
40+
41+
public Object getValue() {
42+
return value;
43+
}
44+
45+
public Map<String, Object> getArgumentValues() {
46+
return argumentValues;
47+
}
48+
49+
public GraphQLSchema getSchema() {
50+
return schema;
51+
}
52+
53+
public static Builder newParameters() {
54+
return new Builder();
55+
}
56+
57+
public static class Builder {
58+
59+
private Field field;
60+
private GraphQLInterfaceType graphQLInterfaceType;
61+
private GraphQLUnionType graphQLUnionType;
62+
private Object value;
63+
private Map<String, Object> argumentValues;
64+
private GraphQLSchema schema;
65+
66+
public Builder field(Field field) {
67+
this.field = field;
68+
return this;
69+
}
70+
71+
public Builder graphQLInterfaceType(GraphQLInterfaceType graphQLInterfaceType) {
72+
this.graphQLInterfaceType = graphQLInterfaceType;
73+
return this;
74+
}
75+
76+
public Builder graphQLUnionType(GraphQLUnionType graphQLUnionType) {
77+
this.graphQLUnionType = graphQLUnionType;
78+
return this;
79+
}
80+
81+
public Builder value(Object value) {
82+
this.value = value;
83+
return this;
84+
}
85+
86+
public Builder argumentValues(Map<String, Object> argumentValues) {
87+
this.argumentValues = argumentValues;
88+
return this;
89+
}
90+
91+
public Builder schema(GraphQLSchema schema) {
92+
this.schema = schema;
93+
return this;
94+
}
95+
96+
public TypeResolutionParameters build() {
97+
return new TypeResolutionParameters(graphQLInterfaceType, graphQLUnionType, field, value, argumentValues, schema);
98+
}
99+
}
100+
}

src/main/java/graphql/execution/batched/BatchedExecutionStrategy.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import graphql.execution.ExecutionContext;
77
import graphql.execution.ExecutionParameters;
88
import graphql.execution.ExecutionStrategy;
9+
import graphql.execution.TypeResolutionParameters;
910
import graphql.language.Field;
1011
import graphql.schema.*;
1112
import org.slf4j.Logger;
@@ -76,32 +77,34 @@ private List<GraphQLExecutionNode> resolveField(ExecutionContext executionContex
7677
}
7778
List<GraphQLExecutionNodeValue> values = fetchData(executionContext, parentType, nodeData, fields, fieldDef);
7879

79-
return completeValues(executionContext, parentType, values, fieldName, fields, fieldDef.getType());
80+
Map<String, Object> argumentValues = valuesResolver.getArgumentValues(
81+
fieldDef.getArguments(), fields.get(0).getArguments(), executionContext.getVariables());
82+
return completeValues(executionContext, parentType, values, fieldName, fields, fieldDef.getType(), argumentValues);
8083
}
8184

8285
/**
8386
* Updates parents and returns new Nodes.
8487
*/
8588
private List<GraphQLExecutionNode> completeValues(ExecutionContext executionContext, GraphQLObjectType parentType,
8689
List<GraphQLExecutionNodeValue> values, String fieldName, List<Field> fields,
87-
GraphQLOutputType outputType) {
90+
GraphQLOutputType outputType, Map<String, Object> argumentValues) {
8891

8992
GraphQLType fieldType = handleNonNullType(outputType, values, parentType, fields);
9093

9194
if (isPrimitive(fieldType)) {
9295
handlePrimitives(values, fieldName, fieldType);
9396
return Collections.emptyList();
9497
} else if (isObject(fieldType)) {
95-
return handleObject(executionContext, values, fieldName, fields, fieldType);
98+
return handleObject(executionContext, argumentValues, values, fieldName, fields, fieldType);
9699
} else if (isList(fieldType)) {
97-
return handleList(executionContext, values, fieldName, fields, parentType, (GraphQLList) fieldType);
100+
return handleList(executionContext, argumentValues, values, fieldName, fields, parentType, (GraphQLList) fieldType);
98101
} else {
99102
throw new IllegalArgumentException("Unrecognized type: " + fieldType);
100103
}
101104
}
102105

103106
@SuppressWarnings("unchecked")
104-
private List<GraphQLExecutionNode> handleList(ExecutionContext executionContext,
107+
private List<GraphQLExecutionNode> handleList(ExecutionContext executionContext, Map<String, Object> argumentValues,
105108
List<GraphQLExecutionNodeValue> values, String fieldName, List<Field> fields,
106109
GraphQLObjectType parentType, GraphQLList listType) {
107110

@@ -120,15 +123,15 @@ private List<GraphQLExecutionNode> handleList(ExecutionContext executionContext,
120123
}
121124

122125
GraphQLOutputType subType = (GraphQLOutputType) listType.getWrappedType();
123-
return completeValues(executionContext, parentType, flattenedNodeValues, fieldName, fields, subType);
126+
return completeValues(executionContext, parentType, flattenedNodeValues, fieldName, fields, subType, argumentValues);
124127

125128
}
126129

127130
@SuppressWarnings("UnnecessaryLocalVariable")
128-
private List<GraphQLExecutionNode> handleObject(ExecutionContext executionContext,
131+
private List<GraphQLExecutionNode> handleObject(ExecutionContext executionContext, Map<String, Object> argumentValues,
129132
List<GraphQLExecutionNodeValue> values, String fieldName, List<Field> fields, GraphQLType fieldType) {
130133

131-
ChildDataCollector collector = createAndPopulateChildData(values, fieldName, fieldType);
134+
ChildDataCollector collector = createAndPopulateChildData(executionContext, fields.get(0), values, fieldName, fieldType, argumentValues);
132135

133136
List<GraphQLExecutionNode> childNodes =
134137
createChildNodes(executionContext, fields, collector);
@@ -148,16 +151,16 @@ private List<GraphQLExecutionNode> createChildNodes(ExecutionContext executionCo
148151
return childNodes;
149152
}
150153

151-
private ChildDataCollector createAndPopulateChildData(List<GraphQLExecutionNodeValue> values, String fieldName,
152-
GraphQLType fieldType) {
154+
private ChildDataCollector createAndPopulateChildData(ExecutionContext executionContext, Field field, List<GraphQLExecutionNodeValue> values, String fieldName,
155+
GraphQLType fieldType, Map<String, Object> argumentValues) {
153156
ChildDataCollector collector = new ChildDataCollector();
154157
for (GraphQLExecutionNodeValue value : values) {
155158
if (value.getValue() == null) {
156159
// We hit a null, insert the null and do not create a child
157160
value.getResultContainer().putResult(fieldName, null);
158161
} else {
159162
GraphQLExecutionNodeDatum childDatum = value.getResultContainer().createAndPutChildDatum(fieldName, value.getValue());
160-
GraphQLObjectType graphQLObjectType = getGraphQLObjectType(fieldType, value.getValue());
163+
GraphQLObjectType graphQLObjectType = getGraphQLObjectType(executionContext, field, fieldType, value.getValue(), argumentValues);
161164
collector.putChildData(graphQLObjectType, childDatum);
162165
}
163166
}
@@ -196,12 +199,24 @@ private Map<String, List<Field>> getChildFields(ExecutionContext executionContex
196199
return subFields;
197200
}
198201

199-
private GraphQLObjectType getGraphQLObjectType(GraphQLType fieldType, Object value) {
202+
private GraphQLObjectType getGraphQLObjectType(ExecutionContext executionContext, Field field, GraphQLType fieldType, Object value, Map<String, Object> argumentValues) {
200203
GraphQLObjectType resolvedType = null;
201204
if (fieldType instanceof GraphQLInterfaceType) {
202-
resolvedType = resolveType((GraphQLInterfaceType) fieldType, value);
205+
resolvedType = resolveTypeForInterface(TypeResolutionParameters.newParameters()
206+
.graphQLInterfaceType((GraphQLInterfaceType) fieldType)
207+
.field(field)
208+
.value(value)
209+
.argumentValues(argumentValues)
210+
.schema(executionContext.getGraphQLSchema())
211+
.build());
203212
} else if (fieldType instanceof GraphQLUnionType) {
204-
resolvedType = resolveType((GraphQLUnionType) fieldType, value);
213+
resolvedType = resolveTypeForUnion(TypeResolutionParameters.newParameters()
214+
.graphQLUnionType((GraphQLUnionType) fieldType)
215+
.field(field)
216+
.value(value)
217+
.argumentValues(argumentValues)
218+
.schema(executionContext.getGraphQLSchema())
219+
.build());
205220
} else if (fieldType instanceof GraphQLObjectType) {
206221
resolvedType = (GraphQLObjectType) fieldType;
207222
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package graphql.schema;
22

33

4-
public interface TypeResolver {
4+
import graphql.TypeResolutionEnvironment;
55

6+
public interface TypeResolver {
67

7-
GraphQLObjectType getType(Object object);
8+
GraphQLObjectType getType(TypeResolutionEnvironment env);
89

910
}

0 commit comments

Comments
 (0)