use of graphql.execution.ExecutionTypeInfo in project graphql-java by graphql-java.
the class BatchedExecutionStrategy method resolveField.
private CompletableFuture<List<ExecutionNode>> resolveField(ExecutionContext executionContext, ExecutionStrategyParameters parameters, String fieldName, ExecutionNode node) {
GraphQLObjectType parentType = node.getType();
List<Field> fields = node.getFields().get(fieldName);
GraphQLFieldDefinition fieldDef = getFieldDef(executionContext.getGraphQLSchema(), parentType, fields.get(0));
Instrumentation instrumentation = executionContext.getInstrumentation();
ExecutionTypeInfo typeInfo = parameters.getTypeInfo();
InstrumentationContext<ExecutionResult> fieldCtx = instrumentation.beginField(new InstrumentationFieldParameters(executionContext, fieldDef, typeInfo));
CompletableFuture<FetchedValues> fetchedData = fetchData(executionContext, parameters, fieldName, node, fieldDef);
CompletableFuture<List<ExecutionNode>> result = fetchedData.thenApply((fetchedValues) -> {
GraphqlFieldVisibility fieldVisibility = executionContext.getGraphQLSchema().getFieldVisibility();
Map<String, Object> argumentValues = valuesResolver.getArgumentValues(fieldVisibility, fieldDef.getArguments(), fields.get(0).getArguments(), executionContext.getVariables());
return completeValues(executionContext, fetchedValues, typeInfo, fieldName, fields, argumentValues);
});
fieldCtx.onDispatched(null);
result.whenComplete((nodes, throwable) -> fieldCtx.onCompleted(null, throwable));
return result;
}
use of graphql.execution.ExecutionTypeInfo in project graphql-java by graphql-java.
the class BatchedExecutionStrategy method handleList.
@SuppressWarnings("unchecked")
private List<ExecutionNode> handleList(ExecutionContext executionContext, Map<String, Object> argumentValues, FetchedValues fetchedValues, String fieldName, List<Field> fields, ExecutionTypeInfo typeInfo) {
GraphQLList listType = (GraphQLList) typeInfo.getType();
List<FetchedValue> flattenedValues = new ArrayList<>();
for (FetchedValue value : fetchedValues.getValues()) {
MapOrList mapOrList = value.getParentResult();
if (value.getValue() == null) {
mapOrList.putOrAdd(fieldName, null);
continue;
}
MapOrList listResult = mapOrList.createAndPutList(fieldName);
for (Object rawValue : toIterable(value.getValue())) {
rawValue = unboxPossibleOptional(rawValue);
flattenedValues.add(new FetchedValue(listResult, rawValue));
}
}
GraphQLOutputType innerSubType = (GraphQLOutputType) listType.getWrappedType();
ExecutionTypeInfo newTypeInfo = typeInfo.treatAs(innerSubType);
FetchedValues flattenedFetchedValues = new FetchedValues(flattenedValues, newTypeInfo, fetchedValues.getPath());
return completeValues(executionContext, flattenedFetchedValues, newTypeInfo, fieldName, fields, argumentValues);
}
use of graphql.execution.ExecutionTypeInfo in project graphql-java by graphql-java.
the class BatchedExecutionStrategy method executeImpl.
private void executeImpl(ExecutionContext executionContext, ExecutionStrategyParameters parameters, ExecutionNode root, ExecutionNode curNode, Queue<ExecutionNode> queueOfNodes, Iterator<String> curFieldNames, CompletableFuture<ExecutionResult> overallResult) {
if (!curFieldNames.hasNext() && queueOfNodes.isEmpty()) {
overallResult.complete(new ExecutionResultImpl(root.getParentResults().get(0).toObject(), executionContext.getErrors()));
return;
}
if (!curFieldNames.hasNext()) {
curNode = queueOfNodes.poll();
curFieldNames = curNode.getFields().keySet().iterator();
}
String fieldName = curFieldNames.next();
List<Field> currentField = curNode.getFields().get(fieldName);
//
// once an object is resolved from a interface / union to a node with an object type, the
// parent type info has effectively changed (it has got more specific), even though the path etc...
// has not changed
ExecutionTypeInfo currentParentTypeInfo = parameters.getTypeInfo();
ExecutionTypeInfo newParentTypeInfo = newTypeInfo().type(curNode.getType()).fieldDefinition(currentParentTypeInfo.getFieldDefinition()).path(currentParentTypeInfo.getPath()).parentInfo(currentParentTypeInfo.getParentTypeInfo()).build();
ExecutionPath fieldPath = curNode.getTypeInfo().getPath().segment(fieldName);
GraphQLFieldDefinition fieldDefinition = getFieldDef(executionContext.getGraphQLSchema(), curNode.getType(), currentField.get(0));
ExecutionTypeInfo typeInfo = newTypeInfo().type(fieldDefinition.getType()).fieldDefinition(fieldDefinition).path(fieldPath).parentInfo(newParentTypeInfo).build();
ExecutionStrategyParameters newParameters = parameters.transform(builder -> builder.path(fieldPath).field(currentField).typeInfo(typeInfo));
ExecutionNode finalCurNode = curNode;
Iterator<String> finalCurFieldNames = curFieldNames;
resolveField(executionContext, newParameters, fieldName, curNode).whenComplete((childNodes, exception) -> {
if (exception != null) {
handleNonNullException(executionContext, overallResult, exception);
return;
}
queueOfNodes.addAll(childNodes);
executeImpl(executionContext, newParameters, root, finalCurNode, queueOfNodes, finalCurFieldNames, overallResult);
});
}
use of graphql.execution.ExecutionTypeInfo in project graphql-java by graphql-java.
the class BatchedExecutionStrategy method handleObject.
@SuppressWarnings("UnnecessaryLocalVariable")
private List<ExecutionNode> handleObject(ExecutionContext executionContext, Map<String, Object> argumentValues, FetchedValues fetchedValues, String fieldName, List<Field> fields, ExecutionTypeInfo typeInfo) {
// collect list of values by actual type (needed because of interfaces and unions)
Map<GraphQLObjectType, List<MapOrList>> resultsByType = new LinkedHashMap<>();
Map<GraphQLObjectType, List<Object>> sourceByType = new LinkedHashMap<>();
for (FetchedValue value : fetchedValues.getValues()) {
MapOrList mapOrList = value.getParentResult();
if (value.getValue() == null) {
mapOrList.putOrAdd(fieldName, null);
continue;
}
MapOrList childResult = mapOrList.createAndPutMap(fieldName);
GraphQLObjectType resolvedType = getGraphQLObjectType(executionContext, fields.get(0), typeInfo.getType(), value.getValue(), argumentValues);
resultsByType.putIfAbsent(resolvedType, new ArrayList<>());
resultsByType.get(resolvedType).add(childResult);
sourceByType.putIfAbsent(resolvedType, new ArrayList<>());
sourceByType.get(resolvedType).add(value.getValue());
}
List<ExecutionNode> childNodes = new ArrayList<>();
for (GraphQLObjectType resolvedType : resultsByType.keySet()) {
List<MapOrList> results = resultsByType.get(resolvedType);
List<Object> sources = sourceByType.get(resolvedType);
Map<String, List<Field>> childFields = getChildFields(executionContext, resolvedType, fields);
ExecutionTypeInfo newTypeInfo = typeInfo.treatAs(resolvedType);
childNodes.add(new ExecutionNode(resolvedType, newTypeInfo, childFields, results, sources));
}
return childNodes;
}
use of graphql.execution.ExecutionTypeInfo in project graphql-java by graphql-java.
the class BatchedExecutionStrategy method handleNonNullType.
private void handleNonNullType(ExecutionContext executionContext, FetchedValues fetchedValues) {
ExecutionTypeInfo typeInfo = fetchedValues.getExecutionTypeInfo();
NonNullableFieldValidator nonNullableFieldValidator = new NonNullableFieldValidator(executionContext, typeInfo);
ExecutionPath path = fetchedValues.getPath();
for (FetchedValue value : fetchedValues.getValues()) {
nonNullableFieldValidator.validate(path, value.getValue());
}
}
Aggregations