private static String mkMessage(ExecutionStepInfo executionStepInfo, ExecutionPath path) { GraphQLType unwrappedTyped = executionStepInfo.getUnwrappedNonNullType(); if (executionStepInfo.hasParent()) { GraphQLType unwrappedParentType = executionStepInfo.getParent().getUnwrappedNonNullType(); return String.format("Cannot return null for non-nullable type: '%s' within parent '%s' (%s)", unwrappedTyped.getName(), unwrappedParentType.getName(), path); } return String.format("Cannot return null for non-nullable type: '%s' (%s)", unwrappedTyped.getName(), path); }
/** * Called to discover the field definition give the current parameters and the AST {@link Field} * * @param executionContext contains the top level execution parameters * @param parameters contains the parameters holding the fields to be executed and source object * @param field the field to find the definition of * * @return a {@link GraphQLFieldDefinition} */ protected GraphQLFieldDefinition getFieldDef(ExecutionContext executionContext, ExecutionStrategyParameters parameters, Field field) { GraphQLObjectType parentType = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType(); return getFieldDef(executionContext.getGraphQLSchema(), parentType, field); }
fetchMap.put("parentType", executionStepInfo.getParent().getUnwrappedNonNullType().getName()); fetchMap.put("returnType", executionStepInfo.simplePrint()); fetchMap.put("fieldName", executionStepInfo.getFieldDefinition().getName());
@SuppressWarnings("UnnecessaryLocalVariable") private List<ExecutionNode> handleObject(ExecutionContext executionContext, Map<String, Object> argumentValues, FetchedValues fetchedValues, String fieldName, MergedField fields, ExecutionStepInfo executionStepInfo) { // 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, executionStepInfo.getUnwrappedNonNullType(), 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); MergedSelectionSet childFields = getChildFields(executionContext, resolvedType, fields); ExecutionStepInfo newExecutionStepInfo = executionStepInfo.changeTypeWithPreservedNonNull(resolvedType); childNodes.add(new ExecutionNode(resolvedType, newExecutionStepInfo, childFields.getSubFields(), results, sources)); } return childNodes; }
private void handleTypeMismatchProblem(ExecutionContext context, ExecutionStrategyParameters parameters, Object result) { TypeMismatchError error = new TypeMismatchError(parameters.getPath(), parameters.getExecutionStepInfo().getUnwrappedNonNullType()); log.warn("{} got {}", error.getMessage(), result.getClass()); context.addError(error); parameters.deferredErrorSupport().onError(error); }
@Override @SuppressWarnings("FutureReturnValueIgnored") public CompletableFuture<ExecutionResult> execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) { InstrumentationContext<ExecutionResult> executionStrategyCtx = executionContext.getInstrumentation() .beginExecutionStrategy(new InstrumentationExecutionStrategyParameters(executionContext, parameters)); GraphQLObjectType type = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType(); ExecutionNode root = new ExecutionNode(type, parameters.getExecutionStepInfo(), parameters.getFields().getSubFields(), singletonList(MapOrList.createMap(new LinkedHashMap<>())), Collections.singletonList(parameters.getSource()) ); Queue<ExecutionNode> nodes = new ArrayDeque<>(); CompletableFuture<ExecutionResult> result = new CompletableFuture<>(); executeImpl(executionContext, parameters, root, root, nodes, root.getFields().keySet().iterator(), result); executionStrategyCtx.onDispatched(result); result.whenComplete(executionStrategyCtx::onCompleted); return result; }
private String mkMessage(ExecutionPath path, UnresolvedTypeException exception, ExecutionStepInfo info) { return format("Can't resolve '%s'. Abstract type '%s' must resolve to an Object type at runtime for field '%s.%s'. %s", path, exception.getInterfaceOrUnionType().getName(), info.getParent().getUnwrappedNonNullType().getName(), info.getFieldDefinition().getName(), exception.getMessage()); }
private List<ExecutionNode> completeValues(ExecutionContext executionContext, FetchedValues fetchedValues, ExecutionStepInfo executionStepInfo, String fieldName, MergedField fields, Map<String, Object> argumentValues) { handleNonNullType(executionContext, fetchedValues); GraphQLType unwrappedFieldType = executionStepInfo.getUnwrappedNonNullType(); if (isPrimitive(unwrappedFieldType)) { handlePrimitives(fetchedValues, fieldName, unwrappedFieldType); return Collections.emptyList(); } else if (isObject(unwrappedFieldType)) { return handleObject(executionContext, argumentValues, fetchedValues, fieldName, fields, executionStepInfo); } else if (isList(unwrappedFieldType)) { return handleList(executionContext, argumentValues, fetchedValues, fieldName, fields, executionStepInfo); } else { return Assert.assertShouldNeverHappen("can't handle type: %s", unwrappedFieldType); } }
public ExecutionStepInfo newExecutionStepInfoForListElement(ExecutionStepInfo executionInfo, int index) { GraphQLList fieldType = (GraphQLList) executionInfo.getUnwrappedNonNullType(); GraphQLOutputType typeInList = (GraphQLOutputType) fieldType.getWrappedType(); ExecutionPath indexedPath = executionInfo.getPath().segment(index); return executionInfo.transform(builder -> builder .parentInfo(executionInfo) .type(typeInList) .path(indexedPath)); }
@SuppressWarnings("FutureReturnValueIgnored") private Supplier<CompletableFuture<ExecutionResult>> deferredExecutionResult(ExecutionContext executionContext, ExecutionStrategyParameters parameters) { return () -> { GraphQLFieldDefinition fieldDef = getFieldDef(executionContext, parameters, parameters.getField().getSingleField()); GraphQLObjectType fieldContainer = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType(); Instrumentation instrumentation = executionContext.getInstrumentation(); DeferredFieldInstrumentationContext fieldCtx = instrumentation.beginDeferredField( new InstrumentationDeferredFieldParameters(executionContext, parameters, fieldDef, createExecutionStepInfo(executionContext, parameters, fieldDef, fieldContainer)) ); CompletableFuture<ExecutionResult> result = new CompletableFuture<>(); fieldCtx.onDispatched(result); CompletableFuture<FieldValueInfo> fieldValueInfoFuture = resolveFieldWithInfo(executionContext, parameters); fieldValueInfoFuture.whenComplete((fieldValueInfo, throwable) -> { fieldCtx.onFieldValueInfo(fieldValueInfo); CompletableFuture<ExecutionResult> execResultFuture = fieldValueInfo.getFieldValue(); execResultFuture = execResultFuture.whenComplete(fieldCtx::onCompleted); Async.copyResults(execResultFuture, result); }); return result; }; } }
@SuppressWarnings("unchecked") private List<ExecutionNode> handleList(ExecutionContext executionContext, Map<String, Object> argumentValues, FetchedValues fetchedValues, String fieldName, MergedField fields, ExecutionStepInfo executionStepInfo) { GraphQLList listType = (GraphQLList) executionStepInfo.getUnwrappedNonNullType(); 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(); ExecutionStepInfo newExecutionStepInfo = executionStepInfo.changeTypeWithPreservedNonNull((GraphQLOutputType) GraphQLTypeUtil.unwrapNonNull(innerSubType)); FetchedValues flattenedFetchedValues = new FetchedValues(flattenedValues, newExecutionStepInfo, fetchedValues.getPath()); return completeValues(executionContext, flattenedFetchedValues, newExecutionStepInfo, fieldName, fields, argumentValues); }
GraphQLObjectType parentType = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType(); GraphQLFieldDefinition fieldDef = getFieldDef(executionContext.getGraphQLSchema(), parentType, field.getSingleField());
public ExecutionStepInfo newExecutionStepInfoForSubField(ExecutionContext executionContext, MergedField mergedField, ExecutionStepInfo parentInfo) { GraphQLObjectType parentType = (GraphQLObjectType) parentInfo.getUnwrappedNonNullType(); GraphQLFieldDefinition fieldDefinition = Introspection.getFieldDef(executionContext.getGraphQLSchema(), parentType, mergedField.getName()); GraphQLOutputType fieldType = fieldDefinition.getType(); List<Argument> fieldArgs = mergedField.getArguments(); GraphQLCodeRegistry codeRegistry = executionContext.getGraphQLSchema().getCodeRegistry(); Map<String, Object> argumentValues = valuesResolver.getArgumentValues(codeRegistry, fieldDefinition.getArguments(), fieldArgs, executionContext.getVariables()); ExecutionPath newPath = parentInfo.getPath().segment(mergedField.getResultKey()); return parentInfo.transform(builder -> builder .parentInfo(parentInfo) .type(fieldType) .fieldDefinition(fieldDefinition) .fieldContainer(parentType) .field(mergedField) .path(newPath) .arguments(argumentValues)); }
GraphQLObjectType parentType = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType(); GraphQLFieldDefinition fieldDef = getFieldDef(executionContext.getGraphQLSchema(), parentType, field); ExecutionStepInfo executionStepInfo = createExecutionStepInfo(executionContext, parameters, fieldDef, parentType);
private FetchedValueAnalysis analyzeFetchedValueImpl(ExecutionContext executionContext, FetchedValue fetchedValue, Object toAnalyze, ExecutionStepInfo executionInfo) throws NonNullableFieldWasNullException { GraphQLType fieldType = executionInfo.getUnwrappedNonNullType(); MergedField field = executionInfo.getField();
ExecutionStepInfo executionStepInfo = parameters.getExecutionStepInfo(); Object result = UnboxPossibleOptional.unboxPossibleOptional(parameters.getSource()); GraphQLType fieldType = executionStepInfo.getUnwrappedNonNullType(); CompletableFuture<ExecutionResult> fieldValue;
public FieldSubSelection createFieldSubSelection(ExecutionContext executionContext, FetchedValueAnalysis analysis) { ExecutionStepInfo executionInfo = analysis.getExecutionStepInfo(); MergedField field = analysis.getField(); Object source = analysis.getCompletedValue(); Object localContext = analysis.getFetchedValue().getLocalContext(); GraphQLOutputType sourceType = executionInfo.getUnwrappedNonNullType(); GraphQLObjectType resolvedObjectType = resolveType.resolveType(executionContext, field, source, executionInfo.getArguments(), sourceType); FieldCollectorParameters collectorParameters = newParameters() .schema(executionContext.getGraphQLSchema()) .objectType(resolvedObjectType) .fragments(executionContext.getFragmentsByName()) .variables(executionContext.getVariables()) .build(); MergedSelectionSet subFields = fieldCollector.collectFields(collectorParameters, executionInfo.getField()); // it is not really a new step but rather a refinement ExecutionStepInfo newExecutionStepInfoWithResolvedType = executionInfo.changeTypeWithPreservedNonNull(resolvedObjectType); return FieldSubSelection.newFieldSubSelection() .source(source) .localContext(localContext) .mergedSelectionSet(subFields) .executionInfo(newExecutionStepInfoWithResolvedType) .build(); }
private static String mkMessage(ExecutionStepInfo executionStepInfo, ExecutionPath path) { GraphQLType unwrappedTyped = executionStepInfo.getUnwrappedNonNullType(); if (executionStepInfo.hasParent()) { GraphQLType unwrappedParentType = executionStepInfo.getParent().getUnwrappedNonNullType(); return String.format("Cannot return null for non-nullable type: '%s' within parent '%s' (%s)", unwrappedTyped.getName(), unwrappedParentType.getName(), path); } return String.format("Cannot return null for non-nullable type: '%s' (%s)", unwrappedTyped.getName(), path); }
private void handleTypeMismatchProblem(ExecutionContext context, ExecutionStrategyParameters parameters, Object result) { TypeMismatchError error = new TypeMismatchError(parameters.getPath(), parameters.getExecutionStepInfo().getUnwrappedNonNullType()); log.warn("{} got {}", error.getMessage(), result.getClass()); context.addError(error); parameters.deferredErrorSupport().onError(error); }
public ExecutionStepInfo newExecutionStepInfoForListElement(ExecutionStepInfo executionInfo, int index) { GraphQLList fieldType = (GraphQLList) executionInfo.getUnwrappedNonNullType(); GraphQLOutputType typeInList = (GraphQLOutputType) fieldType.getWrappedType(); ExecutionPath indexedPath = executionInfo.getPath().segment(index); return executionInfo.transform(builder -> builder .parentInfo(executionInfo) .type(typeInList) .path(indexedPath)); }