From 72bc1ce1e09bc0f64db9101c57a3400fa129a321 Mon Sep 17 00:00:00 2001 From: Evgeny Dudin Date: Mon, 11 Jul 2022 10:05:02 +1000 Subject: [PATCH] use GraphQLAppliedDirective instead of GraphQLDirective --- .../graphqljava/FederationSdlPrinter.java | 111 ++++++------------ .../graphqljava/FederationTest.java | 57 ++++++++- .../schemas/directiveFederated.graphql | 16 +++ .../schemas/directiveFederatedService.graphql | 9 ++ 4 files changed, 113 insertions(+), 80 deletions(-) create mode 100644 graphql-java-support/src/test/resources/com/apollographql/federation/graphqljava/schemas/directiveFederated.graphql create mode 100644 graphql-java-support/src/test/resources/com/apollographql/federation/graphqljava/schemas/directiveFederatedService.graphql diff --git a/graphql-java-support/src/main/java/com/apollographql/federation/graphqljava/FederationSdlPrinter.java b/graphql-java-support/src/main/java/com/apollographql/federation/graphqljava/FederationSdlPrinter.java index 1491a93b..d037bbed 100644 --- a/graphql-java-support/src/main/java/com/apollographql/federation/graphqljava/FederationSdlPrinter.java +++ b/graphql-java-support/src/main/java/com/apollographql/federation/graphqljava/FederationSdlPrinter.java @@ -2,10 +2,6 @@ import static graphql.Directives.DeprecatedDirective; import static graphql.com.google.common.base.Predicates.not; -import static graphql.introspection.Introspection.DirectiveLocation.ARGUMENT_DEFINITION; -import static graphql.introspection.Introspection.DirectiveLocation.ENUM_VALUE; -import static graphql.introspection.Introspection.DirectiveLocation.FIELD_DEFINITION; -import static graphql.introspection.Introspection.DirectiveLocation.INPUT_FIELD_DEFINITION; import static graphql.schema.visibility.DefaultGraphqlFieldVisibility.DEFAULT_FIELD_VISIBILITY; import static graphql.util.EscapeUtil.escapeJsonString; import static java.util.Optional.ofNullable; @@ -15,42 +11,8 @@ import graphql.Assert; import graphql.PublicApi; import graphql.execution.ValuesResolver; -import graphql.language.AstPrinter; -import graphql.language.Description; -import graphql.language.Document; -import graphql.language.EnumTypeDefinition; -import graphql.language.EnumValueDefinition; -import graphql.language.FieldDefinition; -import graphql.language.InputObjectTypeDefinition; -import graphql.language.InputValueDefinition; -import graphql.language.InterfaceTypeDefinition; -import graphql.language.ObjectTypeDefinition; -import graphql.language.ScalarTypeDefinition; -import graphql.language.TypeDefinition; -import graphql.language.UnionTypeDefinition; -import graphql.schema.DefaultGraphqlTypeComparatorRegistry; -import graphql.schema.GraphQLArgument; -import graphql.schema.GraphQLDirective; -import graphql.schema.GraphQLEnumType; -import graphql.schema.GraphQLEnumValueDefinition; -import graphql.schema.GraphQLFieldDefinition; -import graphql.schema.GraphQLInputObjectField; -import graphql.schema.GraphQLInputObjectType; -import graphql.schema.GraphQLInputType; -import graphql.schema.GraphQLInterfaceType; -import graphql.schema.GraphQLNamedOutputType; -import graphql.schema.GraphQLNamedType; -import graphql.schema.GraphQLObjectType; -import graphql.schema.GraphQLOutputType; -import graphql.schema.GraphQLScalarType; -import graphql.schema.GraphQLSchema; -import graphql.schema.GraphQLSchemaElement; -import graphql.schema.GraphQLType; -import graphql.schema.GraphQLTypeUtil; -import graphql.schema.GraphQLUnionType; -import graphql.schema.GraphqlTypeComparatorEnvironment; -import graphql.schema.GraphqlTypeComparatorRegistry; -import graphql.schema.InputValueWithState; +import graphql.language.*; +import graphql.schema.*; import graphql.schema.idl.DirectiveInfo; import graphql.schema.idl.ScalarInfo; import graphql.schema.idl.SchemaParser; @@ -76,11 +38,8 @@ public class FederationSdlPrinter { // we use this so that we get the simple "@deprecated" as text and not a full exploded // text with arguments (but only when we auto add this) // - private static final GraphQLDirective DeprecatedDirective4Printing = - GraphQLDirective.newDirective() - .name("deprecated") - .validLocations(FIELD_DEFINITION, ENUM_VALUE, ARGUMENT_DEFINITION, INPUT_FIELD_DEFINITION) - .build(); + private static final GraphQLAppliedDirective DeprecatedDirective4Printing = + GraphQLAppliedDirective.newDirective().name("deprecated").build(); /** * This predicate excludes all directives which are specified bt the GraphQL Specification. @@ -104,7 +63,7 @@ public static class Options { private final boolean descriptionsAsHashComments; - private final Predicate includeDirective; + private final Predicate includeDirective; private final Predicate includeDirectiveDefinition; @@ -121,7 +80,7 @@ private Options( boolean includeDirectiveDefinitions, boolean useAstDefinitions, boolean descriptionsAsHashComments, - Predicate includeDirective, + Predicate includeDirective, Predicate includeDirectiveDefinition, Predicate includeTypeDefinition, Predicate includeSchemaElement, @@ -155,7 +114,7 @@ public boolean isIncludeDirectiveDefinitions() { return includeDirectiveDefinitions; } - public Predicate getIncludeDirective() { + public Predicate getIncludeDirective() { return includeDirective; } @@ -321,7 +280,7 @@ public Options includeDirectives(boolean flag) { * @param includeDirective the predicate to decide of a directive is printed * @return new instance of options */ - public Options includeDirectives(Predicate includeDirective) { + public Options includeDirectives(Predicate includeDirective) { return new Options( this.includeIntrospectionTypes, this.includeScalars, @@ -580,7 +539,8 @@ private TypePrinter scalarPrinter() { printComments(out, type, ""); out.format( "scalar %s%s\n\n", - type.getName(), directivesString(GraphQLScalarType.class, type.getDirectives())); + type.getName(), + directivesString(GraphQLScalarType.class, type.getAppliedDirectives())); } } }; @@ -606,14 +566,15 @@ private TypePrinter enumPrinter() { printComments(out, type, ""); out.format( "enum %s%s", - type.getName(), directivesString(GraphQLEnumType.class, type.getDirectives())); + type.getName(), directivesString(GraphQLEnumType.class, type.getAppliedDirectives())); List values = type.getValues().stream().sorted(comparator).collect(toList()); if (values.size() > 0) { out.format(" {\n"); for (GraphQLEnumValueDefinition enumValueDefinition : values) { printComments(out, enumValueDefinition, " "); - List enumValueDirectives = enumValueDefinition.getDirectives(); + List enumValueDirectives = + enumValueDefinition.getAppliedDirectives(); if (enumValueDefinition.isDeprecated()) { enumValueDirectives = addDeprecatedDirectiveIfNeeded(enumValueDirectives); } @@ -644,7 +605,7 @@ private void printFieldDefinitions( .forEach( fd -> { printComments(out, fd, " "); - List fieldDirectives = fd.getDirectives(); + List fieldDirectives = fd.getAppliedDirectives(); if (fd.isDeprecated()) { fieldDirectives = addDeprecatedDirectiveIfNeeded(fieldDirectives); } @@ -672,7 +633,8 @@ private TypePrinter interfacePrinter() { if (type.getInterfaces().isEmpty()) { out.format( "interface %s%s", - type.getName(), directivesString(GraphQLInterfaceType.class, type.getDirectives())); + type.getName(), + directivesString(GraphQLInterfaceType.class, type.getAppliedDirectives())); } else { GraphqlTypeComparatorEnvironment environment = @@ -691,7 +653,7 @@ private TypePrinter interfacePrinter() { "interface %s implements %s%s", type.getName(), interfaceNames.collect(joining(" & ")), - directivesString(GraphQLInterfaceType.class, type.getDirectives())); + directivesString(GraphQLInterfaceType.class, type.getAppliedDirectives())); } GraphqlTypeComparatorEnvironment environment = @@ -728,7 +690,7 @@ private TypePrinter unionPrinter() { printComments(out, type, ""); out.format( "union %s%s = ", - type.getName(), directivesString(GraphQLUnionType.class, type.getDirectives())); + type.getName(), directivesString(GraphQLUnionType.class, type.getAppliedDirectives())); List types = type.getTypes().stream().sorted(comparator).collect(toList()); for (int i = 0; i < types.size(); i++) { @@ -755,7 +717,8 @@ private TypePrinter objectPrinter() { if (type.getInterfaces().isEmpty()) { out.format( "type %s%s", - type.getName(), directivesString(GraphQLObjectType.class, type.getDirectives())); + type.getName(), + directivesString(GraphQLObjectType.class, type.getAppliedDirectives())); } else { GraphqlTypeComparatorEnvironment environment = @@ -774,7 +737,7 @@ private TypePrinter objectPrinter() { "type %s implements %s%s", type.getName(), interfaceNames.collect(joining(" & ")), - directivesString(GraphQLObjectType.class, type.getDirectives())); + directivesString(GraphQLObjectType.class, type.getAppliedDirectives())); } GraphqlTypeComparatorEnvironment environment = @@ -810,7 +773,8 @@ private TypePrinter inputObjectPrinter() { out.format( "input %s%s", - type.getName(), directivesString(GraphQLInputObjectType.class, type.getDirectives())); + type.getName(), + directivesString(GraphQLInputObjectType.class, type.getAppliedDirectives())); List inputObjectFields = visibility.getFieldDefinitions(type); if (inputObjectFields.size() > 0) { out.format(" {\n"); @@ -826,7 +790,8 @@ private TypePrinter inputObjectPrinter() { String astValue = printAst(defaultValue, fd.getType()); out.format(" = %s", astValue); } - out.format(directivesString(GraphQLInputObjectField.class, fd.getDirectives())); + out.format( + directivesString(GraphQLInputObjectField.class, fd.getAppliedDirectives())); out.format("\n"); }); out.format("}"); @@ -871,7 +836,7 @@ private static String printAst(InputValueWithState value, GraphQLInputType type) private TypePrinter schemaPrinter() { return (out, schema, visibility) -> { - List schemaDirectives = schema.getSchemaDirectives(); + List schemaDirectives = schema.getSchemaAppliedDirectives(); GraphQLObjectType queryType = schema.getQueryType(); GraphQLObjectType mutationType = schema.getMutationType(); GraphQLObjectType subscriptionType = schema.getSubscriptionType(); @@ -917,7 +882,6 @@ private TypePrinter schemaPrinter() { private List getSchemaDirectives(GraphQLSchema schema) { return schema.getDirectives().stream() - .filter(options.getIncludeDirective()) .filter(options.getIncludeSchemaElement()) .filter(options.getIncludeDirectiveDefinition()) .collect(toList()); @@ -972,7 +936,7 @@ String argsString(Class parent, List !it.isEmpty()) @@ -990,7 +954,7 @@ String argsString(Class parent, List parent, List directives) { + Class parent, List directives) { directives = directives.stream() // @deprecated is special - we always print it if something is deprecated @@ -1019,7 +983,7 @@ String directivesString( directives = directives.stream().sorted(comparator).collect(toList()); for (int i = 0; i < directives.size(); i++) { - GraphQLDirective directive = directives.get(i); + GraphQLAppliedDirective directive = directives.get(i); sb.append(directiveString(directive)); if (i < directives.size() - 1) { sb.append(" "); @@ -1028,7 +992,7 @@ String directivesString( return sb.toString(); } - private String directiveString(GraphQLDirective directive) { + private String directiveString(GraphQLAppliedDirective directive) { if (!options.getIncludeSchemaElement().test(directive)) { return ""; } @@ -1050,21 +1014,19 @@ private String directiveString(GraphQLDirective directive) { Comparator comparator = options.comparatorRegistry.getComparator(environment); - List args = directive.getArguments(); + List args = directive.getArguments(); args = args.stream() - .filter(arg -> arg.getArgumentValue().isSet() || arg.getArgumentDefaultValue().isSet()) + .filter(arg -> arg.getArgumentValue().isSet()) .sorted(comparator) .collect(toList()); if (!args.isEmpty()) { sb.append("("); for (int i = 0; i < args.size(); i++) { - GraphQLArgument arg = args.get(i); + GraphQLAppliedDirectiveArgument arg = args.get(i); String argValue = null; if (arg.hasSetValue()) { argValue = printAst(arg.getArgumentValue(), arg.getType()); - } else if (arg.hasSetDefaultValue()) { - argValue = printAst(arg.getArgumentDefaultValue(), arg.getType()); } if (!isNullOrEmpty(argValue)) { sb.append(arg.getName()); @@ -1080,15 +1042,16 @@ private String directiveString(GraphQLDirective directive) { return sb.toString(); } - private boolean isDeprecatedDirective(GraphQLDirective directive) { + private boolean isDeprecatedDirective(GraphQLAppliedDirective directive) { return directive.getName().equals(DeprecatedDirective.getName()); } - private boolean hasDeprecatedDirective(List directives) { + private boolean hasDeprecatedDirective(List directives) { return directives.stream().filter(this::isDeprecatedDirective).count() == 1; } - private List addDeprecatedDirectiveIfNeeded(List directives) { + private List addDeprecatedDirectiveIfNeeded( + List directives) { if (!hasDeprecatedDirective(directives)) { directives = new ArrayList<>(directives); directives.add(DeprecatedDirective4Printing); diff --git a/graphql-java-support/src/test/java/com/apollographql/federation/graphqljava/FederationTest.java b/graphql-java-support/src/test/java/com/apollographql/federation/graphqljava/FederationTest.java index 0534a2ef..33876354 100644 --- a/graphql-java-support/src/test/java/com/apollographql/federation/graphqljava/FederationTest.java +++ b/graphql-java-support/src/test/java/com/apollographql/federation/graphqljava/FederationTest.java @@ -9,12 +9,8 @@ import graphql.ExecutionResult; import graphql.Scalars; import graphql.com.google.common.collect.ImmutableMap; -import graphql.schema.GraphQLFieldDefinition; -import graphql.schema.GraphQLNamedType; -import graphql.schema.GraphQLObjectType; -import graphql.schema.GraphQLScalarType; -import graphql.schema.GraphQLSchema; -import graphql.schema.GraphQLUnionType; +import graphql.language.StringValue; +import graphql.schema.*; import graphql.schema.idl.RuntimeWiring; import graphql.schema.idl.SchemaGenerator; import graphql.schema.idl.SchemaParser; @@ -51,6 +47,10 @@ class FederationTest { TestUtils.readResource("schemas/printerFilterExpected.graphql"); private final String fed2SDL = TestUtils.readResource("schemas/fed2.graphql"); private final String fed2FederatedSDL = TestUtils.readResource("schemas/fed2Federated.graphql"); + private final String directiveFederatedSDL = + TestUtils.readResource("schemas/directiveFederated.graphql"); + private final String directiveFederatedServiceSDL = + TestUtils.readResource("schemas/directiveFederatedService.graphql"); private final String fed2ServiceSDL = TestUtils.readResource("schemas/fed2Service.graphql"); private final String unionsSDL = TestUtils.readResource("schemas/unions.graphql"); private final String unionsFederatedSDL = @@ -237,6 +237,51 @@ void testFed2() { SchemaUtils.assertSDL(federatedSchema, fed2FederatedSDL, fed2ServiceSDL); } + @Test + void testFederationDirectives() { + final GraphQLSchema federatedSchema = + Federation.transform( + GraphQLSchema.newSchema() + .query( + GraphQLObjectType.newObject() + .name("Query") + .field( + GraphQLFieldDefinition.newFieldDefinition() + .name("dummy") + .type(Scalars.GraphQLString) + .build()) + .build()) + .additionalType( + GraphQLObjectType.newObject() + .name("Test") + .withAppliedDirective( + GraphQLAppliedDirective.newDirective() + .name("key") + .argument( + GraphQLAppliedDirectiveArgument.newArgument() + .name("fields") + .type(_FieldSet.type) + .valueLiteral( + StringValue.newStringValue("dummy").build()) + .build()) + .build()) + .field( + GraphQLFieldDefinition.newFieldDefinition() + .name("dummy") + .type(Scalars.GraphQLString) + .build()) + .build()) + .build(), + true) + .resolveEntityType(env -> env.getSchema().getObjectType("Point")) + .fetchEntities( + entityFetcher -> + ImmutableMap.builder().put("id", "1000").put("x", 0).put("y", 0).build()) + .build(); + + SchemaUtils.assertSDL(federatedSchema, directiveFederatedSDL, directiveFederatedServiceSDL); + } + @Test void testUnions() { final RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring().build(); diff --git a/graphql-java-support/src/test/resources/com/apollographql/federation/graphqljava/schemas/directiveFederated.graphql b/graphql-java-support/src/test/resources/com/apollographql/federation/graphqljava/schemas/directiveFederated.graphql new file mode 100644 index 00000000..bae8f420 --- /dev/null +++ b/graphql-java-support/src/test/resources/com/apollographql/federation/graphqljava/schemas/directiveFederated.graphql @@ -0,0 +1,16 @@ +union _Entity = Test + +type Query { + _entities(representations: [_Any!]!): [_Entity]! + _service: _Service +} + +type Test @key(fields : "dummy") { + dummy: String +} + +type _Service { + sdl: String! +} + +scalar _Any diff --git a/graphql-java-support/src/test/resources/com/apollographql/federation/graphqljava/schemas/directiveFederatedService.graphql b/graphql-java-support/src/test/resources/com/apollographql/federation/graphqljava/schemas/directiveFederatedService.graphql new file mode 100644 index 00000000..96343dbb --- /dev/null +++ b/graphql-java-support/src/test/resources/com/apollographql/federation/graphqljava/schemas/directiveFederatedService.graphql @@ -0,0 +1,9 @@ +schema { + query: Query +} + +type Query + +type Test @key(fields : "dummy") { + dummy: String +}