private void checkFieldTypeCompatibility(GraphQLObjectType objectType, GraphQLInterfaceType interfaceType, SchemaValidationErrorCollector validationErrorCollector, GraphQLFieldDefinition interfaceFieldDef, GraphQLFieldDefinition objectFieldDef) { String interfaceFieldDefStr = simplePrint(interfaceFieldDef.getType()); String objectFieldDefStr = simplePrint(objectFieldDef.getType()); if (!isCompatible(interfaceFieldDef.getType(), objectFieldDef.getType())) { validationErrorCollector.addError( error(format("object type '%s' does not implement interface '%s' because field '%s' is defined as '%s' type and not as '%s' type", objectType.getName(), interfaceType.getName(), interfaceFieldDef.getName(), objectFieldDefStr, interfaceFieldDefStr))); } else { checkFieldArgumentEquivalence(objectType, interfaceType, validationErrorCollector, interfaceFieldDef, objectFieldDef); } }
private void traverse(GraphQLOutputType root, List<SchemaValidationRule> rules, SchemaValidationErrorCollector validationErrorCollector) { if (processed.contains(root)) { return; } processed.add(root); if (root instanceof GraphQLFieldsContainer) { // this deliberately has open field visibility here since its validating the schema // when completely open for (GraphQLFieldDefinition fieldDefinition : ((GraphQLFieldsContainer) root).getFieldDefinitions()) { for (SchemaValidationRule rule : rules) { rule.check(fieldDefinition, validationErrorCollector); } traverse(fieldDefinition.getType(), rules, validationErrorCollector); } } } }
private void collectFieldsForField(Map<String, List<FieldAndType>> fieldMap, GraphQLType parentType, Field field) { String responseName = field.getAlias() != null ? field.getAlias() : field.getName(); if (!fieldMap.containsKey(responseName)) { fieldMap.put(responseName, new ArrayList<>()); } GraphQLOutputType fieldType = null; GraphQLUnmodifiedType unwrappedParent = unwrapAll(parentType); if (unwrappedParent instanceof GraphQLFieldsContainer) { GraphQLFieldsContainer fieldsContainer = (GraphQLFieldsContainer) unwrappedParent; GraphQLFieldDefinition fieldDefinition = getVisibleFieldDefinition(fieldsContainer, field); fieldType = fieldDefinition != null ? fieldDefinition.getType() : null; } fieldMap.get(responseName).add(new FieldAndType(field, fieldType, parentType)); }
private static Object fakeObjectValue(GraphQLObjectType fieldType) { Map<String, Object> map = new LinkedHashMap<>(); fieldType.getFieldDefinitions().forEach(fldDef -> { GraphQLOutputType innerFieldType = fldDef.getType(); Object obj = null; if (innerFieldType instanceof GraphQLObjectType) { obj = fakeObjectValue((GraphQLObjectType) innerFieldType); } else if (innerFieldType instanceof GraphQLScalarType) { obj = fakeScalarValue(fldDef.getName(), (GraphQLScalarType) innerFieldType); } map.put(fldDef.getName(), obj); }); return map; }
private SelectedFieldImpl(String qualifiedName, MergedField parentFields, GraphQLFieldDefinition fieldDefinition, Map<String, Object> arguments) { this.qualifiedName = qualifiedName; this.name = parentFields.getName(); this.fieldDefinition = fieldDefinition; this.arguments = arguments; GraphQLType unwrappedType = GraphQLTypeUtil.unwrapAll(fieldDefinition.getType()); if (unwrappedType instanceof GraphQLFieldsContainer) { this.selectionSet = new DataFetchingFieldSelectionSetImpl(parentFields, (GraphQLFieldsContainer) unwrappedType, graphQLSchema, variables, fragmentsByName); } else { this.selectionSet = NOOP; } }
private TypePrinter<GraphQLInterfaceType> interfacePrinter() { return (out, type, visibility) -> { if (isIntrospectionType(type)) { return; } printComments(out, type, ""); out.format("interface %s%s {\n", type.getName(), directivesString(type.getDirectives())); visibility.getFieldDefinitions(type) .stream() .sorted(Comparator.comparing(GraphQLFieldDefinition::getName)) .forEach(fd -> { printComments(out, fd, " "); out.format(" %s%s: %s%s\n", fd.getName(), argsString(fd.getArguments()), typeString(fd.getType()), directivesString(fd.getDirectives())); }); out.format("}\n\n"); }; }
private TypePrinter<GraphQLObjectType> objectPrinter() { return (out, type, visibility) -> { if (isIntrospectionType(type)) { return; } printComments(out, type, ""); if (type.getInterfaces().isEmpty()) { out.format("type %s%s {\n", type.getName(), directivesString(type.getDirectives())); } else { Stream<String> interfaceNames = type.getInterfaces() .stream() .map(GraphQLType::getName) .sorted(Comparator.naturalOrder()); out.format("type %s implements %s%s {\n", type.getName(), interfaceNames.collect(joining(" & ")), directivesString(type.getDirectives())); } visibility.getFieldDefinitions(type) .stream() .sorted(Comparator.comparing(GraphQLFieldDefinition::getName)) .forEach(fd -> { printComments(out, fd, " "); out.format(" %s%s: %s%s\n", fd.getName(), argsString(fd.getArguments()), typeString(fd.getType()), directivesString(fd.getDirectives())); }); out.format("}\n\n"); }; }
@SuppressWarnings("unchecked") public Builder(GraphQLFieldDefinition existing) { this.name = existing.getName(); this.description = existing.getDescription(); this.type = existing.getType(); this.dataFetcherFactory = DataFetcherFactories.useDataFetcher(existing.getDataFetcher()); this.deprecationReason = existing.getDeprecationReason(); this.definition = existing.getDefinition(); this.arguments.putAll(getByName(existing.getArguments(), GraphQLArgument::getName)); this.directives.putAll(getByName(existing.getDirectives(), GraphQLDirective::getName)); }
private void enterImpl(Field field) { enterName(field.getName()); GraphQLCompositeType parentType = getParentType(); GraphQLFieldDefinition fieldDefinition = null; if (parentType != null) { fieldDefinition = getFieldDef(schema, parentType, field); } addFieldDef(fieldDefinition); addOutputType(fieldDefinition != null ? fieldDefinition.getType() : null); }
void getFields() { DataFetchingFieldSelectionSet selectionSet = env.getSelectionSet(); List<SelectedField> nodeFields = selectionSet.getFields("edges/nodes/*"); nodeFields.forEach(selectedField -> { System.out.println(selectedField.getName()); System.out.println(selectedField.getFieldDefinition().getType()); DataFetchingFieldSelectionSet innerSelectionSet = selectedField.getSelectionSet(); // .. this forms a tree of selection and you can get very fancy with it }); }
private void traverseFields(MergedField fieldList, GraphQLFieldsContainer parentFieldType, String fieldPrefix) { FieldCollectorParameters parameters = FieldCollectorParameters.newParameters() .schema(graphQLSchema) .objectType(asObjectTypeOrNull(parentFieldType)) .fragments(fragmentsByName) .variables(variables) .build(); MergedSelectionSet collectedFields = fieldCollector.collectFields(parameters, fieldList); for (Map.Entry<String, MergedField> entry : collectedFields.getSubFields().entrySet()) { String fieldName = mkFieldName(fieldPrefix, entry.getKey()); MergedField collectedFieldList = entry.getValue(); selectionSetFields.put(fieldName, collectedFieldList); Field field = collectedFieldList.getSingleField(); GraphQLFieldDefinition fieldDef = Introspection.getFieldDef(graphQLSchema, parentFieldType, field.getName()); GraphQLType unwrappedType = GraphQLTypeUtil.unwrapAll(fieldDef.getType()); Map<String, Object> argumentValues = valuesResolver.getArgumentValues(fieldDef.getArguments(), field.getArguments(), variables); selectionSetFieldArgs.put(fieldName, argumentValues); selectionSetFieldDefinitions.put(fieldName, fieldDef); flattenedFields.add(fieldName); if (unwrappedType instanceof GraphQLFieldsContainer) { traverseFields(collectedFieldList, (GraphQLFieldsContainer) unwrappedType, fieldName); } } }
fieldDef.getArguments(), fields.getSingleField().getArguments(), executionContext.getVariables()); GraphQLOutputType fieldType = fieldDef.getType(); DataFetchingFieldSelectionSet fieldCollector = DataFetchingFieldSelectionSetImpl.newCollector(executionContext, fieldType, fields); .fieldDefinition(fieldDef) .mergedField(fields) .fieldType(fieldDef.getType()) .executionStepInfo(parameters.getExecutionStepInfo()) .parentType(parentType)
.type(fieldDefinition.getType()) .fieldDefinition(fieldDefinition) .field(currentField)
Map<String, Object> argumentValues = valuesResolver.getArgumentValues(codeRegistry, fieldDef.getArguments(), field.getArguments(), executionContext.getVariables()); GraphQLOutputType fieldType = fieldDef.getType(); DataFetchingFieldSelectionSet fieldCollector = DataFetchingFieldSelectionSetImpl.newCollector(executionContext, fieldType, parameters.getField()); ExecutionStepInfo executionStepInfo = createExecutionStepInfo(executionContext, parameters, fieldDef, parentType);
public CompletableFuture<FetchedValue> fetchValue(ExecutionContext executionContext, Object source, Object localContext, MergedField sameFields, ExecutionStepInfo executionInfo) { Field field = sameFields.getSingleField(); GraphQLFieldDefinition fieldDef = executionInfo.getFieldDefinition(); GraphQLCodeRegistry codeRegistry = executionContext.getGraphQLSchema().getCodeRegistry(); GraphQLFieldsContainer parentType = getFieldsContainer(executionInfo); Map<String, Object> argumentValues = valuesResolver.getArgumentValues(codeRegistry, fieldDef.getArguments(), field.getArguments(), executionContext.getVariables()); GraphQLOutputType fieldType = fieldDef.getType(); DataFetchingFieldSelectionSet fieldCollector = DataFetchingFieldSelectionSetImpl.newCollector(executionContext, fieldType, sameFields); DataFetchingEnvironment environment = newDataFetchingEnvironment(executionContext) .source(source) .localContext(localContext) .arguments(argumentValues) .fieldDefinition(fieldDef) .mergedField(sameFields) .fieldType(fieldType) .executionStepInfo(executionInfo) .parentType(parentType) .selectionSet(fieldCollector) .build(); ExecutionId executionId = executionContext.getExecutionId(); ExecutionPath path = executionInfo.getPath(); return callDataFetcher(codeRegistry, parentType, fieldDef, environment, executionId, path) .thenApply(rawFetchedValue -> FetchedValue.newFetchedValue() .fetchedValue(rawFetchedValue) .rawFetchedValue(rawFetchedValue) .build()) .exceptionally(exception -> handleExceptionWhileFetching(field, path, exception)) .thenApply(result -> unboxPossibleDataFetcherResult(sameFields, path, result, localContext)) .thenApply(this::unboxPossibleOptional); }
GraphQLUnmodifiedType unmodifiedType = unwrapAll(fieldDefinition.getType()); QueryTraversalContext fieldEnv = (unmodifiedType instanceof GraphQLCompositeType) ? new QueryTraversalContext(fieldDefinition.getType(), (GraphQLCompositeType) unmodifiedType, environment, field) : new QueryTraversalContext(null, null, environment, field);// Terminal (scalar) node, EMPTY FRAME
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)); }
/** * Builds the type info hierarchy for the current field * * @param executionContext the execution context in play * @param parameters contains the parameters holding the fields to be executed and source object * @param fieldDefinition the field definition to build type info for * * @return a new type info */ protected ExecutionStepInfo createExecutionStepInfo(ExecutionContext executionContext, ExecutionStrategyParameters parameters, GraphQLFieldDefinition fieldDefinition, GraphQLObjectType fieldContainer) { GraphQLOutputType fieldType = fieldDefinition.getType(); List<Argument> fieldArgs = parameters.getField().getArguments(); GraphQLCodeRegistry codeRegistry = executionContext.getGraphQLSchema().getCodeRegistry(); Map<String, Object> argumentValues = valuesResolver.getArgumentValues(codeRegistry, fieldDefinition.getArguments(), fieldArgs, executionContext.getVariables()); return newExecutionStepInfo() .type(fieldType) .fieldDefinition(fieldDefinition) .fieldContainer(fieldContainer) .field(parameters.getField()) .path(parameters.getPath()) .parentInfo(parameters.getExecutionStepInfo()) .arguments(argumentValues) .build(); }
private SelectedFieldImpl(String qualifiedName, MergedField parentFields, GraphQLFieldDefinition fieldDefinition, Map<String, Object> arguments) { this.qualifiedName = qualifiedName; this.name = parentFields.getName(); this.fieldDefinition = fieldDefinition; this.arguments = arguments; GraphQLType unwrappedType = GraphQLTypeUtil.unwrapAll(fieldDefinition.getType()); if (unwrappedType instanceof GraphQLFieldsContainer) { this.selectionSet = new DataFetchingFieldSelectionSetImpl(parentFields, (GraphQLFieldsContainer) unwrappedType, graphQLSchema, variables, fragmentsByName); } else { this.selectionSet = NOOP; } }
public ResolvedField(Field field, GraphQLFieldDefinition fieldDefinition, Map<String, Object> arguments, Map<String, ResolvedField> children) { this.name = field.getAlias() != null ? field.getAlias() : field.getName(); this.field = field; this.fieldDefinition = fieldDefinition; this.fieldType = (GraphQLOutputType) GraphQLUtils.unwrap(fieldDefinition.getType()); this.arguments = arguments; this.children = children; this.resolver = findResolver(fieldDefinition, arguments); }