From 9e19738d5e3de82cf5737013448007ec9c012493 Mon Sep 17 00:00:00 2001 From: Gerrit Meier Date: Wed, 28 Apr 2021 23:36:39 +0200 Subject: [PATCH 1/4] Don't fail with enums in directive parameters. --- .../graphql/codegen/mapper/ValueMapper.java | 3 + .../GraphQLCodegenAnnotationsTest.java | 5 ++ .../codegen/GraphQLCodegenApisTest.java | 5 +- .../GraphQLCodegenModelsForRootTypesTest.java | 5 +- .../graphql/codegen/GraphQLCodegenTest.java | 6 +- .../scala/GraphQLCodegenAnnotationsTest.java | 5 ++ .../resources/expected-classes/User.java.txt | 68 ++++++++++++++++++ .../expected-classes/annotation/User.java.txt | 69 +++++++++++++++++++ .../scala/annotation/User.scala.txt | 18 +++++ src/test/resources/schemas/test.graphqls | 6 ++ 10 files changed, 183 insertions(+), 7 deletions(-) create mode 100644 src/test/resources/expected-classes/User.java.txt create mode 100644 src/test/resources/expected-classes/annotation/User.java.txt create mode 100644 src/test/resources/expected-classes/scala/annotation/User.scala.txt diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/ValueMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/ValueMapper.java index 665c070c1..ae6d4d0af 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/ValueMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/ValueMapper.java @@ -129,6 +129,9 @@ private String mapEnum(MappingContext mappingContext, EnumValue value, Type g if (graphQLType instanceof NonNullType) { return mapEnum(mappingContext, value, ((NonNullType) graphQLType).getType()); } + if (graphQLType == null) { + return value.getName(); + } throw new IllegalArgumentException("Unexpected Enum value for list type"); } diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenAnnotationsTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenAnnotationsTest.java index 92443742e..7993cd5fb 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenAnnotationsTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenAnnotationsTest.java @@ -210,6 +210,8 @@ void generate_Directives() throws Exception { "n={{n?toString}})")); directiveAnnotationsMapping.put("valid", singletonList("@javax.validation.Valid")); directiveAnnotationsMapping.put("customResolver", singletonList("@com.example.CustomAnnotation")); + directiveAnnotationsMapping.put("relationship", + singletonList("@com.example.Relationship(type = {{type}}, direction = {{direction}})")); mappingConfig.setDirectiveAnnotationsMapping(directiveAnnotationsMapping); new JavaGraphQLCodegen(singletonList("src/test/resources/schemas/test.graphqls"), @@ -225,6 +227,9 @@ void generate_Directives() throws Exception { assertSameTrimmedContent( new File("src/test/resources/expected-classes/annotation/EventProperty.java.txt"), getFileByName(files, "EventProperty.java")); + assertSameTrimmedContent( + new File("src/test/resources/expected-classes/annotation/User.java.txt"), + getFileByName(files, "User.java")); } } diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenApisTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenApisTest.java index 371ffe5f4..aa4f2186b 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenApisTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenApisTest.java @@ -138,7 +138,7 @@ void generate_DoNotGenerateApiInterfaceForOperations() throws IOException { File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); assertEquals(Arrays.asList( "Event.java", "EventProperty.java", "EventPropertyResolver.java", "EventStatus.java", - "MutationResolver.java", "QueryResolver.java", "SubscriptionResolver.java"), + "MutationResolver.java", "QueryResolver.java", "SubscriptionResolver.java", "User.java"), Arrays.stream(files).map(File::getName).sorted().collect(toList())); } @@ -155,7 +155,8 @@ void generate_DoNotGenerateRootApiInterfaces() throws IOException { assertEquals(Arrays.asList( "CreateEventMutationResolver.java", "Event.java", "EventByIdQueryResolver.java", "EventProperty.java", "EventPropertyResolver.java", "EventStatus.java", "EventsByCategoryAndStatusQueryResolver.java", - "EventsByIdsQueryResolver.java", "EventsCreatedSubscriptionResolver.java", "VersionQueryResolver.java"), + "EventsByIdsQueryResolver.java", "EventsCreatedSubscriptionResolver.java", "User.java", + "VersionQueryResolver.java"), Arrays.stream(files).map(File::getName).sorted().collect(toList())); } diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenModelsForRootTypesTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenModelsForRootTypesTest.java index 3f2f20f2b..b2a6f4ea4 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenModelsForRootTypesTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenModelsForRootTypesTest.java @@ -72,7 +72,7 @@ void generate_CheckFiles_generateApisFalse() throws Exception { File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); List generatedFileNames = Arrays.stream(files).map(File::getName).sorted().collect(toList()); assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventStatus.java", - "Mutation.java", "Query.java", "Subscription.java"), + "Mutation.java", "Query.java", "Subscription.java", "User.java"), generatedFileNames); } @@ -89,7 +89,8 @@ void generate_CheckFiles_generateApisTrue_CustomTypeResolverSuffix() throws Exce "EventsByCategoryAndStatusQueryResolver.java", "EventsByIdsQueryResolver.java", "EventsCreatedSubscriptionResolver.java", "Mutation.java", "MutationResolver.java", "MutationTypeResolver.java", "Query.java", "QueryResolver.java", "QueryTypeResolver.java", - "Subscription.java", "SubscriptionResolver.java", "VersionQueryResolver.java"), generatedFileNames); + "Subscription.java", "SubscriptionResolver.java", "User.java", "VersionQueryResolver.java"), + generatedFileNames); } } diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java index fb75abf12..7522a9006 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java @@ -70,7 +70,7 @@ void generate_CheckFiles() throws Exception { "CreateEventMutationResolver.java", "Event.java", "EventByIdQueryResolver.java", "EventProperty.java", "EventStatus.java", "EventsByCategoryAndStatusQueryResolver.java", "EventsByIdsQueryResolver.java", "EventsCreatedSubscriptionResolver.java", "MutationResolver.java", "QueryResolver.java", - "SubscriptionResolver.java", + "SubscriptionResolver.java", "User.java", "VersionQueryResolver.java"), generatedFileNames); for (File file : files) { @@ -170,7 +170,7 @@ void generate_CustomModelAndApiPackages() throws Exception { File[] modelFiles = Objects.requireNonNull(new File(outputJavaClassesDir, "model").listFiles()); List generatedModelFileNames = Arrays.stream(modelFiles).map(File::getName).sorted().collect(toList()); - assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventStatus.java"), generatedModelFileNames); + assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventStatus.java", "User.java"), generatedModelFileNames); for (File modelFile : modelFiles) { assertThat(Utils.getFileContent(modelFile.getPath()), @@ -296,7 +296,7 @@ void generate_OnlyModel() throws Exception { File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); List generatedFileNames = Arrays.stream(files).map(File::getName).sorted().collect(toList()); - assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventStatus.java"), generatedFileNames); + assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventStatus.java", "User.java"), generatedFileNames); } @Test diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenAnnotationsTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenAnnotationsTest.java index 91c545a5d..f5a288791 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenAnnotationsTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenAnnotationsTest.java @@ -171,6 +171,8 @@ void generate_Directives() throws Exception { "@com.example.CustomAnnotation(roles={{roles?toArray}}, " + "boo={{boo?toArray}}, float={{float?toArrayOfStrings}}, int={{int}}, " + "n={{n?toString}})")); + directiveAnnotationsMapping.put("relationship", + singletonList("@com.example.Relationship(type = {{type}}, direction = {{direction}})")); mappingConfig.setDirectiveAnnotationsMapping(directiveAnnotationsMapping); new ScalaGraphQLCodegen(singletonList("src/test/resources/schemas/test.graphqls"), @@ -183,6 +185,9 @@ void generate_Directives() throws Exception { assertSameTrimmedContent( new File("src/test/resources/expected-classes/scala/annotation/MutationResolver.scala.txt"), getFileByName(files, "MutationResolver.scala")); + assertSameTrimmedContent( + new File("src/test/resources/expected-classes/scala/annotation/User.scala.txt"), + getFileByName(files, "User.scala")); } } diff --git a/src/test/resources/expected-classes/User.java.txt b/src/test/resources/expected-classes/User.java.txt new file mode 100644 index 000000000..2c76824b2 --- /dev/null +++ b/src/test/resources/expected-classes/User.java.txt @@ -0,0 +1,68 @@ +package com.kobylynskyi.graphql.test1; + + +/** + * type with directive using enum value + */ +@javax.annotation.Generated( + value = "com.kobylynskyi.graphql.codegen.GraphQLCodegen", + date = "2020-12-31T23:59:59-0500" +) +public class User implements java.io.Serializable { + + private String name; + private java.util.List friends; + + public User() { + } + + public User(String name, java.util.List friends) { + this.name = name; + this.friends = friends; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public java.util.List getFriends() { + return friends; + } + public void setFriends(java.util.List friends) { + this.friends = friends; + } + + + + public static User.Builder builder() { + return new User.Builder(); + } + + public static class Builder { + + private String name; + private java.util.List friends; + + public Builder() { + } + + public Builder setName(String name) { + this.name = name; + return this; + } + + public Builder setFriends(java.util.List friends) { + this.friends = friends; + return this; + } + + + public User build() { + return new User(name, friends); + } + + } +} diff --git a/src/test/resources/expected-classes/annotation/User.java.txt b/src/test/resources/expected-classes/annotation/User.java.txt new file mode 100644 index 000000000..2ef170f20 --- /dev/null +++ b/src/test/resources/expected-classes/annotation/User.java.txt @@ -0,0 +1,69 @@ +package com.kobylynskyi.graphql.test1; + + +/** + * type with directive using enum value + */ +@javax.annotation.Generated( + value = "com.kobylynskyi.graphql.codegen.GraphQLCodegen", + date = "2020-12-31T23:59:59-0500" +) +public class User implements java.io.Serializable { + + private String name; + @com.example.Relationship(type = "FRIEND_WITH", direction = OUT) + private java.util.List friends; + + public User() { + } + + public User(String name, java.util.List friends) { + this.name = name; + this.friends = friends; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public java.util.List getFriends() { + return friends; + } + public void setFriends(java.util.List friends) { + this.friends = friends; + } + + + + public static User.Builder builder() { + return new User.Builder(); + } + + public static class Builder { + + private String name; + private java.util.List friends; + + public Builder() { + } + + public Builder setName(String name) { + this.name = name; + return this; + } + + public Builder setFriends(java.util.List friends) { + this.friends = friends; + return this; + } + + + public User build() { + return new User(name, friends); + } + + } +} diff --git a/src/test/resources/expected-classes/scala/annotation/User.scala.txt b/src/test/resources/expected-classes/scala/annotation/User.scala.txt new file mode 100644 index 000000000..a8ab13690 --- /dev/null +++ b/src/test/resources/expected-classes/scala/annotation/User.scala.txt @@ -0,0 +1,18 @@ +package com.kobylynskyi.graphql.test1 + +import scala.collection.JavaConverters._ + +/** + * type with directive using enum value + */ +@javax.annotation.Generated( + value = Array("com.kobylynskyi.graphql.codegen.GraphQLCodegen"), + date = "2020-12-31T23:59:59-0500" +) +case class User( + name: String, + @com.example.Relationship(type = "FRIEND_WITH", direction = OUT) + friends: scala.Seq[User] +) { + +} \ No newline at end of file diff --git a/src/test/resources/schemas/test.graphqls b/src/test/resources/schemas/test.graphqls index 2615eb1ef..1fa55eb05 100644 --- a/src/test/resources/schemas/test.graphqls +++ b/src/test/resources/schemas/test.graphqls @@ -95,6 +95,12 @@ enum EventStatus { LOGGED } +# type with directive using enum value +type User { + name: String, + friends: [User] @relationship(type: "FRIEND_WITH", direction: OUT) +} + directive @auth ( roles: [String] = ["viewer"], float: [Float] = [], From 7f93937228c64c6c0cb0b0fcaeb7b6fec325b93e Mon Sep 17 00:00:00 2001 From: Gerrit Meier Date: Thu, 29 Apr 2021 10:56:08 +0200 Subject: [PATCH 2/4] Move null condition to top. --- .../com/kobylynskyi/graphql/codegen/mapper/ValueMapper.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/ValueMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/ValueMapper.java index ae6d4d0af..87f161d12 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/ValueMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/ValueMapper.java @@ -121,6 +121,9 @@ public String map(MappingContext mappingContext, Value value, Type graphQL } private String mapEnum(MappingContext mappingContext, EnumValue value, Type graphQLType) { + if (graphQLType == null) { + return value.getName(); + } if (graphQLType instanceof TypeName) { String typeName = ((TypeName) graphQLType).getName(); typeName = DataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, typeName); @@ -129,9 +132,6 @@ private String mapEnum(MappingContext mappingContext, EnumValue value, Type g if (graphQLType instanceof NonNullType) { return mapEnum(mappingContext, value, ((NonNullType) graphQLType).getType()); } - if (graphQLType == null) { - return value.getName(); - } throw new IllegalArgumentException("Unexpected Enum value for list type"); } From 8d630278eb2676c8f0e449bd5a11f1084e2af318 Mon Sep 17 00:00:00 2001 From: Gerrit Meier Date: Thu, 29 Apr 2021 12:04:15 +0200 Subject: [PATCH 3/4] Avoid duplicates in enum imports (Scala). --- .../scala-lang/scalaClassGraphqlType.ftl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlType.ftl b/src/main/resources/templates/scala-lang/scalaClassGraphqlType.ftl index 5af61b29a..bc2e590d3 100644 --- a/src/main/resources/templates/scala-lang/scalaClassGraphqlType.ftl +++ b/src/main/resources/templates/scala-lang/scalaClassGraphqlType.ftl @@ -15,23 +15,37 @@ import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLRequestSerializer import java.util.Objects import scala.collection.JavaConverters._ +<#assign duplicateEnumImports = [] /> +<#assign enumImports = [] /> <#if fields?has_content> <#if enumImportItSelfInScala?has_content> <#list fields as field> <#list enumImportItSelfInScala as enum> <#if MapperUtil.isScalaCollection(field.type)> <#if enum == MapperUtil.getGenericParameter(field.type)> -import ${enum}._ + <#assign duplicateEnumImports = duplicateEnumImports + [enum] /> <#else > <#if enum == field.type> -import ${enum}._ + <#assign duplicateEnumImports = duplicateEnumImports + [enum] /> +<#if duplicateEnumImports?has_content> + <#list duplicateEnumImports as duplicateEnumImport> + <#if !enumImports?seq_contains(duplicateEnumImport)> + <#assign enumImports = enumImports + [duplicateEnumImport]> + + + +<#if enumImports?has_content> + <#list enumImports as enumImport> +import ${enumImport}._ + + <#assign duplicateParentInterfaces = [] /> <#assign parentInterfaces = [] /> <#if fields?has_content> From aa85c369d96c07781ad786afe832fc378c9149d4 Mon Sep 17 00:00:00 2001 From: Gerrit Meier Date: Thu, 29 Apr 2021 15:08:56 +0200 Subject: [PATCH 4/4] Fix checkstyle. --- .../com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java index 7522a9006..adf646710 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java @@ -170,7 +170,8 @@ void generate_CustomModelAndApiPackages() throws Exception { File[] modelFiles = Objects.requireNonNull(new File(outputJavaClassesDir, "model").listFiles()); List generatedModelFileNames = Arrays.stream(modelFiles).map(File::getName).sorted().collect(toList()); - assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventStatus.java", "User.java"), generatedModelFileNames); + assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventStatus.java", "User.java"), + generatedModelFileNames); for (File modelFile : modelFiles) { assertThat(Utils.getFileContent(modelFile.getPath()), @@ -296,7 +297,8 @@ void generate_OnlyModel() throws Exception { File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); List generatedFileNames = Arrays.stream(files).map(File::getName).sorted().collect(toList()); - assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventStatus.java", "User.java"), generatedFileNames); + assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventStatus.java", "User.java"), + generatedFileNames); } @Test