private List<GraphQLArgument> transferMissingArguments(List<GraphQLArgument> arguments, GraphQLDirective directiveDefinition) { Map<String, GraphQLArgument> declaredArgs = FpKit.getByName(arguments, GraphQLArgument::getName, FpKit.mergeFirst()); List<GraphQLArgument> argumentsOut = new ArrayList<>(arguments); for (GraphQLArgument directiveDefArg : directiveDefinition.getArguments()) { if (!declaredArgs.containsKey(directiveDefArg.getName())) { GraphQLArgument missingArg = GraphQLArgument.newArgument() .name(directiveDefArg.getName()) .description(directiveDefArg.getDescription()) .definition(directiveDefArg.getDefinition()) .type(directiveDefArg.getType()) .defaultValue(directiveDefArg.getDefaultValue()) .value(directiveDefArg.getDefaultValue()) .build(); argumentsOut.add(missingArg); } } return argumentsOut; }
public Builder(GraphQLArgument existing) { this.name = existing.getName(); this.type = existing.getType(); this.value = existing.getValue(); this.defaultValue = existing.getDefaultValue(); this.description = existing.getDescription(); this.definition = existing.getDefinition(); this.directives.putAll(FpKit.getByName(existing.getDirectives(), GraphQLDirective::getName)); }
private String directiveString(GraphQLDirective directive) { StringBuilder sb = new StringBuilder(); sb.append("@").append(directive.getName()); List<GraphQLArgument> args = directive.getArguments(); args = args .stream() .sorted(Comparator.comparing(GraphQLArgument::getName)) .collect(toList()); if (!args.isEmpty()) { sb.append("("); for (int i = 0; i < args.size(); i++) { GraphQLArgument arg = args.get(i); sb.append(arg.getName()); if (arg.getValue() != null) { sb.append(" : "); sb.append(printAst(arg.getValue(), arg.getType())); } else if (arg.getDefaultValue() != null) { sb.append(" : "); sb.append(printAst(arg.getDefaultValue(), arg.getType())); } if (i < args.size() - 1) { sb.append(", "); } } sb.append(")"); } return sb.toString(); }
/** * This helps you transform the current GraphQLArgument into another one by starting a builder with all * the current values and allows you to transform it how you want. * * @param builderConsumer the consumer code that will be given a builder to transform * * @return a new field based on calling build on that builder */ public GraphQLArgument transform(Consumer<Builder> builderConsumer) { Builder builder = newArgument(this); builderConsumer.accept(builder); return builder.build(); }
private Map<String, Object> getArgumentValuesImpl(GraphQLCodeRegistry codeRegistry, List<GraphQLArgument> argumentTypes, List<Argument> arguments, Map<String, Object> variables) { if (argumentTypes.isEmpty()) { return Collections.emptyMap(); } Map<String, Object> result = new LinkedHashMap<>(); Map<String, Argument> argumentMap = argumentMap(arguments); for (GraphQLArgument fieldArgument : argumentTypes) { String argName = fieldArgument.getName(); Argument argument = argumentMap.get(argName); Object value; if (argument != null) { value = coerceValueAst(codeRegistry.getFieldVisibility(), fieldArgument.getType(), argument.getValue(), variables); } else { value = fieldArgument.getDefaultValue(); } // only put an arg into the result IF they specified a variable at all or // the default value ended up being something non null if (argumentMap.containsKey(argName) || value != null) { result.put(argName, value); } } return result; }
private GraphQLArgument buildDirectiveArgument(Argument arg, Optional<GraphQLDirective> directiveDefinition) { Optional<GraphQLArgument> directiveDefArgument = directiveDefinition.map(dd -> dd.getArgument(arg.getName())); GraphQLArgument.Builder builder = GraphQLArgument.newArgument(); builder.name(arg.getName()); GraphQLInputType inputType; Object defaultValue = null; if (directiveDefArgument.isPresent()) { inputType = directiveDefArgument.get().getType(); defaultValue = directiveDefArgument.get().getDefaultValue(); } else { inputType = buildDirectiveInputType(arg.getValue()); } builder.type(inputType); builder.defaultValue(defaultValue); Object value = buildValue(arg.getValue(), inputType); // // we put the default value in if the specified is null builder.value(value == null ? defaultValue : value); return builder.build(); }
private GraphQLFieldDefinition buildRelayMutation(Method method, ProcessingElementsContainer container, GraphQLFieldDefinition.Builder builder, GraphQLOutputType outputType, List<GraphQLArgument> args) { GraphQLFieldDefinition relayFieldDefinition; if (!(outputType instanceof GraphQLObjectType || outputType instanceof GraphQLInterfaceType)) { throw new RuntimeException("outputType should be an object or an interface"); } StringBuilder titleBuffer = new StringBuilder(method.getName()); titleBuffer.setCharAt(0, Character.toUpperCase(titleBuffer.charAt(0))); String title = titleBuffer.toString(); List<GraphQLFieldDefinition> fieldDefinitions = outputType instanceof GraphQLObjectType ? ((GraphQLObjectType) outputType).getFieldDefinitions() : ((GraphQLInterfaceType) outputType).getFieldDefinitions(); relayFieldDefinition = container.getRelay().mutationWithClientMutationId(title, method.getName(), args.stream(). map(t -> newInputObjectField().name(t.getName()).type(t.getType()).description(t.getDescription()).build()). collect(Collectors.toList()), fieldDefinitions, new StaticDataFetcher(null)); builder.argument(relayFieldDefinition.getArguments()).type(relayFieldDefinition.getType()); return relayFieldDefinition; }
@Test public void testDecoratedFieldWithArguments_moreArgumentsThanArgumentsValues_directivesAreBuilt() throws Exception { // Arrange ProcessingElementsContainer processingElementsContainer = new ProcessingElementsContainer(); GraphQLDirective upperCase = newDirective().name("upperCase").argument(builder -> builder.name("arg").type(GraphQLString)) .argument(builder -> builder.name("arg2").type(GraphQLInt).defaultValue("5")).build(); GraphQLDirective lowerCase = newDirective().name("lowerCase").build(); processingElementsContainer.getDirectiveRegistry().put("upperCase", upperCase); processingElementsContainer.getDirectiveRegistry().put("lowerCase", lowerCase); DirectivesBuilder directivesBuilder = new DirectivesBuilder(this.getClass().getField("decoratedFieldWithArguments"), processingElementsContainer); GraphQLDirective[] graphQLDirectives = directivesBuilder.build(); assertEquals(graphQLDirectives.length, 2); assertEquals(graphQLDirectives[0].getArguments().size(), 2); assertEquals(graphQLDirectives[0].getArguments().get(0).getName(), "arg"); assertEquals(graphQLDirectives[0].getArguments().get(0).getValue(), "This is a string"); assertEquals(graphQLDirectives[0].getArguments().get(1).getName(), "arg2"); assertEquals(graphQLDirectives[0].getArguments().get(1).getValue(), "5"); }
public GraphQLArgument getArgument(String name) { for (GraphQLArgument argument : arguments) { if (argument.getName().equals(name)) return argument; } return null; }
@Override public void check(GraphQLFieldDefinition fieldDef, SchemaValidationErrorCollector validationErrorCollector) { for (GraphQLArgument argument : fieldDef.getArguments()) { GraphQLInputType argumentType = argument.getType(); if (argumentType instanceof GraphQLInputObjectType) { List<String> path = new ArrayList<>(); path.add(argumentType.getName()); check((GraphQLInputObjectType) argumentType, new LinkedHashSet<>(), path, validationErrorCollector); } } }
private GraphQLArgument transformArgument(GraphQLArgument argument, TypedElement element, String description, OperationMapper operationMapper, BuildContext buildContext) { if (argument.getDefaultValue() == null && shouldWrap(argument.getType(), element)) { return argument.transform(builder -> builder.type(new GraphQLNonNull(argument.getType()))); } if (shouldUnwrap(argument.getDefaultValue(), argument.getType())) { //do not warn on primitives as their non-nullness is implicit if (!ClassUtils.getRawType(element.getJavaType().getType()).isPrimitive()) { log.warn("Non-null argument with a default value will be treated as nullable: " + description); } return argument.transform(builder -> builder.type((GraphQLInputType) GraphQLUtils.unwrapNonNull(argument.getType()))); } return argument; }
private void checkFieldArgumentEquivalence(GraphQLObjectType objectTyoe, GraphQLInterfaceType interfaceType, SchemaValidationErrorCollector validationErrorCollector, GraphQLFieldDefinition interfaceFieldDef, GraphQLFieldDefinition objectFieldDef) { List<GraphQLArgument> interfaceArgs = interfaceFieldDef.getArguments(); List<GraphQLArgument> objectArgs = objectFieldDef.getArguments(); if (interfaceArgs.size() != objectArgs.size()) { validationErrorCollector.addError( error(format("object type '%s' does not implement interface '%s' because field '%s' has a different number of arguments", objectTyoe.getName(), interfaceType.getName(), interfaceFieldDef.getName()))); } else { for (int i = 0; i < interfaceArgs.size(); i++) { GraphQLArgument interfaceArg = interfaceArgs.get(i); GraphQLArgument objectArg = objectArgs.get(i); String interfaceArgStr = makeArgStr(interfaceArg); String objectArgStr = makeArgStr(objectArg); boolean same = true; if (!interfaceArgStr.equals(objectArgStr)) { same = false; } if (!Objects.equals(interfaceArg.getDefaultValue(), objectArg.getDefaultValue())) { same = false; } if (!same) { validationErrorCollector.addError( error(format("object type '%s' does not implement interface '%s' because field '%s' argument '%s' is defined differently", objectTyoe.getName(), interfaceType.getName(), interfaceFieldDef.getName(), interfaceArg.getName()))); } } } }
@Override public GraphQLArgument transformArgument(GraphQLArgument argument, DirectiveArgument directiveArgument, OperationMapper operationMapper, BuildContext buildContext) { if (directiveArgument.getAnnotation() != null && directiveArgument.getDefaultValue() == null) { return argument.transform(builder -> builder.type(GraphQLNonNull.nonNull(argument.getType()))); } return transformArgument(argument, directiveArgument.getTypedElement(), directiveArgument.toString(), operationMapper, buildContext); }
private String atFetchFromSupport(String fieldName, List<GraphQLDirective> directives) { // @fetch(from : "name") Optional<GraphQLArgument> from = directiveWithArg(directives, FETCH, "from"); return from.map(arg -> String.valueOf(arg.getValue())).orElse(fieldName); }
private GraphQLDirective transformArgs(GraphQLDirective graphQLDirective, String[] argumentValues) { GraphQLDirective.Builder directiveBuilder = newDirective(graphQLDirective); directiveBuilder.clearArguments(); List<GraphQLArgument> arguments = graphQLDirective.getArguments(); if (argumentValues.length > arguments.size()) { throw new GraphQLAnnotationsException(String.format("Directive '%s' is supplied with more argument values than it supports", graphQLDirective.getName()), null); } for (int i = 0; i < argumentValues.length; i++) { transformArgument(argumentValues, directiveBuilder, arguments, i); } for (int i = argumentValues.length; i < arguments.size(); i++) { int finalI = i; directiveBuilder.argument(arguments.get(i).transform(builder -> builder.value(arguments.get(finalI).getDefaultValue()))); } return directiveBuilder.build(); }
/** * Take an argument builder in a function definition and apply. Can be used in a jdk8 lambda * e.g.: * <pre> * {@code * argument(a -> a.name("argumentName")) * } * </pre> * * @param builderFunction a supplier for the builder impl * * @return this */ public Builder argument(UnaryOperator<GraphQLArgument.Builder> builderFunction) { GraphQLArgument.Builder builder = GraphQLArgument.newArgument(); builder = builderFunction.apply(builder); return argument(builder); }
@Override public void checkField(Field field) { GraphQLFieldDefinition fieldDef = getValidationContext().getFieldDef(); if (fieldDef == null) return; Map<String, Argument> argumentMap = argumentMap(field.getArguments()); for (GraphQLArgument graphQLArgument : fieldDef.getArguments()) { Argument argument = argumentMap.get(graphQLArgument.getName()); if (argument == null && (isNonNull(graphQLArgument.getType())) && (graphQLArgument.getDefaultValue() == null)) { String message = String.format("Missing field argument %s", graphQLArgument.getName()); addError(ValidationErrorType.MissingFieldArgument, field.getSourceLocation(), message); } } }
private GraphQLArgument buildDirectiveArgument(Argument arg, Optional<GraphQLDirective> directiveDefinition) { Optional<GraphQLArgument> directiveDefArgument = directiveDefinition.map(dd -> dd.getArgument(arg.getName())); GraphQLArgument.Builder builder = GraphQLArgument.newArgument(); builder.name(arg.getName()); GraphQLInputType inputType; Object defaultValue = null; if (directiveDefArgument.isPresent()) { inputType = directiveDefArgument.get().getType(); defaultValue = directiveDefArgument.get().getDefaultValue(); } else { inputType = buildDirectiveInputType(arg.getValue()); } builder.type(inputType); builder.defaultValue(defaultValue); Object value = buildValue(arg.getValue(), inputType); // // we put the default value in if the specified is null builder.value(value == null ? defaultValue : value); return builder.build(); }
@Override public void checkDirective(Directive directive, List<Node> ancestors) { GraphQLDirective graphQLDirective = getValidationContext().getDirective(); if (graphQLDirective == null) return; Map<String, Argument> argumentMap = argumentMap(directive.getArguments()); for (GraphQLArgument graphQLArgument : graphQLDirective.getArguments()) { Argument argument = argumentMap.get(graphQLArgument.getName()); if (argument == null && (isNonNull(graphQLArgument.getType()))) { String message = String.format("Missing directive argument %s", graphQLArgument.getName()); addError(ValidationErrorType.MissingDirectiveArgument, directive.getSourceLocation(), message); } } } }