From 9e19738d5e3de82cf5737013448007ec9c012493 Mon Sep 17 00:00:00 2001 From: Gerrit Meier Date: Wed, 28 Apr 2021 23:36:39 +0200 Subject: [PATCH 01/23] 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 02/23] 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 03/23] 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 04/23] 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 From c40ec60beb941caa365d525cceb2688816000caf Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Wed, 16 Jun 2021 16:21:00 +0300 Subject: [PATCH 05/23] Update to next development version: 5.2.1-SNAPSHOT --- build.gradle | 2 +- plugins/gradle/example-client-kotlin/build.gradle | 6 +++--- plugins/gradle/example-client/build.gradle | 4 ++-- plugins/gradle/example-server/build.gradle | 2 +- .../gradle/graphql-java-codegen-gradle-plugin/build.gradle | 2 +- plugins/maven/example-client/pom.xml | 2 +- plugins/maven/example-server/pom.xml | 2 +- plugins/maven/graphql-java-codegen-maven-plugin/pom.xml | 4 ++-- .../example-client-scala/project/plugins.sbt | 2 +- .../example-client-scala/version.sbt | 2 +- .../example-client/project/plugins.sbt | 2 +- .../graphql-codegen-sbt-plugin/example-client/version.sbt | 2 +- .../graphql-codegen-sbt-plugin/simple/project/plugins.sbt | 2 +- .../sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt | 2 +- plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt | 2 +- 15 files changed, 19 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index 1f38d5d81..04700a65c 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { id "org.sonarqube" version "3.2.0" } -def graphqlCodegenVersion = '5.2.0' // This variable used in the automatic release process +def graphqlCodegenVersion = '5.2.1-SNAPSHOT' // This variable used in the automatic release process group = "io.github.kobylynskyi" version = graphqlCodegenVersion diff --git a/plugins/gradle/example-client-kotlin/build.gradle b/plugins/gradle/example-client-kotlin/build.gradle index 01b3bd777..fe23583d0 100644 --- a/plugins/gradle/example-client-kotlin/build.gradle +++ b/plugins/gradle/example-client-kotlin/build.gradle @@ -4,10 +4,10 @@ import io.github.kobylynskyi.graphql.codegen.gradle.GraphQLCodegenGradleTask plugins { id 'java' id "org.jetbrains.kotlin.jvm" version "1.3.71" - id "io.github.kobylynskyi.graphql.codegen" version "5.2.0" + id "io.github.kobylynskyi.graphql.codegen" version "5.2.1-SNAPSHOT" } -def graphqlCodegenClientKotlinVersion = '5.2.0' // Variable used in the automatic release process +def graphqlCodegenClientKotlinVersion = '5.2.1-SNAPSHOT' // Variable used in the automatic release process group = 'io.github.dreamylost' version = graphqlCodegenClientKotlinVersion @@ -29,7 +29,7 @@ repositories { dependencies { - implementation "io.github.kobylynskyi:graphql-java-codegen:5.2.0" + implementation "io.github.kobylynskyi:graphql-java-codegen:5.2.1-SNAPSHOT" implementation "javax.validation:validation-api:2.0.1.Final" implementation "com.squareup.okhttp3:okhttp:4.2.2" implementation "com.fasterxml.jackson.core:jackson-core:2.12.0" diff --git a/plugins/gradle/example-client/build.gradle b/plugins/gradle/example-client/build.gradle index 3ac95f100..e25f12db7 100644 --- a/plugins/gradle/example-client/build.gradle +++ b/plugins/gradle/example-client/build.gradle @@ -7,7 +7,7 @@ plugins { // use the latest available version: // https://plugins.gradle.org/plugin/io.github.kobylynskyi.graphql.codegen - id "io.github.kobylynskyi.graphql.codegen" version "5.2.0" + id "io.github.kobylynskyi.graphql.codegen" version "5.2.1-SNAPSHOT" } mainClassName = "io.github.kobylynskyi.order.Application" @@ -22,7 +22,7 @@ dependencies { // use the latest available version: // https://search.maven.org/artifact/io.github.kobylynskyi/graphql-java-codegen - implementation "io.github.kobylynskyi:graphql-java-codegen:5.2.0" + implementation "io.github.kobylynskyi:graphql-java-codegen:5.2.1-SNAPSHOT" implementation "org.apache.httpcomponents:httpclient:4.5.13" implementation "javax.validation:validation-api:2.0.1.Final" diff --git a/plugins/gradle/example-server/build.gradle b/plugins/gradle/example-server/build.gradle index f78bbddd3..676c80a9c 100644 --- a/plugins/gradle/example-server/build.gradle +++ b/plugins/gradle/example-server/build.gradle @@ -6,7 +6,7 @@ plugins { // // use the latest available version: // https://plugins.gradle.org/plugin/io.github.kobylynskyi.graphql.codegen - id "io.github.kobylynskyi.graphql.codegen" version "5.2.0" + id "io.github.kobylynskyi.graphql.codegen" version "5.2.1-SNAPSHOT" } mainClassName = "io.github.kobylynskyi.product.Application" diff --git a/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle b/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle index 3e553b03e..e30c216bf 100644 --- a/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle +++ b/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle @@ -16,7 +16,7 @@ apply plugin: "java" apply plugin: "idea" apply plugin: "maven-publish" -def graphqlCodegenGradlePluginVersion = '5.2.0' // This variable used in the automatic release process +def graphqlCodegenGradlePluginVersion = '5.2.1-SNAPSHOT' // This variable used in the automatic release process group = "io.github.kobylynskyi" version = graphqlCodegenGradlePluginVersion diff --git a/plugins/maven/example-client/pom.xml b/plugins/maven/example-client/pom.xml index 1d963d8bf..4c575f42d 100644 --- a/plugins/maven/example-client/pom.xml +++ b/plugins/maven/example-client/pom.xml @@ -4,7 +4,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin-example-client - 5.2.0 + 5.2.1-SNAPSHOT graphql-codegen-maven-plugin-example-client diff --git a/plugins/maven/example-server/pom.xml b/plugins/maven/example-server/pom.xml index dd8be84af..153ef0b22 100644 --- a/plugins/maven/example-server/pom.xml +++ b/plugins/maven/example-server/pom.xml @@ -4,7 +4,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin-example-server - 5.2.0 + 5.2.1-SNAPSHOT graphql-codegen-maven-plugin-example-server diff --git a/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml b/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml index dfbea7c55..3cd23c453 100644 --- a/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml +++ b/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml @@ -3,7 +3,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin - 5.2.0 + 5.2.1-SNAPSHOT maven-plugin graphql-codegen-maven-plugin @@ -72,7 +72,7 @@ 3.0.1 3.3.4 - 5.2.0 + 5.2.1-SNAPSHOT diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt index 4e93c6101..59e0752c7 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.2.0") +addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.2.1-SNAPSHOT") diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt index 371c2bd0f..871ee4551 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.2.0" +version in ThisBuild := "5.2.1-SNAPSHOT" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt index 4e93c6101..59e0752c7 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.2.0") +addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.2.1-SNAPSHOT") diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt index 371c2bd0f..871ee4551 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.2.0" +version in ThisBuild := "5.2.1-SNAPSHOT" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt index 86976e256..b05df94fd 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt @@ -1,4 +1,4 @@ -sys.props.get("plugin.version").orElse(Some("5.2.0")) match { +sys.props.get("plugin.version").orElse(Some("5.2.1-SNAPSHOT")) match { case Some(x) => addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % x) case _ => sys.error("""|The system property 'plugin.version' is not defined. |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt index 371c2bd0f..871ee4551 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.2.0" +version in ThisBuild := "5.2.1-SNAPSHOT" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt index 371c2bd0f..871ee4551 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.2.0" +version in ThisBuild := "5.2.1-SNAPSHOT" From fb176356e22a6eebadd2ee17ef624c40f417c84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=A6=E5=A2=83=E8=BF=B7=E7=A6=BB?= Date: Mon, 5 Jul 2021 20:07:19 +0800 Subject: [PATCH 06/23] Scala: fix generateModelOpenClasses (#741) When use `generateModelOpenClasses`, add `val` before field declaration --- .../scala-lang/scalaClassGraphqlType.ftl | 2 +- .../scala/GraphQLCodegenOpenclassesTest.java | 10 + .../scala/Commit_no_final_class.scala.txt | 56 +-- .../Commit_normal_class_var_fields.scala.txt | 412 ++++++++++++++++++ 4 files changed, 451 insertions(+), 29 deletions(-) create mode 100644 src/test/resources/expected-classes/scala/Commit_normal_class_var_fields.scala.txt diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlType.ftl b/src/main/resources/templates/scala-lang/scalaClassGraphqlType.ftl index 5af61b29a..3f96b706d 100644 --- a/src/main/resources/templates/scala-lang/scalaClassGraphqlType.ftl +++ b/src/main/resources/templates/scala-lang/scalaClassGraphqlType.ftl @@ -80,7 +80,7 @@ import ${enum}._ <#list field.annotations as annotation> @${annotation} - <#if parentInterfaces?has_content><#list parentInterfaces as parent><#if parent == field.name>override <#if !immutableModels>var <#else><#if parentInterfaces?has_content><#list parentInterfaces as parent><#if parent == field.name>val ${field.name}: ${field.type}<#if field.defaultValue?has_content> = <#if MapperUtil.isScalaOption(field.type)><#if field.defaultValue != "null">Some(${field.defaultValue})<#else>None<#else>${field.defaultValue}<#if field_has_next>, + <#if parentInterfaces?has_content><#list parentInterfaces as parent><#if parent == field.name>override <#if !immutableModels>var <#elseif generateModelOpenClasses>val <#else><#if parentInterfaces?has_content><#list parentInterfaces as parent><#if parent == field.name>val ${field.name}: ${field.type}<#if field.defaultValue?has_content> = <#if MapperUtil.isScalaOption(field.type)><#if field.defaultValue != "null">Some(${field.defaultValue})<#else>None<#else>${field.defaultValue}<#if field_has_next>, )<#if implements?has_content> extends <#list implements as interface>${interface}<#if interface_has_next> with { diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenOpenclassesTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenOpenclassesTest.java index 70a80fe40..ea3a3c49f 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenOpenclassesTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenOpenclassesTest.java @@ -49,4 +49,14 @@ void generate_MultipleInterfacesPerType() throws Exception { getFileByName(files, "Commit.scala")); } + @Test + void generate_MultipleInterfacesPerTypeVarFields() throws Exception { + mappingConfig.setGenerateImmutableModels(false); + new ScalaGraphQLCodegen(singletonList("src/test/resources/schemas/github.graphqls"), + outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); + File[] files = Objects.requireNonNull(outputScalaClassesDir.listFiles()); + + assertSameTrimmedContent(getFileByName(files, "Commit.scala"), + new File("src/test/resources/expected-classes/scala/Commit_normal_class_var_fields.scala.txt")); + } } \ No newline at end of file diff --git a/src/test/resources/expected-classes/scala/Commit_no_final_class.scala.txt b/src/test/resources/expected-classes/scala/Commit_no_final_class.scala.txt index 1b71d9f1b..ff216623c 100644 --- a/src/test/resources/expected-classes/scala/Commit_no_final_class.scala.txt +++ b/src/test/resources/expected-classes/scala/Commit_no_final_class.scala.txt @@ -12,67 +12,67 @@ import SubscriptionState._ class Commit( @javax.validation.constraints.NotNull override val abbreviatedOid: String, - additions: Int, - associatedPullRequests: PullRequestConnection, - author: GitActor, - authoredByCommitter: Boolean, + val additions: Int, + val associatedPullRequests: PullRequestConnection, + val author: GitActor, + val authoredByCommitter: Boolean, @javax.validation.constraints.NotNull - authoredDate: String, + val authoredDate: String, @javax.validation.constraints.NotNull - blame: Blame, - changedFiles: Int, + val blame: Blame, + val changedFiles: Int, @javax.validation.constraints.NotNull - comments: CommitCommentConnection, + val comments: CommitCommentConnection, @javax.validation.constraints.NotNull override val commitResourcePath: String, @javax.validation.constraints.NotNull override val commitUrl: String, @javax.validation.constraints.NotNull - committedDate: String, - committedViaWeb: Boolean, - committer: GitActor, - deletions: Int, - deployments: DeploymentConnection, + val committedDate: String, + val committedViaWeb: Boolean, + val committer: GitActor, + val deletions: Int, + val deployments: DeploymentConnection, @javax.validation.constraints.NotNull - history: CommitHistoryConnection, + val history: CommitHistoryConnection, @javax.validation.constraints.NotNull override val id: String, @javax.validation.constraints.NotNull - message: String, + val message: String, @javax.validation.constraints.NotNull - messageBody: String, + val messageBody: String, @javax.validation.constraints.NotNull - messageBodyHTML: String, + val messageBodyHTML: String, @javax.validation.constraints.NotNull - messageHeadline: String, + val messageHeadline: String, @javax.validation.constraints.NotNull - messageHeadlineHTML: String, + val messageHeadlineHTML: String, @javax.validation.constraints.NotNull override val oid: String, @javax.validation.constraints.NotNull - parents: CommitConnection, - pushedDate: String, + val parents: CommitConnection, + val pushedDate: String, @javax.validation.constraints.NotNull override val repository: Repository, @javax.validation.constraints.NotNull override val resourcePath: String, - signature: GitSignature, - status: Status, + val signature: GitSignature, + val status: Status, @javax.validation.constraints.NotNull - tarballUrl: String, + val tarballUrl: String, @javax.validation.constraints.NotNull - tree: Tree, + val tree: Tree, @javax.validation.constraints.NotNull - treeResourcePath: String, + val treeResourcePath: String, @javax.validation.constraints.NotNull - treeUrl: String, + val treeUrl: String, @javax.validation.constraints.NotNull override val url: String, override val viewerCanSubscribe: Boolean, @com.fasterxml.jackson.module.scala.JsonScalaEnumeration(classOf[com.github.graphql.SubscriptionStateTypeRefer]) override val viewerSubscription: SubscriptionState, @javax.validation.constraints.NotNull - zipballUrl: String + val zipballUrl: String ) extends Closer with IssueTimelineItem with PullRequestTimelineItem with Subscribable with Node with GitObject with UniformResourceLocatable { override def toString(): String = { diff --git a/src/test/resources/expected-classes/scala/Commit_normal_class_var_fields.scala.txt b/src/test/resources/expected-classes/scala/Commit_normal_class_var_fields.scala.txt new file mode 100644 index 000000000..f4b560c7c --- /dev/null +++ b/src/test/resources/expected-classes/scala/Commit_normal_class_var_fields.scala.txt @@ -0,0 +1,412 @@ +package com.github.graphql + +import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLRequestSerializer +import java.util.Objects +import scala.collection.JavaConverters._ +import SubscriptionState._ + +@javax.annotation.Generated( + value = Array("com.kobylynskyi.graphql.codegen.GraphQLCodegen"), + date = "2020-12-31T23:59:59-0500" +) +class Commit( + @javax.validation.constraints.NotNull + override var abbreviatedOid: String, + var additions: Int, + var associatedPullRequests: PullRequestConnection, + var author: GitActor, + var authoredByCommitter: Boolean, + @javax.validation.constraints.NotNull + var authoredDate: String, + @javax.validation.constraints.NotNull + var blame: Blame, + var changedFiles: Int, + @javax.validation.constraints.NotNull + var comments: CommitCommentConnection, + @javax.validation.constraints.NotNull + override var commitResourcePath: String, + @javax.validation.constraints.NotNull + override var commitUrl: String, + @javax.validation.constraints.NotNull + var committedDate: String, + var committedViaWeb: Boolean, + var committer: GitActor, + var deletions: Int, + var deployments: DeploymentConnection, + @javax.validation.constraints.NotNull + var history: CommitHistoryConnection, + @javax.validation.constraints.NotNull + override var id: String, + @javax.validation.constraints.NotNull + var message: String, + @javax.validation.constraints.NotNull + var messageBody: String, + @javax.validation.constraints.NotNull + var messageBodyHTML: String, + @javax.validation.constraints.NotNull + var messageHeadline: String, + @javax.validation.constraints.NotNull + var messageHeadlineHTML: String, + @javax.validation.constraints.NotNull + override var oid: String, + @javax.validation.constraints.NotNull + var parents: CommitConnection, + var pushedDate: String, + @javax.validation.constraints.NotNull + override var repository: Repository, + @javax.validation.constraints.NotNull + override var resourcePath: String, + var signature: GitSignature, + var status: Status, + @javax.validation.constraints.NotNull + var tarballUrl: String, + @javax.validation.constraints.NotNull + var tree: Tree, + @javax.validation.constraints.NotNull + var treeResourcePath: String, + @javax.validation.constraints.NotNull + var treeUrl: String, + @javax.validation.constraints.NotNull + override var url: String, + override var viewerCanSubscribe: Boolean, + @com.fasterxml.jackson.module.scala.JsonScalaEnumeration(classOf[com.github.graphql.SubscriptionStateTypeRefer]) + override var viewerSubscription: SubscriptionState, + @javax.validation.constraints.NotNull + var zipballUrl: String +) extends Closer with IssueTimelineItem with PullRequestTimelineItem with Subscribable with Node with GitObject with UniformResourceLocatable { + + override def toString(): String = { + scala.Seq( + if (abbreviatedOid != null) "abbreviatedOid: " + GraphQLRequestSerializer.getEntry(abbreviatedOid) else "", + "additions: " + GraphQLRequestSerializer.getEntry(additions), + if (associatedPullRequests != null) "associatedPullRequests: " + GraphQLRequestSerializer.getEntry(associatedPullRequests) else "", + if (author != null) "author: " + GraphQLRequestSerializer.getEntry(author) else "", + "authoredByCommitter: " + GraphQLRequestSerializer.getEntry(authoredByCommitter), + if (authoredDate != null) "authoredDate: " + GraphQLRequestSerializer.getEntry(authoredDate) else "", + if (blame != null) "blame: " + GraphQLRequestSerializer.getEntry(blame) else "", + "changedFiles: " + GraphQLRequestSerializer.getEntry(changedFiles), + if (comments != null) "comments: " + GraphQLRequestSerializer.getEntry(comments) else "", + if (commitResourcePath != null) "commitResourcePath: " + GraphQLRequestSerializer.getEntry(commitResourcePath) else "", + if (commitUrl != null) "commitUrl: " + GraphQLRequestSerializer.getEntry(commitUrl) else "", + if (committedDate != null) "committedDate: " + GraphQLRequestSerializer.getEntry(committedDate) else "", + "committedViaWeb: " + GraphQLRequestSerializer.getEntry(committedViaWeb), + if (committer != null) "committer: " + GraphQLRequestSerializer.getEntry(committer) else "", + "deletions: " + GraphQLRequestSerializer.getEntry(deletions), + if (deployments != null) "deployments: " + GraphQLRequestSerializer.getEntry(deployments) else "", + if (history != null) "history: " + GraphQLRequestSerializer.getEntry(history) else "", + if (id != null) "id: " + GraphQLRequestSerializer.getEntry(id) else "", + if (message != null) "message: " + GraphQLRequestSerializer.getEntry(message) else "", + if (messageBody != null) "messageBody: " + GraphQLRequestSerializer.getEntry(messageBody) else "", + if (messageBodyHTML != null) "messageBodyHTML: " + GraphQLRequestSerializer.getEntry(messageBodyHTML) else "", + if (messageHeadline != null) "messageHeadline: " + GraphQLRequestSerializer.getEntry(messageHeadline) else "", + if (messageHeadlineHTML != null) "messageHeadlineHTML: " + GraphQLRequestSerializer.getEntry(messageHeadlineHTML) else "", + if (oid != null) "oid: " + GraphQLRequestSerializer.getEntry(oid) else "", + if (parents != null) "parents: " + GraphQLRequestSerializer.getEntry(parents) else "", + if (pushedDate != null) "pushedDate: " + GraphQLRequestSerializer.getEntry(pushedDate) else "", + if (repository != null) "repository: " + GraphQLRequestSerializer.getEntry(repository) else "", + if (resourcePath != null) "resourcePath: " + GraphQLRequestSerializer.getEntry(resourcePath) else "", + if (signature != null) "signature: " + GraphQLRequestSerializer.getEntry(signature) else "", + if (status != null) "status: " + GraphQLRequestSerializer.getEntry(status) else "", + if (tarballUrl != null) "tarballUrl: " + GraphQLRequestSerializer.getEntry(tarballUrl) else "", + if (tree != null) "tree: " + GraphQLRequestSerializer.getEntry(tree) else "", + if (treeResourcePath != null) "treeResourcePath: " + GraphQLRequestSerializer.getEntry(treeResourcePath) else "", + if (treeUrl != null) "treeUrl: " + GraphQLRequestSerializer.getEntry(treeUrl) else "", + if (url != null) "url: " + GraphQLRequestSerializer.getEntry(url) else "", + "viewerCanSubscribe: " + GraphQLRequestSerializer.getEntry(viewerCanSubscribe), + if (viewerSubscription != null) "viewerSubscription: " + GraphQLRequestSerializer.getEntry(viewerSubscription) else "", + if (zipballUrl != null) "zipballUrl: " + GraphQLRequestSerializer.getEntry(zipballUrl) else "" + ).filter(_ != "").mkString("{", ",", "}") + } + + override def equals(obj: Any): Boolean = { + if (this == obj) { + return true + } + if (obj == null || getClass != obj.getClass) { + return false + } + val that = obj.asInstanceOf[Commit] + Objects.equals(abbreviatedOid, that.abbreviatedOid) && + Objects.equals(additions, that.additions) && + Objects.equals(associatedPullRequests, that.associatedPullRequests) && + Objects.equals(author, that.author) && + Objects.equals(authoredByCommitter, that.authoredByCommitter) && + Objects.equals(authoredDate, that.authoredDate) && + Objects.equals(blame, that.blame) && + Objects.equals(changedFiles, that.changedFiles) && + Objects.equals(comments, that.comments) && + Objects.equals(commitResourcePath, that.commitResourcePath) && + Objects.equals(commitUrl, that.commitUrl) && + Objects.equals(committedDate, that.committedDate) && + Objects.equals(committedViaWeb, that.committedViaWeb) && + Objects.equals(committer, that.committer) && + Objects.equals(deletions, that.deletions) && + Objects.equals(deployments, that.deployments) && + Objects.equals(history, that.history) && + Objects.equals(id, that.id) && + Objects.equals(message, that.message) && + Objects.equals(messageBody, that.messageBody) && + Objects.equals(messageBodyHTML, that.messageBodyHTML) && + Objects.equals(messageHeadline, that.messageHeadline) && + Objects.equals(messageHeadlineHTML, that.messageHeadlineHTML) && + Objects.equals(oid, that.oid) && + Objects.equals(parents, that.parents) && + Objects.equals(pushedDate, that.pushedDate) && + Objects.equals(repository, that.repository) && + Objects.equals(resourcePath, that.resourcePath) && + Objects.equals(signature, that.signature) && + Objects.equals(status, that.status) && + Objects.equals(tarballUrl, that.tarballUrl) && + Objects.equals(tree, that.tree) && + Objects.equals(treeResourcePath, that.treeResourcePath) && + Objects.equals(treeUrl, that.treeUrl) && + Objects.equals(url, that.url) && + Objects.equals(viewerCanSubscribe, that.viewerCanSubscribe) && + Objects.equals(viewerSubscription, that.viewerSubscription) && + Objects.equals(zipballUrl, that.zipballUrl) + } + + override def hashCode(): Int = { + Objects.hash(abbreviatedOid, additions, associatedPullRequests, author, authoredByCommitter, authoredDate, blame, changedFiles, comments, commitResourcePath, commitUrl, committedDate, committedViaWeb, committer, deletions, deployments, history, id, message, messageBody, messageBodyHTML, messageHeadline, messageHeadlineHTML, oid, parents, pushedDate, repository, resourcePath, signature, status, tarballUrl, tree, treeResourcePath, treeUrl, url, viewerCanSubscribe, viewerSubscription, zipballUrl) + } +} + +object Commit { + + def builder(): Commit.Builder = new Builder() + + class Builder { + + private var abbreviatedOid: String = _ + private var additions: Int = _ + private var associatedPullRequests: PullRequestConnection = _ + private var author: GitActor = _ + private var authoredByCommitter: Boolean = _ + private var authoredDate: String = _ + private var blame: Blame = _ + private var changedFiles: Int = _ + private var comments: CommitCommentConnection = _ + private var commitResourcePath: String = _ + private var commitUrl: String = _ + private var committedDate: String = _ + private var committedViaWeb: Boolean = _ + private var committer: GitActor = _ + private var deletions: Int = _ + private var deployments: DeploymentConnection = _ + private var history: CommitHistoryConnection = _ + private var id: String = _ + private var message: String = _ + private var messageBody: String = _ + private var messageBodyHTML: String = _ + private var messageHeadline: String = _ + private var messageHeadlineHTML: String = _ + private var oid: String = _ + private var parents: CommitConnection = _ + private var pushedDate: String = _ + private var repository: Repository = _ + private var resourcePath: String = _ + private var signature: GitSignature = _ + private var status: Status = _ + private var tarballUrl: String = _ + private var tree: Tree = _ + private var treeResourcePath: String = _ + private var treeUrl: String = _ + private var url: String = _ + private var viewerCanSubscribe: Boolean = _ + private var viewerSubscription: SubscriptionState = _ + private var zipballUrl: String = _ + + def setAbbreviatedOid(abbreviatedOid: String): Builder = { + this.abbreviatedOid = abbreviatedOid + this + } + + def setAdditions(additions: Int): Builder = { + this.additions = additions + this + } + + def setAssociatedPullRequests(associatedPullRequests: PullRequestConnection): Builder = { + this.associatedPullRequests = associatedPullRequests + this + } + + def setAuthor(author: GitActor): Builder = { + this.author = author + this + } + + def setAuthoredByCommitter(authoredByCommitter: Boolean): Builder = { + this.authoredByCommitter = authoredByCommitter + this + } + + def setAuthoredDate(authoredDate: String): Builder = { + this.authoredDate = authoredDate + this + } + + def setBlame(blame: Blame): Builder = { + this.blame = blame + this + } + + def setChangedFiles(changedFiles: Int): Builder = { + this.changedFiles = changedFiles + this + } + + def setComments(comments: CommitCommentConnection): Builder = { + this.comments = comments + this + } + + def setCommitResourcePath(commitResourcePath: String): Builder = { + this.commitResourcePath = commitResourcePath + this + } + + def setCommitUrl(commitUrl: String): Builder = { + this.commitUrl = commitUrl + this + } + + def setCommittedDate(committedDate: String): Builder = { + this.committedDate = committedDate + this + } + + def setCommittedViaWeb(committedViaWeb: Boolean): Builder = { + this.committedViaWeb = committedViaWeb + this + } + + def setCommitter(committer: GitActor): Builder = { + this.committer = committer + this + } + + def setDeletions(deletions: Int): Builder = { + this.deletions = deletions + this + } + + def setDeployments(deployments: DeploymentConnection): Builder = { + this.deployments = deployments + this + } + + def setHistory(history: CommitHistoryConnection): Builder = { + this.history = history + this + } + + def setId(id: String): Builder = { + this.id = id + this + } + + def setMessage(message: String): Builder = { + this.message = message + this + } + + def setMessageBody(messageBody: String): Builder = { + this.messageBody = messageBody + this + } + + def setMessageBodyHTML(messageBodyHTML: String): Builder = { + this.messageBodyHTML = messageBodyHTML + this + } + + def setMessageHeadline(messageHeadline: String): Builder = { + this.messageHeadline = messageHeadline + this + } + + def setMessageHeadlineHTML(messageHeadlineHTML: String): Builder = { + this.messageHeadlineHTML = messageHeadlineHTML + this + } + + def setOid(oid: String): Builder = { + this.oid = oid + this + } + + def setParents(parents: CommitConnection): Builder = { + this.parents = parents + this + } + + def setPushedDate(pushedDate: String): Builder = { + this.pushedDate = pushedDate + this + } + + def setRepository(repository: Repository): Builder = { + this.repository = repository + this + } + + def setResourcePath(resourcePath: String): Builder = { + this.resourcePath = resourcePath + this + } + + def setSignature(signature: GitSignature): Builder = { + this.signature = signature + this + } + + def setStatus(status: Status): Builder = { + this.status = status + this + } + + def setTarballUrl(tarballUrl: String): Builder = { + this.tarballUrl = tarballUrl + this + } + + def setTree(tree: Tree): Builder = { + this.tree = tree + this + } + + def setTreeResourcePath(treeResourcePath: String): Builder = { + this.treeResourcePath = treeResourcePath + this + } + + def setTreeUrl(treeUrl: String): Builder = { + this.treeUrl = treeUrl + this + } + + def setUrl(url: String): Builder = { + this.url = url + this + } + + def setViewerCanSubscribe(viewerCanSubscribe: Boolean): Builder = { + this.viewerCanSubscribe = viewerCanSubscribe + this + } + + def setViewerSubscription(viewerSubscription: SubscriptionState): Builder = { + this.viewerSubscription = viewerSubscription + this + } + + def setZipballUrl(zipballUrl: String): Builder = { + this.zipballUrl = zipballUrl + this + } + + def build(): Commit = new Commit(abbreviatedOid, additions, associatedPullRequests, author, authoredByCommitter, authoredDate, blame, changedFiles, comments, commitResourcePath, commitUrl, committedDate, committedViaWeb, committer, deletions, deployments, history, id, message, messageBody, messageBodyHTML, messageHeadline, messageHeadlineHTML, oid, parents, pushedDate, repository, resourcePath, signature, status, tarballUrl, tree, treeResourcePath, treeUrl, url, viewerCanSubscribe, viewerSubscription, zipballUrl) + + } +} \ No newline at end of file From 1ddbbf5c06695161fe9a8e9c813b3c1bfdc80d6c Mon Sep 17 00:00:00 2001 From: Kyle Brooks Date: Fri, 3 Sep 2021 12:07:05 -0700 Subject: [PATCH 07/23] Add @JvmStatic annotation to Kotlin builders (#771) Co-authored-by: Kyle --- CONTRIBUTING.md | 19 ++++++++++--------- .../kotlin-lang/kotlinClassGraphqlRequest.ftl | 2 +- .../kotlin-lang/kotlinClassGraphqlType.ftl | 2 +- .../kt/Commit_no_final_class.kt.txt | 2 +- .../kt/optional/TypeWithMandatoryField.kt.txt | 2 +- .../restricted-words/FunQueryRequest.kt.txt | 2 +- .../kt/restricted-words/Super.kt.txt | 2 +- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f89eb5fa5..57e627d2a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,19 +16,20 @@ Before sending your pull requests, make sure you followed this list: Please follow the steps below in order to make the changes: 1. Clone the repository -2. Checkout **develop** branch. -3. Open repository in your favourite IDE. -4. Enable and configure CheckStyle plugin in your IDE (for IntelliJ it is CheckStyle-IDEA). +2. Set the local java version to 1.8 +3. Checkout **develop** branch. +4. Open repository in your favourite IDE. +5. Enable and configure CheckStyle plugin in your IDE (for IntelliJ it is CheckStyle-IDEA). Import [graphql-codegen-check-style.xml](config/checkstyle/graphql-codegen-check-style.xml) as a . -5. Make code changes to the core library of `graphql-java-codegen`. -6. If changes are required in the plugin code, then **build** and **install** `graphql-java-codegen` first. +6. Make code changes to the core library of `graphql-java-codegen`. +7. If changes are required in the plugin code, then **build** and **install** `graphql-java-codegen` first. ```shell script # This will install the library (including your recent changes) in your local maven repository. ./gradlew clean build publishToMavenLocal ``` -7. Build the plugin project with updated `graphql-java-codegen` library. +8. Build the plugin project with updated `graphql-java-codegen` library. ```shell script # Build Gradle plugin @@ -39,8 +40,8 @@ Please follow the steps below in order to make the changes: mvn clean verify ``` -8. Make changes to the plugin code -9. Install the plugin (copy to your local maven repository). +9. Make changes to the plugin code +10. Install the plugin (copy to your local maven repository). ```shell script # Install Gradle plugin @@ -51,4 +52,4 @@ Please follow the steps below in order to make the changes: mvn clean install ``` -10. Make sure that `example` projects are compiling and running. +11. Make sure that `example` projects are compiling and running. diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlRequest.ftl b/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlRequest.ftl index c510cbda2..7354edda1 100755 --- a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlRequest.ftl +++ b/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlRequest.ftl @@ -32,7 +32,7 @@ open class ${className}(private val alias: String?) : GraphQLOperationRequest { val OPERATION_TYPE: GraphQLOperation = GraphQLOperation.${operationType} <#if builder> - fun builder(): Builder = Builder() + @JvmStatic fun builder(): Builder = Builder() } diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlType.ftl b/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlType.ftl index 02177fad8..bf4c000a2 100755 --- a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlType.ftl +++ b/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlType.ftl @@ -75,7 +75,7 @@ open class ${className}()<#if implements?has_content> : <#list implements as int <#if builder> companion object { - fun builder(): Builder = Builder() + @JvmStatic fun builder(): Builder = Builder() } diff --git a/src/test/resources/expected-classes/kt/Commit_no_final_class.kt.txt b/src/test/resources/expected-classes/kt/Commit_no_final_class.kt.txt index dc4cf3834..d99ceb5bd 100644 --- a/src/test/resources/expected-classes/kt/Commit_no_final_class.kt.txt +++ b/src/test/resources/expected-classes/kt/Commit_no_final_class.kt.txt @@ -60,7 +60,7 @@ open class Commit( ) : Closer, IssueTimelineItem, PullRequestTimelineItem, Subscribable, Node, GitObject, UniformResourceLocatable { companion object { - fun builder(): Builder = Builder() + @JvmStatic fun builder(): Builder = Builder() } // In the future, it maybe change. diff --git a/src/test/resources/expected-classes/kt/optional/TypeWithMandatoryField.kt.txt b/src/test/resources/expected-classes/kt/optional/TypeWithMandatoryField.kt.txt index 95ee51bf8..877c7f112 100644 --- a/src/test/resources/expected-classes/kt/optional/TypeWithMandatoryField.kt.txt +++ b/src/test/resources/expected-classes/kt/optional/TypeWithMandatoryField.kt.txt @@ -10,7 +10,7 @@ data class TypeWithMandatoryField( ) : InterfaceWithOptionalField { companion object { - fun builder(): Builder = Builder() + @JvmStatic fun builder(): Builder = Builder() } // In the future, it maybe change. diff --git a/src/test/resources/expected-classes/kt/restricted-words/FunQueryRequest.kt.txt b/src/test/resources/expected-classes/kt/restricted-words/FunQueryRequest.kt.txt index 0f5be311c..d62346845 100644 --- a/src/test/resources/expected-classes/kt/restricted-words/FunQueryRequest.kt.txt +++ b/src/test/resources/expected-classes/kt/restricted-words/FunQueryRequest.kt.txt @@ -14,7 +14,7 @@ open class FunQueryRequest(private val alias: String?) : GraphQLOperationRequest const val OPERATION_NAME: String = "fun" val OPERATION_TYPE: GraphQLOperation = GraphQLOperation.QUERY - fun builder(): Builder = Builder() + @JvmStatic fun builder(): Builder = Builder() } private val input: MutableMap = LinkedHashMap() diff --git a/src/test/resources/expected-classes/kt/restricted-words/Super.kt.txt b/src/test/resources/expected-classes/kt/restricted-words/Super.kt.txt index 368e5c497..1ef9e5d43 100644 --- a/src/test/resources/expected-classes/kt/restricted-words/Super.kt.txt +++ b/src/test/resources/expected-classes/kt/restricted-words/Super.kt.txt @@ -16,7 +16,7 @@ data class Super( ) { companion object { - fun builder(): Builder = Builder() + @JvmStatic fun builder(): Builder = Builder() } // In the future, it maybe change. From d7ae17656f8863fb4e23ca66e56bc846db59de3a Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Sat, 4 Sep 2021 01:43:29 +0300 Subject: [PATCH 08/23] Code refactor: migrate generators into separate classes --- .../codegen/FreeMarkerTemplatesRegistry.java | 126 ----- .../graphql/codegen/GraphQLCodegen.java | 458 ++---------------- .../codegen/GraphQLCodegenValidate.java | 1 + .../graphql/codegen/MapperFactory.java | 21 - .../codegen/generators/FilesGenerator.java | 14 + .../generators/FilesGeneratorsFactory.java | 49 ++ .../FreeMarkerTemplateFilesCreator.java} | 26 +- .../FreeMarkerTemplateType.java | 7 +- .../FreeMarkerTemplatesRegistry.java | 72 +++ .../generators/impl/EnumsGenerator.java | 44 ++ .../impl/FieldResolversGenerator.java | 69 +++ .../generators/impl/InputGenerator.java | 45 ++ .../generators/impl/InterfaceGenerator.java | 44 ++ .../impl/JacksonTypeIdResolverGenerator.java | 52 ++ .../generators/impl/OperationsGenerator.java | 109 +++++ .../impl/ParametrizedInputGenerator.java | 69 +++ .../impl/RequestResponseGenerator.java | 65 +++ .../impl/ResponseProjectionGenerator.java | 59 +++ .../generators/impl/TypeGenerator.java | 54 +++ .../generators/impl/UnionGenerator.java | 43 ++ .../codegen/java/JavaGraphQLCodegen.java | 2 +- .../codegen/java/JavaMapperFactoryImpl.java | 2 +- .../codegen/kotlin/KotlinGraphQLCodegen.java | 2 +- .../kotlin/KotlinMapperFactoryImpl.java | 2 +- .../mapper/DataModelMapperFactory.java | 2 - .../EnumDefinitionToDataModelMapper.java | 13 +- .../FieldDefinitionToParameterMapper.java | 5 +- ...dDefinitionsToResolverDataModelMapper.java | 8 +- .../codegen/mapper/GraphQLTypeMapper.java | 13 - .../InputDefinitionToDataModelMapper.java | 3 +- ...InputValueDefinitionToParameterMapper.java | 3 +- .../InterfaceDefinitionToDataModelMapper.java | 3 +- .../graphql/codegen/mapper/MapperFactory.java | 16 + ...stResponseDefinitionToDataModelMapper.java | 43 +- .../TypeDefinitionToDataModelMapper.java | 3 +- .../UnionDefinitionToDataModelMapper.java | 3 +- .../graphql/codegen/model/MappingConfig.java | 8 +- .../codegen/model/MappingConfigConstants.java | 1 + ...MappingConfigDefaultValuesInitializer.java | 107 ++++ .../codegen/model/MappingConfigValidator.java | 47 ++ .../graphql/codegen/model/MappingContext.java | 71 ++- .../model/MultiLanguageDeprecated.java | 44 -- .../builders/DeprecatedDefinitionBuilder.java | 72 +++ .../model/builders/JavaDocBuilder.java | 83 ++++ .../model/definitions/ExtendedDefinition.java | 64 +-- .../definitions/ExtendedFieldDefinition.java | 13 - .../codegen/model/graphql/GraphQLRequest.java | 2 +- .../graphql/GraphQLRequestSerializer.java | 2 +- .../{ => parser}/GraphQLDocumentParser.java | 30 +- .../codegen/scala/ScalaGraphQLCodegen.java | 2 +- .../codegen/scala/ScalaMapperFactoryImpl.java | 2 +- .../MergeableMappingConfigSupplier.java | 25 +- .../graphql/codegen/utils/Utils.java | 2 +- .../{javaClassGraphqlEnum.ftl => enum.ftl} | 0 ...lassGraphqlInterface.ftl => interface.ftl} | 0 ...olver.ftl => jackson_type_id_resolver.ftl} | 0 ...ssGraphqlOperations.ftl => operations.ftl} | 0 ...trizedInput.ftl => parametrized_input.ftl} | 0 ...avaClassGraphqlRequest.ftl => request.ftl} | 0 ...aClassGraphqlResponse.ftl => response.ftl} | 0 ...Projection.ftl => response_projection.ftl} | 0 .../{javaClassGraphqlType.ftl => type.ftl} | 0 .../{javaClassGraphqlUnion.ftl => union.ftl} | 0 .../{kotlinClassGraphqlEnum.ftl => enum.ftl} | 0 ...lassGraphqlInterface.ftl => interface.ftl} | 0 ...olver.ftl => jackson_type_id_resolver.ftl} | 0 ...ssGraphqlOperations.ftl => operations.ftl} | 0 ...trizedInput.ftl => parametrized_input.ftl} | 0 ...linClassGraphqlRequest.ftl => request.ftl} | 0 ...nClassGraphqlResponse.ftl => response.ftl} | 0 ...Projection.ftl => response_projection.ftl} | 0 .../{kotlinClassGraphqlType.ftl => type.ftl} | 0 ...{kotlinClassGraphqlUnion.ftl => union.ftl} | 0 .../{scalaClassGraphqlEnum.ftl => enum.ftl} | 0 ...lassGraphqlInterface.ftl => interface.ftl} | 0 ...olver.ftl => jackson_type_id_resolver.ftl} | 0 ...ssGraphqlOperations.ftl => operations.ftl} | 0 ...trizedInput.ftl => parametrized_input.ftl} | 0 ...alaClassGraphqlRequest.ftl => request.ftl} | 0 ...aClassGraphqlResponse.ftl => response.ftl} | 0 ...Projection.ftl => response_projection.ftl} | 0 .../{scalaClassGraphqlType.ftl => type.ftl} | 0 .../{scalaClassGraphqlUnion.ftl => union.ftl} | 0 .../resources/templates/templates.properties | 0 .../GraphQLCodegenFileCreatorTest.java | 19 +- .../graphql/codegen/GraphQLCodegenTest.java | 4 +- 86 files changed, 1351 insertions(+), 797 deletions(-) delete mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/FreeMarkerTemplatesRegistry.java delete mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/MapperFactory.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGeneratorsFactory.java rename src/main/java/com/kobylynskyi/graphql/codegen/{GraphQLCodegenFileCreator.java => generators/FreeMarkerTemplateFilesCreator.java} (72%) rename src/main/java/com/kobylynskyi/graphql/codegen/{ => generators}/FreeMarkerTemplateType.java (56%) create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplatesRegistry.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/EnumsGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/FieldResolversGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/InputGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/InterfaceGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/JacksonTypeIdResolverGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/OperationsGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ParametrizedInputGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/RequestResponseGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ResponseProjectionGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/TypeGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/UnionGenerator.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/mapper/MapperFactory.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigValidator.java delete mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/model/MultiLanguageDeprecated.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/model/builders/DeprecatedDefinitionBuilder.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java rename src/main/java/com/kobylynskyi/graphql/codegen/{ => parser}/GraphQLDocumentParser.java (88%) rename src/main/resources/templates/java-lang/{javaClassGraphqlEnum.ftl => enum.ftl} (100%) rename src/main/resources/templates/java-lang/{javaClassGraphqlInterface.ftl => interface.ftl} (100%) rename src/main/resources/templates/java-lang/{javaClassGraphqlJacksonTypeIdResolver.ftl => jackson_type_id_resolver.ftl} (100%) rename src/main/resources/templates/java-lang/{javaClassGraphqlOperations.ftl => operations.ftl} (100%) rename src/main/resources/templates/java-lang/{javaClassGraphqlParametrizedInput.ftl => parametrized_input.ftl} (100%) rename src/main/resources/templates/java-lang/{javaClassGraphqlRequest.ftl => request.ftl} (100%) rename src/main/resources/templates/java-lang/{javaClassGraphqlResponse.ftl => response.ftl} (100%) rename src/main/resources/templates/java-lang/{javaClassGraphqlResponseProjection.ftl => response_projection.ftl} (100%) rename src/main/resources/templates/java-lang/{javaClassGraphqlType.ftl => type.ftl} (100%) rename src/main/resources/templates/java-lang/{javaClassGraphqlUnion.ftl => union.ftl} (100%) rename src/main/resources/templates/kotlin-lang/{kotlinClassGraphqlEnum.ftl => enum.ftl} (100%) rename src/main/resources/templates/kotlin-lang/{kotlinClassGraphqlInterface.ftl => interface.ftl} (100%) rename src/main/resources/templates/kotlin-lang/{kotlinClassGraphqlJacksonTypeIdResolver.ftl => jackson_type_id_resolver.ftl} (100%) rename src/main/resources/templates/kotlin-lang/{kotlinClassGraphqlOperations.ftl => operations.ftl} (100%) rename src/main/resources/templates/kotlin-lang/{kotlinClassGraphqlParametrizedInput.ftl => parametrized_input.ftl} (100%) rename src/main/resources/templates/kotlin-lang/{kotlinClassGraphqlRequest.ftl => request.ftl} (100%) rename src/main/resources/templates/kotlin-lang/{kotlinClassGraphqlResponse.ftl => response.ftl} (100%) rename src/main/resources/templates/kotlin-lang/{kotlinClassGraphqlResponseProjection.ftl => response_projection.ftl} (100%) rename src/main/resources/templates/kotlin-lang/{kotlinClassGraphqlType.ftl => type.ftl} (100%) rename src/main/resources/templates/kotlin-lang/{kotlinClassGraphqlUnion.ftl => union.ftl} (100%) rename src/main/resources/templates/scala-lang/{scalaClassGraphqlEnum.ftl => enum.ftl} (100%) rename src/main/resources/templates/scala-lang/{scalaClassGraphqlInterface.ftl => interface.ftl} (100%) rename src/main/resources/templates/scala-lang/{scalaClassGraphqlJacksonTypeIdResolver.ftl => jackson_type_id_resolver.ftl} (100%) rename src/main/resources/templates/scala-lang/{scalaClassGraphqlOperations.ftl => operations.ftl} (100%) rename src/main/resources/templates/scala-lang/{scalaClassGraphqlParametrizedInput.ftl => parametrized_input.ftl} (100%) rename src/main/resources/templates/scala-lang/{scalaClassGraphqlRequest.ftl => request.ftl} (100%) rename src/main/resources/templates/scala-lang/{scalaClassGraphqlResponse.ftl => response.ftl} (100%) rename src/main/resources/templates/scala-lang/{scalaClassGraphqlResponseProjection.ftl => response_projection.ftl} (100%) rename src/main/resources/templates/scala-lang/{scalaClassGraphqlType.ftl => type.ftl} (100%) rename src/main/resources/templates/scala-lang/{scalaClassGraphqlUnion.ftl => union.ftl} (100%) create mode 100644 src/main/resources/templates/templates.properties diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/FreeMarkerTemplatesRegistry.java b/src/main/java/com/kobylynskyi/graphql/codegen/FreeMarkerTemplatesRegistry.java deleted file mode 100644 index f29701392..000000000 --- a/src/main/java/com/kobylynskyi/graphql/codegen/FreeMarkerTemplatesRegistry.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.kobylynskyi.graphql.codegen; - -import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage; -import com.kobylynskyi.graphql.codegen.model.exception.UnableToLoadFreeMarkerTemplateException; -import freemarker.core.PlainTextOutputFormat; -import freemarker.ext.beans.BeansWrapper; -import freemarker.template.Configuration; -import freemarker.template.Template; -import freemarker.template.TemplateExceptionHandler; -import freemarker.template.Version; - -import java.io.IOException; -import java.util.EnumMap; - -import static com.kobylynskyi.graphql.codegen.FreeMarkerTemplateType.ENUM; -import static com.kobylynskyi.graphql.codegen.FreeMarkerTemplateType.INTERFACE; -import static com.kobylynskyi.graphql.codegen.FreeMarkerTemplateType.JACKSON_TYPE_ID_RESOLVER; -import static com.kobylynskyi.graphql.codegen.FreeMarkerTemplateType.OPERATIONS; -import static com.kobylynskyi.graphql.codegen.FreeMarkerTemplateType.PARAMETRIZED_INPUT; -import static com.kobylynskyi.graphql.codegen.FreeMarkerTemplateType.REQUEST; -import static com.kobylynskyi.graphql.codegen.FreeMarkerTemplateType.RESPONSE; -import static com.kobylynskyi.graphql.codegen.FreeMarkerTemplateType.RESPONSE_PROJECTION; -import static com.kobylynskyi.graphql.codegen.FreeMarkerTemplateType.TYPE; -import static com.kobylynskyi.graphql.codegen.FreeMarkerTemplateType.UNION; - -class FreeMarkerTemplatesRegistry { - - private static final Version FREEMARKER_TEMPLATE_VERSION = Configuration.VERSION_2_3_30; - private static final EnumMap> templateMap = - new EnumMap<>( - GeneratedLanguage.class); - - static { - BeansWrapper beansWrapper = new BeansWrapper(FREEMARKER_TEMPLATE_VERSION); - Configuration configuration = new Configuration(FREEMARKER_TEMPLATE_VERSION); - configuration.setClassLoaderForTemplateLoading(GraphQLCodegen.class.getClassLoader(), ""); - configuration.setDefaultEncoding("UTF-8"); - configuration.setOutputFormat(PlainTextOutputFormat.INSTANCE); - configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); - configuration.setLogTemplateExceptions(false); - configuration.setWrapUncheckedExceptions(true); - configuration.setSharedVariable("statics", beansWrapper.getStaticModels()); - - try { - EnumMap javaTemplates = new EnumMap<>(FreeMarkerTemplateType.class); - javaTemplates.put(TYPE, - configuration.getTemplate("templates/java-lang/javaClassGraphqlType.ftl")); - javaTemplates.put(ENUM, - configuration.getTemplate("templates/java-lang/javaClassGraphqlEnum.ftl")); - javaTemplates.put(UNION, - configuration.getTemplate("templates/java-lang/javaClassGraphqlUnion.ftl")); - javaTemplates.put(REQUEST, - configuration.getTemplate("templates/java-lang/javaClassGraphqlRequest.ftl")); - javaTemplates.put(RESPONSE, - configuration.getTemplate("templates/java-lang/javaClassGraphqlResponse.ftl")); - javaTemplates.put(INTERFACE, - configuration.getTemplate("templates/java-lang/javaClassGraphqlInterface.ftl")); - javaTemplates.put(OPERATIONS, - configuration.getTemplate("templates/java-lang/javaClassGraphqlOperations.ftl")); - javaTemplates.put(PARAMETRIZED_INPUT, - configuration.getTemplate("templates/java-lang/javaClassGraphqlParametrizedInput.ftl")); - javaTemplates.put(RESPONSE_PROJECTION, - configuration.getTemplate("templates/java-lang/javaClassGraphqlResponseProjection.ftl")); - javaTemplates.put(JACKSON_TYPE_ID_RESOLVER, - configuration.getTemplate("templates/java-lang/javaClassGraphqlJacksonTypeIdResolver.ftl")); - templateMap.put(GeneratedLanguage.JAVA, javaTemplates); - - EnumMap scalaTemplates = new EnumMap<>(FreeMarkerTemplateType.class); - scalaTemplates.put(TYPE, - configuration.getTemplate("templates/scala-lang/scalaClassGraphqlType.ftl")); - scalaTemplates.put(ENUM, - configuration.getTemplate("templates/scala-lang/scalaClassGraphqlEnum.ftl")); - scalaTemplates.put(UNION, - configuration.getTemplate("templates/scala-lang/scalaClassGraphqlUnion.ftl")); - scalaTemplates.put(REQUEST, - configuration.getTemplate("templates/scala-lang/scalaClassGraphqlRequest.ftl")); - scalaTemplates.put(RESPONSE, - configuration.getTemplate("templates/scala-lang/scalaClassGraphqlResponse.ftl")); - scalaTemplates.put(INTERFACE, - configuration.getTemplate("templates/scala-lang/scalaClassGraphqlInterface.ftl")); - scalaTemplates.put(OPERATIONS, - configuration.getTemplate("templates/scala-lang/scalaClassGraphqlOperations.ftl")); - scalaTemplates.put(PARAMETRIZED_INPUT, - configuration.getTemplate("templates/scala-lang/scalaClassGraphqlParametrizedInput.ftl")); - scalaTemplates.put(RESPONSE_PROJECTION, - configuration.getTemplate("templates/scala-lang/scalaClassGraphqlResponseProjection.ftl")); - scalaTemplates.put(JACKSON_TYPE_ID_RESOLVER, - configuration.getTemplate("templates/scala-lang/scalaClassGraphqlJacksonTypeIdResolver.ftl")); - templateMap.put(GeneratedLanguage.SCALA, scalaTemplates); - - EnumMap kotlinTemplates = new EnumMap<>(FreeMarkerTemplateType.class); - kotlinTemplates.put(TYPE, - configuration.getTemplate("templates/kotlin-lang/kotlinClassGraphqlType.ftl")); - kotlinTemplates.put(ENUM, - configuration.getTemplate("templates/kotlin-lang/kotlinClassGraphqlEnum.ftl")); - kotlinTemplates.put(UNION, - configuration.getTemplate("templates/kotlin-lang/kotlinClassGraphqlUnion.ftl")); - kotlinTemplates.put(REQUEST, - configuration.getTemplate("templates/kotlin-lang/kotlinClassGraphqlRequest.ftl")); - kotlinTemplates.put(RESPONSE, - configuration.getTemplate("templates/kotlin-lang/kotlinClassGraphqlResponse.ftl")); - kotlinTemplates.put(INTERFACE, - configuration.getTemplate("templates/kotlin-lang/kotlinClassGraphqlInterface.ftl")); - kotlinTemplates.put(OPERATIONS, - configuration.getTemplate("templates/kotlin-lang/kotlinClassGraphqlOperations.ftl")); - kotlinTemplates.put(PARAMETRIZED_INPUT, - configuration.getTemplate("templates/kotlin-lang/kotlinClassGraphqlParametrizedInput.ftl")); - kotlinTemplates.put(RESPONSE_PROJECTION, - configuration.getTemplate("templates/kotlin-lang/kotlinClassGraphqlResponseProjection.ftl")); - kotlinTemplates.put(JACKSON_TYPE_ID_RESOLVER, - configuration.getTemplate("templates/kotlin-lang/kotlinClassGraphqlJacksonTypeIdResolver.ftl")); - templateMap.put(GeneratedLanguage.KOTLIN, kotlinTemplates); - } catch (IOException e) { - throw new UnableToLoadFreeMarkerTemplateException(e); - } - } - - private FreeMarkerTemplatesRegistry() { - } - - public static Template getTemplateWithLang(GeneratedLanguage generatedLanguage, - FreeMarkerTemplateType templateType) { - return templateMap.get(generatedLanguage).get(templateType); - } - -} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegen.java b/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegen.java index bcc644ef9..638a1871d 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegen.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegen.java @@ -1,45 +1,28 @@ package com.kobylynskyi.graphql.codegen; -import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FilesGeneratorsFactory; import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; -import com.kobylynskyi.graphql.codegen.mapper.FieldDefinitionToParameterMapper; -import com.kobylynskyi.graphql.codegen.model.ApiInterfaceStrategy; -import com.kobylynskyi.graphql.codegen.model.ApiNamePrefixStrategy; -import com.kobylynskyi.graphql.codegen.model.ApiRootInterfaceStrategy; +import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; import com.kobylynskyi.graphql.codegen.model.GeneratedInformation; import com.kobylynskyi.graphql.codegen.model.MappingConfig; -import com.kobylynskyi.graphql.codegen.model.MappingConfigConstants; +import com.kobylynskyi.graphql.codegen.model.MappingConfigDefaultValuesInitializer; +import com.kobylynskyi.graphql.codegen.model.MappingConfigValidator; import com.kobylynskyi.graphql.codegen.model.MappingContext; -import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDocument; -import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedEnumTypeDefinition; -import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; -import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInputObjectTypeDefinition; -import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInterfaceTypeDefinition; -import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedScalarTypeDefinition; -import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedUnionTypeDefinition; +import com.kobylynskyi.graphql.codegen.parser.GraphQLDocumentParser; import com.kobylynskyi.graphql.codegen.supplier.MappingConfigSupplier; import com.kobylynskyi.graphql.codegen.utils.Utils; -import graphql.language.FieldDefinition; import graphql.language.ScalarTypeExtensionDefinition; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; -import static com.kobylynskyi.graphql.codegen.model.DataModelFields.CLASS_NAME; -import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_ANNOTATION; -import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_INFO; -import static com.kobylynskyi.graphql.codegen.model.DataModelFields.MODEL_NAME_PREFIX; -import static com.kobylynskyi.graphql.codegen.model.DataModelFields.MODEL_NAME_SUFFIX; -import static com.kobylynskyi.graphql.codegen.model.DataModelFields.PACKAGE; import static java.util.stream.Collectors.toList; /** @@ -99,10 +82,10 @@ protected GraphQLCodegen(List schemas, this.schemas = schemas; this.introspectionResult = introspectionResult; this.outputDir = outputDir; - this.mappingConfig = mappingConfig; - this.mappingConfig.combine(externalMappingConfigSupplier != null ? externalMappingConfigSupplier.get() : null); this.generatedInformation = generatedInformation; this.dataModelMapperFactory = new DataModelMapperFactory(mapperFactory); + this.mappingConfig = mappingConfig; + this.mappingConfig.combine(externalMappingConfigSupplier != null ? externalMappingConfigSupplier.get() : null); initDefaultValues(mappingConfig); validateConfigs(mappingConfig); @@ -132,435 +115,66 @@ private static void sanitizeValues(MappingConfig mappingConfig) { } protected void initDefaultValues(MappingConfig mappingConfig) { - if (mappingConfig.getModelValidationAnnotation() == null) { - mappingConfig.setModelValidationAnnotation(MappingConfigConstants.DEFAULT_VALIDATION_ANNOTATION); - } - if (mappingConfig.getGenerateBuilder() == null) { - mappingConfig.setGenerateBuilder(MappingConfigConstants.DEFAULT_BUILDER); - } - if (mappingConfig.getGenerateEqualsAndHashCode() == null) { - mappingConfig.setGenerateEqualsAndHashCode(MappingConfigConstants.DEFAULT_EQUALS_AND_HASHCODE); - } - if (mappingConfig.getGenerateClient() == null) { - mappingConfig.setGenerateClient(MappingConfigConstants.DEFAULT_GENERATE_CLIENT); - } - if (mappingConfig.getRequestSuffix() == null) { - mappingConfig.setRequestSuffix(MappingConfigConstants.DEFAULT_REQUEST_SUFFIX); - } - if (mappingConfig.getResponseSuffix() == null) { - mappingConfig.setResponseSuffix(MappingConfigConstants.DEFAULT_RESPONSE_SUFFIX); - } - if (mappingConfig.getResponseProjectionSuffix() == null) { - mappingConfig.setResponseProjectionSuffix(MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_SUFFIX); - } - if (mappingConfig.getParametrizedInputSuffix() == null) { - mappingConfig.setParametrizedInputSuffix(MappingConfigConstants.DEFAULT_PARAMETRIZED_INPUT_SUFFIX); - } - if (mappingConfig.getGenerateImmutableModels() == null) { - mappingConfig.setGenerateImmutableModels(MappingConfigConstants.DEFAULT_GENERATE_IMMUTABLE_MODELS); - } - if (mappingConfig.getGenerateToString() == null) { - mappingConfig.setGenerateToString(MappingConfigConstants.DEFAULT_TO_STRING); - } - if (mappingConfig.getGenerateApis() == null) { - mappingConfig.setGenerateApis(MappingConfigConstants.DEFAULT_GENERATE_APIS); - } - if (mappingConfig.getApiNameSuffix() == null) { - mappingConfig.setApiNameSuffix(MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX); - } - if (mappingConfig.getTypeResolverSuffix() == null) { - mappingConfig.setTypeResolverSuffix(MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX); - } - if (mappingConfig.getGenerateParameterizedFieldsResolvers() == null) { - mappingConfig.setGenerateParameterizedFieldsResolvers( - MappingConfigConstants.DEFAULT_GENERATE_PARAMETERIZED_FIELDS_RESOLVERS); - } - if (mappingConfig.getGenerateExtensionFieldsResolvers() == null) { - mappingConfig.setGenerateExtensionFieldsResolvers( - MappingConfigConstants.DEFAULT_GENERATE_EXTENSION_FIELDS_RESOLVERS); - } - if (mappingConfig.getGenerateDataFetchingEnvironmentArgumentInApis() == null) { - mappingConfig.setGenerateDataFetchingEnvironmentArgumentInApis( - MappingConfigConstants.DEFAULT_GENERATE_DATA_FETCHING_ENV); - } - if (mappingConfig.getGenerateModelsForRootTypes() == null) { - mappingConfig.setGenerateModelsForRootTypes(MappingConfigConstants.DEFAULT_GENERATE_MODELS_FOR_ROOT_TYPES); - } - if (mappingConfig.getGenerateApisWithThrowsException() == null) { - mappingConfig.setGenerateApisWithThrowsException( - MappingConfigConstants.DEFAULT_GENERATE_APIS_WITH_THROWS_EXCEPTION); - } - if (mappingConfig.getAddGeneratedAnnotation() == null) { - mappingConfig.setAddGeneratedAnnotation(MappingConfigConstants.DEFAULT_ADD_GENERATED_ANNOTATION); - } - if (mappingConfig.getGenerateJacksonTypeIdResolver() == null) { - mappingConfig.setGenerateJacksonTypeIdResolver( - MappingConfigConstants.DEFAULT_GENERATE_JACKSON_TYPE_ID_RESOLVER); - } - if (mappingConfig.getUseOptionalForNullableReturnTypes() == null) { - mappingConfig.setUseOptionalForNullableReturnTypes( - MappingConfigConstants.DEFAULT_USE_OPTIONAL_FOR_NULLABLE_RETURN_TYPES); - } - if (mappingConfig.getApiNamePrefixStrategy() == null) { - mappingConfig.setApiNamePrefixStrategy(MappingConfigConstants.DEFAULT_API_NAME_PREFIX_STRATEGY); - } - if (mappingConfig.getApiRootInterfaceStrategy() == null) { - mappingConfig.setApiRootInterfaceStrategy(MappingConfigConstants.DEFAULT_API_ROOT_INTERFACE_STRATEGY); - } - if (mappingConfig.getApiInterfaceStrategy() == null) { - mappingConfig.setApiInterfaceStrategy(MappingConfigConstants.DEFAULT_API_INTERFACE_STRATEGY); - } - if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) { - // required for request serialization - mappingConfig.setGenerateToString(true); - } - if (mappingConfig.getResponseProjectionMaxDepth() == null) { - mappingConfig.setResponseProjectionMaxDepth(MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_MAX_DEPTH); - } - if (mappingConfig.getGeneratedLanguage() == null) { - mappingConfig.setGeneratedLanguage(MappingConfigConstants.DEFAULT_GENERATED_LANGUAGE); - } - if (mappingConfig.getGenerateAllMethodInProjection() == null) { - mappingConfig.setGenerateAllMethodInProjection(MappingConfigConstants.DEFAULT_GENERATE_ALL_METHOD); - } + MappingConfigDefaultValuesInitializer.initDefaultValues(mappingConfig); } private void validateConfigs(MappingConfig mappingConfig) { - if (!Utils.isEmpty(schemas) && introspectionResult != null || - (Utils.isEmpty(schemas) && introspectionResult == null)) { - // either schemas or introspection result should be provided - throw new IllegalArgumentException( - "Either graphql schema path or introspection result path should be supplied"); - } - if (mappingConfig.getApiRootInterfaceStrategy() == ApiRootInterfaceStrategy.INTERFACE_PER_SCHEMA && - mappingConfig.getApiNamePrefixStrategy() == ApiNamePrefixStrategy.CONSTANT) { - // we will have a conflict in case there is "type Query" in multiple graphql schema files - throw new IllegalArgumentException("API prefix should not be CONSTANT for INTERFACE_PER_SCHEMA option"); - } - if (Boolean.TRUE.equals(mappingConfig.getGenerateApis()) - && Boolean.TRUE.equals(mappingConfig.getGenerateModelsForRootTypes()) - && mappingConfig.getApiNamePrefixStrategy() == ApiNamePrefixStrategy.CONSTANT) { - // checking for conflict between root type model classes and api interfaces - if (Utils.stringsEqualIgnoreSpaces( - mappingConfig.getApiNamePrefix(), mappingConfig.getModelNamePrefix()) && - Utils.stringsEqualIgnoreSpaces( - mappingConfig.getApiNameSuffix(), mappingConfig.getModelNameSuffix())) { - // we will have a conflict between model pojo (Query.java) and api interface (Query.java) - throw new IllegalArgumentException("Either disable APIs generation or " + - "set different Prefix/Suffix for API classes and model classes"); - } - // checking for conflict between root type model resolver classes and api interfaces - if (Utils.stringsEqualIgnoreSpaces(mappingConfig.getApiNamePrefix(), - mappingConfig.getTypeResolverPrefix()) && - Utils.stringsEqualIgnoreSpaces(mappingConfig.getApiNameSuffix(), - mappingConfig.getTypeResolverSuffix())) { - // we will have a conflict between model resolver interface (QueryResolver.java) and api interface - // resolver (QueryResolver.java) - throw new IllegalArgumentException("Either disable APIs generation or " + - "set different Prefix/Suffix for API classes and type resolver classes"); - } - } + MappingConfigValidator.validate(mappingConfig); } /** - * Generate class files based on GraphQL schema + * Entry point. + * Generates class files based on GraphQL schema * * @return a list of generated classes * @throws IOException in case some I/O error occurred, e.g.: file can't be created, directory access issues, etc. */ public List generate() throws IOException { - GraphQLCodegenFileCreator.prepareOutputDir(outputDir); long startTime = System.currentTimeMillis(); - List generatedFiles = Collections.emptyList(); + + // prepare output directory + Utils.deleteDir(outputDir); + Utils.createDirIfAbsent(outputDir); + if (!Utils.isEmpty(schemas)) { ExtendedDocument document = GraphQLDocumentParser.getDocumentFromSchemas(mappingConfig, schemas); - initCustomTypeMappings(document.getScalarDefinitions()); - generatedFiles = processDefinitions(document); + List generatedFiles = processDefinitions(document); System.out.printf("Finished processing %d schema(s) in %d ms%n", schemas.size(), System.currentTimeMillis() - startTime); + return generatedFiles; } else if (introspectionResult != null) { ExtendedDocument document = GraphQLDocumentParser .getDocumentFromIntrospectionResult(mappingConfig, introspectionResult); - initCustomTypeMappings(document.getScalarDefinitions()); - generatedFiles = processDefinitions(document); + List generatedFiles = processDefinitions(document); System.out.printf("Finished processing introspection result in %d ms%n", System.currentTimeMillis() - startTime); + return generatedFiles; + } else { + // either schemas or introspection result should be provided + throw new IllegalArgumentException( + "Either graphql schema path or introspection result path should be supplied"); } - - return generatedFiles; } private List processDefinitions(ExtendedDocument document) { - MappingContext context = new MappingContext(mappingConfig, document, generatedInformation, - dataModelMapperFactory); + initCustomTypeMappings(document.getScalarDefinitions()); + MappingContext context = MappingContext.builder() + .setMappingConfig(mappingConfig) + .setOutputDirectory(outputDir) + .setGeneratedInformation(generatedInformation) + .setDataModelMapperFactory(dataModelMapperFactory) + .setDocument(document) + .build(); + List generatedFiles = new ArrayList<>(); - for (ExtendedEnumTypeDefinition extendedEnumTypeDefinition : document.getEnumDefinitions()) { - generatedFiles.add(generateEnum(context, extendedEnumTypeDefinition)); - } - for (ExtendedInterfaceTypeDefinition extendedInterfaceTypeDefinition : document.getInterfaceDefinitions()) { - generatedFiles.addAll(generateInterface(context, extendedInterfaceTypeDefinition)); - } - for (ExtendedObjectTypeDefinition extendedObjectTypeDefinition : document.getTypeDefinitions()) { - generatedFiles.addAll(generateType(context, extendedObjectTypeDefinition)); - } - for (ExtendedObjectTypeDefinition extendedObjectTypeDefinition : document.getTypeDefinitions()) { - generateFieldResolver(context, extendedObjectTypeDefinition.getFieldDefinitions(), - extendedObjectTypeDefinition) - .ifPresent(generatedFiles::add); - } - for (ExtendedObjectTypeDefinition extendedObjectTypeDefinition : document.getOperationDefinitions()) { - if (Boolean.TRUE.equals(mappingConfig.getGenerateApis())) { - generatedFiles.addAll(generateServerOperations(context, extendedObjectTypeDefinition)); - } - if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) { - generatedFiles.addAll(generateClient(context, extendedObjectTypeDefinition)); - } - } - for (ExtendedInputObjectTypeDefinition extendedInputObjectTypeDefinition : document.getInputDefinitions()) { - generatedFiles.add(generateInput(context, extendedInputObjectTypeDefinition)); - } - for (ExtendedUnionTypeDefinition extendedUnionTypeDefinition : document.getUnionDefinitions()) { - generatedFiles.addAll(generateUnion(context, extendedUnionTypeDefinition)); - } - for (ExtendedInterfaceTypeDefinition definition : document.getInterfaceDefinitions()) { - generateFieldResolver(context, definition.getFieldDefinitions(), definition).ifPresent(generatedFiles::add); - } - if (Boolean.TRUE.equals(mappingConfig.getGenerateJacksonTypeIdResolver())) { - generatedFiles.add(generateJacksonTypeIdResolver(context)); + for (FilesGenerator generator : FilesGeneratorsFactory.getAll(context, dataModelMapperFactory)) { + generatedFiles.addAll(generator.generate()); } System.out.printf("Generated %d definition classes in folder %s%n", generatedFiles.size(), outputDir.getAbsolutePath()); return generatedFiles; } - private List generateUnion(MappingContext mappingContext, ExtendedUnionTypeDefinition definition) { - List generatedFiles = new ArrayList<>(); - Map dataModel = dataModelMapperFactory.getUnionDefinitionMapper() - .map(mappingContext, definition); - generatedFiles.add(GraphQLCodegenFileCreator.generateFile( - mappingContext, FreeMarkerTemplateType.UNION, dataModel, outputDir)); - - if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) { - Map responseProjDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper() - .mapResponseProjection(mappingContext, - definition); - generatedFiles.add(GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.RESPONSE_PROJECTION, - responseProjDataModel, outputDir)); - } - return generatedFiles; - } - - private List generateInterface(MappingContext mappingContext, ExtendedInterfaceTypeDefinition definition) { - List generatedFiles = new ArrayList<>(); - Map dataModel = dataModelMapperFactory.getInterfaceDefinitionMapper() - .map(mappingContext, definition); - generatedFiles.add(GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.INTERFACE, dataModel, outputDir)); - - if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) { - Map responseProjDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper() - .mapResponseProjection(mappingContext, - definition); - generatedFiles.add(GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.RESPONSE_PROJECTION, - responseProjDataModel, outputDir)); - - for (ExtendedFieldDefinition fieldDefinition : definition.getFieldDefinitions()) { - if (!Utils.isEmpty(fieldDefinition.getInputValueDefinitions())) { - Map fieldProjDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper() - .mapParametrizedInput(mappingContext, - fieldDefinition, - definition); - generatedFiles.add(GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.PARAMETRIZED_INPUT, - fieldProjDataModel, outputDir)); - } - } - } - return generatedFiles; - } - - private List generateServerOperations(MappingContext mappingContext, - ExtendedObjectTypeDefinition definition) { - List generatedFiles = new ArrayList<>(); - // Generate a root interface with all operations inside - // Relates to https://github.com/facebook/relay/issues/112 - switch (mappingContext.getApiRootInterfaceStrategy()) { - case INTERFACE_PER_SCHEMA: - for (ExtendedObjectTypeDefinition defInFile : definition.groupBySourceLocationFile().values()) { - generatedFiles.add(generateRootApi(mappingContext, defInFile)); - } - break; - case DO_NOT_GENERATE: - break; - case SINGLE_INTERFACE: - default: - generatedFiles.add(generateRootApi(mappingContext, definition)); - break; - } - - if (mappingContext.getApiInterfaceStrategy() == ApiInterfaceStrategy.INTERFACE_PER_OPERATION) { - // Generate separate interfaces for all queries, mutations and subscriptions - List fieldNames = definition.getFieldDefinitions().stream().map(FieldDefinition::getName) - .collect(toList()); - switch (mappingContext.getApiNamePrefixStrategy()) { - case FOLDER_NAME_AS_PREFIX: - for (ExtendedObjectTypeDefinition fileDef : definition.groupBySourceLocationFolder().values()) { - generatedFiles.addAll(generateApis(mappingContext, fileDef, fieldNames)); - } - break; - case FILE_NAME_AS_PREFIX: - for (ExtendedObjectTypeDefinition fileDef : definition.groupBySourceLocationFile().values()) { - generatedFiles.addAll(generateApis(mappingContext, fileDef, fieldNames)); - } - break; - case CONSTANT: - default: - generatedFiles.addAll(generateApis(mappingContext, definition, fieldNames)); - break; - } - } - return generatedFiles; - } - - private List generateClient(MappingContext mappingContext, ExtendedObjectTypeDefinition definition) { - List generatedFiles = new ArrayList<>(); - List fieldNames = definition.getFieldDefinitions().stream().map(FieldDefinition::getName) - .collect(toList()); - for (ExtendedFieldDefinition operationDef : definition.getFieldDefinitions()) { - Map requestDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper() - .mapRequest(mappingContext, operationDef, - definition.getName(), fieldNames); - generatedFiles.add(GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.REQUEST, requestDataModel, - outputDir)); - - Map responseDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper() - .mapResponse(mappingContext, operationDef, - definition.getName(), - fieldNames); - generatedFiles.add(GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.RESPONSE, responseDataModel, - outputDir)); - } - return generatedFiles; - } - - private List generateApis(MappingContext mappingContext, ExtendedObjectTypeDefinition definition, - List fieldNames) { - List generatedFiles = new ArrayList<>(); - for (ExtendedFieldDefinition operationDef : definition.getFieldDefinitions()) { - Map dataModel = dataModelMapperFactory.getFieldDefinitionsToResolverMapper() - .mapRootTypeField(mappingContext, operationDef, - definition.getName(), fieldNames); - generatedFiles.add(GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.OPERATIONS, dataModel, - outputDir)); - } - return generatedFiles; - } - - private File generateRootApi(MappingContext mappingContext, ExtendedObjectTypeDefinition definition) { - Map dataModel = dataModelMapperFactory.getFieldDefinitionsToResolverMapper() - .mapRootTypeFields(mappingContext, definition); - return GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.OPERATIONS, dataModel, outputDir); - } - - private List generateType(MappingContext mappingContext, ExtendedObjectTypeDefinition definition) { - List generatedFiles = new ArrayList<>(); - Map dataModel = dataModelMapperFactory.getTypeDefinitionMapper() - .map(mappingContext, definition); - - boolean typeAsInterface = mappingConfig.getTypesAsInterfaces().contains(definition.getName()); - - if (!typeAsInterface) { - typeAsInterface = definition.getDirectiveNames().stream().anyMatch(directiveName -> - mappingConfig.getTypesAsInterfaces().contains("@" + directiveName) - ); - } - - if (typeAsInterface) { - generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, - FreeMarkerTemplateType.INTERFACE, dataModel, outputDir)); - } else { - generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, - FreeMarkerTemplateType.TYPE, dataModel, outputDir)); - } - - if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) { - Map responseProjDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper() - .mapResponseProjection(mappingContext, - definition); - generatedFiles.add(GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.RESPONSE_PROJECTION, - responseProjDataModel, outputDir)); - - for (ExtendedFieldDefinition fieldDefinition : definition.getFieldDefinitions()) { - if (!Utils.isEmpty(fieldDefinition.getInputValueDefinitions())) { - Map fieldProjDataModel = - dataModelMapperFactory.getRequestResponseDefinitionMapper() - .mapParametrizedInput(mappingContext, fieldDefinition, definition); - generatedFiles.add(GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.PARAMETRIZED_INPUT, - fieldProjDataModel, outputDir)); - } - } - } - return generatedFiles; - } - - private Optional generateFieldResolver(MappingContext mappingContext, - List fieldDefinitions, - ExtendedDefinition parentDefinition) { - if (Boolean.TRUE.equals(mappingConfig.getGenerateApis())) { - List fieldDefsWithResolvers = fieldDefinitions.stream() - .filter( - fieldDef -> FieldDefinitionToParameterMapper - .generateResolversForField( - mappingContext, fieldDef, - parentDefinition)) - .collect(toList()); - if (!fieldDefsWithResolvers.isEmpty()) { - Map dataModel = dataModelMapperFactory.getFieldDefinitionsToResolverMapper() - .mapToTypeResolver(mappingContext, - fieldDefsWithResolvers, - parentDefinition.getName()); - return Optional.of(GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.OPERATIONS, dataModel, - outputDir)); - } - } - return Optional.empty(); - } - - private File generateInput(MappingContext mappingContext, ExtendedInputObjectTypeDefinition definition) { - Map dataModel = dataModelMapperFactory.getInputDefinitionMapper() - .map(mappingContext, definition); - return GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.TYPE, dataModel, outputDir); - } - - private File generateEnum(MappingContext mappingContext, ExtendedEnumTypeDefinition definition) { - Map dataModel = dataModelMapperFactory.getEnumDefinitionMapper() - .map(mappingContext, definition); - return GraphQLCodegenFileCreator - .generateFile(mappingContext, FreeMarkerTemplateType.ENUM, dataModel, outputDir); - } - - private File generateJacksonTypeIdResolver(MappingContext context) { - Map dataModel = new HashMap<>(); - dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(context)); - dataModel.put(MODEL_NAME_PREFIX, context.getModelNamePrefix()); - dataModel.put(MODEL_NAME_SUFFIX, context.getModelNameSuffix()); - dataModel.put(CLASS_NAME, "GraphqlJacksonTypeIdResolver"); - dataModel.put(GENERATED_ANNOTATION, context.getAddGeneratedAnnotation()); - dataModel.put(GENERATED_INFO, context.getGeneratedInformation()); - return GraphQLCodegenFileCreator - .generateFile(context, FreeMarkerTemplateType.JACKSON_TYPE_ID_RESOLVER, dataModel, outputDir); - } - protected void initCustomTypeMappings(Collection scalarTypeDefinitions) { for (ExtendedScalarTypeDefinition definition : scalarTypeDefinitions) { if (definition.getDefinition() != null) { diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenValidate.java b/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenValidate.java index 218de8aae..cdf60cc68 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenValidate.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenValidate.java @@ -1,6 +1,7 @@ package com.kobylynskyi.graphql.codegen; import com.kobylynskyi.graphql.codegen.model.exception.SchemaValidationException; +import com.kobylynskyi.graphql.codegen.parser.GraphQLDocumentParser; import graphql.GraphQLException; import graphql.parser.MultiSourceReader; import graphql.parser.Parser; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/MapperFactory.java b/src/main/java/com/kobylynskyi/graphql/codegen/MapperFactory.java deleted file mode 100644 index 7b74dfd2e..000000000 --- a/src/main/java/com/kobylynskyi/graphql/codegen/MapperFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.kobylynskyi.graphql.codegen; - -import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; -import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; -import com.kobylynskyi.graphql.codegen.mapper.ValueFormatter; -import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; - -/** - * Factory for creating JVM-language-specific mappers - * - * @author kobylynskyi - */ -public interface MapperFactory { - - DataModelMapper createDataModelMapper(); - - GraphQLTypeMapper createGraphQLTypeMapper(ValueMapper valueMapper); - - ValueFormatter createValueFormatter(); - -} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGenerator.java new file mode 100644 index 000000000..c2087d0ad --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGenerator.java @@ -0,0 +1,14 @@ +package com.kobylynskyi.graphql.codegen.generators; + +import java.io.File; +import java.util.List; + +/** + * Represents files generator + */ +@FunctionalInterface +public interface FilesGenerator { + + List generate(); + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGeneratorsFactory.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGeneratorsFactory.java new file mode 100644 index 000000000..860da75d9 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGeneratorsFactory.java @@ -0,0 +1,49 @@ +package com.kobylynskyi.graphql.codegen.generators; + +import com.kobylynskyi.graphql.codegen.generators.impl.EnumsGenerator; +import com.kobylynskyi.graphql.codegen.generators.impl.FieldResolversGenerator; +import com.kobylynskyi.graphql.codegen.generators.impl.InputGenerator; +import com.kobylynskyi.graphql.codegen.generators.impl.InterfaceGenerator; +import com.kobylynskyi.graphql.codegen.generators.impl.JacksonTypeIdResolverGenerator; +import com.kobylynskyi.graphql.codegen.generators.impl.OperationsGenerator; +import com.kobylynskyi.graphql.codegen.generators.impl.ParametrizedInputGenerator; +import com.kobylynskyi.graphql.codegen.generators.impl.RequestResponseGenerator; +import com.kobylynskyi.graphql.codegen.generators.impl.ResponseProjectionGenerator; +import com.kobylynskyi.graphql.codegen.generators.impl.TypeGenerator; +import com.kobylynskyi.graphql.codegen.generators.impl.UnionGenerator; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.model.MappingContext; + +import java.util.ArrayList; +import java.util.List; + +/** + * Factory for building files generators + */ +public class FilesGeneratorsFactory { + + /** + * Factory method for building files generators + * + * @param context Global mapping context + * @param dataModelMapperFactory Data model mapper factory + * @return a list of all files generators + */ + public static List getAll(MappingContext context, + DataModelMapperFactory dataModelMapperFactory) { + List generators = new ArrayList<>(); + generators.add(new EnumsGenerator(context, dataModelMapperFactory)); + generators.add(new InterfaceGenerator(context, dataModelMapperFactory)); + generators.add(new TypeGenerator(context, dataModelMapperFactory)); + generators.add(new ResponseProjectionGenerator(context, dataModelMapperFactory)); + generators.add(new ParametrizedInputGenerator(context, dataModelMapperFactory)); + generators.add(new FieldResolversGenerator(context, dataModelMapperFactory)); + generators.add(new InputGenerator(context, dataModelMapperFactory)); + generators.add(new UnionGenerator(context, dataModelMapperFactory)); + generators.add(new RequestResponseGenerator(context, dataModelMapperFactory)); + generators.add(new OperationsGenerator(context, dataModelMapperFactory)); + generators.add(new JacksonTypeIdResolverGenerator(context)); + return generators; + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFileCreator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplateFilesCreator.java similarity index 72% rename from src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFileCreator.java rename to src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplateFilesCreator.java index 21428b230..b8b544242 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFileCreator.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplateFilesCreator.java @@ -1,4 +1,4 @@ -package com.kobylynskyi.graphql.codegen; +package com.kobylynskyi.graphql.codegen.generators; import com.kobylynskyi.graphql.codegen.model.DataModelFields; import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage; @@ -17,16 +17,25 @@ * * @author kobylynskyi */ -class GraphQLCodegenFileCreator { +public class FreeMarkerTemplateFilesCreator { - private GraphQLCodegenFileCreator() { + private FreeMarkerTemplateFilesCreator() { } - static File generateFile(MappingContext mappingContext, FreeMarkerTemplateType templateType, - Map dataModel, File outputDir) { + /** + * Crates a new file according to template + * + * @param mappingContext Global mapping context + * @param templateType Template type + * @param dataModel FreeMarker data model + * @return a created file + */ + public static File create(MappingContext mappingContext, + FreeMarkerTemplateType templateType, + Map dataModel) { GeneratedLanguage language = mappingContext.getGeneratedLanguage(); String fileName = dataModel.get(DataModelFields.CLASS_NAME) + language.getFileExtension(); - File fileOutputDir = getFileTargetDirectory(dataModel, outputDir); + File fileOutputDir = getFileTargetDirectory(dataModel, mappingContext.getOutputDirectory()); File javaSourceFile = new File(fileOutputDir, fileName); try { if (!javaSourceFile.createNewFile()) { @@ -40,11 +49,6 @@ static File generateFile(MappingContext mappingContext, FreeMarkerTemplateType t return javaSourceFile; } - static void prepareOutputDir(File outputDir) { - Utils.deleteDir(outputDir); - Utils.createDirIfAbsent(outputDir); - } - private static File getFileTargetDirectory(Map dataModel, File outputDir) { File targetDir; Object packageName = dataModel.get(DataModelFields.PACKAGE); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/FreeMarkerTemplateType.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplateType.java similarity index 56% rename from src/main/java/com/kobylynskyi/graphql/codegen/FreeMarkerTemplateType.java rename to src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplateType.java index d98f0552a..87229e4f4 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/FreeMarkerTemplateType.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplateType.java @@ -1,6 +1,9 @@ -package com.kobylynskyi.graphql.codegen; +package com.kobylynskyi.graphql.codegen.generators; -enum FreeMarkerTemplateType { +/** + * Type of the FreeMarker template + */ +public enum FreeMarkerTemplateType { TYPE, ENUM, diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplatesRegistry.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplatesRegistry.java new file mode 100644 index 000000000..95dc3db7a --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplatesRegistry.java @@ -0,0 +1,72 @@ +package com.kobylynskyi.graphql.codegen.generators; + +import com.kobylynskyi.graphql.codegen.GraphQLCodegen; +import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage; +import com.kobylynskyi.graphql.codegen.model.exception.UnableToLoadFreeMarkerTemplateException; +import freemarker.core.PlainTextOutputFormat; +import freemarker.ext.beans.BeansWrapper; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateExceptionHandler; +import freemarker.template.Version; + +import java.io.IOException; +import java.util.EnumMap; + +class FreeMarkerTemplatesRegistry { + + private static final String DEFAULT_ENCODING = "UTF-8"; + + private static final Version FREEMARKER_TEMPLATE_VERSION = Configuration.VERSION_2_3_31; + + private static final EnumMap> templateMap = + new EnumMap<>(GeneratedLanguage.class); + + static { + Configuration configuration = buildFreeMarkerTemplateConfiguration(); + + try { + templateMap.put(GeneratedLanguage.JAVA, getTemplates(configuration, GeneratedLanguage.JAVA)); + templateMap.put(GeneratedLanguage.SCALA, getTemplates(configuration, GeneratedLanguage.SCALA)); + templateMap.put(GeneratedLanguage.KOTLIN, getTemplates(configuration, GeneratedLanguage.KOTLIN)); + } catch (IOException e) { + throw new UnableToLoadFreeMarkerTemplateException(e); + } + } + + private FreeMarkerTemplatesRegistry() { + } + + public static Template getTemplateWithLang(GeneratedLanguage generatedLanguage, + FreeMarkerTemplateType templateType) { + return templateMap.get(generatedLanguage).get(templateType); + } + + private static EnumMap getTemplates(Configuration configuration, + GeneratedLanguage language) throws IOException { + EnumMap templates = new EnumMap<>(FreeMarkerTemplateType.class); + for (FreeMarkerTemplateType templateType : FreeMarkerTemplateType.values()) { + templates.put(templateType, configuration.getTemplate(buildTemplatePath(templateType, language))); + } + return templates; + } + + private static String buildTemplatePath(FreeMarkerTemplateType templateType, GeneratedLanguage language) { + return String.format("templates/%s-lang/%s.ftl", + language.name().toLowerCase(), + templateType.name().toLowerCase()); + } + + private static Configuration buildFreeMarkerTemplateConfiguration() { + Configuration configuration = new Configuration(FREEMARKER_TEMPLATE_VERSION); + configuration.setClassLoaderForTemplateLoading(GraphQLCodegen.class.getClassLoader(), ""); + configuration.setDefaultEncoding(DEFAULT_ENCODING); + configuration.setOutputFormat(PlainTextOutputFormat.INSTANCE); + configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + configuration.setLogTemplateExceptions(false); + configuration.setWrapUncheckedExceptions(true); + configuration.setSharedVariable("statics", new BeansWrapper(FREEMARKER_TEMPLATE_VERSION).getStaticModels()); + return configuration; + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/EnumsGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/EnumsGenerator.java new file mode 100644 index 000000000..aa48f4788 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/EnumsGenerator.java @@ -0,0 +1,44 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.EnumDefinitionToDataModelMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedEnumTypeDefinition; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Generates files for enums + */ +public class EnumsGenerator implements FilesGenerator { + + private final MappingContext mappingContext; + private final EnumDefinitionToDataModelMapper enumDefinitionMapper; + + public EnumsGenerator(MappingContext mappingContext, + DataModelMapperFactory dataModelMapperFactory) { + this.mappingContext = mappingContext; + this.enumDefinitionMapper = dataModelMapperFactory.getEnumDefinitionMapper(); + } + + @Override + public List generate() { + List generatedFiles = new ArrayList<>(); + for (ExtendedEnumTypeDefinition definition : mappingContext.getDocument().getEnumDefinitions()) { + generatedFiles.add(generate(definition)); + } + return generatedFiles; + } + + private File generate(ExtendedEnumTypeDefinition definition) { + Map dataModel = enumDefinitionMapper.map(mappingContext, definition); + return FreeMarkerTemplateFilesCreator.create(mappingContext, FreeMarkerTemplateType.ENUM, dataModel); + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/FieldResolversGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/FieldResolversGenerator.java new file mode 100644 index 000000000..e668ad7bf --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/FieldResolversGenerator.java @@ -0,0 +1,69 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.FieldDefinitionToParameterMapper; +import com.kobylynskyi.graphql.codegen.mapper.FieldDefinitionsToResolverDataModelMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInterfaceTypeDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static java.util.stream.Collectors.toList; + +/** + * Generates files for field resolvers + */ +public class FieldResolversGenerator implements FilesGenerator { + + private final MappingContext mappingContext; + private final FieldDefinitionsToResolverDataModelMapper fieldDefinitionsToResolverMapper; + + public FieldResolversGenerator(MappingContext mappingContext, + DataModelMapperFactory dataModelMapperFactory) { + this.mappingContext = mappingContext; + this.fieldDefinitionsToResolverMapper = dataModelMapperFactory.getFieldDefinitionsToResolverMapper(); + } + + @Override + public List generate() { + List generatedFiles = new ArrayList<>(); + for (ExtendedObjectTypeDefinition definition : mappingContext.getDocument().getTypeDefinitions()) { + generatedFiles.addAll(generate(definition.getFieldDefinitions(), definition)); + } + for (ExtendedInterfaceTypeDefinition definition : mappingContext.getDocument().getInterfaceDefinitions()) { + generatedFiles.addAll(generate(definition.getFieldDefinitions(), definition)); + } + return generatedFiles; + } + + private List generate(List fieldDefinitions, + ExtendedDefinition parentDefinition) { + if (!Boolean.TRUE.equals(mappingContext.getGenerateApis())) { + return Collections.emptyList(); + } + List fieldDefsWithResolvers = fieldDefinitions.stream() + .filter(fieldDef -> FieldDefinitionToParameterMapper.generateResolversForField( + mappingContext, fieldDef, parentDefinition)) + .collect(toList()); + + List generatedFiles = new ArrayList<>(); + if (!fieldDefsWithResolvers.isEmpty()) { + Map dataModel = fieldDefinitionsToResolverMapper + .mapToTypeResolver(mappingContext, fieldDefsWithResolvers, parentDefinition.getName()); + File file = FreeMarkerTemplateFilesCreator.create( + mappingContext, FreeMarkerTemplateType.OPERATIONS, dataModel); + generatedFiles.add(file); + } + return generatedFiles; + } +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/InputGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/InputGenerator.java new file mode 100644 index 000000000..7517081f2 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/InputGenerator.java @@ -0,0 +1,45 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.InputDefinitionToDataModelMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInputObjectTypeDefinition; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Generates files for inputs + */ +public class InputGenerator implements FilesGenerator { + + private final MappingContext mappingContext; + private final InputDefinitionToDataModelMapper inputDefinitionMapper; + + public InputGenerator(MappingContext mappingContext, + DataModelMapperFactory dataModelMapperFactory) { + this.mappingContext = mappingContext; + this.inputDefinitionMapper = dataModelMapperFactory.getInputDefinitionMapper(); + } + + @Override + public List generate() { + List generatedFiles = new ArrayList<>(); + for (ExtendedInputObjectTypeDefinition definition : mappingContext.getDocument().getInputDefinitions()) { + generatedFiles.add(generate(definition)); + } + return generatedFiles; + } + + private File generate(ExtendedInputObjectTypeDefinition definition) { + Map dataModel = inputDefinitionMapper.map(mappingContext, definition); + return FreeMarkerTemplateFilesCreator + .create(mappingContext, FreeMarkerTemplateType.TYPE, dataModel); + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/InterfaceGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/InterfaceGenerator.java new file mode 100644 index 000000000..7c2b5cca3 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/InterfaceGenerator.java @@ -0,0 +1,44 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.InterfaceDefinitionToDataModelMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInterfaceTypeDefinition; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Generates files for interfaces + */ +public class InterfaceGenerator implements FilesGenerator { + + private final MappingContext mappingContext; + private final InterfaceDefinitionToDataModelMapper interfaceDefinitionMapper; + + public InterfaceGenerator(MappingContext mappingContext, + DataModelMapperFactory dataModelMapperFactory) { + this.mappingContext = mappingContext; + this.interfaceDefinitionMapper = dataModelMapperFactory.getInterfaceDefinitionMapper(); + } + + @Override + public List generate() { + List generatedFiles = new ArrayList<>(); + for (ExtendedInterfaceTypeDefinition definition : mappingContext.getDocument().getInterfaceDefinitions()) { + generatedFiles.add(generate(definition)); + } + return generatedFiles; + } + + private File generate(ExtendedInterfaceTypeDefinition definition) { + Map dataModel = interfaceDefinitionMapper.map(mappingContext, definition); + return FreeMarkerTemplateFilesCreator.create(mappingContext, FreeMarkerTemplateType.INTERFACE, dataModel); + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/JacksonTypeIdResolverGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/JacksonTypeIdResolverGenerator.java new file mode 100644 index 000000000..b466995e7 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/JacksonTypeIdResolverGenerator.java @@ -0,0 +1,52 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.CLASS_NAME; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_ANNOTATION; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_INFO; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.MODEL_NAME_PREFIX; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.MODEL_NAME_SUFFIX; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.PACKAGE; + +/** + * Generates a JacksonTypeIdResolver file + */ +public class JacksonTypeIdResolverGenerator implements FilesGenerator { + + private static final String CLASS_NAME_GRAPHQL_JACKSON_TYPE_ID_RESOLVER = "GraphqlJacksonTypeIdResolver"; + + private final MappingContext mappingContext; + + public JacksonTypeIdResolverGenerator(MappingContext mappingContext) { + this.mappingContext = mappingContext; + } + + @Override + public List generate() { + List generatedFiles = new ArrayList<>(1); + if (Boolean.TRUE.equals(mappingContext.getGenerateJacksonTypeIdResolver())) { + Map dataModel = new HashMap<>(); + dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); + dataModel.put(MODEL_NAME_PREFIX, mappingContext.getModelNamePrefix()); + dataModel.put(MODEL_NAME_SUFFIX, mappingContext.getModelNameSuffix()); + dataModel.put(CLASS_NAME, CLASS_NAME_GRAPHQL_JACKSON_TYPE_ID_RESOLVER); + dataModel.put(GENERATED_ANNOTATION, mappingContext.getAddGeneratedAnnotation()); + dataModel.put(GENERATED_INFO, mappingContext.getGeneratedInformation()); + File file = FreeMarkerTemplateFilesCreator.create(mappingContext, FreeMarkerTemplateType.JACKSON_TYPE_ID_RESOLVER, dataModel); + generatedFiles.add(file); + } + return generatedFiles; + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/OperationsGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/OperationsGenerator.java new file mode 100644 index 000000000..18932e7d8 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/OperationsGenerator.java @@ -0,0 +1,109 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.model.ApiInterfaceStrategy; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition; +import graphql.language.FieldDefinition; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static java.util.stream.Collectors.toList; + +/** + * Generates files for oeprations + */ +public class OperationsGenerator implements FilesGenerator { + + private final MappingContext mappingContext; + private final DataModelMapperFactory dataModelMapperFactory; + + public OperationsGenerator(MappingContext mappingContext, + DataModelMapperFactory dataModelMapperFactory) { + this.mappingContext = mappingContext; + this.dataModelMapperFactory = dataModelMapperFactory; + } + + @Override + public List generate() { + if (!Boolean.TRUE.equals(mappingContext.getGenerateApis())) { + return Collections.emptyList(); + } + List generatedFiles = new ArrayList<>(); + for (ExtendedObjectTypeDefinition definition : mappingContext.getDocument().getOperationDefinitions()) { + generatedFiles.addAll(generateServerOperations(definition)); + } + return generatedFiles; + } + + private List generateServerOperations(ExtendedObjectTypeDefinition definition) { + List generatedFiles = new ArrayList<>(); + // Generate a root interface with all operations inside + // Relates to https://github.com/facebook/relay/issues/112 + switch (mappingContext.getApiRootInterfaceStrategy()) { + case INTERFACE_PER_SCHEMA: + for (ExtendedObjectTypeDefinition defInFile : definition.groupBySourceLocationFile().values()) { + generatedFiles.add(generateRootApi(defInFile)); + } + break; + case DO_NOT_GENERATE: + break; + case SINGLE_INTERFACE: + default: + generatedFiles.add(generateRootApi(definition)); + break; + } + + if (mappingContext.getApiInterfaceStrategy() == ApiInterfaceStrategy.INTERFACE_PER_OPERATION) { + // Generate separate interfaces for all queries, mutations and subscriptions + List fieldNames = definition.getFieldDefinitions().stream().map(FieldDefinition::getName) + .collect(toList()); + switch (mappingContext.getApiNamePrefixStrategy()) { + case FOLDER_NAME_AS_PREFIX: + for (ExtendedObjectTypeDefinition fileDef : definition.groupBySourceLocationFolder().values()) { + generatedFiles.addAll(generateApis(fileDef, fieldNames)); + } + break; + case FILE_NAME_AS_PREFIX: + for (ExtendedObjectTypeDefinition fileDef : definition.groupBySourceLocationFile().values()) { + generatedFiles.addAll(generateApis(fileDef, fieldNames)); + } + break; + case CONSTANT: + default: + generatedFiles.addAll(generateApis(definition, fieldNames)); + break; + } + } + return generatedFiles; + } + + private List generateApis(ExtendedObjectTypeDefinition definition, + List fieldNames) { + List generatedFiles = new ArrayList<>(); + for (ExtendedFieldDefinition operationDef : definition.getFieldDefinitions()) { + Map dataModel = dataModelMapperFactory.getFieldDefinitionsToResolverMapper() + .mapRootTypeField(mappingContext, operationDef, + definition.getName(), fieldNames); + generatedFiles.add(FreeMarkerTemplateFilesCreator + .create(mappingContext, FreeMarkerTemplateType.OPERATIONS, dataModel)); + } + return generatedFiles; + } + + private File generateRootApi(ExtendedObjectTypeDefinition definition) { + Map dataModel = dataModelMapperFactory.getFieldDefinitionsToResolverMapper() + .mapRootTypeFields(mappingContext, definition); + return FreeMarkerTemplateFilesCreator + .create(mappingContext, FreeMarkerTemplateType.OPERATIONS, dataModel); + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ParametrizedInputGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ParametrizedInputGenerator.java new file mode 100644 index 000000000..8f9cb67a7 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ParametrizedInputGenerator.java @@ -0,0 +1,69 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.RequestResponseDefinitionToDataModelMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInterfaceTypeDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition; +import com.kobylynskyi.graphql.codegen.utils.Utils; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Generates files for parametrized inputs + */ +public class ParametrizedInputGenerator implements FilesGenerator { + + private final MappingContext mappingContext; + private final RequestResponseDefinitionToDataModelMapper requestResponseDefinitionMapper; + + public ParametrizedInputGenerator(MappingContext mappingContext, + DataModelMapperFactory dataModelMapperFactory) { + this.mappingContext = mappingContext; + this.requestResponseDefinitionMapper = dataModelMapperFactory.getRequestResponseDefinitionMapper(); + } + + @Override + public List generate() { + if (!Boolean.TRUE.equals(mappingContext.getGenerateClient())) { + return Collections.emptyList(); + } + List generatedFiles = new ArrayList<>(); + for (ExtendedInterfaceTypeDefinition definition : mappingContext.getDocument().getInterfaceDefinitions()) { + generatedFiles.addAll(generate(definition, definition.getFieldDefinitions())); + } + for (ExtendedObjectTypeDefinition definition : mappingContext.getDocument().getTypeDefinitions()) { + generatedFiles.addAll(generate(definition, definition.getFieldDefinitions())); + } + return generatedFiles; + } + + private List generate(ExtendedDefinition definition, + List fieldDefinitions) { + List generatedFiles = new ArrayList<>(); + for (ExtendedFieldDefinition fieldDefinition : fieldDefinitions) { + if (Utils.isEmpty(fieldDefinition.getInputValueDefinitions())) { + continue; + } + File file = generate(definition, fieldDefinition); + generatedFiles.add(file); + } + return generatedFiles; + } + + private File generate(ExtendedDefinition definition, + ExtendedFieldDefinition fieldDefinition) { + Map dataModel = requestResponseDefinitionMapper.mapParametrizedInput(mappingContext, fieldDefinition, definition); + return FreeMarkerTemplateFilesCreator.create(mappingContext, FreeMarkerTemplateType.PARAMETRIZED_INPUT, dataModel); + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/RequestResponseGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/RequestResponseGenerator.java new file mode 100644 index 000000000..ccaadd1dc --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/RequestResponseGenerator.java @@ -0,0 +1,65 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.RequestResponseDefinitionToDataModelMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition; +import graphql.language.FieldDefinition; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static java.util.stream.Collectors.toList; + +/** + * Generates files for requests and responses + */ +public class RequestResponseGenerator implements FilesGenerator { + + private final MappingContext mappingContext; + private final RequestResponseDefinitionToDataModelMapper requestResponseDefinitionMapper; + + public RequestResponseGenerator(MappingContext mappingContext, + DataModelMapperFactory dataModelMapperFactory) { + this.mappingContext = mappingContext; + this.requestResponseDefinitionMapper = dataModelMapperFactory.getRequestResponseDefinitionMapper(); + } + + @Override + public List generate() { + if (!Boolean.TRUE.equals(mappingContext.getGenerateClient())) { + return Collections.emptyList(); + } + List generatedFiles = new ArrayList<>(); + for (ExtendedObjectTypeDefinition definition : mappingContext.getDocument().getOperationDefinitions()) { + generatedFiles.addAll(generate(definition)); + } + return generatedFiles; + } + + private List generate(ExtendedObjectTypeDefinition definition) { + List generatedFiles = new ArrayList<>(); + List fieldNames = definition.getFieldDefinitions().stream().map(FieldDefinition::getName) + .collect(toList()); + for (ExtendedFieldDefinition operationDef : definition.getFieldDefinitions()) { + Map requestDataModel = requestResponseDefinitionMapper + .mapRequest(mappingContext, operationDef, definition.getName(), fieldNames); + generatedFiles.add(FreeMarkerTemplateFilesCreator + .create(mappingContext, FreeMarkerTemplateType.REQUEST, requestDataModel)); + + Map responseDataModel = requestResponseDefinitionMapper + .mapResponse(mappingContext, operationDef, definition.getName(), fieldNames); + generatedFiles.add(FreeMarkerTemplateFilesCreator + .create(mappingContext, FreeMarkerTemplateType.RESPONSE, responseDataModel)); + } + return generatedFiles; + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ResponseProjectionGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ResponseProjectionGenerator.java new file mode 100644 index 000000000..82fce048b --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ResponseProjectionGenerator.java @@ -0,0 +1,59 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.RequestResponseDefinitionToDataModelMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInterfaceTypeDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedUnionTypeDefinition; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Generates files for response projections + */ +public class ResponseProjectionGenerator implements FilesGenerator { + + private final MappingContext mappingContext; + private final RequestResponseDefinitionToDataModelMapper requestResponseDefinitionMapper; + + public ResponseProjectionGenerator(MappingContext mappingContext, + DataModelMapperFactory dataModelMapperFactory) { + this.mappingContext = mappingContext; + this.requestResponseDefinitionMapper = dataModelMapperFactory.getRequestResponseDefinitionMapper(); + } + + @Override + public List generate() { + if (!Boolean.TRUE.equals(mappingContext.getGenerateClient())) { + return Collections.emptyList(); + } + List generatedFiles = new ArrayList<>(); + for (ExtendedInterfaceTypeDefinition definition : mappingContext.getDocument().getInterfaceDefinitions()) { + generatedFiles.add(generate(definition)); + } + for (ExtendedObjectTypeDefinition definition : mappingContext.getDocument().getTypeDefinitions()) { + generatedFiles.add(generate(definition)); + } + for (ExtendedUnionTypeDefinition definition : mappingContext.getDocument().getUnionDefinitions()) { + generatedFiles.add(generate(definition)); + } + return generatedFiles; + } + + private File generate(ExtendedDefinition definition) { + Map responseProjDataModel = requestResponseDefinitionMapper.mapResponseProjection( + mappingContext, definition); + return FreeMarkerTemplateFilesCreator.create( + mappingContext, FreeMarkerTemplateType.RESPONSE_PROJECTION, responseProjDataModel); + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/TypeGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/TypeGenerator.java new file mode 100644 index 000000000..532762f40 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/TypeGenerator.java @@ -0,0 +1,54 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.TypeDefinitionToDataModelMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Generates files for types + */ +public class TypeGenerator implements FilesGenerator { + + private final MappingContext mappingContext; + private final TypeDefinitionToDataModelMapper typeDefinitionMapper; + + public TypeGenerator(MappingContext mappingContext, DataModelMapperFactory dataModelMapperFactory) { + this.mappingContext = mappingContext; + this.typeDefinitionMapper = dataModelMapperFactory.getTypeDefinitionMapper(); + } + + @Override + public List generate() { + List generatedFiles = new ArrayList<>(); + for (ExtendedObjectTypeDefinition definition : mappingContext.getDocument().getTypeDefinitions()) { + generatedFiles.add(generate(definition)); + } + return generatedFiles; + } + + private File generate(ExtendedObjectTypeDefinition definition) { + boolean typeAsInterface = mappingContext.getTypesAsInterfaces().contains(definition.getName()); + if (!typeAsInterface) { + typeAsInterface = definition.getDirectiveNames().stream().anyMatch(directiveName -> + mappingContext.getTypesAsInterfaces().contains("@" + directiveName)); + } + + Map dataModel = typeDefinitionMapper.map(mappingContext, definition); + if (typeAsInterface) { + return FreeMarkerTemplateFilesCreator.create( + mappingContext, FreeMarkerTemplateType.INTERFACE, dataModel); + } else { + return FreeMarkerTemplateFilesCreator.create( + mappingContext, FreeMarkerTemplateType.TYPE, dataModel); + } + } +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/UnionGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/UnionGenerator.java new file mode 100644 index 000000000..0fbab6c1b --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/UnionGenerator.java @@ -0,0 +1,43 @@ +package com.kobylynskyi.graphql.codegen.generators.impl; + +import com.kobylynskyi.graphql.codegen.generators.FilesGenerator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.UnionDefinitionToDataModelMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedUnionTypeDefinition; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Generates files for unions + */ +public class UnionGenerator implements FilesGenerator { + + private final MappingContext mappingContext; + private final UnionDefinitionToDataModelMapper unionDefinitionToDataModelMapper; + + public UnionGenerator(MappingContext mappingContext, DataModelMapperFactory dataModelMapperFactory) { + this.mappingContext = mappingContext; + this.unionDefinitionToDataModelMapper = dataModelMapperFactory.getUnionDefinitionMapper(); + } + + @Override + public List generate() { + List generatedFiles = new ArrayList<>(); + for (ExtendedUnionTypeDefinition definition : mappingContext.getDocument().getUnionDefinitions()) { + generatedFiles.add(generate(definition)); + } + return generatedFiles; + } + + private File generate(ExtendedUnionTypeDefinition definition) { + Map dataModel = unionDefinitionToDataModelMapper.map(mappingContext, definition); + return FreeMarkerTemplateFilesCreator.create(mappingContext, FreeMarkerTemplateType.UNION, dataModel); + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaGraphQLCodegen.java b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaGraphQLCodegen.java index aee3dcb8b..2485f78cc 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaGraphQLCodegen.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaGraphQLCodegen.java @@ -1,7 +1,7 @@ package com.kobylynskyi.graphql.codegen.java; import com.kobylynskyi.graphql.codegen.GraphQLCodegen; -import com.kobylynskyi.graphql.codegen.MapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; import com.kobylynskyi.graphql.codegen.model.GeneratedInformation; import com.kobylynskyi.graphql.codegen.model.MappingConfig; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedScalarTypeDefinition; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaMapperFactoryImpl.java b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaMapperFactoryImpl.java index 41e8d3bee..49328e5ef 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaMapperFactoryImpl.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaMapperFactoryImpl.java @@ -1,8 +1,8 @@ package com.kobylynskyi.graphql.codegen.java; -import com.kobylynskyi.graphql.codegen.MapperFactory; import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; +import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; import com.kobylynskyi.graphql.codegen.mapper.ValueFormatter; import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java index 9934f7de8..1c515512d 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java @@ -1,7 +1,7 @@ package com.kobylynskyi.graphql.codegen.kotlin; import com.kobylynskyi.graphql.codegen.GraphQLCodegen; -import com.kobylynskyi.graphql.codegen.MapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; import com.kobylynskyi.graphql.codegen.model.GeneratedInformation; import com.kobylynskyi.graphql.codegen.model.MappingConfig; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedScalarTypeDefinition; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinMapperFactoryImpl.java b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinMapperFactoryImpl.java index 040e7ae22..0079084d9 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinMapperFactoryImpl.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinMapperFactoryImpl.java @@ -1,8 +1,8 @@ package com.kobylynskyi.graphql.codegen.kotlin; -import com.kobylynskyi.graphql.codegen.MapperFactory; import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; +import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; import com.kobylynskyi.graphql.codegen.mapper.ValueFormatter; import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java index 52da8119e..baf84073e 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java @@ -1,7 +1,5 @@ package com.kobylynskyi.graphql.codegen.mapper; -import com.kobylynskyi.graphql.codegen.MapperFactory; - /** * Factory of data model mappers */ diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/EnumDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/EnumDefinitionToDataModelMapper.java index 1d841ebea..ad93baa0b 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/EnumDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/EnumDefinitionToDataModelMapper.java @@ -1,14 +1,14 @@ package com.kobylynskyi.graphql.codegen.mapper; -import com.kobylynskyi.graphql.codegen.model.DeprecatedDefinition; import com.kobylynskyi.graphql.codegen.model.EnumValueDefinition; import com.kobylynskyi.graphql.codegen.model.MappingConfigConstants; import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.builders.DeprecatedDefinitionBuilder; +import com.kobylynskyi.graphql.codegen.model.builders.JavaDocBuilder; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedEnumTypeDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedUnionTypeDefinition; import com.kobylynskyi.graphql.codegen.utils.Utils; import graphql.language.Comment; -import graphql.language.DirectivesContainer; import java.util.Collections; import java.util.HashMap; @@ -65,11 +65,6 @@ private static List getJavaDoc(graphql.language.EnumValueDefinition def) .map(String::trim).collect(Collectors.toList()); } - public DeprecatedDefinition getDeprecated(MappingContext mappingContext, - DirectivesContainer directivesContainer) { - return graphQlTypeMapper.getDeprecated(mappingContext, directivesContainer); - } - /** * Map field definition to a Freemarker data model * @@ -84,7 +79,7 @@ public Map map(MappingContext mappingContext, ExtendedEnumTypeDe dataModel.put(CLASS_NAME, dataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, definition)); dataModel.put(IMPLEMENTS, getUnionInterfaces(mappingContext, definition)); dataModel.put(ANNOTATIONS, graphQlTypeMapper.getAnnotations(mappingContext, definition)); - dataModel.put(JAVA_DOC, definition.getJavaDoc()); + dataModel.put(JAVA_DOC, JavaDocBuilder.build(definition)); dataModel.put(FIELDS, map(mappingContext, definition.getValueDefinitions())); dataModel.put(GENERATED_ANNOTATION, mappingContext.getAddGeneratedAnnotation()); dataModel.put(GENERATED_INFO, mappingContext.getGeneratedInformation()); @@ -106,7 +101,7 @@ private List map(MappingContext mappingContext, dataModelMapper.capitalizeIfRestricted(mappingContext, f.getName()), f.getName(), getJavaDoc(f), - getDeprecated(mappingContext, f))) + DeprecatedDefinitionBuilder.build(mappingContext, f))) .collect(Collectors.toList()); } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java index 7f3cfd1d9..564aa6a18 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java @@ -4,6 +4,7 @@ import com.kobylynskyi.graphql.codegen.model.NamedDefinition; import com.kobylynskyi.graphql.codegen.model.ParameterDefinition; import com.kobylynskyi.graphql.codegen.model.ProjectionParameterDefinition; +import com.kobylynskyi.graphql.codegen.model.builders.DeprecatedDefinitionBuilder; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; import com.kobylynskyi.graphql.codegen.utils.Utils; @@ -132,7 +133,7 @@ private ParameterDefinition mapField(MappingContext mappingContext, ExtendedFiel parameter.setAnnotations( graphQLTypeMapper.getAnnotations(mappingContext, fieldDef.getType(), fieldDef, parentTypeName, false)); parameter.setJavaDoc(fieldDef.getJavaDoc()); - parameter.setDeprecated(fieldDef.getDeprecated(mappingContext)); + parameter.setDeprecated(DeprecatedDefinitionBuilder.build(mappingContext, fieldDef)); parameter.setMandatory(namedDefinition.isMandatory()); parameter.setSerializeUsingObjectMapper(namedDefinition.isSerializeUsingObjectMapper()); return parameter; @@ -160,7 +161,7 @@ private ProjectionParameterDefinition mapProjectionField(MappingContext mappingC parameter.setParametrizedInputClassName( DataModelMapper.getParametrizedInputClassName(mappingContext, fieldDef, parentTypeDef)); } - parameter.setDeprecated(fieldDef.getDeprecated(mappingContext)); + parameter.setDeprecated(DeprecatedDefinitionBuilder.build(mappingContext, fieldDef)); return parameter; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java index 44bde4ba6..d191a984b 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java @@ -5,6 +5,8 @@ import com.kobylynskyi.graphql.codegen.model.OperationDefinition; import com.kobylynskyi.graphql.codegen.model.ParameterDefinition; import com.kobylynskyi.graphql.codegen.model.RelayConfig; +import com.kobylynskyi.graphql.codegen.model.builders.DeprecatedDefinitionBuilder; +import com.kobylynskyi.graphql.codegen.model.builders.JavaDocBuilder; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition; import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation; @@ -135,7 +137,7 @@ public Map mapRootTypeFields(MappingContext mappingContext, String className = DataModelMapper.getApiClassNameWithPrefixAndSuffix(mappingContext, definition); // For root types like "Query", we create resolvers for all fields return mapToResolverModel(mappingContext, definition.getName(), className, - definition.getFieldDefinitions(), definition.getJavaDoc(), + definition.getFieldDefinitions(), JavaDocBuilder.build(definition), getParentInterface(mappingContext, definition.getName())); } @@ -205,7 +207,7 @@ private OperationDefinition map(MappingContext mappingContext, ExtendedFieldDefi operation.setAnnotations(annotations); operation.setParameters(parameters); operation.setJavaDoc(fieldDef.getJavaDoc()); - operation.setDeprecated(fieldDef.getDeprecated(mappingContext)); + operation.setDeprecated(DeprecatedDefinitionBuilder.build(mappingContext, fieldDef)); operation.setThrowsException(mappingContext.getGenerateApisWithThrowsException()); return operation; } @@ -225,7 +227,7 @@ private List getOperationParameters(MappingContext mappingC parameterDefinition.setType(parentObjectParamType); parameterDefinition.setName(parentObjectParamName); parameterDefinition.setOriginalName(parentObjectParamName); - parameterDefinition.setDeprecated(resolvedField.getDeprecated(mappingContext)); + parameterDefinition.setDeprecated(DeprecatedDefinitionBuilder.build(mappingContext, resolvedField)); parameters.add(parameterDefinition); } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/GraphQLTypeMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/GraphQLTypeMapper.java index 7f2242317..2625de689 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/GraphQLTypeMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/GraphQLTypeMapper.java @@ -1,8 +1,6 @@ package com.kobylynskyi.graphql.codegen.mapper; -import com.kobylynskyi.graphql.codegen.model.DeprecatedDefinition; import com.kobylynskyi.graphql.codegen.model.MappingContext; -import com.kobylynskyi.graphql.codegen.model.MultiLanguageDeprecated; import com.kobylynskyi.graphql.codegen.model.NamedDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; @@ -419,17 +417,6 @@ default String getResponseReturnType(MappingContext mappingContext, return computedTypeName; } - default DeprecatedDefinition getDeprecated(MappingContext mappingContext, - DirectivesContainer directivesContainer) { - return directivesContainer.getDirectives() - .stream() - .filter(d -> d.getName().equalsIgnoreCase(Deprecated.class.getSimpleName())) - .findFirst() - .map(directive -> MultiLanguageDeprecated - .getLanguageDeprecated(mappingContext.getGeneratedLanguage(), directive)) - .orElse(null); - } - ValueMapper getValueMapper(); } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java index ae11edaac..d613b8329 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java @@ -1,6 +1,7 @@ package com.kobylynskyi.graphql.codegen.mapper; import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.builders.JavaDocBuilder; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInputObjectTypeDefinition; import java.util.HashMap; @@ -53,7 +54,7 @@ public Map map(MappingContext mappingContext, ExtendedInputObjec // type/enum/input/interface/union classes do not require any imports dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); dataModel.put(CLASS_NAME, dataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, definition)); - dataModel.put(JAVA_DOC, definition.getJavaDoc()); + dataModel.put(JAVA_DOC, JavaDocBuilder.build(definition)); dataModel.put(NAME, definition.getName()); dataModel.put(FIELDS, inputValueDefinitionToParameterMapper .map(mappingContext, definition.getValueDefinitions(), definition.getName())); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputValueDefinitionToParameterMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputValueDefinitionToParameterMapper.java index 83ed0faa4..e5e95bdb9 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputValueDefinitionToParameterMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputValueDefinitionToParameterMapper.java @@ -3,6 +3,7 @@ import com.kobylynskyi.graphql.codegen.model.MappingContext; import com.kobylynskyi.graphql.codegen.model.NamedDefinition; import com.kobylynskyi.graphql.codegen.model.ParameterDefinition; +import com.kobylynskyi.graphql.codegen.model.builders.DeprecatedDefinitionBuilder; import graphql.language.InputValueDefinition; import java.util.List; @@ -66,7 +67,7 @@ private ParameterDefinition map(MappingContext mappingContext, InputValueDefinit mappingContext, inputValueDefinition.getDefaultValue(), inputValueDefinition.getType())); parameter.setAnnotations(graphQLTypeMapper.getAnnotations(mappingContext, inputValueDefinition.getType(), inputValueDefinition, parentTypeName, false)); - parameter.setDeprecated(graphQLTypeMapper.getDeprecated(mappingContext, inputValueDefinition)); + parameter.setDeprecated(DeprecatedDefinitionBuilder.build(mappingContext, inputValueDefinition)); parameter.setMandatory(namedDefinition.isMandatory()); parameter.setSerializeUsingObjectMapper(namedDefinition.isSerializeUsingObjectMapper()); return parameter; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java index dbef3f258..0d9b209b8 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java @@ -1,6 +1,7 @@ package com.kobylynskyi.graphql.codegen.mapper; import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.builders.JavaDocBuilder; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInterfaceTypeDefinition; import java.util.HashMap; @@ -51,7 +52,7 @@ public Map map(MappingContext mappingContext, ExtendedInterfaceT // type/enum/input/interface/union classes do not require any imports dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); dataModel.put(CLASS_NAME, dataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, definition)); - dataModel.put(JAVA_DOC, definition.getJavaDoc()); + dataModel.put(JAVA_DOC, JavaDocBuilder.build(definition)); dataModel.put(IMPLEMENTS, getInterfaces(mappingContext, definition)); dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, definition)); dataModel.put(FIELDS, fieldDefinitionToParameterMapper diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/MapperFactory.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/MapperFactory.java new file mode 100644 index 000000000..cdc759aa6 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/MapperFactory.java @@ -0,0 +1,16 @@ +package com.kobylynskyi.graphql.codegen.mapper; + +/** + * Factory for creating JVM-language-specific mappers + * + * @author kobylynskyi + */ +public interface MapperFactory { + + DataModelMapper createDataModelMapper(); + + GraphQLTypeMapper createGraphQLTypeMapper(ValueMapper valueMapper); + + ValueFormatter createValueFormatter(); + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java index d57e79dcc..0ece353d3 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java @@ -3,6 +3,7 @@ import com.kobylynskyi.graphql.codegen.model.MappingContext; import com.kobylynskyi.graphql.codegen.model.NamedDefinition; import com.kobylynskyi.graphql.codegen.model.ProjectionParameterDefinition; +import com.kobylynskyi.graphql.codegen.model.builders.DeprecatedDefinitionBuilder; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInterfaceTypeDefinition; @@ -181,7 +182,7 @@ public Map mapResponse(MappingContext mappingContext, dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, className)); dataModel.put(CLASS_NAME, className); dataModel.put(JAVA_DOC, operationDef.getJavaDoc()); - dataModel.put(DEPRECATED, operationDef.getDeprecated(mappingContext)); + dataModel.put(DEPRECATED, DeprecatedDefinitionBuilder.build(mappingContext, operationDef)); dataModel.put(OPERATION_NAME, operationDef.getName()); dataModel.put(METHOD_NAME, dataModelMapper.capitalizeMethodNameIfRestricted( mappingContext, operationDef.getName())); @@ -226,26 +227,6 @@ public Map mapRequest(MappingContext mappingContext, return dataModel; } - /** - * Get merged attributes from the type and attributes from the interface. - * - * @param mappingContext Global mapping context - * @param unionDefinition GraphQL union definition - * @return Freemarker data model for response projection of the GraphQL union - */ - private static Collection getProjectionFields( - MappingContext mappingContext, ExtendedUnionTypeDefinition unionDefinition) { - // using the map to exclude duplicate fields from the type and interfaces - Map allParameters = new LinkedHashMap<>(); - for (String memberTypeName : unionDefinition.getMemberTypeNames()) { - ProjectionParameterDefinition memberDef = getChildDefinition(mappingContext, memberTypeName); - allParameters.put(memberDef.getMethodName(), memberDef); - } - ProjectionParameterDefinition typeNameProjParamDef = getTypeNameProjectionParameterDefinition(); - allParameters.put(typeNameProjParamDef.getMethodName(), typeNameProjParamDef); - return allParameters.values(); - } - /** * Get merged attributes from the type and attributes from the interface. * @@ -266,6 +247,26 @@ private Collection getProjectionFields(MappingCon return Collections.emptyList(); } + /** + * Get merged attributes from the type and attributes from the interface. + * + * @param mappingContext Global mapping context + * @param unionDefinition GraphQL union definition + * @return Freemarker data model for response projection of the GraphQL union + */ + private static Collection getProjectionFields( + MappingContext mappingContext, ExtendedUnionTypeDefinition unionDefinition) { + // using the map to exclude duplicate fields from the type and interfaces + Map allParameters = new LinkedHashMap<>(); + for (String memberTypeName : unionDefinition.getMemberTypeNames()) { + ProjectionParameterDefinition memberDef = getChildDefinition(mappingContext, memberTypeName); + allParameters.put(memberDef.getMethodName(), memberDef); + } + ProjectionParameterDefinition typeNameProjParamDef = getTypeNameProjectionParameterDefinition(); + allParameters.put(typeNameProjParamDef.getMethodName(), typeNameProjParamDef); + return allParameters.values(); + } + /** * Get merged attributes from the type and attributes from the interface. * diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java index e6f72cb6e..0d835b216 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java @@ -2,6 +2,7 @@ import com.kobylynskyi.graphql.codegen.model.MappingContext; import com.kobylynskyi.graphql.codegen.model.ParameterDefinition; +import com.kobylynskyi.graphql.codegen.model.builders.JavaDocBuilder; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDocument; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedUnionTypeDefinition; @@ -86,7 +87,7 @@ public Map map(MappingContext mappingContext, // type/enum/input/interface/union classes do not require any imports dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); dataModel.put(CLASS_NAME, dataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, definition)); - dataModel.put(JAVA_DOC, definition.getJavaDoc()); + dataModel.put(JAVA_DOC, JavaDocBuilder.build(definition)); dataModel.put(IMPLEMENTS, getInterfaces(mappingContext, definition)); dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, definition)); dataModel.put(FIELDS, getFields(mappingContext, definition, document)); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java index eead1353f..9baebc0c4 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java @@ -1,6 +1,7 @@ package com.kobylynskyi.graphql.codegen.mapper; import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.builders.JavaDocBuilder; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedUnionTypeDefinition; import java.util.HashMap; @@ -43,7 +44,7 @@ public Map map(MappingContext mappingContext, ExtendedUnionTypeD dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); dataModel.put(CLASS_NAME, dataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, definition)); dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, definition)); - dataModel.put(JAVA_DOC, definition.getJavaDoc()); + dataModel.put(JAVA_DOC, JavaDocBuilder.build(definition)); dataModel.put(GENERATED_ANNOTATION, mappingContext.getAddGeneratedAnnotation()); dataModel.put(GENERATED_INFO, mappingContext.getGeneratedInformation()); dataModel.put(ENUM_IMPORT_IT_SELF_IN_SCALA, mappingContext.getEnumImportItSelfInScala()); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java index 3df14256a..0a337d299 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java @@ -602,15 +602,15 @@ public void setParametrizedInputSuffix(String parametrizedInputSuffix) { this.parametrizedInputSuffix = parametrizedInputSuffix; } - public void setGenerateAllMethodInProjection(Boolean generateAllMethodInProjection) { - this.generateAllMethodInProjection = generateAllMethodInProjection; - } - @Override public Boolean getGenerateAllMethodInProjection() { return generateAllMethodInProjection; } + public void setGenerateAllMethodInProjection(Boolean generateAllMethodInProjection) { + this.generateAllMethodInProjection = generateAllMethodInProjection; + } + @Override public Integer getResponseProjectionMaxDepth() { return responseProjectionMaxDepth; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java index e066d15c0..68197d007 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java @@ -2,6 +2,7 @@ /** * Various constants used in code generation process + * Constants with "_STRING" suffix are used by plugins */ public class MappingConfigConstants { diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java new file mode 100644 index 000000000..49730616d --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java @@ -0,0 +1,107 @@ +package com.kobylynskyi.graphql.codegen.model; + +/** + * Initializes mapping config with default values + */ +public class MappingConfigDefaultValuesInitializer { + + /** + * Initializes mapping config with default values + * + * @param mappingConfig Global mapping config + */ + public static void initDefaultValues(MappingConfig mappingConfig) { + if (mappingConfig.getModelValidationAnnotation() == null) { + mappingConfig.setModelValidationAnnotation(MappingConfigConstants.DEFAULT_VALIDATION_ANNOTATION); + } + if (mappingConfig.getGenerateBuilder() == null) { + mappingConfig.setGenerateBuilder(MappingConfigConstants.DEFAULT_BUILDER); + } + if (mappingConfig.getGenerateEqualsAndHashCode() == null) { + mappingConfig.setGenerateEqualsAndHashCode(MappingConfigConstants.DEFAULT_EQUALS_AND_HASHCODE); + } + if (mappingConfig.getGenerateClient() == null) { + mappingConfig.setGenerateClient(MappingConfigConstants.DEFAULT_GENERATE_CLIENT); + } + if (mappingConfig.getRequestSuffix() == null) { + mappingConfig.setRequestSuffix(MappingConfigConstants.DEFAULT_REQUEST_SUFFIX); + } + if (mappingConfig.getResponseSuffix() == null) { + mappingConfig.setResponseSuffix(MappingConfigConstants.DEFAULT_RESPONSE_SUFFIX); + } + if (mappingConfig.getResponseProjectionSuffix() == null) { + mappingConfig.setResponseProjectionSuffix(MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_SUFFIX); + } + if (mappingConfig.getParametrizedInputSuffix() == null) { + mappingConfig.setParametrizedInputSuffix(MappingConfigConstants.DEFAULT_PARAMETRIZED_INPUT_SUFFIX); + } + if (mappingConfig.getGenerateImmutableModels() == null) { + mappingConfig.setGenerateImmutableModels(MappingConfigConstants.DEFAULT_GENERATE_IMMUTABLE_MODELS); + } + if (mappingConfig.getGenerateToString() == null) { + mappingConfig.setGenerateToString(MappingConfigConstants.DEFAULT_TO_STRING); + } + if (mappingConfig.getGenerateApis() == null) { + mappingConfig.setGenerateApis(MappingConfigConstants.DEFAULT_GENERATE_APIS); + } + if (mappingConfig.getApiNameSuffix() == null) { + mappingConfig.setApiNameSuffix(MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX); + } + if (mappingConfig.getTypeResolverSuffix() == null) { + mappingConfig.setTypeResolverSuffix(MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX); + } + if (mappingConfig.getGenerateParameterizedFieldsResolvers() == null) { + mappingConfig.setGenerateParameterizedFieldsResolvers( + MappingConfigConstants.DEFAULT_GENERATE_PARAMETERIZED_FIELDS_RESOLVERS); + } + if (mappingConfig.getGenerateExtensionFieldsResolvers() == null) { + mappingConfig.setGenerateExtensionFieldsResolvers( + MappingConfigConstants.DEFAULT_GENERATE_EXTENSION_FIELDS_RESOLVERS); + } + if (mappingConfig.getGenerateDataFetchingEnvironmentArgumentInApis() == null) { + mappingConfig.setGenerateDataFetchingEnvironmentArgumentInApis( + MappingConfigConstants.DEFAULT_GENERATE_DATA_FETCHING_ENV); + } + if (mappingConfig.getGenerateModelsForRootTypes() == null) { + mappingConfig.setGenerateModelsForRootTypes(MappingConfigConstants.DEFAULT_GENERATE_MODELS_FOR_ROOT_TYPES); + } + if (mappingConfig.getGenerateApisWithThrowsException() == null) { + mappingConfig.setGenerateApisWithThrowsException( + MappingConfigConstants.DEFAULT_GENERATE_APIS_WITH_THROWS_EXCEPTION); + } + if (mappingConfig.getAddGeneratedAnnotation() == null) { + mappingConfig.setAddGeneratedAnnotation(MappingConfigConstants.DEFAULT_ADD_GENERATED_ANNOTATION); + } + if (mappingConfig.getGenerateJacksonTypeIdResolver() == null) { + mappingConfig.setGenerateJacksonTypeIdResolver( + MappingConfigConstants.DEFAULT_GENERATE_JACKSON_TYPE_ID_RESOLVER); + } + if (mappingConfig.getUseOptionalForNullableReturnTypes() == null) { + mappingConfig.setUseOptionalForNullableReturnTypes( + MappingConfigConstants.DEFAULT_USE_OPTIONAL_FOR_NULLABLE_RETURN_TYPES); + } + if (mappingConfig.getApiNamePrefixStrategy() == null) { + mappingConfig.setApiNamePrefixStrategy(MappingConfigConstants.DEFAULT_API_NAME_PREFIX_STRATEGY); + } + if (mappingConfig.getApiRootInterfaceStrategy() == null) { + mappingConfig.setApiRootInterfaceStrategy(MappingConfigConstants.DEFAULT_API_ROOT_INTERFACE_STRATEGY); + } + if (mappingConfig.getApiInterfaceStrategy() == null) { + mappingConfig.setApiInterfaceStrategy(MappingConfigConstants.DEFAULT_API_INTERFACE_STRATEGY); + } + if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) { + // required for request serialization + mappingConfig.setGenerateToString(true); + } + if (mappingConfig.getResponseProjectionMaxDepth() == null) { + mappingConfig.setResponseProjectionMaxDepth(MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_MAX_DEPTH); + } + if (mappingConfig.getGeneratedLanguage() == null) { + mappingConfig.setGeneratedLanguage(MappingConfigConstants.DEFAULT_GENERATED_LANGUAGE); + } + if (mappingConfig.getGenerateAllMethodInProjection() == null) { + mappingConfig.setGenerateAllMethodInProjection(MappingConfigConstants.DEFAULT_GENERATE_ALL_METHOD); + } + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigValidator.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigValidator.java new file mode 100644 index 000000000..c2be67a5a --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigValidator.java @@ -0,0 +1,47 @@ +package com.kobylynskyi.graphql.codegen.model; + +import com.kobylynskyi.graphql.codegen.utils.Utils; + +/** + * Validator of the mapping config + */ +public class MappingConfigValidator { + + /** + * Validator of the mapping config + * + * @param mappingConfig Global mapping config + * @throws IllegalArgumentException in case config is not valid + */ + public static void validate(MappingConfig mappingConfig) { + if (mappingConfig.getApiRootInterfaceStrategy() == ApiRootInterfaceStrategy.INTERFACE_PER_SCHEMA && + mappingConfig.getApiNamePrefixStrategy() == ApiNamePrefixStrategy.CONSTANT) { + // we will have a conflict in case there is "type Query" in multiple graphql schema files + throw new IllegalArgumentException("API prefix should not be CONSTANT for INTERFACE_PER_SCHEMA option"); + } + if (Boolean.TRUE.equals(mappingConfig.getGenerateApis()) + && Boolean.TRUE.equals(mappingConfig.getGenerateModelsForRootTypes()) + && mappingConfig.getApiNamePrefixStrategy() == ApiNamePrefixStrategy.CONSTANT) { + // checking for conflict between root type model classes and api interfaces + if (Utils.stringsEqualIgnoreSpaces( + mappingConfig.getApiNamePrefix(), mappingConfig.getModelNamePrefix()) && + Utils.stringsEqualIgnoreSpaces( + mappingConfig.getApiNameSuffix(), mappingConfig.getModelNameSuffix())) { + // we will have a conflict between model pojo (Query.java) and api interface (Query.java) + throw new IllegalArgumentException("Either disable APIs generation or " + + "set different Prefix/Suffix for API classes and model classes"); + } + // checking for conflict between root type model resolver classes and api interfaces + if (Utils.stringsEqualIgnoreSpaces(mappingConfig.getApiNamePrefix(), + mappingConfig.getTypeResolverPrefix()) && + Utils.stringsEqualIgnoreSpaces(mappingConfig.getApiNameSuffix(), + mappingConfig.getTypeResolverSuffix())) { + // we will have a conflict between model resolver interface (QueryResolver.java) and api interface + // resolver (QueryResolver.java) + throw new IllegalArgumentException("Either disable APIs generation or " + + "set different Prefix/Suffix for API classes and type resolver classes"); + } + } + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java index 9ef568953..cae443737 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java @@ -8,6 +8,7 @@ import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInterfaceTypeDefinition; +import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -20,6 +21,7 @@ */ public class MappingContext implements GraphQLCodegenConfiguration { + private final File outputDirectory; private final MappingConfig config; private final ExtendedDocument document; private final Set typesUnionsInterfacesNames; @@ -27,12 +29,15 @@ public class MappingContext implements GraphQLCodegenConfiguration { private final Map> interfaceChildren; private final GeneratedInformation generatedInformation; private final DataModelMapperFactory dataModelMapperFactory; - private Set enumImportItSelfInScala = null; - private Map> parentInterfaceProperties = null; - - public MappingContext(MappingConfig mappingConfig, - ExtendedDocument document, - GeneratedInformation generatedInformation, DataModelMapperFactory dataModelMapperFactory) { + private Set enumImportItSelfInScala; + private Map> parentInterfaceProperties; + + private MappingContext(File outputDirectory, + MappingConfig mappingConfig, + ExtendedDocument document, + GeneratedInformation generatedInformation, + DataModelMapperFactory dataModelMapperFactory) { + this.outputDirectory = outputDirectory; this.config = mappingConfig; this.document = document; this.typesUnionsInterfacesNames = document.getTypesUnionsInterfacesNames(); @@ -42,6 +47,10 @@ public MappingContext(MappingConfig mappingConfig, this.dataModelMapperFactory = dataModelMapperFactory; } + public static MappingContext.Builder builder() { + return new MappingContext.Builder(); + } + @Override public GeneratedLanguage getGeneratedLanguage() { return config.getGeneratedLanguage(); @@ -312,6 +321,10 @@ public GeneratedInformation getGeneratedInformation() { return generatedInformation; } + public File getOutputDirectory() { + return outputDirectory; + } + public Set getEnumImportItSelfInScala() { // Only for scala if (GeneratedLanguage.SCALA.equals(this.config.getGeneratedLanguage()) && enumImportItSelfInScala == null) { @@ -365,4 +378,50 @@ private List getFields(List fieldD .mapFields(this, fieldDefinitions, parentDefinition); } + /** + * Builder of the mapping context + */ + public static class Builder { + + private File outputDirectory; + private MappingConfig mappingConfig; + private ExtendedDocument document; + private GeneratedInformation generatedInformation; + private DataModelMapperFactory dataModelMapperFactory; + + public Builder() { + } + + public Builder setOutputDirectory(File outputDirectory) { + this.outputDirectory = outputDirectory; + return this; + } + + public Builder setMappingConfig(MappingConfig mappingConfig) { + this.mappingConfig = mappingConfig; + return this; + } + + public Builder setDocument(ExtendedDocument document) { + this.document = document; + return this; + } + + public Builder setGeneratedInformation(GeneratedInformation generatedInformation) { + this.generatedInformation = generatedInformation; + return this; + } + + public Builder setDataModelMapperFactory(DataModelMapperFactory dataModelMapperFactory) { + this.dataModelMapperFactory = dataModelMapperFactory; + return this; + } + + public MappingContext build() { + return new MappingContext( + outputDirectory, mappingConfig, document, generatedInformation, dataModelMapperFactory); + } + + } + } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MultiLanguageDeprecated.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MultiLanguageDeprecated.java deleted file mode 100644 index 04cbc8ebf..000000000 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MultiLanguageDeprecated.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.kobylynskyi.graphql.codegen.model; - -import graphql.language.Directive; -import graphql.language.StringValue; - -/** - * @author liguobin@growingio.com - * @version 1.0, 2020/12/28 - */ -public class MultiLanguageDeprecated { - - private static final String REASON = "reason"; - private static final String SCALA_ANNOTATION = "deprecated"; - private static final String JAVA_ANNOTATION = "Deprecated"; - private static final String KOTLIN_ANNOTATION = "Deprecated"; - - private MultiLanguageDeprecated() { - } - - /** - * Get a definition of @deprecated annotation for a specified language. - * - * @param generatedLanguage Language of code generation - * @param directive GraphQL @deprecated directive - * @return a definition of a deprecation having reason and annotation - */ - @SuppressWarnings({"java:S1133", "java:S1123"}) // sonar treats this is a deprecated method - public static DeprecatedDefinition getLanguageDeprecated(GeneratedLanguage generatedLanguage, Directive directive) { - String msg = null; - if (directive.getArguments().stream().anyMatch(argument -> argument.getName().equals(REASON))) { - msg = ((StringValue) directive.getArgument(REASON).getValue()).getValue(); - } - switch (generatedLanguage) { - case KOTLIN: - return new DeprecatedDefinition(KOTLIN_ANNOTATION, msg); - case SCALA: - return new DeprecatedDefinition(SCALA_ANNOTATION, msg); - //ignore msg - case JAVA: - default: - return new DeprecatedDefinition(JAVA_ANNOTATION); - } - } -} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/DeprecatedDefinitionBuilder.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/DeprecatedDefinitionBuilder.java new file mode 100644 index 000000000..48219b8a9 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/DeprecatedDefinitionBuilder.java @@ -0,0 +1,72 @@ +package com.kobylynskyi.graphql.codegen.model.builders; + +import com.kobylynskyi.graphql.codegen.model.DeprecatedDefinition; +import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import graphql.language.Argument; +import graphql.language.Directive; +import graphql.language.DirectivesContainer; +import graphql.language.StringValue; + +/** + * Builder of @deprecated annotation definition + */ +@SuppressWarnings({"java:S1133", "java:S1123"}) // sonar treats this is a deprecated method +public class DeprecatedDefinitionBuilder { + + private static final String REASON = "reason"; + private static final String SCALA_ANNOTATION = "deprecated"; + private static final String JAVA_ANNOTATION = "Deprecated"; + private static final String KOTLIN_ANNOTATION = "Deprecated"; + + /** + * Get a definition of @deprecated based on a given directive + * + * @param mappingContext Global mapping context + * @param directivesContainer GraphQL directive container + * @return a definition of a deprecation having reason and annotation + */ + public static DeprecatedDefinition build(MappingContext mappingContext, + DirectivesContainer directivesContainer) { + for (Directive d : directivesContainer.getDirectives()) { + if (d.getName().equalsIgnoreCase(Deprecated.class.getSimpleName())) { + return build(mappingContext.getGeneratedLanguage(), d); + } + } + return null; + } + + /** + * Get a definition of @deprecated annotation for a specified language. + * + * @param generatedLanguage Language of code generation + * @param directive GraphQL @deprecated directive + * @return a definition of a deprecation having reason and annotation + */ + public static DeprecatedDefinition build(GeneratedLanguage generatedLanguage, + Directive directive) { + switch (generatedLanguage) { + case KOTLIN: + return new DeprecatedDefinition(KOTLIN_ANNOTATION, getMessage(directive)); + case SCALA: + return new DeprecatedDefinition(SCALA_ANNOTATION, getMessage(directive)); + case JAVA: + default: + return new DeprecatedDefinition(JAVA_ANNOTATION); // message is ignored + } + } + + private static String getMessage(Directive directive) { + for (Argument argument : directive.getArguments()) { + if (argument.getName().equals(REASON)) { + return getReasonString(directive).getValue(); + } + } + return null; + } + + private static StringValue getReasonString(Directive directive) { + return (StringValue) directive.getArgument(REASON).getValue(); + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java new file mode 100644 index 000000000..67a7cbd06 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java @@ -0,0 +1,83 @@ +package com.kobylynskyi.graphql.codegen.model.builders; + +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; +import com.kobylynskyi.graphql.codegen.utils.Utils; +import graphql.language.AbstractDescribedNode; +import graphql.language.Comment; +import graphql.language.Description; +import graphql.language.NamedNode; +import graphql.language.Node; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +/** + * Java doc builder + */ +public class JavaDocBuilder { + + /** + * Get java doc from description of the definition and it's extensions. + * If no description is present in the definition and extension then return from comments + * + * @return List of java docs + */ + public static , E extends T> List build(ExtendedDefinition extendedDefinition) { + List javaDocFromDescription = buildFromDescription(extendedDefinition); + if (javaDocFromDescription.isEmpty()) { + return buildFromComments(extendedDefinition); + } + return javaDocFromDescription; + } + + /** + * Get java doc from description for the given definition + * + * @return List of java docs + */ + public static , E extends T> List buildFromDescription( + ExtendedDefinition extendedDefinition) { + T definition = extendedDefinition.getDefinition(); + List extensions = extendedDefinition.getExtensions(); + + List descriptions = new ArrayList<>(); + if (definition instanceof AbstractDescribedNode) { + Description description = ((AbstractDescribedNode) definition).getDescription(); + if (description != null && Utils.isNotBlank(description.getContent())) { + descriptions.add(description.getContent().trim()); + } + extensions.stream() + .filter(Objects::nonNull) + .map(AbstractDescribedNode.class::cast) + .map(AbstractDescribedNode::getDescription).filter(Objects::nonNull) + .map(Description::getContent).filter(Utils::isNotBlank) + .map(String::trim).forEach(descriptions::add); + } + return descriptions; + } + + /** + * Get java doc from comments for the given definition + * + * @return List of java docs + */ + public static , E extends T> List buildFromComments(ExtendedDefinition extendedDefinition) { + T definition = extendedDefinition.getDefinition(); + List extensions = extendedDefinition.getExtensions(); + + List comments = new ArrayList<>(); + if (definition != null && definition.getComments() != null) { + definition.getComments().stream() + .map(Comment::getContent).filter(Utils::isNotBlank) + .map(String::trim).forEach(comments::add); + } + extensions.stream() + .map(Node::getComments) + .flatMap(Collection::stream).filter(Objects::nonNull) + .map(Comment::getContent).filter(Utils::isNotBlank) + .map(String::trim).forEach(comments::add); + return comments; + } +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/definitions/ExtendedDefinition.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/definitions/ExtendedDefinition.java index ce4748780..ae17bb494 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/definitions/ExtendedDefinition.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/definitions/ExtendedDefinition.java @@ -1,9 +1,6 @@ package com.kobylynskyi.graphql.codegen.model.definitions; import com.kobylynskyi.graphql.codegen.utils.Utils; -import graphql.language.AbstractDescribedNode; -import graphql.language.Comment; -import graphql.language.Description; import graphql.language.Directive; import graphql.language.DirectivesContainer; import graphql.language.NamedNode; @@ -11,7 +8,6 @@ import graphql.language.SourceLocation; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @@ -46,56 +42,6 @@ public SourceLocation getSourceLocation() { } } - public List getJavaDoc() { - List javaDocFromDescription = getJavaDocFromDescription(); - if (javaDocFromDescription.isEmpty()) { - return getJavaDocFromComments(); - } - return javaDocFromDescription; - } - - /** - * Get java doc from description for this definition - * - * @return List of java docs - */ - public List getJavaDocFromDescription() { - List descriptions = new ArrayList<>(); - if (this.definition instanceof AbstractDescribedNode) { - Description description = ((AbstractDescribedNode) this.definition).getDescription(); - if (description != null && Utils.isNotBlank(description.getContent())) { - descriptions.add(description.getContent().trim()); - } - this.extensions.stream() - .filter(Objects::nonNull) - .map(AbstractDescribedNode.class::cast) - .map(AbstractDescribedNode::getDescription).filter(Objects::nonNull) - .map(Description::getContent).filter(Utils::isNotBlank) - .map(String::trim).forEach(descriptions::add); - } - return descriptions; - } - - /** - * Get java doc from description for this definition - * - * @return List of java docs - */ - public List getJavaDocFromComments() { - List comments = new ArrayList<>(); - if (definition != null && definition.getComments() != null) { - definition.getComments().stream() - .map(Comment::getContent).filter(Utils::isNotBlank) - .map(String::trim).forEach(comments::add); - } - extensions.stream() - .map(Node::getComments) - .flatMap(Collection::stream).filter(Objects::nonNull) - .map(Comment::getContent).filter(Utils::isNotBlank) - .map(String::trim).forEach(comments::add); - return comments; - } - /** * Return all directives for this definition * @@ -120,11 +66,11 @@ public List getDirectives() { directives.addAll(definitionDirectives); } this.extensions.stream() - .filter(Objects::nonNull) - .map(DirectivesContainer.class::cast) - .map(DirectivesContainer::getDirectives) - .filter(dc -> !Utils.isEmpty(dc)) - .forEach(directives::addAll); + .filter(Objects::nonNull) + .map(DirectivesContainer.class::cast) + .map(DirectivesContainer::getDirectives) + .filter(dc -> !Utils.isEmpty(dc)) + .forEach(directives::addAll); } return directives; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/definitions/ExtendedFieldDefinition.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/definitions/ExtendedFieldDefinition.java index e349e6f78..d79ea62ab 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/definitions/ExtendedFieldDefinition.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/definitions/ExtendedFieldDefinition.java @@ -1,8 +1,5 @@ package com.kobylynskyi.graphql.codegen.model.definitions; -import com.kobylynskyi.graphql.codegen.model.DeprecatedDefinition; -import com.kobylynskyi.graphql.codegen.model.MappingContext; -import com.kobylynskyi.graphql.codegen.model.MultiLanguageDeprecated; import com.kobylynskyi.graphql.codegen.utils.Utils; import graphql.language.Comment; import graphql.language.Description; @@ -26,16 +23,6 @@ protected ExtendedFieldDefinition(FieldDefinition f, boolean fromExtension) { this.fromExtension = fromExtension; } - public DeprecatedDefinition getDeprecated(MappingContext mappingContext) { - return getDirectives() - .stream() - .filter(d -> d.getName().equalsIgnoreCase(Deprecated.class.getSimpleName())) - .findFirst() - .map(directive -> MultiLanguageDeprecated - .getLanguageDeprecated(mappingContext.getGeneratedLanguage(), directive)) - .orElse(null); - } - /** * Get java doc of GraphQL field * diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequest.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequest.java index 0f10b065a..2968d4676 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequest.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequest.java @@ -22,7 +22,7 @@ public GraphQLRequest(GraphQLOperationRequest request, GraphQLResponseProjection } public GraphQLRequest(String operationName, GraphQLOperationRequest request, - GraphQLResponseProjection responseProjection) { + GraphQLResponseProjection responseProjection) { this.operationName = operationName; this.request = request; this.responseProjection = responseProjection; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequestSerializer.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequestSerializer.java index f16800a4b..7eed10332 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequestSerializer.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequestSerializer.java @@ -79,7 +79,7 @@ public static String toQueryString(GraphQLRequest graphQLRequest) { } String operationName = graphQLRequest.getOperationName() == null ? - graphQLRequest.getRequest().getOperationName() : graphQLRequest.getOperationName(); + graphQLRequest.getRequest().getOperationName() : graphQLRequest.getOperationName(); return operationWrapper( graphQLRequest.getRequest().getOperationType(), diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLDocumentParser.java b/src/main/java/com/kobylynskyi/graphql/codegen/parser/GraphQLDocumentParser.java similarity index 88% rename from src/main/java/com/kobylynskyi/graphql/codegen/GraphQLDocumentParser.java rename to src/main/java/com/kobylynskyi/graphql/codegen/parser/GraphQLDocumentParser.java index 6f2bd2109..0044d7c1d 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLDocumentParser.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/parser/GraphQLDocumentParser.java @@ -1,4 +1,4 @@ -package com.kobylynskyi.graphql.codegen; +package com.kobylynskyi.graphql.codegen.parser; import com.fasterxml.jackson.core.type.TypeReference; import com.kobylynskyi.graphql.codegen.model.MappingConfig; @@ -36,12 +36,23 @@ import java.util.Map; import java.util.function.Function; -class GraphQLDocumentParser { +/** + * Provides methods for extended document generation + */ +public class GraphQLDocumentParser { private GraphQLDocumentParser() { } - static ExtendedDocument getDocumentFromSchemas(MappingConfig mappingConfig, List schemaPaths) + /** + * Generate an extended document from schema files + * + * @param mappingConfig Global mapping config + * @param schemaPaths Paths to GraphQL schema files + * @return extended document definition + * @throws IOException in case unable to read the file content + */ + public static ExtendedDocument getDocumentFromSchemas(MappingConfig mappingConfig, List schemaPaths) throws IOException { Document document = readDocument(schemaPaths); @@ -53,8 +64,16 @@ static ExtendedDocument getDocumentFromSchemas(MappingConfig mappingConfig, List return extendedDocumentBuilder.build(); } - static ExtendedDocument getDocumentFromIntrospectionResult(MappingConfig mappingConfig, String introspectionResult) - throws IOException { + /** + * Generate an extended document from introspection result file + * + * @param mappingConfig Global mapping config + * @param introspectionResult Path to introspection result file + * @return extended document definition + * @throws IOException in case unable to read the file content + */ + public static ExtendedDocument getDocumentFromIntrospectionResult(MappingConfig mappingConfig, + String introspectionResult) throws IOException { String introspectionResultContent = Utils.getFileContent(introspectionResult); Map introspectionResultMap = Utils.OBJECT_MAPPER.readValue(introspectionResultContent, new TypeReference) introspectionResultMap.get("data"); } Document document = new IntrospectionResultToSchema().createSchemaDefinition(introspectionResultMap); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaGraphQLCodegen.java b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaGraphQLCodegen.java index 7cb87241b..55343d52b 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaGraphQLCodegen.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaGraphQLCodegen.java @@ -1,7 +1,7 @@ package com.kobylynskyi.graphql.codegen.scala; import com.kobylynskyi.graphql.codegen.GraphQLCodegen; -import com.kobylynskyi.graphql.codegen.MapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; import com.kobylynskyi.graphql.codegen.model.GeneratedInformation; import com.kobylynskyi.graphql.codegen.model.MappingConfig; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedScalarTypeDefinition; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaMapperFactoryImpl.java b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaMapperFactoryImpl.java index ae79cb8e0..8d30a31e6 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaMapperFactoryImpl.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaMapperFactoryImpl.java @@ -1,8 +1,8 @@ package com.kobylynskyi.graphql.codegen.scala; -import com.kobylynskyi.graphql.codegen.MapperFactory; import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; +import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; import com.kobylynskyi.graphql.codegen.mapper.ValueFormatter; import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/supplier/MergeableMappingConfigSupplier.java b/src/main/java/com/kobylynskyi/graphql/codegen/supplier/MergeableMappingConfigSupplier.java index d459d244e..0d12e4f43 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/supplier/MergeableMappingConfigSupplier.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/supplier/MergeableMappingConfigSupplier.java @@ -31,19 +31,6 @@ public MergeableMappingConfigSupplier(List configFiles) { this.jsonConfig = parseConfigAndMerged(configFiles); } - @Override - public MappingConfig get() { - if (jsonConfig != null && !jsonConfig.isEmpty()) { - try { - return Utils.OBJECT_MAPPER.readValue(jsonConfig, MappingConfig.class); - } catch (ConfigException | JsonProcessingException e) { - throw new IllegalArgumentException(e); - } - } - return null; - } - - /** * parser list of config files. * @@ -65,4 +52,16 @@ private static String parseConfigAndMerged(List confFiles) { return null; } } + + @Override + public MappingConfig get() { + if (jsonConfig != null && !jsonConfig.isEmpty()) { + try { + return Utils.OBJECT_MAPPER.readValue(jsonConfig, MappingConfig.class); + } catch (ConfigException | JsonProcessingException e) { + throw new IllegalArgumentException(e); + } + } + return null; + } } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/utils/Utils.java b/src/main/java/com/kobylynskyi/graphql/codegen/utils/Utils.java index b1b8dfd57..f369876ea 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/utils/Utils.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/utils/Utils.java @@ -262,5 +262,5 @@ public static String wrapString(String str, String wrapStart, String wrapEnd) { } return wrapStart + str + wrapEnd; } - + } diff --git a/src/main/resources/templates/java-lang/javaClassGraphqlEnum.ftl b/src/main/resources/templates/java-lang/enum.ftl similarity index 100% rename from src/main/resources/templates/java-lang/javaClassGraphqlEnum.ftl rename to src/main/resources/templates/java-lang/enum.ftl diff --git a/src/main/resources/templates/java-lang/javaClassGraphqlInterface.ftl b/src/main/resources/templates/java-lang/interface.ftl similarity index 100% rename from src/main/resources/templates/java-lang/javaClassGraphqlInterface.ftl rename to src/main/resources/templates/java-lang/interface.ftl diff --git a/src/main/resources/templates/java-lang/javaClassGraphqlJacksonTypeIdResolver.ftl b/src/main/resources/templates/java-lang/jackson_type_id_resolver.ftl similarity index 100% rename from src/main/resources/templates/java-lang/javaClassGraphqlJacksonTypeIdResolver.ftl rename to src/main/resources/templates/java-lang/jackson_type_id_resolver.ftl diff --git a/src/main/resources/templates/java-lang/javaClassGraphqlOperations.ftl b/src/main/resources/templates/java-lang/operations.ftl similarity index 100% rename from src/main/resources/templates/java-lang/javaClassGraphqlOperations.ftl rename to src/main/resources/templates/java-lang/operations.ftl diff --git a/src/main/resources/templates/java-lang/javaClassGraphqlParametrizedInput.ftl b/src/main/resources/templates/java-lang/parametrized_input.ftl similarity index 100% rename from src/main/resources/templates/java-lang/javaClassGraphqlParametrizedInput.ftl rename to src/main/resources/templates/java-lang/parametrized_input.ftl diff --git a/src/main/resources/templates/java-lang/javaClassGraphqlRequest.ftl b/src/main/resources/templates/java-lang/request.ftl similarity index 100% rename from src/main/resources/templates/java-lang/javaClassGraphqlRequest.ftl rename to src/main/resources/templates/java-lang/request.ftl diff --git a/src/main/resources/templates/java-lang/javaClassGraphqlResponse.ftl b/src/main/resources/templates/java-lang/response.ftl similarity index 100% rename from src/main/resources/templates/java-lang/javaClassGraphqlResponse.ftl rename to src/main/resources/templates/java-lang/response.ftl diff --git a/src/main/resources/templates/java-lang/javaClassGraphqlResponseProjection.ftl b/src/main/resources/templates/java-lang/response_projection.ftl similarity index 100% rename from src/main/resources/templates/java-lang/javaClassGraphqlResponseProjection.ftl rename to src/main/resources/templates/java-lang/response_projection.ftl diff --git a/src/main/resources/templates/java-lang/javaClassGraphqlType.ftl b/src/main/resources/templates/java-lang/type.ftl similarity index 100% rename from src/main/resources/templates/java-lang/javaClassGraphqlType.ftl rename to src/main/resources/templates/java-lang/type.ftl diff --git a/src/main/resources/templates/java-lang/javaClassGraphqlUnion.ftl b/src/main/resources/templates/java-lang/union.ftl similarity index 100% rename from src/main/resources/templates/java-lang/javaClassGraphqlUnion.ftl rename to src/main/resources/templates/java-lang/union.ftl diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlEnum.ftl b/src/main/resources/templates/kotlin-lang/enum.ftl similarity index 100% rename from src/main/resources/templates/kotlin-lang/kotlinClassGraphqlEnum.ftl rename to src/main/resources/templates/kotlin-lang/enum.ftl diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlInterface.ftl b/src/main/resources/templates/kotlin-lang/interface.ftl similarity index 100% rename from src/main/resources/templates/kotlin-lang/kotlinClassGraphqlInterface.ftl rename to src/main/resources/templates/kotlin-lang/interface.ftl diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlJacksonTypeIdResolver.ftl b/src/main/resources/templates/kotlin-lang/jackson_type_id_resolver.ftl similarity index 100% rename from src/main/resources/templates/kotlin-lang/kotlinClassGraphqlJacksonTypeIdResolver.ftl rename to src/main/resources/templates/kotlin-lang/jackson_type_id_resolver.ftl diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlOperations.ftl b/src/main/resources/templates/kotlin-lang/operations.ftl similarity index 100% rename from src/main/resources/templates/kotlin-lang/kotlinClassGraphqlOperations.ftl rename to src/main/resources/templates/kotlin-lang/operations.ftl diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlParametrizedInput.ftl b/src/main/resources/templates/kotlin-lang/parametrized_input.ftl similarity index 100% rename from src/main/resources/templates/kotlin-lang/kotlinClassGraphqlParametrizedInput.ftl rename to src/main/resources/templates/kotlin-lang/parametrized_input.ftl diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlRequest.ftl b/src/main/resources/templates/kotlin-lang/request.ftl similarity index 100% rename from src/main/resources/templates/kotlin-lang/kotlinClassGraphqlRequest.ftl rename to src/main/resources/templates/kotlin-lang/request.ftl diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlResponse.ftl b/src/main/resources/templates/kotlin-lang/response.ftl similarity index 100% rename from src/main/resources/templates/kotlin-lang/kotlinClassGraphqlResponse.ftl rename to src/main/resources/templates/kotlin-lang/response.ftl diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlResponseProjection.ftl b/src/main/resources/templates/kotlin-lang/response_projection.ftl similarity index 100% rename from src/main/resources/templates/kotlin-lang/kotlinClassGraphqlResponseProjection.ftl rename to src/main/resources/templates/kotlin-lang/response_projection.ftl diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlType.ftl b/src/main/resources/templates/kotlin-lang/type.ftl similarity index 100% rename from src/main/resources/templates/kotlin-lang/kotlinClassGraphqlType.ftl rename to src/main/resources/templates/kotlin-lang/type.ftl diff --git a/src/main/resources/templates/kotlin-lang/kotlinClassGraphqlUnion.ftl b/src/main/resources/templates/kotlin-lang/union.ftl similarity index 100% rename from src/main/resources/templates/kotlin-lang/kotlinClassGraphqlUnion.ftl rename to src/main/resources/templates/kotlin-lang/union.ftl diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlEnum.ftl b/src/main/resources/templates/scala-lang/enum.ftl similarity index 100% rename from src/main/resources/templates/scala-lang/scalaClassGraphqlEnum.ftl rename to src/main/resources/templates/scala-lang/enum.ftl diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlInterface.ftl b/src/main/resources/templates/scala-lang/interface.ftl similarity index 100% rename from src/main/resources/templates/scala-lang/scalaClassGraphqlInterface.ftl rename to src/main/resources/templates/scala-lang/interface.ftl diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlJacksonTypeIdResolver.ftl b/src/main/resources/templates/scala-lang/jackson_type_id_resolver.ftl similarity index 100% rename from src/main/resources/templates/scala-lang/scalaClassGraphqlJacksonTypeIdResolver.ftl rename to src/main/resources/templates/scala-lang/jackson_type_id_resolver.ftl diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlOperations.ftl b/src/main/resources/templates/scala-lang/operations.ftl similarity index 100% rename from src/main/resources/templates/scala-lang/scalaClassGraphqlOperations.ftl rename to src/main/resources/templates/scala-lang/operations.ftl diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlParametrizedInput.ftl b/src/main/resources/templates/scala-lang/parametrized_input.ftl similarity index 100% rename from src/main/resources/templates/scala-lang/scalaClassGraphqlParametrizedInput.ftl rename to src/main/resources/templates/scala-lang/parametrized_input.ftl diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlRequest.ftl b/src/main/resources/templates/scala-lang/request.ftl similarity index 100% rename from src/main/resources/templates/scala-lang/scalaClassGraphqlRequest.ftl rename to src/main/resources/templates/scala-lang/request.ftl diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlResponse.ftl b/src/main/resources/templates/scala-lang/response.ftl similarity index 100% rename from src/main/resources/templates/scala-lang/scalaClassGraphqlResponse.ftl rename to src/main/resources/templates/scala-lang/response.ftl diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlResponseProjection.ftl b/src/main/resources/templates/scala-lang/response_projection.ftl similarity index 100% rename from src/main/resources/templates/scala-lang/scalaClassGraphqlResponseProjection.ftl rename to src/main/resources/templates/scala-lang/response_projection.ftl diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlType.ftl b/src/main/resources/templates/scala-lang/type.ftl similarity index 100% rename from src/main/resources/templates/scala-lang/scalaClassGraphqlType.ftl rename to src/main/resources/templates/scala-lang/type.ftl diff --git a/src/main/resources/templates/scala-lang/scalaClassGraphqlUnion.ftl b/src/main/resources/templates/scala-lang/union.ftl similarity index 100% rename from src/main/resources/templates/scala-lang/scalaClassGraphqlUnion.ftl rename to src/main/resources/templates/scala-lang/union.ftl diff --git a/src/main/resources/templates/templates.properties b/src/main/resources/templates/templates.properties new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFileCreatorTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFileCreatorTest.java index 0eccacd44..eadfebb54 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFileCreatorTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFileCreatorTest.java @@ -1,7 +1,10 @@ package com.kobylynskyi.graphql.codegen; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateFilesCreator; +import com.kobylynskyi.graphql.codegen.generators.FreeMarkerTemplateType; import com.kobylynskyi.graphql.codegen.java.JavaMapperFactoryImpl; import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory; +import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; import com.kobylynskyi.graphql.codegen.model.DataModelFields; import com.kobylynskyi.graphql.codegen.model.GeneratedInformation; import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage; @@ -9,6 +12,7 @@ import com.kobylynskyi.graphql.codegen.model.MappingContext; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDocument; import com.kobylynskyi.graphql.codegen.model.exception.UnableToCreateFileException; +import com.kobylynskyi.graphql.codegen.parser.GraphQLDocumentParser; import com.kobylynskyi.graphql.codegen.utils.Utils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -45,12 +49,17 @@ void generateFile() throws IOException { dataModel.put(DataModelFields.GENERATED_ANNOTATION, false); dataModel.put(DataModelFields.GENERATED_INFO, new GeneratedInformation()); - MappingContext mappingContext = new MappingContext(mappingConfig, extendedDocument, - new GeneratedInformation(), new DataModelMapperFactory(MAPPER_FACTORY)); + MappingContext mappingContext = MappingContext.builder() + .setMappingConfig(mappingConfig) + .setDocument(extendedDocument) + .setGeneratedInformation(new GeneratedInformation()) + .setDataModelMapperFactory(new DataModelMapperFactory(MAPPER_FACTORY)) + .setOutputDirectory(OUTPUT_DIR) + .build(); - GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.ENUM, dataModel, OUTPUT_DIR); + FreeMarkerTemplateFilesCreator.create(mappingContext, FreeMarkerTemplateType.ENUM, dataModel); assertThrows(UnableToCreateFileException.class, - () -> GraphQLCodegenFileCreator.generateFile( - mappingContext, FreeMarkerTemplateType.ENUM, dataModel, OUTPUT_DIR)); + () -> FreeMarkerTemplateFilesCreator.create( + mappingContext, FreeMarkerTemplateType.ENUM, dataModel)); } } diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java index fb75abf12..31f65554b 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java @@ -251,8 +251,8 @@ void generate_GeneratedAnnotation() throws Exception { void generate_NoSchemas() { GeneratedInformation staticGeneratedInfo = TestUtils.getStaticGeneratedInfo(); List schemas = emptyList(); - assertThrows(IllegalArgumentException.class, () -> - new JavaGraphQLCodegen(schemas, outputBuildDir, mappingConfig, staticGeneratedInfo)); + JavaGraphQLCodegen codegen = new JavaGraphQLCodegen(schemas, outputBuildDir, mappingConfig, staticGeneratedInfo); + assertThrows(IllegalArgumentException.class, codegen::generate); } @Test From 894fbd461fe9954f89d333080344e571b6afe742 Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Sat, 4 Sep 2021 17:34:04 +0300 Subject: [PATCH 09/23] Support RegEx in customAnnotationsMapping #783 Also refactor mappers --- .../codegen/java/JavaAnnotationsMapper.java | 41 +++ .../codegen/java/JavaDataModelMapper.java | 2 +- .../codegen/java/JavaGraphQLTypeMapper.java | 24 +- .../codegen/java/JavaMapperFactoryImpl.java | 31 ++- .../kotlin/KotlinAnnotationsMapper.java | 44 ++++ .../codegen/kotlin/KotlinDataModelMapper.java | 9 +- .../kotlin/KotlinGraphQLTypeMapper.java | 26 +- .../kotlin/KotlinMapperFactoryImpl.java | 31 ++- .../codegen/mapper/AnnotationsMapper.java | 233 ++++++++++++++++++ .../codegen/mapper/DataModelMapper.java | 14 +- .../mapper/DataModelMapperFactory.java | 58 ++--- .../EnumDefinitionToDataModelMapper.java | 11 +- .../FieldDefinitionToParameterMapper.java | 11 +- ...dDefinitionsToResolverDataModelMapper.java | 11 +- .../codegen/mapper/GraphQLTypeMapper.java | 222 ++--------------- .../InputDefinitionToDataModelMapper.java | 11 +- ...InputValueDefinitionToParameterMapper.java | 14 +- .../InterfaceDefinitionToDataModelMapper.java | 11 +- .../graphql/codegen/mapper/MapperFactory.java | 8 +- ...stResponseDefinitionToDataModelMapper.java | 20 +- .../TypeDefinitionToDataModelMapper.java | 14 +- .../UnionDefinitionToDataModelMapper.java | 11 +- .../graphql/codegen/model/MappingContext.java | 2 +- .../codegen/scala/ScalaAnnotationsMapper.java | 64 +++++ .../codegen/scala/ScalaDataModelMapper.java | 2 +- .../codegen/scala/ScalaGraphQLTypeMapper.java | 52 +--- .../codegen/scala/ScalaMapperFactoryImpl.java | 31 ++- .../GraphQLCodegenAnnotationsTest.java | 34 +++ 28 files changed, 617 insertions(+), 425 deletions(-) create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/java/JavaAnnotationsMapper.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinAnnotationsMapper.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/mapper/AnnotationsMapper.java create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaAnnotationsMapper.java diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaAnnotationsMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaAnnotationsMapper.java new file mode 100644 index 000000000..8fa0238bc --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaAnnotationsMapper.java @@ -0,0 +1,41 @@ +package com.kobylynskyi.graphql.codegen.java; + +import com.kobylynskyi.graphql.codegen.mapper.AnnotationsMapper; +import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; + +import java.util.Collections; +import java.util.List; + +/** + * Mapper class for converting GraphQL types to Java types + */ +public class JavaAnnotationsMapper extends AnnotationsMapper { + + private final ValueMapper valueMapper; + + public JavaAnnotationsMapper(ValueMapper valueMapper) { + this.valueMapper = valueMapper; + } + + @Override + public boolean addModelValidationAnnotationForType(String type) { + return !JavaGraphQLTypeMapper.isJavaPrimitive(type); + } + + @Override + public ValueMapper getValueMapper() { + return valueMapper; + } + + @Override + public String getJacksonResolverTypeIdAnnotation(String modelPackageName) { + return "com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver(" + modelPackageName + + "GraphqlJacksonTypeIdResolver.class)"; + } + + @Override + protected List getAdditionalAnnotations(MappingContext mappingContext, String typeName) { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaDataModelMapper.java index 68e707601..ee56fcafd 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaDataModelMapper.java @@ -11,7 +11,7 @@ /** * Data model mapper for JAVA generated classes */ -public class JavaDataModelMapper implements DataModelMapper { +public class JavaDataModelMapper extends DataModelMapper { private static final Set JAVA_RESTRICTED_KEYWORDS = new HashSet<>(Arrays.asList( "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaGraphQLTypeMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaGraphQLTypeMapper.java index 9165b617b..08499e6d0 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaGraphQLTypeMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaGraphQLTypeMapper.java @@ -2,7 +2,6 @@ import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; -import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; import com.kobylynskyi.graphql.codegen.model.MappingContext; import com.kobylynskyi.graphql.codegen.model.NamedDefinition; import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation; @@ -17,19 +16,13 @@ /** * Mapper class for converting GraphQL types to Java types */ -public class JavaGraphQLTypeMapper implements GraphQLTypeMapper { +public class JavaGraphQLTypeMapper extends GraphQLTypeMapper { public static final String JAVA_UTIL_LIST = "java.util.List"; private static final String JAVA_UTIL_OPTIONAL = "java.util.Optional"; private static final Set JAVA_PRIMITIVE_TYPES = new HashSet<>(asList( "byte", "short", "int", "long", "float", "double", "char", "boolean")); - private final ValueMapper valueMapper; - - public JavaGraphQLTypeMapper(ValueMapper valueMapper) { - this.valueMapper = valueMapper; - } - public static boolean isJavaPrimitive(String possiblyPrimitiveType) { return JAVA_PRIMITIVE_TYPES.contains(possiblyPrimitiveType); } @@ -86,11 +79,6 @@ public boolean isPrimitive(String possiblyPrimitiveType) { return isJavaPrimitive(possiblyPrimitiveType); } - @Override - public boolean addModelValidationAnnotationForType(String type) { - return !isPrimitive(type); - } - @Override public NamedDefinition getLanguageType(MappingContext mappingContext, String graphQLType, String name, String parentTypeName, boolean mandatory, boolean collection) { @@ -117,14 +105,4 @@ public NamedDefinition getLanguageType(MappingContext mappingContext, String gra mandatory, primitiveCanBeUsed, serializeUsingObjectMapper); } - @Override - public ValueMapper getValueMapper() { - return valueMapper; - } - - @Override - public String getJacksonResolverTypeIdAnnotation(String modelPackageName) { - return "com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver(" + modelPackageName + - "GraphqlJacksonTypeIdResolver.class)"; - } } \ No newline at end of file diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaMapperFactoryImpl.java b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaMapperFactoryImpl.java index 49328e5ef..292e0e854 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaMapperFactoryImpl.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/java/JavaMapperFactoryImpl.java @@ -1,9 +1,9 @@ package com.kobylynskyi.graphql.codegen.java; +import com.kobylynskyi.graphql.codegen.mapper.AnnotationsMapper; import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; -import com.kobylynskyi.graphql.codegen.mapper.ValueFormatter; import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; /** @@ -11,19 +11,36 @@ */ public class JavaMapperFactoryImpl implements MapperFactory { + private final DataModelMapper dataModelMapper; + private final ValueMapper valueMapper; + private final GraphQLTypeMapper graphQLTypeMapper; + private final AnnotationsMapper annotationsMapper; + + public JavaMapperFactoryImpl() { + dataModelMapper = new JavaDataModelMapper(); + valueMapper = new ValueMapper(new JavaValueFormatter(), dataModelMapper); + graphQLTypeMapper = new JavaGraphQLTypeMapper(); + annotationsMapper = new JavaAnnotationsMapper(valueMapper); + } + + @Override + public DataModelMapper getDataModelMapper() { + return dataModelMapper; + } + @Override - public DataModelMapper createDataModelMapper() { - return new JavaDataModelMapper(); + public GraphQLTypeMapper getGraphQLTypeMapper() { + return graphQLTypeMapper; } @Override - public GraphQLTypeMapper createGraphQLTypeMapper(ValueMapper valueMapper) { - return new JavaGraphQLTypeMapper(valueMapper); + public AnnotationsMapper getAnnotationsMapper() { + return annotationsMapper; } @Override - public ValueFormatter createValueFormatter() { - return new JavaValueFormatter(); + public ValueMapper getValueMapper() { + return valueMapper; } } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinAnnotationsMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinAnnotationsMapper.java new file mode 100644 index 000000000..349581eaa --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinAnnotationsMapper.java @@ -0,0 +1,44 @@ +package com.kobylynskyi.graphql.codegen.kotlin; + +import com.kobylynskyi.graphql.codegen.mapper.AnnotationsMapper; +import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; + +import java.util.Collections; +import java.util.List; + +/** + * Mapper class for converting GraphQL types to Kotlin types + * + * @author 梦境迷离 + * @since 2020/12/09 + */ +public class KotlinAnnotationsMapper extends AnnotationsMapper { + + private final ValueMapper valueMapper; + + public KotlinAnnotationsMapper(ValueMapper valueMapper) { + this.valueMapper = valueMapper; + } + + @Override + public boolean addModelValidationAnnotationForType(String possiblyPrimitiveType) { + return false; + } + + @Override + public String getJacksonResolverTypeIdAnnotation(String modelPackageName) { + return "com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver(" + modelPackageName + + "GraphqlJacksonTypeIdResolver::class)"; + } + + @Override + protected List getAdditionalAnnotations(MappingContext mappingContext, String typeName) { + return Collections.emptyList(); + } + + @Override + public ValueMapper getValueMapper() { + return valueMapper; + } +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinDataModelMapper.java index 40c9076ba..33698a75b 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinDataModelMapper.java @@ -2,7 +2,6 @@ import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; import com.kobylynskyi.graphql.codegen.model.MappingContext; -import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; import com.kobylynskyi.graphql.codegen.utils.Utils; import java.util.Arrays; @@ -17,7 +16,7 @@ * @author 梦境迷离 * @since 2020/12/09 */ -public class KotlinDataModelMapper implements DataModelMapper { +public class KotlinDataModelMapper extends DataModelMapper { private static final String RESTRICTED_KEYWORDS_WRAP_WITH = "`"; private static final Set KOTLIN_RESTRICTED_KEYWORDS = new HashSet<>( @@ -48,10 +47,4 @@ public String capitalizeMethodNameIfRestricted(MappingContext mappingContext, St return methodName; } - @Override - public String getModelClassNameWithPrefixAndSuffix(MappingContext mappingContext, - ExtendedDefinition extendedDefinition) { - return DataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, extendedDefinition.getName()); - } - } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLTypeMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLTypeMapper.java index 1d94c903c..ee105ae81 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLTypeMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLTypeMapper.java @@ -2,7 +2,6 @@ import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; -import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; import com.kobylynskyi.graphql.codegen.model.MappingContext; import com.kobylynskyi.graphql.codegen.model.NamedDefinition; import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation; @@ -19,7 +18,7 @@ * @author 梦境迷离 * @since 2020/12/09 */ -public class KotlinGraphQLTypeMapper implements GraphQLTypeMapper { +public class KotlinGraphQLTypeMapper extends GraphQLTypeMapper { private static final String KOTLIN_UTIL_LIST = "List"; private static final String KOTLIN_UTIL_NULLABLE = "?"; @@ -27,12 +26,6 @@ public class KotlinGraphQLTypeMapper implements GraphQLTypeMapper { private static final Set KOTLIN_PRIMITIVE_TYPES = new HashSet<>( asList("Byte", "Short", "Int", "Long", "Float", "Double", "Char", "Boolean")); - private final ValueMapper valueMapper; - - public KotlinGraphQLTypeMapper(ValueMapper valueMapper) { - this.valueMapper = valueMapper; - } - public static boolean isKotlinPrimitive(String scalaType) { return KOTLIN_PRIMITIVE_TYPES.contains(scalaType); } @@ -43,6 +36,7 @@ public static boolean isKotlinPrimitive(String scalaType) { * @param kotlinType type get from Type template * @return default value */ + @SuppressWarnings("unused") public static String defaultValueKotlinPrimitive(String kotlinType) { switch (kotlinType) { case "Long": @@ -111,11 +105,6 @@ public boolean isPrimitive(String kotlinType) { return isKotlinPrimitive(kotlinType); } - @Override - public boolean addModelValidationAnnotationForType(String possiblyPrimitiveType) { - return false; - } - @Override public String getTypeConsideringPrimitive(MappingContext mappingContext, NamedDefinition namedDefinition, @@ -159,11 +148,6 @@ public String getTypeConsideringPrimitive(MappingContext mappingContext, return computedTypeName; } - @Override - public ValueMapper getValueMapper() { - return valueMapper; - } - @Override public String getResponseReturnType(MappingContext mappingContext, NamedDefinition namedDefinition, String computedTypeName) { @@ -173,10 +157,4 @@ public String getResponseReturnType(MappingContext mappingContext, NamedDefiniti // Should fix it when generate response class. return getTypeConsideringPrimitive(mappingContext, namedDefinition, computedTypeName); } - - @Override - public String getJacksonResolverTypeIdAnnotation(String modelPackageName) { - return "com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver(" + modelPackageName + - "GraphqlJacksonTypeIdResolver::class)"; - } } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinMapperFactoryImpl.java b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinMapperFactoryImpl.java index 0079084d9..88eda2bfc 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinMapperFactoryImpl.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinMapperFactoryImpl.java @@ -1,9 +1,9 @@ package com.kobylynskyi.graphql.codegen.kotlin; +import com.kobylynskyi.graphql.codegen.mapper.AnnotationsMapper; import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; -import com.kobylynskyi.graphql.codegen.mapper.ValueFormatter; import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; /** @@ -14,19 +14,36 @@ */ public class KotlinMapperFactoryImpl implements MapperFactory { + private final DataModelMapper dataModelMapper; + private final ValueMapper valueMapper; + private final GraphQLTypeMapper graphQLTypeMapper; + private final AnnotationsMapper annotationsMapper; + + public KotlinMapperFactoryImpl() { + dataModelMapper = new KotlinDataModelMapper(); + valueMapper = new ValueMapper(new KotlinValueFormatter(), dataModelMapper); + graphQLTypeMapper = new KotlinGraphQLTypeMapper(); + annotationsMapper = new KotlinAnnotationsMapper(valueMapper); + } + + @Override + public DataModelMapper getDataModelMapper() { + return dataModelMapper; + } + @Override - public DataModelMapper createDataModelMapper() { - return new KotlinDataModelMapper(); + public GraphQLTypeMapper getGraphQLTypeMapper() { + return graphQLTypeMapper; } @Override - public GraphQLTypeMapper createGraphQLTypeMapper(ValueMapper valueMapper) { - return new KotlinGraphQLTypeMapper(valueMapper); + public AnnotationsMapper getAnnotationsMapper() { + return annotationsMapper; } @Override - public ValueFormatter createValueFormatter() { - return new KotlinValueFormatter(); + public ValueMapper getValueMapper() { + return valueMapper; } } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/AnnotationsMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/AnnotationsMapper.java new file mode 100644 index 000000000..f246d65c1 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/AnnotationsMapper.java @@ -0,0 +1,233 @@ +package com.kobylynskyi.graphql.codegen.mapper; + +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; +import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; +import com.kobylynskyi.graphql.codegen.utils.Utils; +import graphql.language.Argument; +import graphql.language.Directive; +import graphql.language.ListType; +import graphql.language.NamedNode; +import graphql.language.NonNullType; +import graphql.language.Type; +import graphql.language.TypeName; +import graphql.language.UnionTypeDefinition; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper.getDirectives; +import static com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper.getMandatoryType; + +/** + * Mapper for annotations + */ +public abstract class AnnotationsMapper { + + /** + * Get annotations for a given GraphQL type + * + * @param mappingContext Global mapping context + * @param type GraphQL type + * @param def GraphQL definition + * @param parentTypeName Name of the parent type + * @param mandatory Type is mandatory + * @return list of Java annotations for a given GraphQL type + */ + public List getAnnotations(MappingContext mappingContext, Type type, + NamedNode def, String parentTypeName, boolean mandatory) { + if (type instanceof ListType) { + return getAnnotations(mappingContext, ((ListType) type).getType(), def, parentTypeName, mandatory); + } else if (type instanceof NonNullType) { + return getAnnotations(mappingContext, ((NonNullType) type).getType(), def, parentTypeName, true); + } else if (type instanceof TypeName) { + return getAnnotations(mappingContext, ((TypeName) type).getName(), def.getName(), parentTypeName, + getDirectives(def), mandatory, def); + } + return Collections.emptyList(); + } + + public List getAnnotations(MappingContext mappingContext, ExtendedDefinition extendedDefinition) { + if (extendedDefinition == null) { + return Collections.emptyList(); + } + + NamedNode def = extendedDefinition.getDefinition(); + return getAnnotations(mappingContext, extendedDefinition.getName(), extendedDefinition.getName(), null, + extendedDefinition.getDirectives(), false, def); + } + + public List getAnnotations(MappingContext mappingContext, String name) { + return getAnnotations(mappingContext, name, name, null, Collections.emptyList(), false, null); + } + + /** + * Get annotations for a given GraphQL type + * + * @param mappingContext Global mapping context + * @param graphQLTypeName GraphQL type + * @param name Name of the GraphQL type + * @param parentTypeName Name of the parent type + * @param directives List of GraphQL directive + * @param mandatory Type is mandatory + * @param def GraphQL definition + * @return list of Java annotations for a given GraphQL type + */ + public List getAnnotations(MappingContext mappingContext, String graphQLTypeName, String name, + String parentTypeName, List directives, boolean mandatory, + NamedNode def) { + // 1. Add model validation annotation + List annotations = new ArrayList<>(); + if (mandatory) { + String modelValidationAnnotation = getModelValidationAnnotation(mappingContext, graphQLTypeName); + if (modelValidationAnnotation != null) { + annotations.add(modelValidationAnnotation); + } + } + + // 2. Add custom annotations from the configuration + List typeAnnotations = getTypeAnnotations(mappingContext, graphQLTypeName, name, parentTypeName); + annotations.addAll(typeAnnotations); + + // 3. Add Jackson-related annotations + annotations.addAll(getJacksonTypeIdAnnotations(mappingContext, def)); + + // 4. Get additional language-specific annotations + if (def instanceof ExtendedFieldDefinition) { + annotations.addAll(getAdditionalAnnotations(mappingContext, graphQLTypeName)); + } + + // 5. Add annotations according to directives configurations + Map> directiveAnnotationsMapping = mappingContext.getDirectiveAnnotationsMapping(); + for (Directive directive : directives) { + List directiveAnnotations = directiveAnnotationsMapping.get(directive.getName()); + if (!Utils.isEmpty(directiveAnnotations)) { + annotations.addAll(getAnnotationsForDirective(mappingContext, directiveAnnotations, directive)); + } + } + return annotations; + } + + private List getTypeAnnotations(MappingContext mappingContext, + String graphQLType, + String fieldName, + String parentTypeName) { + Map> customAnnotationsMapping = mappingContext.getCustomAnnotationsMapping(); + + List typeAnnotations = new ArrayList<>(); + + if (parentTypeName != null) { + String typeNameKey = parentTypeName + "." + fieldName; + List fullTypeAnnotations = customAnnotationsMapping.get(typeNameKey); + if (!Utils.isEmpty(fullTypeAnnotations)) { + typeAnnotations.addAll(fullTypeAnnotations); + } else { + // try finding if there's a RegEx present for this type + for (Map.Entry> entry : customAnnotationsMapping.entrySet()) { + if (typeNameKey.matches(entry.getKey()) && !Utils.isEmpty(entry.getValue())) { + typeAnnotations.addAll(entry.getValue()); + } + } + } + } + List specificTypeAnnotations = customAnnotationsMapping.get(graphQLType); + if (!Utils.isEmpty(specificTypeAnnotations)) { + typeAnnotations.addAll(specificTypeAnnotations); + } else { + // try finding if there's a RegEx present for this type + for (Map.Entry> entry : customAnnotationsMapping.entrySet()) { + if (graphQLType.matches(entry.getKey()) && !Utils.isEmpty(entry.getValue())) { + typeAnnotations.addAll(entry.getValue()); + } + } + } + return typeAnnotations; + } + + private String getModelValidationAnnotation(MappingContext mappingContext, String graphQLTypeName) { + String possiblyPrimitiveType = mappingContext.getCustomTypesMapping() + .get(getMandatoryType(graphQLTypeName)); + String modelValidationAnnotation = mappingContext.getModelValidationAnnotation(); + if (Utils.isNotBlank(modelValidationAnnotation) && + addModelValidationAnnotationForType(possiblyPrimitiveType)) { + return modelValidationAnnotation; + } + return null; + } + + /** + * Get a list of annotations for a given directive based on mapping config + * + * @param mappingContext Global mapping context + * @param directiveAnnotations List of directive annotations + * @param directive GraphQL Directive + * @return a list of annotations to be added for all types that have given directive + */ + public List getAnnotationsForDirective(MappingContext mappingContext, + List directiveAnnotations, + Directive directive) { + List directiveAnnotationsMapped = new ArrayList<>(); + for (String annotation : directiveAnnotations) { + String directiveAnnotationMapped = annotation; + for (Argument dirArg : directive.getArguments()) { + String argumentValueFormatter = Utils.substringBetween(annotation, "{{" + dirArg.getName(), "}}"); + // if argumentValueFormatter == null then the placeholder {{dirArg.getName()}} does not exist + if (argumentValueFormatter != null) { + String replace = String.format("{{%s%s}}", dirArg.getName(), argumentValueFormatter); + String replaceWith = getValueMapper().map( + mappingContext, dirArg.getValue(), null, argumentValueFormatter); + directiveAnnotationMapped = directiveAnnotationMapped.replace(replace, replaceWith); + } + } + directiveAnnotationsMapped.add(directiveAnnotationMapped); + } + return directiveAnnotationsMapped; + } + + /** + * Get Jackson type id resolver annotations + * + * @param mappingContext Global mapping context + * @param def GraphQL definition + * @return list of Jackson type id resolver annotations + */ + public List getJacksonTypeIdAnnotations(MappingContext mappingContext, NamedNode def) { + List defaults = new ArrayList<>(); + if (Boolean.TRUE.equals(mappingContext.getGenerateJacksonTypeIdResolver()) + && def instanceof UnionTypeDefinition) { + defaults.add("com.fasterxml.jackson.annotation.JsonTypeInfo(use = " + + "com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, property = \"__typename\")"); + String modelPackageName = DataModelMapper.getModelPackageName(mappingContext); + if (modelPackageName == null) { + modelPackageName = ""; + } else if (Utils.isNotBlank(modelPackageName)) { + modelPackageName += "."; + } + defaults.add(getJacksonResolverTypeIdAnnotation(modelPackageName)); + } + return defaults; + } + + /** + * Get language specific Jackson type id resolver annotation + * + * @param modelPackageName Model package name property + * @return language specific Jackson type id resolver annotation + */ + public abstract String getJacksonResolverTypeIdAnnotation(String modelPackageName); + + protected abstract List getAdditionalAnnotations(MappingContext mappingContext, String typeName); + + /** + * Whether to add model validation annotation to a type + * + * @param type GraphQL type name + * @return true if model validation annotation should be added to a type + */ + public abstract boolean addModelValidationAnnotationForType(String type); + + public abstract ValueMapper getValueMapper(); + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapper.java index a75cf30ba..0eab1476e 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapper.java @@ -25,7 +25,7 @@ /** * Generic mapper for all languages */ -public interface DataModelMapper { +public abstract class DataModelMapper { /** * Generates a model class name including prefix and suffix (if any) @@ -34,8 +34,8 @@ public interface DataModelMapper { * @param extendedDefinition GraphQL extended definition * @return Class name of GraphQL model node */ - default String getModelClassNameWithPrefixAndSuffix(MappingContext mappingContext, - ExtendedDefinition extendedDefinition) { + public String getModelClassNameWithPrefixAndSuffix(MappingContext mappingContext, + ExtendedDefinition extendedDefinition) { return getModelClassNameWithPrefixAndSuffix(mappingContext, extendedDefinition.getName()); } @@ -46,7 +46,7 @@ default String getModelClassNameWithPrefixAndSuffix(MappingContext mappingContex * @param definitionName GraphQL node name * @return Class name of GraphQL model node */ - static String getModelClassNameWithPrefixAndSuffix(MappingContext mappingContext, String definitionName) { + public static String getModelClassNameWithPrefixAndSuffix(MappingContext mappingContext, String definitionName) { StringBuilder classNameBuilder = new StringBuilder(); if (Utils.isNotBlank(mappingContext.getModelNamePrefix())) { classNameBuilder.append(mappingContext.getModelNamePrefix()); @@ -219,7 +219,7 @@ static String getApiPackageName(MappingContext mappingContext) { * @param mappingContext Global mapping context * @return model package name if present. Generic package name otherwise */ - static String getModelPackageName(MappingContext mappingContext) { + public static String getModelPackageName(MappingContext mappingContext) { if (Utils.isNotBlank(mappingContext.getModelPackageName())) { return mappingContext.getModelPackageName(); } else { @@ -309,7 +309,7 @@ static Function getParentFileNameFunction() { * @param mappingContext Global mapping context * @return capitalized value if it is restricted in java/scala/kotlin/etc, same value as parameter otherwise */ - String capitalizeIfRestricted(MappingContext mappingContext, String fieldName); + public abstract String capitalizeIfRestricted(MappingContext mappingContext, String fieldName); /** * Capitalize method name if it is language-restricted. @@ -322,6 +322,6 @@ static Function getParentFileNameFunction() { * @param mappingContext Global mapping context * @return capitalized value if it is restricted in java/scala/kotlin/etc, same value as parameter otherwise */ - String capitalizeMethodNameIfRestricted(MappingContext mappingContext, String methodName); + public abstract String capitalizeMethodNameIfRestricted(MappingContext mappingContext, String methodName); } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java index baf84073e..7fe3a8825 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java @@ -5,42 +5,38 @@ */ public class DataModelMapperFactory { + private final MapperFactory mapperFactory; + private final FieldDefinitionToParameterMapper fieldDefToParamMapper; private final EnumDefinitionToDataModelMapper enumDefToDataModelMapper; - private final FieldDefinitionsToResolverDataModelMapper fieldDefsToResolverDataModelMapper; - private final InputDefinitionToDataModelMapper inputDefToDataModelMapper; + private final UnionDefinitionToDataModelMapper unionDefToDataModelMapper; + private final TypeDefinitionToDataModelMapper typeDefToDataModelMapper; private final InterfaceDefinitionToDataModelMapper interfaceDefToDataModelMapper; + private final InputDefinitionToDataModelMapper inputDefToDataModelMapper; + private final FieldDefinitionsToResolverDataModelMapper fieldDefsToResolverDataModelMapper; private final RequestResponseDefinitionToDataModelMapper requestResponseDefToDataModelMapper; - private final TypeDefinitionToDataModelMapper typeDefToDataModelMapper; - private final UnionDefinitionToDataModelMapper unionDefToDataModelMapper; - - private final DataModelMapper dataModelMapper; - private final FieldDefinitionToParameterMapper fieldDefToParamMapper; /** * Constructor for creating a new DataModelMapperFactory based on a MapperFactory * - * @param generatedLanguageMapperFactory Mapper factory of a generated language + * @param mapperFactory Mapper factory of a generated language */ - public DataModelMapperFactory(MapperFactory generatedLanguageMapperFactory) { - ValueFormatter valueFormatter = generatedLanguageMapperFactory.createValueFormatter(); - dataModelMapper = generatedLanguageMapperFactory.createDataModelMapper(); - ValueMapper valueMapper = new ValueMapper(valueFormatter, dataModelMapper); - GraphQLTypeMapper graphQlTypeMapper = generatedLanguageMapperFactory.createGraphQLTypeMapper(valueMapper); - fieldDefToParamMapper = new FieldDefinitionToParameterMapper(graphQlTypeMapper, dataModelMapper); - enumDefToDataModelMapper = new EnumDefinitionToDataModelMapper(graphQlTypeMapper, dataModelMapper); - unionDefToDataModelMapper = new UnionDefinitionToDataModelMapper(graphQlTypeMapper, dataModelMapper); - typeDefToDataModelMapper = new TypeDefinitionToDataModelMapper(graphQlTypeMapper, dataModelMapper, - fieldDefToParamMapper); - interfaceDefToDataModelMapper = new InterfaceDefinitionToDataModelMapper(graphQlTypeMapper, dataModelMapper, - fieldDefToParamMapper); + public DataModelMapperFactory(MapperFactory mapperFactory) { + this.mapperFactory = mapperFactory; + + this.fieldDefToParamMapper = new FieldDefinitionToParameterMapper(mapperFactory); + this.enumDefToDataModelMapper = new EnumDefinitionToDataModelMapper(mapperFactory); + this.unionDefToDataModelMapper = new UnionDefinitionToDataModelMapper(mapperFactory); + this.typeDefToDataModelMapper = new TypeDefinitionToDataModelMapper(mapperFactory, fieldDefToParamMapper); + this.interfaceDefToDataModelMapper = new InterfaceDefinitionToDataModelMapper( + mapperFactory, fieldDefToParamMapper); InputValueDefinitionToParameterMapper inputValueDefToParamMapper = new InputValueDefinitionToParameterMapper( - valueMapper, graphQlTypeMapper, dataModelMapper); - inputDefToDataModelMapper = new InputDefinitionToDataModelMapper(graphQlTypeMapper, dataModelMapper, - inputValueDefToParamMapper); - fieldDefsToResolverDataModelMapper = new FieldDefinitionsToResolverDataModelMapper( - graphQlTypeMapper, dataModelMapper, inputValueDefToParamMapper); - requestResponseDefToDataModelMapper = new RequestResponseDefinitionToDataModelMapper( - graphQlTypeMapper, dataModelMapper, fieldDefToParamMapper, inputValueDefToParamMapper); + mapperFactory); + this.inputDefToDataModelMapper = new InputDefinitionToDataModelMapper( + mapperFactory, inputValueDefToParamMapper); + this.fieldDefsToResolverDataModelMapper = new FieldDefinitionsToResolverDataModelMapper( + mapperFactory, inputValueDefToParamMapper); + this.requestResponseDefToDataModelMapper = new RequestResponseDefinitionToDataModelMapper( + mapperFactory, fieldDefToParamMapper, inputValueDefToParamMapper); } public EnumDefinitionToDataModelMapper getEnumDefinitionMapper() { @@ -71,11 +67,11 @@ public TypeDefinitionToDataModelMapper getTypeDefinitionMapper() { return typeDefToDataModelMapper; } - public DataModelMapper getDataModelMapper() { - return dataModelMapper; - } - public FieldDefinitionToParameterMapper getFieldDefToParamMapper() { return fieldDefToParamMapper; } + + public MapperFactory getMapperFactory() { + return mapperFactory; + } } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/EnumDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/EnumDefinitionToDataModelMapper.java index ad93baa0b..2ec471e3f 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/EnumDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/EnumDefinitionToDataModelMapper.java @@ -34,13 +34,12 @@ */ public class EnumDefinitionToDataModelMapper { - private final GraphQLTypeMapper graphQlTypeMapper; + private final AnnotationsMapper annotationsMapper; private final DataModelMapper dataModelMapper; - public EnumDefinitionToDataModelMapper(GraphQLTypeMapper graphQlTypeMapper, - DataModelMapper dataModelMapper) { - this.graphQlTypeMapper = graphQlTypeMapper; - this.dataModelMapper = dataModelMapper; + public EnumDefinitionToDataModelMapper(MapperFactory mapperFactory) { + this.annotationsMapper = mapperFactory.getAnnotationsMapper(); + this.dataModelMapper = mapperFactory.getDataModelMapper(); } private static Set getUnionInterfaces(MappingContext mappingContext, @@ -78,7 +77,7 @@ public Map map(MappingContext mappingContext, ExtendedEnumTypeDe dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); dataModel.put(CLASS_NAME, dataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, definition)); dataModel.put(IMPLEMENTS, getUnionInterfaces(mappingContext, definition)); - dataModel.put(ANNOTATIONS, graphQlTypeMapper.getAnnotations(mappingContext, definition)); + dataModel.put(ANNOTATIONS, annotationsMapper.getAnnotations(mappingContext, definition)); dataModel.put(JAVA_DOC, JavaDocBuilder.build(definition)); dataModel.put(FIELDS, map(mappingContext, definition.getValueDefinitions())); dataModel.put(GENERATED_ANNOTATION, mappingContext.getAddGeneratedAnnotation()); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java index 564aa6a18..e9848ffb9 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java @@ -22,11 +22,12 @@ public class FieldDefinitionToParameterMapper { private final GraphQLTypeMapper graphQLTypeMapper; private final DataModelMapper dataModelMapper; + private final AnnotationsMapper annotationsMapper; - public FieldDefinitionToParameterMapper(GraphQLTypeMapper graphQLTypeMapper, - DataModelMapper dataModelMapper) { - this.graphQLTypeMapper = graphQLTypeMapper; - this.dataModelMapper = dataModelMapper; + public FieldDefinitionToParameterMapper(MapperFactory mapperFactory) { + this.graphQLTypeMapper = mapperFactory.getGraphQLTypeMapper(); + this.dataModelMapper = mapperFactory.getDataModelMapper(); + this.annotationsMapper = mapperFactory.getAnnotationsMapper(); } /** @@ -131,7 +132,7 @@ private ParameterDefinition mapField(MappingContext mappingContext, ExtendedFiel parameter.setType(graphQLTypeMapper.getTypeConsideringPrimitive(mappingContext, namedDefinition, namedDefinition.getJavaName())); parameter.setAnnotations( - graphQLTypeMapper.getAnnotations(mappingContext, fieldDef.getType(), fieldDef, parentTypeName, false)); + annotationsMapper.getAnnotations(mappingContext, fieldDef.getType(), fieldDef, parentTypeName, false)); parameter.setJavaDoc(fieldDef.getJavaDoc()); parameter.setDeprecated(DeprecatedDefinitionBuilder.build(mappingContext, fieldDef)); parameter.setMandatory(namedDefinition.isMandatory()); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java index d191a984b..ffbe9ca45 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java @@ -43,14 +43,15 @@ public class FieldDefinitionsToResolverDataModelMapper { private final GraphQLTypeMapper graphQLTypeMapper; + private final AnnotationsMapper annotationsMapper; private final DataModelMapper dataModelMapper; private final InputValueDefinitionToParameterMapper inputValueDefinitionToParameterMapper; - public FieldDefinitionsToResolverDataModelMapper(GraphQLTypeMapper graphQLTypeMapper, - DataModelMapper dataModelMapper, + public FieldDefinitionsToResolverDataModelMapper(MapperFactory mapperFactory, InputValueDefinitionToParameterMapper inputValueDefToParamMapper) { - this.graphQLTypeMapper = graphQLTypeMapper; - this.dataModelMapper = dataModelMapper; + this.graphQLTypeMapper = mapperFactory.getGraphQLTypeMapper(); + this.annotationsMapper = mapperFactory.getAnnotationsMapper(); + this.dataModelMapper = mapperFactory.getDataModelMapper(); this.inputValueDefinitionToParameterMapper = inputValueDefToParamMapper; } @@ -196,7 +197,7 @@ private OperationDefinition map(MappingContext mappingContext, ExtendedFieldDefi NamedDefinition javaType = graphQLTypeMapper .getLanguageType(mappingContext, fieldDef.getType(), fieldDef.getName(), parentTypeName); String returnType = getReturnType(mappingContext, fieldDef, javaType, parentTypeName); - List annotations = graphQLTypeMapper + List annotations = annotationsMapper .getAnnotations(mappingContext, fieldDef.getType(), fieldDef, parentTypeName, false); List parameters = getOperationParameters(mappingContext, fieldDef, parentTypeName); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/GraphQLTypeMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/GraphQLTypeMapper.java index 2625de689..c2baadbdf 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/GraphQLTypeMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/GraphQLTypeMapper.java @@ -2,10 +2,6 @@ import com.kobylynskyi.graphql.codegen.model.MappingContext; import com.kobylynskyi.graphql.codegen.model.NamedDefinition; -import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition; -import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition; -import com.kobylynskyi.graphql.codegen.utils.Utils; -import graphql.language.Argument; import graphql.language.Directive; import graphql.language.DirectivesContainer; import graphql.language.ListType; @@ -13,9 +9,7 @@ import graphql.language.NonNullType; import graphql.language.Type; import graphql.language.TypeName; -import graphql.language.UnionTypeDefinition; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -26,7 +20,7 @@ * * @author kobylynskyi */ -public interface GraphQLTypeMapper { +public abstract class GraphQLTypeMapper { /** * Get nested type of GraphQL Type. Example: @@ -38,7 +32,7 @@ public interface GraphQLTypeMapper { * @param graphqlType GraphQL type * @return GraphQL type without List/NonNull wrapping */ - static String getNestedTypeName(Type graphqlType) { + public static String getNestedTypeName(Type graphqlType) { if (graphqlType instanceof TypeName) { return ((TypeName) graphqlType).getName(); } else if (graphqlType instanceof ListType) { @@ -49,11 +43,11 @@ static String getNestedTypeName(Type graphqlType) { return null; } - static String getMandatoryType(String typeName) { + public static String getMandatoryType(String typeName) { return typeName + "!"; } - static List getDirectives(NamedNode def) { + public static List getDirectives(NamedNode def) { if (def instanceof DirectivesContainer) { return ((DirectivesContainer) def).getDirectives(); } @@ -69,7 +63,7 @@ static List getDirectives(NamedNode def) { * @param mandatory Type is it mandatory * @return String The name of the given type, wrapped into {@code List<>} */ - String wrapIntoList(MappingContext mappingContext, String type, boolean mandatory); + public abstract String wrapIntoList(MappingContext mappingContext, String type, boolean mandatory); /** * Return upper bounded wildcard for the given interface type: @@ -80,7 +74,7 @@ static List getDirectives(NamedNode def) { * @param mandatory Type is it mandatory * @return String The name of the the wrapped type. */ - String wrapSuperTypeIntoList(MappingContext mappingContext, String type, boolean mandatory); + public abstract String wrapSuperTypeIntoList(MappingContext mappingContext, String type, boolean mandatory); /** * Wraps type into apiReturnType or subscriptionReturnType (defined in the mapping configuration). @@ -110,9 +104,9 @@ static List getDirectives(NamedNode def) { * @param parentTypeName Name of the parent type * @return Java/Scala type wrapped into the subscriptionReturnType */ - String wrapApiReturnTypeIfRequired(MappingContext mappingContext, - NamedDefinition namedDefinition, - String parentTypeName); + public abstract String wrapApiReturnTypeIfRequired(MappingContext mappingContext, + NamedDefinition namedDefinition, + String parentTypeName); /** * Check if the time is primitive. @@ -120,15 +114,7 @@ String wrapApiReturnTypeIfRequired(MappingContext mappingContext, * @param possiblyPrimitiveType type to check * @return true if the provided type is primitive, false if the provided type is not primitive */ - boolean isPrimitive(String possiblyPrimitiveType); - - /** - * Whether to add model validation annotation to a type - * - * @param type GraphQL type name - * @return true if model validation annotation should be added to a type - */ - boolean addModelValidationAnnotationForType(String type); + public abstract boolean isPrimitive(String possiblyPrimitiveType); /** * Wrap string into generics type @@ -138,7 +124,7 @@ String wrapApiReturnTypeIfRequired(MappingContext mappingContext, * @param typeParameter Parameter of generics type * @return type wrapped into generics */ - default String getGenericsString(MappingContext mappingContext, String genericType, String typeParameter) { + public String getGenericsString(MappingContext mappingContext, String genericType, String typeParameter) { if (genericType.contains("%s")) { return String.format(genericType, typeParameter); } else { @@ -153,7 +139,7 @@ default String getGenericsString(MappingContext mappingContext, String genericTy * @param type GraphQL type * @return Corresponding language-specific type (java/scala/kotlin/etc) */ - default String getLanguageType(MappingContext mappingContext, Type type) { + public String getLanguageType(MappingContext mappingContext, Type type) { return getLanguageType(mappingContext, type, null, null).getJavaName(); } @@ -166,8 +152,8 @@ default String getLanguageType(MappingContext mappingContext, Type type) { * @param parentTypeName Name of the parent type * @return Corresponding language-specific type (java/scala/kotlin/etc) */ - default NamedDefinition getLanguageType(MappingContext mappingContext, Type graphqlType, String name, - String parentTypeName) { + public NamedDefinition getLanguageType(MappingContext mappingContext, Type graphqlType, String name, + String parentTypeName) { return getLanguageType(mappingContext, graphqlType, name, parentTypeName, false, false); } @@ -182,9 +168,9 @@ default NamedDefinition getLanguageType(MappingContext mappingContext, Type g * @param collection GraphQL type is collection * @return Corresponding language-specific type (java/scala/kotlin/etc) */ - default NamedDefinition getLanguageType(MappingContext mappingContext, Type graphqlType, - String name, String parentTypeName, - boolean mandatory, boolean collection) { + public NamedDefinition getLanguageType(MappingContext mappingContext, Type graphqlType, + String name, String parentTypeName, + boolean mandatory, boolean collection) { if (graphqlType instanceof TypeName) { return getLanguageType(mappingContext, ((TypeName) graphqlType).getName(), name, parentTypeName, mandatory, collection); @@ -217,8 +203,8 @@ default NamedDefinition getLanguageType(MappingContext mappingContext, Type g * @param collection GraphQL type is collection * @return Corresponding language-specific type (java/scala/kotlin/etc) */ - default NamedDefinition getLanguageType(MappingContext mappingContext, String graphQLType, String name, - String parentTypeName, boolean mandatory, boolean collection) { + public NamedDefinition getLanguageType(MappingContext mappingContext, String graphQLType, String name, + String parentTypeName, boolean mandatory, boolean collection) { Map customTypesMapping = mappingContext.getCustomTypesMapping(); Set serializeFieldsUsingObjectMapper = mappingContext.getUseObjectMapperForRequestSerialization(); String langTypeName; @@ -241,165 +227,9 @@ default NamedDefinition getLanguageType(MappingContext mappingContext, String gr mandatory, primitiveCanBeUsed, serializeUsingObjectMapper); } - /** - * Get annotations for a given GraphQL type - * - * @param mappingContext Global mapping context - * @param type GraphQL type - * @param def GraphQL definition - * @param parentTypeName Name of the parent type - * @param mandatory Type is mandatory - * @return list of Java annotations for a given GraphQL type - */ - default List getAnnotations(MappingContext mappingContext, Type type, - NamedNode def, String parentTypeName, boolean mandatory) { - if (type instanceof ListType) { - return getAnnotations(mappingContext, ((ListType) type).getType(), def, parentTypeName, mandatory); - } else if (type instanceof NonNullType) { - return getAnnotations(mappingContext, ((NonNullType) type).getType(), def, parentTypeName, true); - } else if (type instanceof TypeName) { - return getAnnotations(mappingContext, ((TypeName) type).getName(), def.getName(), parentTypeName, - getDirectives(def), mandatory, def); - } - return Collections.emptyList(); - } - - default List getAnnotations(MappingContext mappingContext, ExtendedDefinition extendedDefinition) { - if (extendedDefinition == null) { - return Collections.emptyList(); - } - - NamedNode def = extendedDefinition.getDefinition(); - return getAnnotations(mappingContext, extendedDefinition.getName(), extendedDefinition.getName(), null, - extendedDefinition.getDirectives(), false, def); - } - - default List getAnnotations(MappingContext mappingContext, String name) { - return getAnnotations(mappingContext, name, name, null, Collections.emptyList(), false, null); - } - - /** - * Get annotations for a given GraphQL type - * - * @param mappingContext Global mapping context - * @param graphQLTypeName GraphQL type - * @param name Name of the GraphQL type - * @param parentTypeName Name of the parent type - * @param directives List of GraphQL directive - * @param mandatory Type is mandatory - * @param def GraphQL definition - * @return list of Java annotations for a given GraphQL type - */ - default List getAnnotations(MappingContext mappingContext, String graphQLTypeName, String name, - String parentTypeName, List directives, boolean mandatory, - NamedNode def) { - List annotations = new ArrayList<>(); - if (mandatory) { - String possiblyPrimitiveType = mappingContext.getCustomTypesMapping() - .get(getMandatoryType(graphQLTypeName)); - String modelValidationAnnotation = mappingContext.getModelValidationAnnotation(); - if (Utils.isNotBlank(modelValidationAnnotation) && addModelValidationAnnotationForType( - possiblyPrimitiveType)) { - annotations.add(modelValidationAnnotation); - } - } - - Map> customAnnotationsMapping = mappingContext.getCustomAnnotationsMapping(); - if (name != null && parentTypeName != null && customAnnotationsMapping - .containsKey(parentTypeName + "." + name)) { - List annotationsToAdd = customAnnotationsMapping.get(parentTypeName + "." + name); - if (!Utils.isEmpty(annotationsToAdd)) { - annotations.addAll(annotationsToAdd); - } - } else if (customAnnotationsMapping.containsKey(graphQLTypeName)) { - List annotationsToAdd = customAnnotationsMapping.get(graphQLTypeName); - if (!Utils.isEmpty(annotationsToAdd)) { - annotations.addAll(annotationsToAdd); - } - } - - annotations.addAll(getJacksonTypeIdAnnotations(mappingContext, def)); - if (def instanceof ExtendedFieldDefinition) { - annotations.addAll(getAdditionalAnnotations(mappingContext, graphQLTypeName)); - } - - Map> directiveAnnotationsMapping = mappingContext.getDirectiveAnnotationsMapping(); - for (Directive directive : directives) { - if (directiveAnnotationsMapping.containsKey(directive.getName())) { - annotations.addAll(getAnnotationsForDirective( - mappingContext, directiveAnnotationsMapping.get(directive.getName()), directive)); - } - } - return annotations; - } - - /** - * Get Jackson type id resolver annotations - * - * @param mappingContext Global mapping context - * @param def GraphQL definition - * @return list of Jackson type id resolver annotations - */ - default List getJacksonTypeIdAnnotations(MappingContext mappingContext, NamedNode def) { - List defaults = new ArrayList<>(); - if (Boolean.TRUE.equals(mappingContext.getGenerateJacksonTypeIdResolver()) - && def instanceof UnionTypeDefinition) { - defaults.add("com.fasterxml.jackson.annotation.JsonTypeInfo(use = " + - "com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, property = \"__typename\")"); - String modelPackageName = DataModelMapper.getModelPackageName(mappingContext); - if (modelPackageName == null) { - modelPackageName = ""; - } else if (Utils.isNotBlank(modelPackageName)) { - modelPackageName += "."; - } - defaults.add(getJacksonResolverTypeIdAnnotation(modelPackageName)); - } - return defaults; - } - - /** - * Get language specific Jackson type id resolver annotation - * - * @param modelPackageName Model package name property - * @return language specific Jackson type id resolver annotation - */ - String getJacksonResolverTypeIdAnnotation(String modelPackageName); - - default List getAdditionalAnnotations(MappingContext mappingContext, String typeName) { - return new ArrayList<>(); - } - - /** - * Get a list of annotations for a given directive based on mapping config - * - * @param mappingContext Global mapping context - * @param directiveAnnotations List of directive annotations - * @param directive GraphQL Directive - * @return a list of annotations to be added for all types that have given directive - */ - default List getAnnotationsForDirective(MappingContext mappingContext, - List directiveAnnotations, - Directive directive) { - List directiveAnnotationsMapped = new ArrayList<>(); - for (String annotation : directiveAnnotations) { - String directiveAnnotationMapped = annotation; - for (Argument dirArg : directive.getArguments()) { - String argumentValueFormatter = Utils.substringBetween(annotation, "{{" + dirArg.getName(), "}}"); - // if argumentValueFormatter == null then the placeholder {{dirArg.getName()}} does not exist - if (argumentValueFormatter != null) { - directiveAnnotationMapped = directiveAnnotationMapped.replace( - String.format("{{%s%s}}", dirArg.getName(), argumentValueFormatter), - getValueMapper().map(mappingContext, dirArg.getValue(), null, argumentValueFormatter)); - } - } - directiveAnnotationsMapped.add(directiveAnnotationMapped); - } - return directiveAnnotationsMapped; - } - - default String getTypeConsideringPrimitive(MappingContext mappingContext, - NamedDefinition namedDefinition, - String computedTypeName) { + public String getTypeConsideringPrimitive(MappingContext mappingContext, + NamedDefinition namedDefinition, + String computedTypeName) { String graphqlTypeName = namedDefinition.getGraphqlTypeName(); if (namedDefinition.isMandatory() && namedDefinition.isPrimitiveCanBeUsed()) { String possiblyPrimitiveType = mappingContext.getCustomTypesMapping() @@ -411,12 +241,10 @@ default String getTypeConsideringPrimitive(MappingContext mappingContext, return computedTypeName; } - default String getResponseReturnType(MappingContext mappingContext, - NamedDefinition namedDefinition, - String computedTypeName) { + public String getResponseReturnType(MappingContext mappingContext, + NamedDefinition namedDefinition, + String computedTypeName) { return computedTypeName; } - ValueMapper getValueMapper(); - } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java index d613b8329..3df7a4749 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java @@ -30,15 +30,14 @@ */ public class InputDefinitionToDataModelMapper { - private final GraphQLTypeMapper graphQLTypeMapper; + private final AnnotationsMapper annotationsMapper; private final DataModelMapper dataModelMapper; private final InputValueDefinitionToParameterMapper inputValueDefinitionToParameterMapper; - public InputDefinitionToDataModelMapper(GraphQLTypeMapper graphQLTypeMapper, - DataModelMapper dataModelMapper, + public InputDefinitionToDataModelMapper(MapperFactory mapperFactory, InputValueDefinitionToParameterMapper inputValueDefToParamMapper) { - this.graphQLTypeMapper = graphQLTypeMapper; - this.dataModelMapper = dataModelMapper; + this.annotationsMapper = mapperFactory.getAnnotationsMapper(); + this.dataModelMapper = mapperFactory.getDataModelMapper(); this.inputValueDefinitionToParameterMapper = inputValueDefToParamMapper; } @@ -58,7 +57,7 @@ public Map map(MappingContext mappingContext, ExtendedInputObjec dataModel.put(NAME, definition.getName()); dataModel.put(FIELDS, inputValueDefinitionToParameterMapper .map(mappingContext, definition.getValueDefinitions(), definition.getName())); - dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, definition)); + dataModel.put(ANNOTATIONS, annotationsMapper.getAnnotations(mappingContext, definition)); dataModel.put(BUILDER, mappingContext.getGenerateBuilder()); dataModel.put(EQUALS_AND_HASH_CODE, mappingContext.getGenerateEqualsAndHashCode()); dataModel.put(IMMUTABLE_MODELS, mappingContext.getGenerateImmutableModels()); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputValueDefinitionToParameterMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputValueDefinitionToParameterMapper.java index e5e95bdb9..f21dd847e 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputValueDefinitionToParameterMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputValueDefinitionToParameterMapper.java @@ -19,14 +19,14 @@ public class InputValueDefinitionToParameterMapper { private final ValueMapper valueMapper; private final GraphQLTypeMapper graphQLTypeMapper; + private final AnnotationsMapper annotationsMapper; private final DataModelMapper dataModelMapper; - public InputValueDefinitionToParameterMapper(ValueMapper valueMapper, - GraphQLTypeMapper graphQLTypeMapper, - DataModelMapper dataModelMapper) { - this.valueMapper = valueMapper; - this.graphQLTypeMapper = graphQLTypeMapper; - this.dataModelMapper = dataModelMapper; + public InputValueDefinitionToParameterMapper(MapperFactory mapperFactory) { + this.valueMapper = mapperFactory.getValueMapper(); + this.graphQLTypeMapper = mapperFactory.getGraphQLTypeMapper(); + this.annotationsMapper = mapperFactory.getAnnotationsMapper(); + this.dataModelMapper = mapperFactory.getDataModelMapper(); } /** @@ -65,7 +65,7 @@ private ParameterDefinition map(MappingContext mappingContext, InputValueDefinit namedDefinition.getJavaName())); parameter.setDefaultValue(valueMapper.map( mappingContext, inputValueDefinition.getDefaultValue(), inputValueDefinition.getType())); - parameter.setAnnotations(graphQLTypeMapper.getAnnotations(mappingContext, inputValueDefinition.getType(), + parameter.setAnnotations(annotationsMapper.getAnnotations(mappingContext, inputValueDefinition.getType(), inputValueDefinition, parentTypeName, false)); parameter.setDeprecated(DeprecatedDefinitionBuilder.build(mappingContext, inputValueDefinition)); parameter.setMandatory(namedDefinition.isMandatory()); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java index 0d9b209b8..e25e6cdc4 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java @@ -29,14 +29,15 @@ public class InterfaceDefinitionToDataModelMapper { private final GraphQLTypeMapper graphQLTypeMapper; + private final AnnotationsMapper annotationsMapper; private final DataModelMapper dataModelMapper; private final FieldDefinitionToParameterMapper fieldDefinitionToParameterMapper; - public InterfaceDefinitionToDataModelMapper(GraphQLTypeMapper graphQLTypeMapper, - DataModelMapper dataModelMapper, + public InterfaceDefinitionToDataModelMapper(MapperFactory mapperFactory, FieldDefinitionToParameterMapper fieldDefinitionToParameterMapper) { - this.graphQLTypeMapper = graphQLTypeMapper; - this.dataModelMapper = dataModelMapper; + this.graphQLTypeMapper = mapperFactory.getGraphQLTypeMapper(); + this.annotationsMapper = mapperFactory.getAnnotationsMapper(); + this.dataModelMapper = mapperFactory.getDataModelMapper(); this.fieldDefinitionToParameterMapper = fieldDefinitionToParameterMapper; } @@ -54,7 +55,7 @@ public Map map(MappingContext mappingContext, ExtendedInterfaceT dataModel.put(CLASS_NAME, dataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, definition)); dataModel.put(JAVA_DOC, JavaDocBuilder.build(definition)); dataModel.put(IMPLEMENTS, getInterfaces(mappingContext, definition)); - dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, definition)); + dataModel.put(ANNOTATIONS, annotationsMapper.getAnnotations(mappingContext, definition)); dataModel.put(FIELDS, fieldDefinitionToParameterMapper .mapFields(mappingContext, definition.getFieldDefinitions(), definition)); dataModel.put(GENERATED_ANNOTATION, mappingContext.getAddGeneratedAnnotation()); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/MapperFactory.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/MapperFactory.java index cdc759aa6..4cf7ed335 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/MapperFactory.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/MapperFactory.java @@ -7,10 +7,12 @@ */ public interface MapperFactory { - DataModelMapper createDataModelMapper(); + DataModelMapper getDataModelMapper(); - GraphQLTypeMapper createGraphQLTypeMapper(ValueMapper valueMapper); + GraphQLTypeMapper getGraphQLTypeMapper(); - ValueFormatter createValueFormatter(); + AnnotationsMapper getAnnotationsMapper(); + + ValueMapper getValueMapper(); } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java index 0ece353d3..39bf24ff7 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java @@ -47,16 +47,17 @@ public class RequestResponseDefinitionToDataModelMapper { private final GraphQLTypeMapper graphQLTypeMapper; + private final AnnotationsMapper annotationsMapper; private final DataModelMapper dataModelMapper; private final FieldDefinitionToParameterMapper fieldDefinitionToParameterMapper; private final InputValueDefinitionToParameterMapper inputValueDefinitionToParameterMapper; - public RequestResponseDefinitionToDataModelMapper(GraphQLTypeMapper graphQLTypeMapper, - DataModelMapper dataModelMapper, + public RequestResponseDefinitionToDataModelMapper(MapperFactory mapperFactory, FieldDefinitionToParameterMapper fieldDefinitionToParameterMapper, InputValueDefinitionToParameterMapper inputValDefToParamMapper) { - this.graphQLTypeMapper = graphQLTypeMapper; - this.dataModelMapper = dataModelMapper; + this.graphQLTypeMapper = mapperFactory.getGraphQLTypeMapper(); + this.annotationsMapper = mapperFactory.getAnnotationsMapper(); + this.dataModelMapper = mapperFactory.getDataModelMapper(); this.fieldDefinitionToParameterMapper = fieldDefinitionToParameterMapper; this.inputValueDefinitionToParameterMapper = inputValDefToParamMapper; } @@ -113,7 +114,7 @@ public Map mapResponseProjection(MappingContext mappingContext, // ResponseProjection classes are sharing the package with the model classes, so no imports are needed dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); dataModel.put(CLASS_NAME, className); - dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, className)); + dataModel.put(ANNOTATIONS, annotationsMapper.getAnnotations(mappingContext, className)); dataModel.put(JAVA_DOC, Collections.singletonList("Response projection for " + definition.getName())); dataModel.put(FIELDS, getProjectionFields(mappingContext, definition)); dataModel.put(BUILDER, mappingContext.getGenerateBuilder()); @@ -143,10 +144,9 @@ public Map mapParametrizedInput(MappingContext mappingContext, // ParametrizedInput classes are sharing the package with the model classes, so no imports are needed dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); dataModel.put(CLASS_NAME, className); - dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, className)); + dataModel.put(ANNOTATIONS, annotationsMapper.getAnnotations(mappingContext, className)); dataModel.put(JAVA_DOC, Collections.singletonList(String.format("Parametrized input for field %s in type %s", - fieldDefinition.getName(), - parentTypeDefinition.getName()))); + fieldDefinition.getName(), parentTypeDefinition.getName()))); dataModel.put(FIELDS, inputValueDefinitionToParameterMapper.map( mappingContext, fieldDefinition.getInputValueDefinitions(), parentTypeDefinition.getName())); dataModel.put(BUILDER, mappingContext.getGenerateBuilder()); @@ -179,7 +179,7 @@ public Map mapResponse(MappingContext mappingContext, Map dataModel = new HashMap<>(); // Response classes are sharing the package with the model classes, so no imports are needed dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); - dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, className)); + dataModel.put(ANNOTATIONS, annotationsMapper.getAnnotations(mappingContext, className)); dataModel.put(CLASS_NAME, className); dataModel.put(JAVA_DOC, operationDef.getJavaDoc()); dataModel.put(DEPRECATED, DeprecatedDefinitionBuilder.build(mappingContext, operationDef)); @@ -210,7 +210,7 @@ public Map mapRequest(MappingContext mappingContext, Map dataModel = new HashMap<>(); // Request classes are sharing the package with the model classes, so no imports are needed dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); - dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, className)); + dataModel.put(ANNOTATIONS, annotationsMapper.getAnnotations(mappingContext, className)); dataModel.put(CLASS_NAME, className); dataModel.put(JAVA_DOC, operationDef.getJavaDoc()); dataModel.put(OPERATION_NAME, operationDef.getName()); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java index 0d835b216..5760ad4eb 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java @@ -42,14 +42,15 @@ public class TypeDefinitionToDataModelMapper { private final GraphQLTypeMapper graphQLTypeMapper; + private final AnnotationsMapper annotationsMapper; private final DataModelMapper dataModelMapper; private final FieldDefinitionToParameterMapper fieldDefinitionToParameterMapper; - public TypeDefinitionToDataModelMapper(GraphQLTypeMapper graphQLTypeMapper, - DataModelMapper dataModelMapper, + public TypeDefinitionToDataModelMapper(MapperFactory mapperFactory, FieldDefinitionToParameterMapper fieldDefinitionToParameterMapper) { - this.graphQLTypeMapper = graphQLTypeMapper; - this.dataModelMapper = dataModelMapper; + this.graphQLTypeMapper = mapperFactory.getGraphQLTypeMapper(); + this.annotationsMapper = mapperFactory.getAnnotationsMapper(); + this.dataModelMapper = mapperFactory.getDataModelMapper(); this.fieldDefinitionToParameterMapper = fieldDefinitionToParameterMapper; } @@ -89,7 +90,7 @@ public Map map(MappingContext mappingContext, dataModel.put(CLASS_NAME, dataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, definition)); dataModel.put(JAVA_DOC, JavaDocBuilder.build(definition)); dataModel.put(IMPLEMENTS, getInterfaces(mappingContext, definition)); - dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, definition)); + dataModel.put(ANNOTATIONS, annotationsMapper.getAnnotations(mappingContext, definition)); dataModel.put(FIELDS, getFields(mappingContext, definition, document)); dataModel.put(BUILDER, mappingContext.getGenerateBuilder()); dataModel.put(EQUALS_AND_HASH_CODE, mappingContext.getGenerateEqualsAndHashCode()); @@ -141,8 +142,7 @@ private Set getInterfaces(MappingContext mappingContext, .collect(Collectors.toList()); Set interfaceNames = definition.getImplements() .stream() - .map(anImplement -> graphQLTypeMapper - .getLanguageType(mappingContext, anImplement)) + .map(anImplement -> graphQLTypeMapper.getLanguageType(mappingContext, anImplement)) .collect(Collectors.toSet()); Set allInterfaces = new LinkedHashSet<>(); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java index 9baebc0c4..a0ea2c4f4 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java @@ -22,13 +22,12 @@ */ public class UnionDefinitionToDataModelMapper { - private final GraphQLTypeMapper graphQLTypeMapper; + private final AnnotationsMapper annotationsMapper; private final DataModelMapper dataModelMapper; - public UnionDefinitionToDataModelMapper(GraphQLTypeMapper graphQLTypeMapper, - DataModelMapper dataModelMapper) { - this.graphQLTypeMapper = graphQLTypeMapper; - this.dataModelMapper = dataModelMapper; + public UnionDefinitionToDataModelMapper(MapperFactory mapperFactory) { + this.annotationsMapper = mapperFactory.getAnnotationsMapper(); + this.dataModelMapper = mapperFactory.getDataModelMapper(); } /** @@ -43,7 +42,7 @@ public Map map(MappingContext mappingContext, ExtendedUnionTypeD // type/enum/input/interface/union classes do not require any imports dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); dataModel.put(CLASS_NAME, dataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, definition)); - dataModel.put(ANNOTATIONS, graphQLTypeMapper.getAnnotations(mappingContext, definition)); + dataModel.put(ANNOTATIONS, annotationsMapper.getAnnotations(mappingContext, definition)); dataModel.put(JAVA_DOC, JavaDocBuilder.build(definition)); dataModel.put(GENERATED_ANNOTATION, mappingContext.getAddGeneratedAnnotation()); dataModel.put(GENERATED_INFO, mappingContext.getGeneratedInformation()); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java index cae443737..5b58d1d53 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java @@ -368,7 +368,7 @@ private String getModelClassNameWithPrefixAndSuffix(ExtendedEnumTypeDefinition e } private String getModelClassNameWithPrefixAndSuffix(ExtendedDefinition extendedDefinition) { - return this.dataModelMapperFactory.getDataModelMapper() + return this.dataModelMapperFactory.getMapperFactory().getDataModelMapper() .getModelClassNameWithPrefixAndSuffix(this, extendedDefinition); } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaAnnotationsMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaAnnotationsMapper.java new file mode 100644 index 000000000..12a7bf393 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaAnnotationsMapper.java @@ -0,0 +1,64 @@ +package com.kobylynskyi.graphql.codegen.scala; + +import com.kobylynskyi.graphql.codegen.mapper.AnnotationsMapper; +import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; +import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.utils.Utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Mapper class for converting GraphQL types to Scala types + */ +public class ScalaAnnotationsMapper extends AnnotationsMapper { + + private final ValueMapper valueMapper; + + public ScalaAnnotationsMapper(ValueMapper valueMapper) { + this.valueMapper = valueMapper; + } + + @Override + public boolean addModelValidationAnnotationForType(String possiblyPrimitiveType) { + return !ScalaGraphQLTypeMapper.isScalaPrimitive(possiblyPrimitiveType); + } + + @Override + public String getJacksonResolverTypeIdAnnotation(String modelPackageName) { + return "com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver(classOf[" + modelPackageName + + "GraphqlJacksonTypeIdResolver])"; + } + + @Override + public List getAdditionalAnnotations(MappingContext mappingContext, String typeName) { + List defaults = new ArrayList<>(); + String typeNameWithPrefixAndSuffix = (mappingContext.getModelNamePrefix() == null ? "" + : mappingContext.getModelNamePrefix()) + + typeName + + (mappingContext.getModelNameSuffix() == null ? "" : mappingContext.getModelNameSuffix()); + boolean exists = null != mappingContext.getEnumImportItSelfInScala() + && mappingContext.getEnumImportItSelfInScala() + .contains(typeNameWithPrefixAndSuffix); + // todo use switch + // Inspired by the pr https://github.com/kobylynskyi/graphql-java-codegen/pull/637/files + if (exists) { + String modelPackageName = DataModelMapper.getModelPackageName(mappingContext); + if (modelPackageName == null) { + modelPackageName = ""; + } else if (Utils.isNotBlank(modelPackageName)) { + modelPackageName += "."; + } + defaults.add("com.fasterxml.jackson.module.scala.JsonScalaEnumeration(classOf[" + modelPackageName + + typeNameWithPrefixAndSuffix + "TypeRefer])"); + } + return defaults; + } + + @Override + public ValueMapper getValueMapper() { + return valueMapper; + } + +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaDataModelMapper.java index 4fead00b8..5eef26d7e 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaDataModelMapper.java @@ -13,7 +13,7 @@ /** * Data model mapper for SCALA generated classes */ -public class ScalaDataModelMapper implements DataModelMapper { +public class ScalaDataModelMapper extends DataModelMapper { private static final String RESTRICTED_WORDS_WRAP_WITH = "`"; private static final Set SCALA_RESTRICTED_KEYWORDS = new HashSet<>(Arrays.asList( diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaGraphQLTypeMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaGraphQLTypeMapper.java index 798b09725..2967d9a26 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaGraphQLTypeMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaGraphQLTypeMapper.java @@ -1,16 +1,12 @@ package com.kobylynskyi.graphql.codegen.scala; -import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; -import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; import com.kobylynskyi.graphql.codegen.model.MappingContext; import com.kobylynskyi.graphql.codegen.model.NamedDefinition; import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation; import com.kobylynskyi.graphql.codegen.utils.Utils; -import java.util.ArrayList; import java.util.HashSet; -import java.util.List; import java.util.Set; import static com.kobylynskyi.graphql.codegen.java.JavaGraphQLTypeMapper.JAVA_UTIL_LIST; @@ -19,19 +15,13 @@ /** * Mapper class for converting GraphQL types to Scala types */ -public class ScalaGraphQLTypeMapper implements GraphQLTypeMapper { +public class ScalaGraphQLTypeMapper extends GraphQLTypeMapper { private static final String SCALA_UTIL_LIST = "scala.Seq"; private static final String SCALA_UTIL_OPTIONAL = "scala.Option"; private static final Set SCALA_PRIMITIVE_TYPES = new HashSet<>(asList( "Byte", "Short", "Int", "Long", "Float", "Double", "Char", "Boolean")); - private final ValueMapper valueMapper; - - public ScalaGraphQLTypeMapper(ValueMapper valueMapper) { - this.valueMapper = valueMapper; - } - public static boolean isScalaPrimitive(String scalaType) { return SCALA_PRIMITIVE_TYPES.contains(scalaType); } @@ -105,44 +95,4 @@ public String getGenericsString(MappingContext mappingContext, String genericTyp } } - @Override - public boolean addModelValidationAnnotationForType(String possiblyPrimitiveType) { - return !ScalaGraphQLTypeMapper.isScalaPrimitive(possiblyPrimitiveType); - } - - @Override - public ValueMapper getValueMapper() { - return valueMapper; - } - - @Override - public String getJacksonResolverTypeIdAnnotation(String modelPackageName) { - return "com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver(classOf[" + modelPackageName + - "GraphqlJacksonTypeIdResolver])"; - } - - @Override - public List getAdditionalAnnotations(MappingContext mappingContext, String typeName) { - List defaults = new ArrayList<>(); - String typeNameWithPrefixAndSuffix = (mappingContext.getModelNamePrefix() == null ? "" - : mappingContext.getModelNamePrefix()) - + typeName - + (mappingContext.getModelNameSuffix() == null ? "" : mappingContext.getModelNameSuffix()); - boolean exists = null != mappingContext.getEnumImportItSelfInScala() - && mappingContext.getEnumImportItSelfInScala() - .contains(typeNameWithPrefixAndSuffix); - // todo use switch - // Inspired by the pr https://github.com/kobylynskyi/graphql-java-codegen/pull/637/files - if (exists) { - String modelPackageName = DataModelMapper.getModelPackageName(mappingContext); - if (modelPackageName == null) { - modelPackageName = ""; - } else if (Utils.isNotBlank(modelPackageName)) { - modelPackageName += "."; - } - defaults.add("com.fasterxml.jackson.module.scala.JsonScalaEnumeration(classOf[" + modelPackageName - + typeNameWithPrefixAndSuffix + "TypeRefer])"); - } - return defaults; - } } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaMapperFactoryImpl.java b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaMapperFactoryImpl.java index 8d30a31e6..af195744f 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaMapperFactoryImpl.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaMapperFactoryImpl.java @@ -1,9 +1,9 @@ package com.kobylynskyi.graphql.codegen.scala; +import com.kobylynskyi.graphql.codegen.mapper.AnnotationsMapper; import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; import com.kobylynskyi.graphql.codegen.mapper.MapperFactory; -import com.kobylynskyi.graphql.codegen.mapper.ValueFormatter; import com.kobylynskyi.graphql.codegen.mapper.ValueMapper; /** @@ -11,19 +11,36 @@ */ public class ScalaMapperFactoryImpl implements MapperFactory { + private final DataModelMapper dataModelMapper; + private final ValueMapper valueMapper; + private final GraphQLTypeMapper graphQLTypeMapper; + private final AnnotationsMapper annotationsMapper; + + public ScalaMapperFactoryImpl() { + dataModelMapper = new ScalaDataModelMapper(); + valueMapper = new ValueMapper(new ScalaValueFormatter(), dataModelMapper); + graphQLTypeMapper = new ScalaGraphQLTypeMapper(); + annotationsMapper = new ScalaAnnotationsMapper(valueMapper); + } + + @Override + public DataModelMapper getDataModelMapper() { + return dataModelMapper; + } + @Override - public DataModelMapper createDataModelMapper() { - return new ScalaDataModelMapper(); + public GraphQLTypeMapper getGraphQLTypeMapper() { + return graphQLTypeMapper; } @Override - public GraphQLTypeMapper createGraphQLTypeMapper(ValueMapper valueMapper) { - return new ScalaGraphQLTypeMapper(valueMapper); + public AnnotationsMapper getAnnotationsMapper() { + return annotationsMapper; } @Override - public ValueFormatter createValueFormatter() { - return new ScalaValueFormatter(); + public ValueMapper getValueMapper() { + return valueMapper; } } diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenAnnotationsTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenAnnotationsTest.java index 92443742e..f7aeb8764 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenAnnotationsTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenAnnotationsTest.java @@ -74,6 +74,23 @@ void generate_CustomAnnotationMappings_Type() throws Exception { + System.lineSeparator() + " private org.joda.time.DateTime createdDateTime;"); } + @Test + void generate_CustomAnnotationMappings_Regexp() throws Exception { + mappingConfig.setCustomTypesMapping(new HashMap<>(singletonMap("DateTime", "org.joda.time.DateTime"))); + mappingConfig.setCustomAnnotationsMapping(new HashMap<>(singletonMap("Date.*", + singletonList("com.fasterxml.jackson.databind.annotation.JsonDeserialize(" + + "using = com.example.json.DateTimeScalarDeserializer.class)")))); + + new JavaGraphQLCodegen(singletonList("src/test/resources/schemas/test.graphqls"), + outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); + + File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); + assertFileContainsElements(files, "Event.java", + "@com.fasterxml.jackson.databind.annotation.JsonDeserialize(" + + "using = com.example.json.DateTimeScalarDeserializer.class)" + + System.lineSeparator() + " private org.joda.time.DateTime createdDateTime;"); + } + @Test void generate_CustomAnnotationMappings_FieldType() throws Exception { mappingConfig.setCustomTypesMapping(new HashMap<>(singletonMap("DateTime", "org.joda.time.DateTime"))); @@ -91,6 +108,23 @@ void generate_CustomAnnotationMappings_FieldType() throws Exception { + System.lineSeparator() + " private org.joda.time.DateTime createdDateTime;"); } + @Test + void generate_CustomAnnotationMappings_FieldType_Regexp() throws Exception { + mappingConfig.setCustomTypesMapping(new HashMap<>(singletonMap("DateTime", "org.joda.time.DateTime"))); + mappingConfig.setCustomAnnotationsMapping(new HashMap<>(singletonMap("Event..*Date.*", + singletonList("@com.fasterxml.jackson.databind.annotation.JsonDeserialize(" + + "using = com.example.json.DateTimeScalarDeserializer.class)")))); + + new JavaGraphQLCodegen(singletonList("src/test/resources/schemas/test.graphqls"), + outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); + + File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); + assertFileContainsElements(files, "Event.java", + "@com.fasterxml.jackson.databind.annotation.JsonDeserialize(" + + "using = com.example.json.DateTimeScalarDeserializer.class)" + + System.lineSeparator() + " private org.joda.time.DateTime createdDateTime;"); + } + @Test void generate_CustomAnnotationMappings_Class() throws Exception { Map> customAnnotationsMapping = new HashMap<>(); From 09cc22c7e8b654d164c6dd2dbe2d4b204318f510 Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Sat, 4 Sep 2021 17:43:32 +0300 Subject: [PATCH 10/23] Fix minor checkstyle issues --- .../codegen/generators/FreeMarkerTemplatesRegistry.java | 3 ++- .../generators/impl/JacksonTypeIdResolverGenerator.java | 3 ++- .../codegen/generators/impl/ParametrizedInputGenerator.java | 6 ++++-- .../graphql/codegen/model/builders/JavaDocBuilder.java | 6 ++++-- .../com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java | 3 ++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplatesRegistry.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplatesRegistry.java index 95dc3db7a..9d467641e 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplatesRegistry.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FreeMarkerTemplatesRegistry.java @@ -43,7 +43,8 @@ public static Template getTemplateWithLang(GeneratedLanguage generatedLanguage, } private static EnumMap getTemplates(Configuration configuration, - GeneratedLanguage language) throws IOException { + GeneratedLanguage language) + throws IOException { EnumMap templates = new EnumMap<>(FreeMarkerTemplateType.class); for (FreeMarkerTemplateType templateType : FreeMarkerTemplateType.values()) { templates.put(templateType, configuration.getTemplate(buildTemplatePath(templateType, language))); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/JacksonTypeIdResolverGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/JacksonTypeIdResolverGenerator.java index b466995e7..becd6f15e 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/JacksonTypeIdResolverGenerator.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/JacksonTypeIdResolverGenerator.java @@ -43,7 +43,8 @@ public List generate() { dataModel.put(CLASS_NAME, CLASS_NAME_GRAPHQL_JACKSON_TYPE_ID_RESOLVER); dataModel.put(GENERATED_ANNOTATION, mappingContext.getAddGeneratedAnnotation()); dataModel.put(GENERATED_INFO, mappingContext.getGeneratedInformation()); - File file = FreeMarkerTemplateFilesCreator.create(mappingContext, FreeMarkerTemplateType.JACKSON_TYPE_ID_RESOLVER, dataModel); + File file = FreeMarkerTemplateFilesCreator.create( + mappingContext, FreeMarkerTemplateType.JACKSON_TYPE_ID_RESOLVER, dataModel); generatedFiles.add(file); } return generatedFiles; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ParametrizedInputGenerator.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ParametrizedInputGenerator.java index 8f9cb67a7..8fa06af0c 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ParametrizedInputGenerator.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/ParametrizedInputGenerator.java @@ -62,8 +62,10 @@ private List generate(ExtendedDefinition definition, private File generate(ExtendedDefinition definition, ExtendedFieldDefinition fieldDefinition) { - Map dataModel = requestResponseDefinitionMapper.mapParametrizedInput(mappingContext, fieldDefinition, definition); - return FreeMarkerTemplateFilesCreator.create(mappingContext, FreeMarkerTemplateType.PARAMETRIZED_INPUT, dataModel); + Map dataModel = requestResponseDefinitionMapper.mapParametrizedInput( + mappingContext, fieldDefinition, definition); + return FreeMarkerTemplateFilesCreator.create( + mappingContext, FreeMarkerTemplateType.PARAMETRIZED_INPUT, dataModel); } } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java index 67a7cbd06..0f526cae6 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java @@ -24,7 +24,8 @@ public class JavaDocBuilder { * * @return List of java docs */ - public static , E extends T> List build(ExtendedDefinition extendedDefinition) { + public static , E extends T> List build( + ExtendedDefinition extendedDefinition) { List javaDocFromDescription = buildFromDescription(extendedDefinition); if (javaDocFromDescription.isEmpty()) { return buildFromComments(extendedDefinition); @@ -63,7 +64,8 @@ public static , E extends T> List buildFromDescri * * @return List of java docs */ - public static , E extends T> List buildFromComments(ExtendedDefinition extendedDefinition) { + public static , E extends T> List buildFromComments( + ExtendedDefinition extendedDefinition) { T definition = extendedDefinition.getDefinition(); List extensions = extendedDefinition.getExtensions(); diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java index 31f65554b..863e246a4 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTest.java @@ -251,7 +251,8 @@ void generate_GeneratedAnnotation() throws Exception { void generate_NoSchemas() { GeneratedInformation staticGeneratedInfo = TestUtils.getStaticGeneratedInfo(); List schemas = emptyList(); - JavaGraphQLCodegen codegen = new JavaGraphQLCodegen(schemas, outputBuildDir, mappingConfig, staticGeneratedInfo); + JavaGraphQLCodegen codegen = new JavaGraphQLCodegen( + schemas, outputBuildDir, mappingConfig, staticGeneratedInfo); assertThrows(IllegalArgumentException.class, codegen::generate); } From 36e267950f95488a52b797441a3ed9ea396deaee Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Sat, 4 Sep 2021 17:53:01 +0300 Subject: [PATCH 11/23] Fix GraphQLCodegenOpenclassesTest --- .../codegen/scala/GraphQLCodegenOpenclassesTest.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenOpenclassesTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenOpenclassesTest.java index ea3a3c49f..8cb512b0a 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenOpenclassesTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/scala/GraphQLCodegenOpenclassesTest.java @@ -45,7 +45,8 @@ void generate_MultipleInterfacesPerType() throws Exception { outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); File[] files = Objects.requireNonNull(outputScalaClassesDir.listFiles()); - assertSameTrimmedContent(new File("src/test/resources/expected-classes/scala/Commit_no_final_class.scala.txt"), + assertSameTrimmedContent( + new File("src/test/resources/expected-classes/scala/Commit_no_final_class.scala.txt"), getFileByName(files, "Commit.scala")); } @@ -56,7 +57,8 @@ void generate_MultipleInterfacesPerTypeVarFields() throws Exception { outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); File[] files = Objects.requireNonNull(outputScalaClassesDir.listFiles()); - assertSameTrimmedContent(getFileByName(files, "Commit.scala"), - new File("src/test/resources/expected-classes/scala/Commit_normal_class_var_fields.scala.txt")); + assertSameTrimmedContent( + new File("src/test/resources/expected-classes/scala/Commit_normal_class_var_fields.scala.txt"), + getFileByName(files, "Commit.scala")); } } \ No newline at end of file From 1cb802490cbe80ff9b64120330a509a5d3fd9c74 Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Sat, 4 Sep 2021 18:39:15 +0300 Subject: [PATCH 12/23] Prepare for the next release version: 5.3.0 --- build.gradle | 2 +- plugins/gradle/example-client-kotlin/build.gradle | 6 +++--- plugins/gradle/example-client/build.gradle | 4 ++-- plugins/gradle/example-server/build.gradle | 2 +- .../gradle/graphql-java-codegen-gradle-plugin/build.gradle | 2 +- plugins/maven/example-client/pom.xml | 2 +- plugins/maven/example-server/pom.xml | 2 +- plugins/maven/graphql-java-codegen-maven-plugin/pom.xml | 4 ++-- .../example-client-scala/project/plugins.sbt | 2 +- .../example-client-scala/version.sbt | 2 +- .../example-client/project/plugins.sbt | 2 +- .../graphql-codegen-sbt-plugin/example-client/version.sbt | 2 +- .../graphql-codegen-sbt-plugin/simple/project/plugins.sbt | 2 +- .../sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt | 2 +- plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt | 2 +- 15 files changed, 19 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index 04700a65c..9dd2e0e1e 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { id "org.sonarqube" version "3.2.0" } -def graphqlCodegenVersion = '5.2.1-SNAPSHOT' // This variable used in the automatic release process +def graphqlCodegenVersion = '5.3.0-SNAPSHOT' // This variable used in the automatic release process group = "io.github.kobylynskyi" version = graphqlCodegenVersion diff --git a/plugins/gradle/example-client-kotlin/build.gradle b/plugins/gradle/example-client-kotlin/build.gradle index fe23583d0..8f4a39c4a 100644 --- a/plugins/gradle/example-client-kotlin/build.gradle +++ b/plugins/gradle/example-client-kotlin/build.gradle @@ -4,10 +4,10 @@ import io.github.kobylynskyi.graphql.codegen.gradle.GraphQLCodegenGradleTask plugins { id 'java' id "org.jetbrains.kotlin.jvm" version "1.3.71" - id "io.github.kobylynskyi.graphql.codegen" version "5.2.1-SNAPSHOT" + id "io.github.kobylynskyi.graphql.codegen" version "5.3.0-SNAPSHOT" } -def graphqlCodegenClientKotlinVersion = '5.2.1-SNAPSHOT' // Variable used in the automatic release process +def graphqlCodegenClientKotlinVersion = '5.3.0-SNAPSHOT' // Variable used in the automatic release process group = 'io.github.dreamylost' version = graphqlCodegenClientKotlinVersion @@ -29,7 +29,7 @@ repositories { dependencies { - implementation "io.github.kobylynskyi:graphql-java-codegen:5.2.1-SNAPSHOT" + implementation "io.github.kobylynskyi:graphql-java-codegen:5.3.0-SNAPSHOT" implementation "javax.validation:validation-api:2.0.1.Final" implementation "com.squareup.okhttp3:okhttp:4.2.2" implementation "com.fasterxml.jackson.core:jackson-core:2.12.0" diff --git a/plugins/gradle/example-client/build.gradle b/plugins/gradle/example-client/build.gradle index e25f12db7..81d82834f 100644 --- a/plugins/gradle/example-client/build.gradle +++ b/plugins/gradle/example-client/build.gradle @@ -7,7 +7,7 @@ plugins { // use the latest available version: // https://plugins.gradle.org/plugin/io.github.kobylynskyi.graphql.codegen - id "io.github.kobylynskyi.graphql.codegen" version "5.2.1-SNAPSHOT" + id "io.github.kobylynskyi.graphql.codegen" version "5.3.0-SNAPSHOT" } mainClassName = "io.github.kobylynskyi.order.Application" @@ -22,7 +22,7 @@ dependencies { // use the latest available version: // https://search.maven.org/artifact/io.github.kobylynskyi/graphql-java-codegen - implementation "io.github.kobylynskyi:graphql-java-codegen:5.2.1-SNAPSHOT" + implementation "io.github.kobylynskyi:graphql-java-codegen:5.3.0-SNAPSHOT" implementation "org.apache.httpcomponents:httpclient:4.5.13" implementation "javax.validation:validation-api:2.0.1.Final" diff --git a/plugins/gradle/example-server/build.gradle b/plugins/gradle/example-server/build.gradle index 676c80a9c..f77596a58 100644 --- a/plugins/gradle/example-server/build.gradle +++ b/plugins/gradle/example-server/build.gradle @@ -6,7 +6,7 @@ plugins { // // use the latest available version: // https://plugins.gradle.org/plugin/io.github.kobylynskyi.graphql.codegen - id "io.github.kobylynskyi.graphql.codegen" version "5.2.1-SNAPSHOT" + id "io.github.kobylynskyi.graphql.codegen" version "5.3.0-SNAPSHOT" } mainClassName = "io.github.kobylynskyi.product.Application" diff --git a/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle b/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle index e30c216bf..9feb9b8b2 100644 --- a/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle +++ b/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle @@ -16,7 +16,7 @@ apply plugin: "java" apply plugin: "idea" apply plugin: "maven-publish" -def graphqlCodegenGradlePluginVersion = '5.2.1-SNAPSHOT' // This variable used in the automatic release process +def graphqlCodegenGradlePluginVersion = '5.3.0-SNAPSHOT' // This variable used in the automatic release process group = "io.github.kobylynskyi" version = graphqlCodegenGradlePluginVersion diff --git a/plugins/maven/example-client/pom.xml b/plugins/maven/example-client/pom.xml index 4c575f42d..8b18d8627 100644 --- a/plugins/maven/example-client/pom.xml +++ b/plugins/maven/example-client/pom.xml @@ -4,7 +4,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin-example-client - 5.2.1-SNAPSHOT + 5.3.0-SNAPSHOT graphql-codegen-maven-plugin-example-client diff --git a/plugins/maven/example-server/pom.xml b/plugins/maven/example-server/pom.xml index 153ef0b22..2642de03e 100644 --- a/plugins/maven/example-server/pom.xml +++ b/plugins/maven/example-server/pom.xml @@ -4,7 +4,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin-example-server - 5.2.1-SNAPSHOT + 5.3.0-SNAPSHOT graphql-codegen-maven-plugin-example-server diff --git a/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml b/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml index 3cd23c453..c1af4175f 100644 --- a/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml +++ b/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml @@ -3,7 +3,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin - 5.2.1-SNAPSHOT + 5.3.0-SNAPSHOT maven-plugin graphql-codegen-maven-plugin @@ -72,7 +72,7 @@ 3.0.1 3.3.4 - 5.2.1-SNAPSHOT + 5.3.0-SNAPSHOT diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt index 59e0752c7..8c5de0980 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.2.1-SNAPSHOT") +addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.3.0-SNAPSHOT") diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt index 871ee4551..097191ac4 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.2.1-SNAPSHOT" +version in ThisBuild := "5.3.0-SNAPSHOT" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt index 59e0752c7..8c5de0980 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.2.1-SNAPSHOT") +addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.3.0-SNAPSHOT") diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt index 871ee4551..097191ac4 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.2.1-SNAPSHOT" +version in ThisBuild := "5.3.0-SNAPSHOT" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt index b05df94fd..7234f0dd8 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt @@ -1,4 +1,4 @@ -sys.props.get("plugin.version").orElse(Some("5.2.1-SNAPSHOT")) match { +sys.props.get("plugin.version").orElse(Some("5.3.0-SNAPSHOT")) match { case Some(x) => addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % x) case _ => sys.error("""|The system property 'plugin.version' is not defined. |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt index 871ee4551..097191ac4 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.2.1-SNAPSHOT" +version in ThisBuild := "5.3.0-SNAPSHOT" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt index 871ee4551..097191ac4 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.2.1-SNAPSHOT" +version in ThisBuild := "5.3.0-SNAPSHOT" From 06c8bd8a5023cbab3f79bcf904463b189115e669 Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Sat, 4 Sep 2021 22:50:13 +0300 Subject: [PATCH 13/23] Minor refactor and code-style fixes --- .../generators/FilesGeneratorsFactory.java | 3 ++ .../codegen/mapper/AnnotationsMapper.java | 43 ++++++------------- ...MappingConfigDefaultValuesInitializer.java | 3 ++ .../codegen/model/MappingConfigValidator.java | 3 ++ .../graphql/codegen/model/MappingContext.java | 10 ++--- .../builders/DeprecatedDefinitionBuilder.java | 3 ++ .../model/builders/JavaDocBuilder.java | 3 ++ .../codegen/scala/ScalaAnnotationsMapper.java | 42 +++++++++--------- 8 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGeneratorsFactory.java b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGeneratorsFactory.java index 860da75d9..a444d4536 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGeneratorsFactory.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/generators/FilesGeneratorsFactory.java @@ -22,6 +22,9 @@ */ public class FilesGeneratorsFactory { + private FilesGeneratorsFactory() { + } + /** * Factory method for building files generators * diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/AnnotationsMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/AnnotationsMapper.java index f246d65c1..85f1430d5 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/AnnotationsMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/AnnotationsMapper.java @@ -87,9 +87,10 @@ public List getAnnotations(MappingContext mappingContext, String graphQL } } - // 2. Add custom annotations from the configuration - List typeAnnotations = getTypeAnnotations(mappingContext, graphQLTypeName, name, parentTypeName); - annotations.addAll(typeAnnotations); + // 2.1. Add custom annotations from the configuration for: GraphQLObjectName.fieldName + annotations.addAll(getTypeAnnotationsForKey(mappingContext, parentTypeName + "." + name)); + // 2.2. Add custom annotations from the configuration for: GraphQLTypeName + annotations.addAll(getTypeAnnotationsForKey(mappingContext, graphQLTypeName)); // 3. Add Jackson-related annotations annotations.addAll(getJacksonTypeIdAnnotations(mappingContext, def)); @@ -110,40 +111,22 @@ public List getAnnotations(MappingContext mappingContext, String graphQL return annotations; } - private List getTypeAnnotations(MappingContext mappingContext, - String graphQLType, - String fieldName, - String parentTypeName) { + private static List getTypeAnnotationsForKey(MappingContext mappingContext, + String key) { + List result = new ArrayList<>(); Map> customAnnotationsMapping = mappingContext.getCustomAnnotationsMapping(); - - List typeAnnotations = new ArrayList<>(); - - if (parentTypeName != null) { - String typeNameKey = parentTypeName + "." + fieldName; - List fullTypeAnnotations = customAnnotationsMapping.get(typeNameKey); - if (!Utils.isEmpty(fullTypeAnnotations)) { - typeAnnotations.addAll(fullTypeAnnotations); - } else { - // try finding if there's a RegEx present for this type - for (Map.Entry> entry : customAnnotationsMapping.entrySet()) { - if (typeNameKey.matches(entry.getKey()) && !Utils.isEmpty(entry.getValue())) { - typeAnnotations.addAll(entry.getValue()); - } - } - } - } - List specificTypeAnnotations = customAnnotationsMapping.get(graphQLType); - if (!Utils.isEmpty(specificTypeAnnotations)) { - typeAnnotations.addAll(specificTypeAnnotations); + List typeAnnotations = customAnnotationsMapping.get(key); + if (!Utils.isEmpty(typeAnnotations)) { + result.addAll(typeAnnotations); } else { // try finding if there's a RegEx present for this type for (Map.Entry> entry : customAnnotationsMapping.entrySet()) { - if (graphQLType.matches(entry.getKey()) && !Utils.isEmpty(entry.getValue())) { - typeAnnotations.addAll(entry.getValue()); + if (key.matches(entry.getKey()) && !Utils.isEmpty(entry.getValue())) { + result.addAll(entry.getValue()); } } } - return typeAnnotations; + return result; } private String getModelValidationAnnotation(MappingContext mappingContext, String graphQLTypeName) { diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java index 49730616d..1aa446a02 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java @@ -5,6 +5,9 @@ */ public class MappingConfigDefaultValuesInitializer { + private MappingConfigDefaultValuesInitializer() { + } + /** * Initializes mapping config with default values * diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigValidator.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigValidator.java index c2be67a5a..7783bbf91 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigValidator.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigValidator.java @@ -7,6 +7,9 @@ */ public class MappingConfigValidator { + private MappingConfigValidator() { + } + /** * Validator of the mapping config * diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java index 5b58d1d53..10d452918 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java @@ -47,10 +47,6 @@ private MappingContext(File outputDirectory, this.dataModelMapperFactory = dataModelMapperFactory; } - public static MappingContext.Builder builder() { - return new MappingContext.Builder(); - } - @Override public GeneratedLanguage getGeneratedLanguage() { return config.getGeneratedLanguage(); @@ -378,6 +374,10 @@ private List getFields(List fieldD .mapFields(this, fieldDefinitions, parentDefinition); } + public static MappingContext.Builder builder() { + return new MappingContext.Builder(); + } + /** * Builder of the mapping context */ @@ -389,7 +389,7 @@ public static class Builder { private GeneratedInformation generatedInformation; private DataModelMapperFactory dataModelMapperFactory; - public Builder() { + private Builder() { } public Builder setOutputDirectory(File outputDirectory) { diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/DeprecatedDefinitionBuilder.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/DeprecatedDefinitionBuilder.java index 48219b8a9..074107997 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/DeprecatedDefinitionBuilder.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/DeprecatedDefinitionBuilder.java @@ -19,6 +19,9 @@ public class DeprecatedDefinitionBuilder { private static final String JAVA_ANNOTATION = "Deprecated"; private static final String KOTLIN_ANNOTATION = "Deprecated"; + private DeprecatedDefinitionBuilder() { + } + /** * Get a definition of @deprecated based on a given directive * diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java index 0f526cae6..71694d8a5 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/builders/JavaDocBuilder.java @@ -18,6 +18,9 @@ */ public class JavaDocBuilder { + private JavaDocBuilder() { + } + /** * Get java doc from description of the definition and it's extensions. * If no description is present in the definition and extension then return from comments diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaAnnotationsMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaAnnotationsMapper.java index 12a7bf393..411860222 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaAnnotationsMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/scala/ScalaAnnotationsMapper.java @@ -6,8 +6,9 @@ import com.kobylynskyi.graphql.codegen.model.MappingContext; import com.kobylynskyi.graphql.codegen.utils.Utils; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Set; /** * Mapper class for converting GraphQL types to Scala types @@ -33,27 +34,28 @@ public String getJacksonResolverTypeIdAnnotation(String modelPackageName) { @Override public List getAdditionalAnnotations(MappingContext mappingContext, String typeName) { - List defaults = new ArrayList<>(); - String typeNameWithPrefixAndSuffix = (mappingContext.getModelNamePrefix() == null ? "" - : mappingContext.getModelNamePrefix()) - + typeName - + (mappingContext.getModelNameSuffix() == null ? "" : mappingContext.getModelNameSuffix()); - boolean exists = null != mappingContext.getEnumImportItSelfInScala() - && mappingContext.getEnumImportItSelfInScala() - .contains(typeNameWithPrefixAndSuffix); - // todo use switch + StringBuilder typeNameWithPrefixAndSuffixBuilder = new StringBuilder(); + if (mappingContext.getModelNamePrefix() != null) { + typeNameWithPrefixAndSuffixBuilder.append(mappingContext.getModelNamePrefix()); + } + typeNameWithPrefixAndSuffixBuilder.append(typeName); + if (mappingContext.getModelNameSuffix() != null) { + typeNameWithPrefixAndSuffixBuilder.append(mappingContext.getModelNameSuffix()); + } + Set enumImportItSelf = mappingContext.getEnumImportItSelfInScala(); + if (enumImportItSelf == null || + !enumImportItSelf.contains(typeNameWithPrefixAndSuffixBuilder.toString())) { + return Collections.emptyList(); + } // Inspired by the pr https://github.com/kobylynskyi/graphql-java-codegen/pull/637/files - if (exists) { - String modelPackageName = DataModelMapper.getModelPackageName(mappingContext); - if (modelPackageName == null) { - modelPackageName = ""; - } else if (Utils.isNotBlank(modelPackageName)) { - modelPackageName += "."; - } - defaults.add("com.fasterxml.jackson.module.scala.JsonScalaEnumeration(classOf[" + modelPackageName - + typeNameWithPrefixAndSuffix + "TypeRefer])"); + String modelPackageName = DataModelMapper.getModelPackageName(mappingContext); + if (Utils.isNotBlank(modelPackageName)) { + typeNameWithPrefixAndSuffixBuilder.insert(0, modelPackageName + "."); } - return defaults; + String annotation = String.format( + "com.fasterxml.jackson.module.scala.JsonScalaEnumeration(classOf[%sTypeRefer])", + typeNameWithPrefixAndSuffixBuilder); + return Collections.singletonList(annotation); } @Override From cbd9f647627670ee9a1e07178b22aa90b0b29762 Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Sun, 5 Sep 2021 21:10:54 +0300 Subject: [PATCH 14/23] Bump version to 5.3.0 - release --- build.gradle | 2 +- plugins/gradle/README.md | 4 ++-- plugins/gradle/example-client-kotlin/build.gradle | 6 +++--- plugins/gradle/example-client/build.gradle | 4 ++-- plugins/gradle/example-server/build.gradle | 2 +- .../gradle/graphql-java-codegen-gradle-plugin/build.gradle | 2 +- plugins/maven/README.md | 2 +- plugins/maven/example-client/pom.xml | 2 +- plugins/maven/example-server/pom.xml | 2 +- plugins/maven/graphql-java-codegen-maven-plugin/pom.xml | 4 ++-- .../example-client-scala/project/plugins.sbt | 2 +- .../example-client-scala/version.sbt | 2 +- .../example-client/project/plugins.sbt | 2 +- .../graphql-codegen-sbt-plugin/example-client/version.sbt | 2 +- .../graphql-codegen-sbt-plugin/simple/project/plugins.sbt | 2 +- .../sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt | 2 +- plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt | 2 +- 17 files changed, 22 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index 9dd2e0e1e..244b5d602 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { id "org.sonarqube" version "3.2.0" } -def graphqlCodegenVersion = '5.3.0-SNAPSHOT' // This variable used in the automatic release process +def graphqlCodegenVersion = '5.3.0' // This variable used in the automatic release process group = "io.github.kobylynskyi" version = graphqlCodegenVersion diff --git a/plugins/gradle/README.md b/plugins/gradle/README.md index 9de452060..635c913ea 100644 --- a/plugins/gradle/README.md +++ b/plugins/gradle/README.md @@ -17,7 +17,7 @@ ```groovy plugins { - id "io.github.kobylynskyi.graphql.codegen" version "5.2.0" + id "io.github.kobylynskyi.graphql.codegen" version "5.3.0" } ``` @@ -31,7 +31,7 @@ buildscript { } } dependencies { - classpath "io.github.kobylynskyi.graphql.codegen:graphql-codegen-gradle-plugin:5.2.0" + classpath "io.github.kobylynskyi.graphql.codegen:graphql-codegen-gradle-plugin:5.3.0" } } diff --git a/plugins/gradle/example-client-kotlin/build.gradle b/plugins/gradle/example-client-kotlin/build.gradle index 8f4a39c4a..0ab0ccce3 100644 --- a/plugins/gradle/example-client-kotlin/build.gradle +++ b/plugins/gradle/example-client-kotlin/build.gradle @@ -4,10 +4,10 @@ import io.github.kobylynskyi.graphql.codegen.gradle.GraphQLCodegenGradleTask plugins { id 'java' id "org.jetbrains.kotlin.jvm" version "1.3.71" - id "io.github.kobylynskyi.graphql.codegen" version "5.3.0-SNAPSHOT" + id "io.github.kobylynskyi.graphql.codegen" version "5.3.0" } -def graphqlCodegenClientKotlinVersion = '5.3.0-SNAPSHOT' // Variable used in the automatic release process +def graphqlCodegenClientKotlinVersion = '5.3.0' // Variable used in the automatic release process group = 'io.github.dreamylost' version = graphqlCodegenClientKotlinVersion @@ -29,7 +29,7 @@ repositories { dependencies { - implementation "io.github.kobylynskyi:graphql-java-codegen:5.3.0-SNAPSHOT" + implementation "io.github.kobylynskyi:graphql-java-codegen:5.3.0" implementation "javax.validation:validation-api:2.0.1.Final" implementation "com.squareup.okhttp3:okhttp:4.2.2" implementation "com.fasterxml.jackson.core:jackson-core:2.12.0" diff --git a/plugins/gradle/example-client/build.gradle b/plugins/gradle/example-client/build.gradle index 81d82834f..fa7573f53 100644 --- a/plugins/gradle/example-client/build.gradle +++ b/plugins/gradle/example-client/build.gradle @@ -7,7 +7,7 @@ plugins { // use the latest available version: // https://plugins.gradle.org/plugin/io.github.kobylynskyi.graphql.codegen - id "io.github.kobylynskyi.graphql.codegen" version "5.3.0-SNAPSHOT" + id "io.github.kobylynskyi.graphql.codegen" version "5.3.0" } mainClassName = "io.github.kobylynskyi.order.Application" @@ -22,7 +22,7 @@ dependencies { // use the latest available version: // https://search.maven.org/artifact/io.github.kobylynskyi/graphql-java-codegen - implementation "io.github.kobylynskyi:graphql-java-codegen:5.3.0-SNAPSHOT" + implementation "io.github.kobylynskyi:graphql-java-codegen:5.3.0" implementation "org.apache.httpcomponents:httpclient:4.5.13" implementation "javax.validation:validation-api:2.0.1.Final" diff --git a/plugins/gradle/example-server/build.gradle b/plugins/gradle/example-server/build.gradle index f77596a58..34e4492f2 100644 --- a/plugins/gradle/example-server/build.gradle +++ b/plugins/gradle/example-server/build.gradle @@ -6,7 +6,7 @@ plugins { // // use the latest available version: // https://plugins.gradle.org/plugin/io.github.kobylynskyi.graphql.codegen - id "io.github.kobylynskyi.graphql.codegen" version "5.3.0-SNAPSHOT" + id "io.github.kobylynskyi.graphql.codegen" version "5.3.0" } mainClassName = "io.github.kobylynskyi.product.Application" diff --git a/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle b/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle index 9feb9b8b2..7e04ddbfc 100644 --- a/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle +++ b/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle @@ -16,7 +16,7 @@ apply plugin: "java" apply plugin: "idea" apply plugin: "maven-publish" -def graphqlCodegenGradlePluginVersion = '5.3.0-SNAPSHOT' // This variable used in the automatic release process +def graphqlCodegenGradlePluginVersion = '5.3.0' // This variable used in the automatic release process group = "io.github.kobylynskyi" version = graphqlCodegenGradlePluginVersion diff --git a/plugins/maven/README.md b/plugins/maven/README.md index 5f8b825f8..edcd653c8 100644 --- a/plugins/maven/README.md +++ b/plugins/maven/README.md @@ -20,7 +20,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin - 5.2.0 + 5.3.0 diff --git a/plugins/maven/example-client/pom.xml b/plugins/maven/example-client/pom.xml index 8b18d8627..d665e5c31 100644 --- a/plugins/maven/example-client/pom.xml +++ b/plugins/maven/example-client/pom.xml @@ -4,7 +4,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin-example-client - 5.3.0-SNAPSHOT + 5.3.0 graphql-codegen-maven-plugin-example-client diff --git a/plugins/maven/example-server/pom.xml b/plugins/maven/example-server/pom.xml index 2642de03e..6d001ca7c 100644 --- a/plugins/maven/example-server/pom.xml +++ b/plugins/maven/example-server/pom.xml @@ -4,7 +4,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin-example-server - 5.3.0-SNAPSHOT + 5.3.0 graphql-codegen-maven-plugin-example-server diff --git a/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml b/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml index c1af4175f..553c0bdfb 100644 --- a/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml +++ b/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml @@ -3,7 +3,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin - 5.3.0-SNAPSHOT + 5.3.0 maven-plugin graphql-codegen-maven-plugin @@ -72,7 +72,7 @@ 3.0.1 3.3.4 - 5.3.0-SNAPSHOT + 5.3.0 diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt index 8c5de0980..0cf2afa22 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.3.0-SNAPSHOT") +addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.3.0") diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt index 097191ac4..385e378a3 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.3.0-SNAPSHOT" +version in ThisBuild := "5.3.0" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt index 8c5de0980..0cf2afa22 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.3.0-SNAPSHOT") +addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.3.0") diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt index 097191ac4..385e378a3 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.3.0-SNAPSHOT" +version in ThisBuild := "5.3.0" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt index 7234f0dd8..79367de42 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt @@ -1,4 +1,4 @@ -sys.props.get("plugin.version").orElse(Some("5.3.0-SNAPSHOT")) match { +sys.props.get("plugin.version").orElse(Some("5.3.0")) match { case Some(x) => addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % x) case _ => sys.error("""|The system property 'plugin.version' is not defined. |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt index 097191ac4..385e378a3 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.3.0-SNAPSHOT" +version in ThisBuild := "5.3.0" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt index 097191ac4..385e378a3 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.3.0-SNAPSHOT" +version in ThisBuild := "5.3.0" From 69dee51d27637bf4087044786aa9bdfc04f0a848 Mon Sep 17 00:00:00 2001 From: rolevinks <78790667+rolevinks@users.noreply.github.com> Date: Sun, 7 Nov 2021 01:22:49 +0100 Subject: [PATCH 15/23] Add serialVersionUID to generated classes that implement Serializable (#811) Co-authored-by: Bogdan Kobylynskyi <92bogdan@gmail.com> Co-authored-by: Stein Rolevink --- plugins/maven/graphql-java-codegen-maven-plugin/pom.xml | 2 +- src/main/resources/templates/java-lang/type.ftl | 2 ++ .../resources/expected-classes/CommentDeletedEvent.java.txt | 4 +++- src/test/resources/expected-classes/Commit.java.txt | 4 +++- .../expected-classes/Commit_noParametrizedFields.java.txt | 4 +++- .../expected-classes/Commit_noValidationAnnotation.java.txt | 4 +++- .../expected-classes/Commit_withoutPrimitives.java.txt | 4 +++- src/test/resources/expected-classes/Event.java.txt | 4 +++- src/test/resources/expected-classes/EventProperty.java.txt | 4 +++- .../expected-classes/EventPropertyTO_toString.java.txt | 4 +++- .../EventPropertyTO_withEqualsAndHashCode.java.txt | 4 +++- .../EventPropertyTO_withoutGeneratedAnnotation.java.txt | 2 ++ src/test/resources/expected-classes/Event_noBuilder.java.txt | 4 +++- .../GithubAcceptTopicSuggestionInputTO.java.txt | 4 +++- .../GithubAcceptTopicSuggestionPayloadTO.java.txt | 4 +++- src/test/resources/expected-classes/GithubCommitTO.java.txt | 4 +++- src/test/resources/expected-classes/Person.java.txt | 2 ++ src/test/resources/expected-classes/Person1.java.txt | 4 +++- src/test/resources/expected-classes/UnionMember1.java.txt | 4 +++- src/test/resources/expected-classes/UnionMember2.java.txt | 4 +++- src/test/resources/expected-classes/User.java.txt | 2 ++ .../expected-classes/annotation/EventProperty.java.txt | 4 +++- src/test/resources/expected-classes/annotation/User.java.txt | 2 ++ .../custom-type/ResponseContainingDate.java.txt | 4 +++- .../expected-classes/defaults/InputWithDefaults.java.txt | 4 +++- .../expected-classes/defaults/InputWithDefaultsDTO.java.txt | 2 ++ .../expected-classes/defaults/InputWithDefaultsTO.java.txt | 4 +++- .../resources/expected-classes/defaults/SomeObject.java.txt | 4 +++- .../expected-classes/defaults/SomeObjectDTO.java.txt | 2 ++ .../resources/expected-classes/defaults/SomeObjectTO.java.txt | 4 +++- src/test/resources/expected-classes/deprecated/Event.java.txt | 4 +++- .../resources/expected-classes/deprecated/EventInput.java.txt | 4 +++- src/test/resources/expected-classes/empty/Event.java.txt | 4 +++- src/test/resources/expected-classes/empty/EventInput.java.txt | 4 +++- .../expected-classes/extend-with-resolvers/Asset.java.txt | 4 +++- .../extend-with-resolvers/AssetInput.java.txt | 2 ++ .../expected-classes/extend-with-resolvers/Event.java.txt | 4 +++- .../extend-with-resolvers/EventInput.java.txt | 2 ++ src/test/resources/expected-classes/extend/Asset.java.txt | 4 +++- .../resources/expected-classes/extend/AssetInput.java.txt | 2 ++ src/test/resources/expected-classes/extend/Event.java.txt | 4 +++- .../resources/expected-classes/extend/EventInput.java.txt | 2 ++ .../from-introspection-result/Product.java.txt | 2 ++ .../from-introspection-result/ProductInput.java.txt | 2 ++ src/test/resources/expected-classes/immutable/Event.java.txt | 4 +++- src/test/resources/expected-classes/interfaces/Bar1.java.txt | 4 +++- src/test/resources/expected-classes/interfaces/Foo1.java.txt | 4 +++- .../jackson-resolver-union/UnionMemberA.java.txt | 4 +++- .../jackson-resolver-union/UnionMemberB.java.txt | 4 +++- .../without-model-package/MyUnionMemberASuffix.java.txt | 4 +++- .../without-model-package/MyUnionMemberBSuffix.java.txt | 4 +++- .../expected-classes/optional/TypeWithMandatoryField.java.txt | 4 +++- .../resources/expected-classes/relay/Organization.java.txt | 2 ++ src/test/resources/expected-classes/relay/User.java.txt | 2 ++ .../request/AcceptTopicSuggestionInput.java.txt | 4 +++- .../Event_useObjectMapperForRequestSerialization.java.txt | 4 +++- src/test/resources/expected-classes/resolvers/Event.java.txt | 2 ++ .../expected-classes/resolvers/EventProperty.java.txt | 4 +++- .../expected-classes/restricted-words/Query.java.txt | 4 +++- .../expected-classes/restricted-words/Synchronized.java.txt | 4 +++- .../types-as-interfaces-extends-interface/Profile.java.txt | 2 ++ 61 files changed, 164 insertions(+), 44 deletions(-) diff --git a/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml b/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml index 828af36fc..cceb650f9 100644 --- a/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml +++ b/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml @@ -36,7 +36,7 @@ scm:git:git@github.com:kobylynskyi/graphql-java-codegen.git https://github.com/kobylynskyi/graphql-java-codegen/tree/master/plugins/maven - v5.3.0 + HEAD diff --git a/src/main/resources/templates/java-lang/type.ftl b/src/main/resources/templates/java-lang/type.ftl index 242764d01..8b3e56187 100644 --- a/src/main/resources/templates/java-lang/type.ftl +++ b/src/main/resources/templates/java-lang/type.ftl @@ -36,6 +36,8 @@ import java.util.StringJoiner; public class ${className} implements java.io.Serializable<#if implements?has_content><#list implements as interface>, ${interface}<#if interface_has_next> { + private static final long serialVersionUID = 1L; + <#if fields?has_content> <#list fields as field> <#if field.deprecated?has_content> diff --git a/src/test/resources/expected-classes/CommentDeletedEvent.java.txt b/src/test/resources/expected-classes/CommentDeletedEvent.java.txt index 788076193..f24977a86 100644 --- a/src/test/resources/expected-classes/CommentDeletedEvent.java.txt +++ b/src/test/resources/expected-classes/CommentDeletedEvent.java.txt @@ -7,6 +7,8 @@ package com.github.graphql; ) public class CommentDeletedEvent implements java.io.Serializable, IssueTimelineItems, PullRequestTimelineItems, Node { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String id; @@ -48,4 +50,4 @@ public class CommentDeletedEvent implements java.io.Serializable, IssueTimelineI } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/Commit.java.txt b/src/test/resources/expected-classes/Commit.java.txt index 627b2bd0d..2cfc3ea36 100644 --- a/src/test/resources/expected-classes/Commit.java.txt +++ b/src/test/resources/expected-classes/Commit.java.txt @@ -7,6 +7,8 @@ package com.github.graphql; ) public class Commit implements java.io.Serializable, Closer, IssueTimelineItem, PullRequestTimelineItem, Subscribable, Node, GitObject, UniformResourceLocatable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String abbreviatedOid; private int additions; @@ -626,4 +628,4 @@ public class Commit implements java.io.Serializable, Closer, IssueTimelineItem, } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/Commit_noParametrizedFields.java.txt b/src/test/resources/expected-classes/Commit_noParametrizedFields.java.txt index 16d2a2927..cd09b1dc6 100644 --- a/src/test/resources/expected-classes/Commit_noParametrizedFields.java.txt +++ b/src/test/resources/expected-classes/Commit_noParametrizedFields.java.txt @@ -7,6 +7,8 @@ package com.github.graphql; ) public class Commit implements java.io.Serializable, Closer, IssueTimelineItem, PullRequestTimelineItem, Subscribable, Node, GitObject, UniformResourceLocatable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String abbreviatedOid; private int additions; @@ -532,4 +534,4 @@ public class Commit implements java.io.Serializable, Closer, IssueTimelineItem, } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/Commit_noValidationAnnotation.java.txt b/src/test/resources/expected-classes/Commit_noValidationAnnotation.java.txt index d9a7f550a..d572b6e05 100644 --- a/src/test/resources/expected-classes/Commit_noValidationAnnotation.java.txt +++ b/src/test/resources/expected-classes/Commit_noValidationAnnotation.java.txt @@ -7,6 +7,8 @@ package com.github.graphql; ) public class Commit implements java.io.Serializable, Closer, IssueTimelineItem, PullRequestTimelineItem, Subscribable, Node, GitObject, UniformResourceLocatable { + private static final long serialVersionUID = 1L; + private String abbreviatedOid; private int additions; private PullRequestConnection associatedPullRequests; @@ -602,4 +604,4 @@ public class Commit implements java.io.Serializable, Closer, IssueTimelineItem, } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/Commit_withoutPrimitives.java.txt b/src/test/resources/expected-classes/Commit_withoutPrimitives.java.txt index 443487912..91a88e054 100644 --- a/src/test/resources/expected-classes/Commit_withoutPrimitives.java.txt +++ b/src/test/resources/expected-classes/Commit_withoutPrimitives.java.txt @@ -7,6 +7,8 @@ package com.github.graphql; ) public class Commit implements java.io.Serializable, Closer, IssueTimelineItem, PullRequestTimelineItem, Subscribable, Node, GitObject, UniformResourceLocatable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String abbreviatedOid; @javax.validation.constraints.NotNull @@ -632,4 +634,4 @@ public class Commit implements java.io.Serializable, Closer, IssueTimelineItem, } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/Event.java.txt b/src/test/resources/expected-classes/Event.java.txt index b9cd645b0..68416933d 100644 --- a/src/test/resources/expected-classes/Event.java.txt +++ b/src/test/resources/expected-classes/Event.java.txt @@ -10,6 +10,8 @@ package com.kobylynskyi.graphql.test1; ) public class Event implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String id; private String categoryId; private java.util.List properties; @@ -155,4 +157,4 @@ public class Event implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/EventProperty.java.txt b/src/test/resources/expected-classes/EventProperty.java.txt index aa9c6ff21..4664c762c 100644 --- a/src/test/resources/expected-classes/EventProperty.java.txt +++ b/src/test/resources/expected-classes/EventProperty.java.txt @@ -10,6 +10,8 @@ package com.kobylynskyi.graphql.test1; ) public class EventProperty implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private Double floatVal; private Boolean booleanVal; private int intVal; @@ -188,4 +190,4 @@ public class EventProperty implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/EventPropertyTO_toString.java.txt b/src/test/resources/expected-classes/EventPropertyTO_toString.java.txt index ca7cc374c..2fd460a42 100644 --- a/src/test/resources/expected-classes/EventPropertyTO_toString.java.txt +++ b/src/test/resources/expected-classes/EventPropertyTO_toString.java.txt @@ -11,6 +11,8 @@ import java.util.StringJoiner; ) public class EventPropertyTO implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private Double floatVal; private Boolean booleanVal; private int intVal; @@ -213,4 +215,4 @@ public class EventPropertyTO implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/EventPropertyTO_withEqualsAndHashCode.java.txt b/src/test/resources/expected-classes/EventPropertyTO_withEqualsAndHashCode.java.txt index cafb7d5d8..62eb0e4cc 100644 --- a/src/test/resources/expected-classes/EventPropertyTO_withEqualsAndHashCode.java.txt +++ b/src/test/resources/expected-classes/EventPropertyTO_withEqualsAndHashCode.java.txt @@ -11,6 +11,8 @@ import java.util.Objects; ) public class EventPropertyTO implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private Double floatVal; private Boolean booleanVal; private int intVal; @@ -211,4 +213,4 @@ public class EventPropertyTO implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/EventPropertyTO_withoutGeneratedAnnotation.java.txt b/src/test/resources/expected-classes/EventPropertyTO_withoutGeneratedAnnotation.java.txt index 109d91bed..125d19b7a 100644 --- a/src/test/resources/expected-classes/EventPropertyTO_withoutGeneratedAnnotation.java.txt +++ b/src/test/resources/expected-classes/EventPropertyTO_withoutGeneratedAnnotation.java.txt @@ -6,6 +6,8 @@ package com.kobylynskyi.graphql.test1; */ public class EventPropertyTO implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private Double floatVal; private Boolean booleanVal; private int intVal; diff --git a/src/test/resources/expected-classes/Event_noBuilder.java.txt b/src/test/resources/expected-classes/Event_noBuilder.java.txt index 8e2dd4088..14ff02763 100644 --- a/src/test/resources/expected-classes/Event_noBuilder.java.txt +++ b/src/test/resources/expected-classes/Event_noBuilder.java.txt @@ -10,6 +10,8 @@ package com.kobylynskyi.graphql.test1; ) public class Event implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String id; private String categoryId; private java.util.List properties; @@ -91,4 +93,4 @@ public class Event implements java.io.Serializable { -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/GithubAcceptTopicSuggestionInputTO.java.txt b/src/test/resources/expected-classes/GithubAcceptTopicSuggestionInputTO.java.txt index 5281447b8..f86c24c18 100644 --- a/src/test/resources/expected-classes/GithubAcceptTopicSuggestionInputTO.java.txt +++ b/src/test/resources/expected-classes/GithubAcceptTopicSuggestionInputTO.java.txt @@ -7,6 +7,8 @@ package com.github.graphql; ) public class GithubAcceptTopicSuggestionInputTO implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String clientMutationId; @javax.validation.constraints.NotNull private String name; @@ -79,4 +81,4 @@ public class GithubAcceptTopicSuggestionInputTO implements java.io.Serializable } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/GithubAcceptTopicSuggestionPayloadTO.java.txt b/src/test/resources/expected-classes/GithubAcceptTopicSuggestionPayloadTO.java.txt index bf5ab23fc..aabd7984b 100644 --- a/src/test/resources/expected-classes/GithubAcceptTopicSuggestionPayloadTO.java.txt +++ b/src/test/resources/expected-classes/GithubAcceptTopicSuggestionPayloadTO.java.txt @@ -7,6 +7,8 @@ package com.github.graphql; ) public class GithubAcceptTopicSuggestionPayloadTO implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String clientMutationId; public GithubAcceptTopicSuggestionPayloadTO() { @@ -47,4 +49,4 @@ public class GithubAcceptTopicSuggestionPayloadTO implements java.io.Serializabl } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/GithubCommitTO.java.txt b/src/test/resources/expected-classes/GithubCommitTO.java.txt index 3cfef2926..dda379ef9 100644 --- a/src/test/resources/expected-classes/GithubCommitTO.java.txt +++ b/src/test/resources/expected-classes/GithubCommitTO.java.txt @@ -7,6 +7,8 @@ package com.github.graphql; ) public class GithubCommitTO implements java.io.Serializable, GithubCloserTO, GithubIssueTimelineItemTO, GithubPullRequestTimelineItemTO, GithubGitObjectTO, GithubNodeTO, GithubSubscribableTO, GithubUniformResourceLocatableTO { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String abbreviatedOid; private int additions; @@ -626,4 +628,4 @@ public class GithubCommitTO implements java.io.Serializable, GithubCloserTO, Git } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/Person.java.txt b/src/test/resources/expected-classes/Person.java.txt index c3b6f602d..e8e9582e5 100644 --- a/src/test/resources/expected-classes/Person.java.txt +++ b/src/test/resources/expected-classes/Person.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.test1; ) public class Person implements java.io.Serializable, NamedEntity { + private static final long serialVersionUID = 1L; + private String name; private Integer age; diff --git a/src/test/resources/expected-classes/Person1.java.txt b/src/test/resources/expected-classes/Person1.java.txt index 705249908..89ae390c1 100644 --- a/src/test/resources/expected-classes/Person1.java.txt +++ b/src/test/resources/expected-classes/Person1.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.test1; ) public class Person implements java.io.Serializable, NamedEntity { + private static final long serialVersionUID = 1L; + @Deprecated private String name; private Integer age; @@ -84,4 +86,4 @@ public class Person implements java.io.Serializable, NamedEntity { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/UnionMember1.java.txt b/src/test/resources/expected-classes/UnionMember1.java.txt index bfc48ca6b..ed5861b45 100644 --- a/src/test/resources/expected-classes/UnionMember1.java.txt +++ b/src/test/resources/expected-classes/UnionMember1.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.multifiles; ) public class UnionMember1 implements java.io.Serializable, MyUnion { + private static final long serialVersionUID = 1L; + private Integer someField; public UnionMember1() { @@ -47,4 +49,4 @@ public class UnionMember1 implements java.io.Serializable, MyUnion { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/UnionMember2.java.txt b/src/test/resources/expected-classes/UnionMember2.java.txt index f17773cfb..001659317 100644 --- a/src/test/resources/expected-classes/UnionMember2.java.txt +++ b/src/test/resources/expected-classes/UnionMember2.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.multifiles; ) public class UnionMember2 implements java.io.Serializable, MyUnion { + private static final long serialVersionUID = 1L; + private String someField; public UnionMember2() { @@ -47,4 +49,4 @@ public class UnionMember2 implements java.io.Serializable, MyUnion { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/User.java.txt b/src/test/resources/expected-classes/User.java.txt index 2c76824b2..3962e4311 100644 --- a/src/test/resources/expected-classes/User.java.txt +++ b/src/test/resources/expected-classes/User.java.txt @@ -10,6 +10,8 @@ package com.kobylynskyi.graphql.test1; ) public class User implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String name; private java.util.List friends; diff --git a/src/test/resources/expected-classes/annotation/EventProperty.java.txt b/src/test/resources/expected-classes/annotation/EventProperty.java.txt index 014aedb06..12bbcb787 100644 --- a/src/test/resources/expected-classes/annotation/EventProperty.java.txt +++ b/src/test/resources/expected-classes/annotation/EventProperty.java.txt @@ -11,6 +11,8 @@ package com.kobylynskyi.graphql.test1; @com.example.CustomAnnotation public class EventProperty implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private Double floatVal; private Boolean booleanVal; private int intVal; @@ -189,4 +191,4 @@ public class EventProperty implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/annotation/User.java.txt b/src/test/resources/expected-classes/annotation/User.java.txt index 2ef170f20..4dd342bb4 100644 --- a/src/test/resources/expected-classes/annotation/User.java.txt +++ b/src/test/resources/expected-classes/annotation/User.java.txt @@ -10,6 +10,8 @@ package com.kobylynskyi.graphql.test1; ) public class User implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String name; @com.example.Relationship(type = "FRIEND_WITH", direction = OUT) private java.util.List friends; diff --git a/src/test/resources/expected-classes/custom-type/ResponseContainingDate.java.txt b/src/test/resources/expected-classes/custom-type/ResponseContainingDate.java.txt index 5aec90729..a0023bb01 100644 --- a/src/test/resources/expected-classes/custom-type/ResponseContainingDate.java.txt +++ b/src/test/resources/expected-classes/custom-type/ResponseContainingDate.java.txt @@ -9,6 +9,8 @@ import java.util.StringJoiner; ) public class ResponseContainingDate implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private java.time.ZonedDateTime a; public ResponseContainingDate() { @@ -57,4 +59,4 @@ public class ResponseContainingDate implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/defaults/InputWithDefaults.java.txt b/src/test/resources/expected-classes/defaults/InputWithDefaults.java.txt index 5a906e4e9..91bd5111e 100644 --- a/src/test/resources/expected-classes/defaults/InputWithDefaults.java.txt +++ b/src/test/resources/expected-classes/defaults/InputWithDefaults.java.txt @@ -10,6 +10,8 @@ package com.kobylynskyi.graphql.testdefaults; ) public class InputWithDefaults implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private Double floatVal = 1.23; private Boolean booleanVal = false; private Integer intVal = 42; @@ -202,4 +204,4 @@ public class InputWithDefaults implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/defaults/InputWithDefaultsDTO.java.txt b/src/test/resources/expected-classes/defaults/InputWithDefaultsDTO.java.txt index 8d92b9718..3f20b4cac 100644 --- a/src/test/resources/expected-classes/defaults/InputWithDefaultsDTO.java.txt +++ b/src/test/resources/expected-classes/defaults/InputWithDefaultsDTO.java.txt @@ -10,6 +10,8 @@ package com.kobylynskyi.graphql.testdefaults; ) public class InputWithDefaultsDTO implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private Double floatVal = 1.23; private Boolean booleanVal = false; private Integer intVal = 42; diff --git a/src/test/resources/expected-classes/defaults/InputWithDefaultsTO.java.txt b/src/test/resources/expected-classes/defaults/InputWithDefaultsTO.java.txt index 1777c0864..1505e9ee9 100644 --- a/src/test/resources/expected-classes/defaults/InputWithDefaultsTO.java.txt +++ b/src/test/resources/expected-classes/defaults/InputWithDefaultsTO.java.txt @@ -10,6 +10,8 @@ package com.kobylynskyi.graphql.testdefaults; ) public class InputWithDefaultsTO implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private Double floatVal = 1.23; private Boolean booleanVal = false; private Integer intVal = 42; @@ -202,4 +204,4 @@ public class InputWithDefaultsTO implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/defaults/SomeObject.java.txt b/src/test/resources/expected-classes/defaults/SomeObject.java.txt index 380b17f37..eb21593b3 100644 --- a/src/test/resources/expected-classes/defaults/SomeObject.java.txt +++ b/src/test/resources/expected-classes/defaults/SomeObject.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.testdefaults; ) public class SomeObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String name; @@ -48,4 +50,4 @@ public class SomeObject implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/defaults/SomeObjectDTO.java.txt b/src/test/resources/expected-classes/defaults/SomeObjectDTO.java.txt index 6acb509f6..3ed8cd5bd 100644 --- a/src/test/resources/expected-classes/defaults/SomeObjectDTO.java.txt +++ b/src/test/resources/expected-classes/defaults/SomeObjectDTO.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.testdefaults; ) public class SomeObjectDTO implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String name; diff --git a/src/test/resources/expected-classes/defaults/SomeObjectTO.java.txt b/src/test/resources/expected-classes/defaults/SomeObjectTO.java.txt index 1f3cc1783..6976c23b3 100644 --- a/src/test/resources/expected-classes/defaults/SomeObjectTO.java.txt +++ b/src/test/resources/expected-classes/defaults/SomeObjectTO.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.testdefaults; ) public class SomeObjectTO implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String name; @@ -48,4 +50,4 @@ public class SomeObjectTO implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/deprecated/Event.java.txt b/src/test/resources/expected-classes/deprecated/Event.java.txt index db54f5879..f8da8351c 100644 --- a/src/test/resources/expected-classes/deprecated/Event.java.txt +++ b/src/test/resources/expected-classes/deprecated/Event.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.test1; ) public class Event implements java.io.Serializable, PinnableItem, Node { + private static final long serialVersionUID = 1L; + @Deprecated @javax.validation.constraints.NotNull private Status status; @@ -92,4 +94,4 @@ public class Event implements java.io.Serializable, PinnableItem, Node { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/deprecated/EventInput.java.txt b/src/test/resources/expected-classes/deprecated/EventInput.java.txt index c901f3d15..89e47d0a2 100644 --- a/src/test/resources/expected-classes/deprecated/EventInput.java.txt +++ b/src/test/resources/expected-classes/deprecated/EventInput.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.test1; ) public class EventInput implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @Deprecated @javax.validation.constraints.NotNull private Status status; @@ -52,4 +54,4 @@ public class EventInput implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/empty/Event.java.txt b/src/test/resources/expected-classes/empty/Event.java.txt index bb1c08135..578790df8 100644 --- a/src/test/resources/expected-classes/empty/Event.java.txt +++ b/src/test/resources/expected-classes/empty/Event.java.txt @@ -4,6 +4,8 @@ ) public class Event implements java.io.Serializable { + private static final long serialVersionUID = 1L; + public Event() { } @@ -27,4 +29,4 @@ public class Event implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/empty/EventInput.java.txt b/src/test/resources/expected-classes/empty/EventInput.java.txt index ee22ff655..c5aff43c5 100644 --- a/src/test/resources/expected-classes/empty/EventInput.java.txt +++ b/src/test/resources/expected-classes/empty/EventInput.java.txt @@ -4,6 +4,8 @@ ) public class EventInput implements java.io.Serializable { + private static final long serialVersionUID = 1L; + public EventInput() { } @@ -27,4 +29,4 @@ public class EventInput implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/extend-with-resolvers/Asset.java.txt b/src/test/resources/expected-classes/extend-with-resolvers/Asset.java.txt index 7ef0a174f..f69c36721 100644 --- a/src/test/resources/expected-classes/extend-with-resolvers/Asset.java.txt +++ b/src/test/resources/expected-classes/extend-with-resolvers/Asset.java.txt @@ -4,6 +4,8 @@ ) public class Asset implements java.io.Serializable, PinnableItem, Node { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String name; @javax.validation.constraints.NotNull @@ -77,4 +79,4 @@ public class Asset implements java.io.Serializable, PinnableItem, Node { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/extend-with-resolvers/AssetInput.java.txt b/src/test/resources/expected-classes/extend-with-resolvers/AssetInput.java.txt index 1528e114d..5a41c1c66 100644 --- a/src/test/resources/expected-classes/extend-with-resolvers/AssetInput.java.txt +++ b/src/test/resources/expected-classes/extend-with-resolvers/AssetInput.java.txt @@ -4,6 +4,8 @@ ) public class AssetInput implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String name; diff --git a/src/test/resources/expected-classes/extend-with-resolvers/Event.java.txt b/src/test/resources/expected-classes/extend-with-resolvers/Event.java.txt index 8e2f71c0f..624ecde90 100644 --- a/src/test/resources/expected-classes/extend-with-resolvers/Event.java.txt +++ b/src/test/resources/expected-classes/extend-with-resolvers/Event.java.txt @@ -4,6 +4,8 @@ ) public class Event implements java.io.Serializable, PinnableItem, Node { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private Status status; @javax.validation.constraints.NotNull @@ -77,4 +79,4 @@ public class Event implements java.io.Serializable, PinnableItem, Node { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/extend-with-resolvers/EventInput.java.txt b/src/test/resources/expected-classes/extend-with-resolvers/EventInput.java.txt index 201223773..56b4d5269 100644 --- a/src/test/resources/expected-classes/extend-with-resolvers/EventInput.java.txt +++ b/src/test/resources/expected-classes/extend-with-resolvers/EventInput.java.txt @@ -4,6 +4,8 @@ ) public class EventInput implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private Status status; @javax.validation.constraints.NotNull diff --git a/src/test/resources/expected-classes/extend/Asset.java.txt b/src/test/resources/expected-classes/extend/Asset.java.txt index bfa05b522..705faca56 100644 --- a/src/test/resources/expected-classes/extend/Asset.java.txt +++ b/src/test/resources/expected-classes/extend/Asset.java.txt @@ -4,6 +4,8 @@ ) public class Asset implements java.io.Serializable, PinnableItem, Node { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String name; @javax.validation.constraints.NotNull @@ -92,4 +94,4 @@ public class Asset implements java.io.Serializable, PinnableItem, Node { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/extend/AssetInput.java.txt b/src/test/resources/expected-classes/extend/AssetInput.java.txt index 1528e114d..5a41c1c66 100644 --- a/src/test/resources/expected-classes/extend/AssetInput.java.txt +++ b/src/test/resources/expected-classes/extend/AssetInput.java.txt @@ -4,6 +4,8 @@ ) public class AssetInput implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String name; diff --git a/src/test/resources/expected-classes/extend/Event.java.txt b/src/test/resources/expected-classes/extend/Event.java.txt index a7d2763be..fd440bd82 100644 --- a/src/test/resources/expected-classes/extend/Event.java.txt +++ b/src/test/resources/expected-classes/extend/Event.java.txt @@ -4,6 +4,8 @@ ) public class Event implements java.io.Serializable, PinnableItem, Node { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private Status status; @javax.validation.constraints.NotNull @@ -117,4 +119,4 @@ public class Event implements java.io.Serializable, PinnableItem, Node { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/extend/EventInput.java.txt b/src/test/resources/expected-classes/extend/EventInput.java.txt index 201223773..56b4d5269 100644 --- a/src/test/resources/expected-classes/extend/EventInput.java.txt +++ b/src/test/resources/expected-classes/extend/EventInput.java.txt @@ -4,6 +4,8 @@ ) public class EventInput implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private Status status; @javax.validation.constraints.NotNull diff --git a/src/test/resources/expected-classes/from-introspection-result/Product.java.txt b/src/test/resources/expected-classes/from-introspection-result/Product.java.txt index e9b569d8d..a07cf1d21 100644 --- a/src/test/resources/expected-classes/from-introspection-result/Product.java.txt +++ b/src/test/resources/expected-classes/from-introspection-result/Product.java.txt @@ -9,6 +9,8 @@ import java.util.StringJoiner; ) public class Product implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String id; @javax.validation.constraints.NotNull diff --git a/src/test/resources/expected-classes/from-introspection-result/ProductInput.java.txt b/src/test/resources/expected-classes/from-introspection-result/ProductInput.java.txt index a010d56bc..f48aacbc8 100644 --- a/src/test/resources/expected-classes/from-introspection-result/ProductInput.java.txt +++ b/src/test/resources/expected-classes/from-introspection-result/ProductInput.java.txt @@ -9,6 +9,8 @@ import java.util.StringJoiner; ) public class ProductInput implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String title; private String description; diff --git a/src/test/resources/expected-classes/immutable/Event.java.txt b/src/test/resources/expected-classes/immutable/Event.java.txt index f84b9dcf1..3533cb780 100644 --- a/src/test/resources/expected-classes/immutable/Event.java.txt +++ b/src/test/resources/expected-classes/immutable/Event.java.txt @@ -10,6 +10,8 @@ package com.kobylynskyi.graphql.immutable; ) public class Event implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String id; private String categoryId; private java.util.List properties; @@ -131,4 +133,4 @@ public class Event implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/interfaces/Bar1.java.txt b/src/test/resources/expected-classes/interfaces/Bar1.java.txt index 3e8a10a3b..2f1445cf3 100644 --- a/src/test/resources/expected-classes/interfaces/Bar1.java.txt +++ b/src/test/resources/expected-classes/interfaces/Bar1.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.interfaces; ) public class Bar1 implements java.io.Serializable, Bar { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String id; @@ -48,4 +50,4 @@ public class Bar1 implements java.io.Serializable, Bar { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/interfaces/Foo1.java.txt b/src/test/resources/expected-classes/interfaces/Foo1.java.txt index ecbfc5379..84c1ae002 100644 --- a/src/test/resources/expected-classes/interfaces/Foo1.java.txt +++ b/src/test/resources/expected-classes/interfaces/Foo1.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.interfaces; ) public class Foo1 implements java.io.Serializable, Foo { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String id; private java.util.List bars; @@ -63,4 +65,4 @@ public class Foo1 implements java.io.Serializable, Foo { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/jackson-resolver-union/UnionMemberA.java.txt b/src/test/resources/expected-classes/jackson-resolver-union/UnionMemberA.java.txt index efabf09e2..e63cf709f 100644 --- a/src/test/resources/expected-classes/jackson-resolver-union/UnionMemberA.java.txt +++ b/src/test/resources/expected-classes/jackson-resolver-union/UnionMemberA.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.unionresolver; ) public class UnionMemberA implements java.io.Serializable, UnionToResolve { + private static final long serialVersionUID = 1L; + private Integer someField; public UnionMemberA() { @@ -47,4 +49,4 @@ public class UnionMemberA implements java.io.Serializable, UnionToResolve { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/jackson-resolver-union/UnionMemberB.java.txt b/src/test/resources/expected-classes/jackson-resolver-union/UnionMemberB.java.txt index 1cd23b14a..203ee4e6d 100644 --- a/src/test/resources/expected-classes/jackson-resolver-union/UnionMemberB.java.txt +++ b/src/test/resources/expected-classes/jackson-resolver-union/UnionMemberB.java.txt @@ -7,6 +7,8 @@ package com.kobylynskyi.graphql.unionresolver; ) public class UnionMemberB implements java.io.Serializable, UnionToResolve { + private static final long serialVersionUID = 1L; + private String someField; public UnionMemberB() { @@ -47,4 +49,4 @@ public class UnionMemberB implements java.io.Serializable, UnionToResolve { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/jackson-resolver-union/without-model-package/MyUnionMemberASuffix.java.txt b/src/test/resources/expected-classes/jackson-resolver-union/without-model-package/MyUnionMemberASuffix.java.txt index ec09ffd50..cd8b10758 100644 --- a/src/test/resources/expected-classes/jackson-resolver-union/without-model-package/MyUnionMemberASuffix.java.txt +++ b/src/test/resources/expected-classes/jackson-resolver-union/without-model-package/MyUnionMemberASuffix.java.txt @@ -4,6 +4,8 @@ ) public class MyUnionMemberASuffix implements java.io.Serializable, MyUnionToResolveSuffix { + private static final long serialVersionUID = 1L; + private Integer someField; public MyUnionMemberASuffix() { @@ -44,4 +46,4 @@ public class MyUnionMemberASuffix implements java.io.Serializable, MyUnionToReso } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/jackson-resolver-union/without-model-package/MyUnionMemberBSuffix.java.txt b/src/test/resources/expected-classes/jackson-resolver-union/without-model-package/MyUnionMemberBSuffix.java.txt index 867d41baf..80488d274 100644 --- a/src/test/resources/expected-classes/jackson-resolver-union/without-model-package/MyUnionMemberBSuffix.java.txt +++ b/src/test/resources/expected-classes/jackson-resolver-union/without-model-package/MyUnionMemberBSuffix.java.txt @@ -4,6 +4,8 @@ ) public class MyUnionMemberBSuffix implements java.io.Serializable, MyUnionToResolveSuffix { + private static final long serialVersionUID = 1L; + private String someField; public MyUnionMemberBSuffix() { @@ -44,4 +46,4 @@ public class MyUnionMemberBSuffix implements java.io.Serializable, MyUnionToReso } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/optional/TypeWithMandatoryField.java.txt b/src/test/resources/expected-classes/optional/TypeWithMandatoryField.java.txt index e58a01207..7d4f4d0cd 100644 --- a/src/test/resources/expected-classes/optional/TypeWithMandatoryField.java.txt +++ b/src/test/resources/expected-classes/optional/TypeWithMandatoryField.java.txt @@ -7,6 +7,8 @@ import java.util.StringJoiner; ) public class TypeWithMandatoryField implements java.io.Serializable, InterfaceWithOptionalField { + private static final long serialVersionUID = 1L; + private int test; public TypeWithMandatoryField() { @@ -69,4 +71,4 @@ public class TypeWithMandatoryField implements java.io.Serializable, InterfaceWi } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/relay/Organization.java.txt b/src/test/resources/expected-classes/relay/Organization.java.txt index 5d49011e3..51cf25c3b 100644 --- a/src/test/resources/expected-classes/relay/Organization.java.txt +++ b/src/test/resources/expected-classes/relay/Organization.java.txt @@ -5,6 +5,8 @@ ) public class Organization implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String id; diff --git a/src/test/resources/expected-classes/relay/User.java.txt b/src/test/resources/expected-classes/relay/User.java.txt index f8718ef2c..25b0bcb14 100644 --- a/src/test/resources/expected-classes/relay/User.java.txt +++ b/src/test/resources/expected-classes/relay/User.java.txt @@ -5,6 +5,8 @@ ) public class User implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String id; private String name; diff --git a/src/test/resources/expected-classes/request/AcceptTopicSuggestionInput.java.txt b/src/test/resources/expected-classes/request/AcceptTopicSuggestionInput.java.txt index cb56d84b5..079e2cea6 100644 --- a/src/test/resources/expected-classes/request/AcceptTopicSuggestionInput.java.txt +++ b/src/test/resources/expected-classes/request/AcceptTopicSuggestionInput.java.txt @@ -10,6 +10,8 @@ import java.util.StringJoiner; ) public class AcceptTopicSuggestionInput implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String clientMutationId; @javax.validation.constraints.NotNull private String name; @@ -114,4 +116,4 @@ public class AcceptTopicSuggestionInput implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/request/Event_useObjectMapperForRequestSerialization.java.txt b/src/test/resources/expected-classes/request/Event_useObjectMapperForRequestSerialization.java.txt index f53397b05..37a0ae031 100644 --- a/src/test/resources/expected-classes/request/Event_useObjectMapperForRequestSerialization.java.txt +++ b/src/test/resources/expected-classes/request/Event_useObjectMapperForRequestSerialization.java.txt @@ -13,6 +13,8 @@ import java.util.StringJoiner; ) public class Event implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String id; private String categoryId; private java.util.List properties; @@ -210,4 +212,4 @@ public class Event implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/resolvers/Event.java.txt b/src/test/resources/expected-classes/resolvers/Event.java.txt index fe0169a7c..35781becd 100644 --- a/src/test/resources/expected-classes/resolvers/Event.java.txt +++ b/src/test/resources/expected-classes/resolvers/Event.java.txt @@ -10,6 +10,8 @@ package com.github.graphql; ) public class Event implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String id; private String categoryId; private EventStatus status; diff --git a/src/test/resources/expected-classes/resolvers/EventProperty.java.txt b/src/test/resources/expected-classes/resolvers/EventProperty.java.txt index 38d6e199b..131431b50 100644 --- a/src/test/resources/expected-classes/resolvers/EventProperty.java.txt +++ b/src/test/resources/expected-classes/resolvers/EventProperty.java.txt @@ -10,6 +10,8 @@ package com.github.graphql; ) public class EventProperty implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private Double floatVal; public EventProperty() { @@ -62,4 +64,4 @@ public class EventProperty implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/restricted-words/Query.java.txt b/src/test/resources/expected-classes/restricted-words/Query.java.txt index 4aef5e501..3edd0cf5d 100644 --- a/src/test/resources/expected-classes/restricted-words/Query.java.txt +++ b/src/test/resources/expected-classes/restricted-words/Query.java.txt @@ -10,6 +10,8 @@ import java.util.StringJoiner; ) public class Query implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String Native; public Query() { @@ -74,4 +76,4 @@ public class Query implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/restricted-words/Synchronized.java.txt b/src/test/resources/expected-classes/restricted-words/Synchronized.java.txt index 0df3320c5..14206a901 100644 --- a/src/test/resources/expected-classes/restricted-words/Synchronized.java.txt +++ b/src/test/resources/expected-classes/restricted-words/Synchronized.java.txt @@ -10,6 +10,8 @@ import java.util.StringJoiner; ) public class Synchronized implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String Void; private Char wait; @@ -93,4 +95,4 @@ public class Synchronized implements java.io.Serializable { } } -} \ No newline at end of file +} diff --git a/src/test/resources/expected-classes/types-as-interfaces-extends-interface/Profile.java.txt b/src/test/resources/expected-classes/types-as-interfaces-extends-interface/Profile.java.txt index 8aae6800d..59ba1109e 100644 --- a/src/test/resources/expected-classes/types-as-interfaces-extends-interface/Profile.java.txt +++ b/src/test/resources/expected-classes/types-as-interfaces-extends-interface/Profile.java.txt @@ -7,6 +7,8 @@ package com.github.graphql; ) public class Profile implements java.io.Serializable { + private static final long serialVersionUID = 1L; + @javax.validation.constraints.NotNull private String firstName; @javax.validation.constraints.NotNull From 96bdde748bafb4d3b177d66cbb6b323ef9ad2626 Mon Sep 17 00:00:00 2001 From: Andrei Bocan Date: Wed, 10 Nov 2021 18:13:52 -0800 Subject: [PATCH 16/23] Kotlin: Add option to add defaults to nullable fields (#863) --- docs/codegen-options.md | 1 + .../gradle/GraphQLCodegenGradleTask.java | 13 + .../graphql/codegen/GraphQLCodegenMojo.java | 9 + .../codegen/kotlin/KotlinGraphQLCodegen.java | 3 + ...dDefinitionsToResolverDataModelMapper.java | 2 + .../InputDefinitionToDataModelMapper.java | 2 + .../TypeDefinitionToDataModelMapper.java | 2 + .../codegen/model/DataModelFields.java | 1 + .../model/GraphQLCodegenConfiguration.java | 8 + .../graphql/codegen/model/MappingConfig.java | 12 +- .../codegen/model/MappingConfigConstants.java | 4 + .../graphql/codegen/model/MappingContext.java | 5 + .../resources/templates/kotlin-lang/type.ftl | 2 +- ...hQLCodegenInitializeNullableTypesTest.java | 53 +++ .../Commit_initialize_nullable_types.kt.txt | 360 ++++++++++++++++++ 15 files changed, 475 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenInitializeNullableTypesTest.java create mode 100644 src/test/resources/expected-classes/kt/Commit_initialize_nullable_types.kt.txt diff --git a/docs/codegen-options.md b/docs/codegen-options.md index ea6c0b481..2538fab1f 100644 --- a/docs/codegen-options.md +++ b/docs/codegen-options.md @@ -56,6 +56,7 @@ See [DirectiveAnnotationsMapping](#option-directiveannotationsmapping)* | | `responseProjectionMaxDepth` | Integer | 3 | Sets max depth when use `all$()` which for facilitating the construction of projection automatically, the fields on all projections are provided when it be invoked. This is a global configuration, of course, you can use `all$(max)` to set for each method. For self recursive types, too big depth may result in a large number of returned data!| | `generatedLanguage` | Enum | GeneratedLanguage.JAVA | Choose which language you want to generate, Java,Scala,Kotlin were supported. Note that due to language features, there are slight differences in default values between languages.| | `generateModelOpenClasses` | Boolean | false | The class type of the generated model. If true, generate normal classes, else generate data classes. It only support in kotlin(```data class```) and scala(```case class```). Maybe we will consider to support Java ```record``` in the future.| +| `initializeNullableTypes` | Boolean | false | Adds a default null value to nullable arguments. Only supported in Kotlin. | `typesAsInterfaces` | Set(String) | Empty | Types that must generated as interfaces should be defined here in format: `TypeName` or `@directive`. E.g.: `User`, `@asInterface`. | ### Option `graphqlSchemas` diff --git a/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java b/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java index 3a3289d61..57fbe3215 100644 --- a/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java +++ b/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java @@ -103,6 +103,7 @@ public class GraphQLCodegenGradleTask extends DefaultTask implements GraphQLCode private List configurationFiles; private GeneratedLanguage generatedLanguage = MappingConfigConstants.DEFAULT_GENERATED_LANGUAGE; private Boolean generateModelOpenClasses = MappingConfigConstants.DEFAULT_GENERATE_MODEL_OPEN_CLASSES; + private Boolean initializeNullableTypes = MappingConfigConstants.DEFAULT_INITIALIZE_NULLABLE_TYPES; public GraphQLCodegenGradleTask() { setGroup("codegen"); @@ -178,6 +179,7 @@ public void generate() throws Exception { mappingConfig.setGeneratedLanguage(generatedLanguage); mappingConfig.setGenerateModelOpenClasses(generateModelOpenClasses); + mappingConfig.setInitializeNullableTypes(initializeNullableTypes); instantiateCodegen(mappingConfig).generate(); } @@ -844,4 +846,15 @@ public Boolean isGenerateModelOpenClasses() { public void setGenerateModelOpenClasses(Boolean generateModelOpenClasses) { this.generateModelOpenClasses = generateModelOpenClasses; } + + @Input + @Optional + @Override + public Boolean isInitializeNullableTypes() { + return initializeNullableTypes; + } + + public void setInitializeNullableTypes(Boolean initializeNullableTypes) { + this.initializeNullableTypes = initializeNullableTypes; + } } diff --git a/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java b/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java index 7c00c07b6..d88b37a0a 100644 --- a/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java +++ b/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java @@ -209,6 +209,9 @@ public class GraphQLCodegenMojo extends AbstractMojo implements GraphQLCodegenCo @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATE_MODEL_OPEN_CLASSES_STRING) private boolean generateModelOpenClasses; + @Parameter(defaultValue = MappingConfigConstants.DEFAULT_INITIALIZE_NULLABLE_TYPES_STRING) + private boolean initializeNullableTypes; + @Override public void execute() throws MojoExecutionException { addCompileSourceRootIfConfigured(); @@ -267,6 +270,7 @@ public void execute() throws MojoExecutionException { mappingConfig.setGeneratedLanguage(generatedLanguage); mappingConfig.setGenerateModelOpenClasses(isGenerateModelOpenClasses()); + mappingConfig.setInitializeNullableTypes(isInitializeNullableTypes()); try { instantiateCodegen(mappingConfig).generate(); @@ -603,6 +607,11 @@ public Boolean isGenerateModelOpenClasses() { return generateModelOpenClasses; } + @Override + public Boolean isInitializeNullableTypes() { + return initializeNullableTypes; + } + public ParentInterfacesConfig getParentInterfaces() { return parentInterfaces; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java index 1c515512d..df3fcb64c 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java @@ -49,6 +49,9 @@ protected void initDefaultValues(MappingConfig mappingConfig) { if (mappingConfig.isGenerateModelOpenClasses() == null) { mappingConfig.setGenerateModelOpenClasses(false); } + if (mappingConfig.isInitializeNullableTypes() == null) { + mappingConfig.setInitializeNullableTypes(false); + } if (mappingConfig.getGenerateBuilder() == null) { // functional expression mappingConfig.setGenerateBuilder(false); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java index ffbe9ca45..971beca11 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java @@ -24,6 +24,7 @@ import java.util.Set; import java.util.stream.Collectors; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.INITIALIZE_NULLABLE_TYPES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.CLASS_NAME; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ENUM_IMPORT_IT_SELF_IN_SCALA; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_ANNOTATION; @@ -162,6 +163,7 @@ private Map mapToResolverModel(MappingContext mappingContext, St dataModel.put(GENERATED_INFO, mappingContext.getGeneratedInformation()); dataModel.put(ENUM_IMPORT_IT_SELF_IN_SCALA, mappingContext.getEnumImportItSelfInScala()); dataModel.put(GENERATE_MODEL_OPEN_CLASSES, mappingContext.isGenerateModelOpenClasses()); + dataModel.put(INITIALIZE_NULLABLE_TYPES, mappingContext.isInitializeNullableTypes()); return dataModel; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java index 3df7a4749..f587095cb 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java @@ -8,6 +8,7 @@ import java.util.Map; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ANNOTATIONS; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.INITIALIZE_NULLABLE_TYPES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.BUILDER; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.CLASS_NAME; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ENUM_IMPORT_IT_SELF_IN_SCALA; @@ -67,6 +68,7 @@ public Map map(MappingContext mappingContext, ExtendedInputObjec dataModel.put(GENERATED_INFO, mappingContext.getGeneratedInformation()); dataModel.put(ENUM_IMPORT_IT_SELF_IN_SCALA, mappingContext.getEnumImportItSelfInScala()); dataModel.put(GENERATE_MODEL_OPEN_CLASSES, mappingContext.isGenerateModelOpenClasses()); + dataModel.put(INITIALIZE_NULLABLE_TYPES, mappingContext.isInitializeNullableTypes()); return dataModel; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java index 5760ad4eb..b72a73a02 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java @@ -18,6 +18,7 @@ import java.util.stream.Collectors; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ANNOTATIONS; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.INITIALIZE_NULLABLE_TYPES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.BUILDER; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.CLASS_NAME; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ENUM_IMPORT_IT_SELF_IN_SCALA; @@ -102,6 +103,7 @@ public Map map(MappingContext mappingContext, dataModel.put(ENUM_IMPORT_IT_SELF_IN_SCALA, mappingContext.getEnumImportItSelfInScala()); dataModel.put(PARENT_INTERFACE_PROPERTIES, mappingContext.getParentInterfaceProperties()); dataModel.put(GENERATE_MODEL_OPEN_CLASSES, mappingContext.isGenerateModelOpenClasses()); + dataModel.put(INITIALIZE_NULLABLE_TYPES, mappingContext.isInitializeNullableTypes()); return dataModel; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java index df670b27b..5797ecda4 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java @@ -36,6 +36,7 @@ public final class DataModelFields { public static final String PARENT_INTERFACE_PROPERTIES = "parentInterfaceProperties"; public static final String SERIALIZATION_LIBRARY = "serializationLibrary"; public static final String GENERATE_MODEL_OPEN_CLASSES = "generateModelOpenClasses"; + public static final String INITIALIZE_NULLABLE_TYPES = "initializeNullableTypes"; private DataModelFields() { } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java index 81ca953de..f02504562 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java @@ -446,4 +446,12 @@ public interface GraphQLCodegenConfiguration { */ Boolean isGenerateModelOpenClasses(); + /** + * Specifies whether classes should be generated with constructors setting the + * default value for nullable fields to null. + * + * @return true if nullable fields should be defaulted to null. + */ + Boolean isInitializeNullableTypes(); + } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java index 0a337d299..db376eb35 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java @@ -78,6 +78,7 @@ public class MappingConfig implements GraphQLCodegenConfiguration, Combinable typesAsInterfaces = new HashSet<>(); private boolean generateModelOpenClasses; + private boolean initializeNullableTypes; private GeneratedLanguage generatedLanguage; @@ -185,6 +186,8 @@ public void combine(MappingConfig source) { generatedLanguage = getValueOrDefaultToThis(source, GraphQLCodegenConfiguration::getGeneratedLanguage); generateModelOpenClasses = getValueOrDefaultToThis(source, GraphQLCodegenConfiguration::isGenerateModelOpenClasses); + initializeNullableTypes = getValueOrDefaultToThis(source, + GraphQLCodegenConfiguration::isInitializeNullableTypes); } private T getValueOrDefaultToThis(MappingConfig source, Function getValueFunction) { @@ -647,7 +650,6 @@ public void setGeneratedLanguage(GeneratedLanguage generatedLanguage) { this.generatedLanguage = generatedLanguage; } - public Boolean isGenerateModelOpenClasses() { return generateModelOpenClasses; } @@ -656,4 +658,12 @@ public void setGenerateModelOpenClasses(boolean generateModelOpenClasses) { this.generateModelOpenClasses = generateModelOpenClasses; } + public Boolean isInitializeNullableTypes() { + return initializeNullableTypes; + } + + public void setInitializeNullableTypes(boolean initializeNullableTypes) { + this.initializeNullableTypes = initializeNullableTypes; + } + } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java index 68197d007..f557e3142 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java @@ -68,6 +68,10 @@ public class MappingConfigConstants { public static final boolean DEFAULT_GENERATE_MODEL_OPEN_CLASSES = false; public static final String DEFAULT_GENERATE_MODEL_OPEN_CLASSES_STRING = "false"; + //Only supported in kotlin. + public static final boolean DEFAULT_INITIALIZE_NULLABLE_TYPES = false; + public static final String DEFAULT_INITIALIZE_NULLABLE_TYPES_STRING = "false"; + private MappingConfigConstants() { } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java index 10d452918..457696056 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java @@ -57,6 +57,11 @@ public Boolean isGenerateModelOpenClasses() { return config.isGenerateModelOpenClasses(); } + @Override + public Boolean isInitializeNullableTypes() { + return config.isInitializeNullableTypes(); + } + @Override public Map getCustomTypesMapping() { return config.getCustomTypesMapping(); diff --git a/src/main/resources/templates/kotlin-lang/type.ftl b/src/main/resources/templates/kotlin-lang/type.ftl index bf4c000a2..4ef1f4c8d 100755 --- a/src/main/resources/templates/kotlin-lang/type.ftl +++ b/src/main/resources/templates/kotlin-lang/type.ftl @@ -68,7 +68,7 @@ open class ${className}()<#if implements?has_content> : <#list implements as int <#if parentInterfaces?has_content><#list parentInterfaces as parent><#if parent == field.name>override <#if !immutableModels><#list field.annotations as annotation>@get:${annotation} var <#else><#list field.annotations as annotation>@get:${annotation} - val ${field.name}: ${field.type}<#if field.defaultValue?has_content> = ${field.defaultValue}<#if field_has_next>, + val ${field.name}: ${field.type}<#if field.defaultValue?has_content> = ${field.defaultValue}<#elseif field.type?ends_with("?") && (initializeNullableTypes == true)> = null<#if field_has_next>, )<#if implements?has_content> : <#list implements as interface>${interface}<#if interface_has_next>, { diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenInitializeNullableTypesTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenInitializeNullableTypesTest.java new file mode 100644 index 000000000..ee4460dc6 --- /dev/null +++ b/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenInitializeNullableTypesTest.java @@ -0,0 +1,53 @@ +package com.kobylynskyi.graphql.codegen.kotlin; + +import com.kobylynskyi.graphql.codegen.TestUtils; +import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage; +import com.kobylynskyi.graphql.codegen.model.MappingConfig; +import com.kobylynskyi.graphql.codegen.utils.Utils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.Objects; + +import static com.kobylynskyi.graphql.codegen.TestUtils.assertSameTrimmedContent; +import static com.kobylynskyi.graphql.codegen.TestUtils.getFileByName; +import static java.util.Collections.singletonList; + +class GraphQLCodegenInitializeNullableTypesTest { + + private final File outputBuildDir = new File("build/generated"); + private final File outputScalaClassesDir = new File("build/generated/com/github/graphql"); + private final MappingConfig mappingConfig = new MappingConfig(); + + @BeforeEach + void init() { + mappingConfig.setGenerateParameterizedFieldsResolvers(false); + mappingConfig.setPackageName("com.github.graphql"); + mappingConfig.setGeneratedLanguage(GeneratedLanguage.KOTLIN); + mappingConfig.setGenerateToString(true); + mappingConfig.setGenerateApis(true); + mappingConfig.setGenerateClient(true); + mappingConfig.setGenerateEqualsAndHashCode(true); + mappingConfig.setInitializeNullableTypes(true); + mappingConfig.setGenerateBuilder(true); + } + + @AfterEach + void cleanup() { + Utils.deleteDir(outputBuildDir); + } + + @Test + void generate_InitializeNullableTypes() throws Exception { + new KotlinGraphQLCodegen(singletonList("src/test/resources/schemas/github.graphqls"), + outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); + File[] files = Objects.requireNonNull(outputScalaClassesDir.listFiles()); + + assertSameTrimmedContent( + new File("src/test/resources/expected-classes/kt/Commit_initialize_nullable_types.kt.txt"), + getFileByName(files, "Commit.kt")); + } + +} diff --git a/src/test/resources/expected-classes/kt/Commit_initialize_nullable_types.kt.txt b/src/test/resources/expected-classes/kt/Commit_initialize_nullable_types.kt.txt new file mode 100644 index 000000000..1ec67aeec --- /dev/null +++ b/src/test/resources/expected-classes/kt/Commit_initialize_nullable_types.kt.txt @@ -0,0 +1,360 @@ +package com.github.graphql + +import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLRequestSerializer +import java.util.StringJoiner + +@javax.annotation.Generated( + value = ["com.kobylynskyi.graphql.codegen.GraphQLCodegen"], + date = "2020-12-31T23:59:59-0500" +) +data class Commit( + override + val abbreviatedOid: String, + val additions: Int, + val associatedPullRequests: PullRequestConnection? = null, + val author: GitActor? = null, + val authoredByCommitter: Boolean, + val authoredDate: String, + val blame: Blame, + val changedFiles: Int, + val comments: CommitCommentConnection, + override + val commitResourcePath: String, + override + val commitUrl: String, + val committedDate: String, + val committedViaWeb: Boolean, + val committer: GitActor? = null, + val deletions: Int, + val deployments: DeploymentConnection? = null, + val history: CommitHistoryConnection, + override + val id: String, + val message: String, + val messageBody: String, + val messageBodyHTML: String, + val messageHeadline: String, + val messageHeadlineHTML: String, + override + val oid: String, + val parents: CommitConnection, + val pushedDate: String? = null, + override + val repository: Repository, + override + val resourcePath: String, + val signature: GitSignature? = null, + val status: Status? = null, + val tarballUrl: String, + val tree: Tree, + val treeResourcePath: String, + val treeUrl: String, + override + val url: String, + override + val viewerCanSubscribe: Boolean, + override + val viewerSubscription: SubscriptionState? = null, + val zipballUrl: String +) : Closer, IssueTimelineItem, PullRequestTimelineItem, Subscribable, Node, GitObject, UniformResourceLocatable { + + companion object { + @JvmStatic fun builder(): Builder = Builder() + } + + // In the future, it maybe change. + override fun toString(): String { + val joiner = StringJoiner(", ", "{ ", " }") + joiner.add("abbreviatedOid: " + GraphQLRequestSerializer.getEntry(abbreviatedOid)) + joiner.add("additions: " + GraphQLRequestSerializer.getEntry(additions)) + if (associatedPullRequests != null) { + joiner.add("associatedPullRequests: " + GraphQLRequestSerializer.getEntry(associatedPullRequests)) + } + if (author != null) { + joiner.add("author: " + GraphQLRequestSerializer.getEntry(author)) + } + joiner.add("authoredByCommitter: " + GraphQLRequestSerializer.getEntry(authoredByCommitter)) + joiner.add("authoredDate: " + GraphQLRequestSerializer.getEntry(authoredDate)) + joiner.add("blame: " + GraphQLRequestSerializer.getEntry(blame)) + joiner.add("changedFiles: " + GraphQLRequestSerializer.getEntry(changedFiles)) + joiner.add("comments: " + GraphQLRequestSerializer.getEntry(comments)) + joiner.add("commitResourcePath: " + GraphQLRequestSerializer.getEntry(commitResourcePath)) + joiner.add("commitUrl: " + GraphQLRequestSerializer.getEntry(commitUrl)) + joiner.add("committedDate: " + GraphQLRequestSerializer.getEntry(committedDate)) + joiner.add("committedViaWeb: " + GraphQLRequestSerializer.getEntry(committedViaWeb)) + if (committer != null) { + joiner.add("committer: " + GraphQLRequestSerializer.getEntry(committer)) + } + joiner.add("deletions: " + GraphQLRequestSerializer.getEntry(deletions)) + if (deployments != null) { + joiner.add("deployments: " + GraphQLRequestSerializer.getEntry(deployments)) + } + joiner.add("history: " + GraphQLRequestSerializer.getEntry(history)) + joiner.add("id: " + GraphQLRequestSerializer.getEntry(id)) + joiner.add("message: " + GraphQLRequestSerializer.getEntry(message)) + joiner.add("messageBody: " + GraphQLRequestSerializer.getEntry(messageBody)) + joiner.add("messageBodyHTML: " + GraphQLRequestSerializer.getEntry(messageBodyHTML)) + joiner.add("messageHeadline: " + GraphQLRequestSerializer.getEntry(messageHeadline)) + joiner.add("messageHeadlineHTML: " + GraphQLRequestSerializer.getEntry(messageHeadlineHTML)) + joiner.add("oid: " + GraphQLRequestSerializer.getEntry(oid)) + joiner.add("parents: " + GraphQLRequestSerializer.getEntry(parents)) + if (pushedDate != null) { + joiner.add("pushedDate: " + GraphQLRequestSerializer.getEntry(pushedDate)) + } + joiner.add("repository: " + GraphQLRequestSerializer.getEntry(repository)) + joiner.add("resourcePath: " + GraphQLRequestSerializer.getEntry(resourcePath)) + if (signature != null) { + joiner.add("signature: " + GraphQLRequestSerializer.getEntry(signature)) + } + if (status != null) { + joiner.add("status: " + GraphQLRequestSerializer.getEntry(status)) + } + joiner.add("tarballUrl: " + GraphQLRequestSerializer.getEntry(tarballUrl)) + joiner.add("tree: " + GraphQLRequestSerializer.getEntry(tree)) + joiner.add("treeResourcePath: " + GraphQLRequestSerializer.getEntry(treeResourcePath)) + joiner.add("treeUrl: " + GraphQLRequestSerializer.getEntry(treeUrl)) + joiner.add("url: " + GraphQLRequestSerializer.getEntry(url)) + joiner.add("viewerCanSubscribe: " + GraphQLRequestSerializer.getEntry(viewerCanSubscribe)) + if (viewerSubscription != null) { + joiner.add("viewerSubscription: " + GraphQLRequestSerializer.getEntry(viewerSubscription)) + } + joiner.add("zipballUrl: " + GraphQLRequestSerializer.getEntry(zipballUrl)) + return joiner.toString() + } + + class Builder { + + private lateinit var abbreviatedOid: String + private var additions: Int = 0 + private var associatedPullRequests: PullRequestConnection? = null + private var author: GitActor? = null + private var authoredByCommitter: Boolean = false + private lateinit var authoredDate: String + private lateinit var blame: Blame + private var changedFiles: Int = 0 + private lateinit var comments: CommitCommentConnection + private lateinit var commitResourcePath: String + private lateinit var commitUrl: String + private lateinit var committedDate: String + private var committedViaWeb: Boolean = false + private var committer: GitActor? = null + private var deletions: Int = 0 + private var deployments: DeploymentConnection? = null + private lateinit var history: CommitHistoryConnection + private lateinit var id: String + private lateinit var message: String + private lateinit var messageBody: String + private lateinit var messageBodyHTML: String + private lateinit var messageHeadline: String + private lateinit var messageHeadlineHTML: String + private lateinit var oid: String + private lateinit var parents: CommitConnection + private var pushedDate: String? = null + private lateinit var repository: Repository + private lateinit var resourcePath: String + private var signature: GitSignature? = null + private var status: Status? = null + private lateinit var tarballUrl: String + private lateinit var tree: Tree + private lateinit var treeResourcePath: String + private lateinit var treeUrl: String + private lateinit var url: String + private var viewerCanSubscribe: Boolean = false + private var viewerSubscription: SubscriptionState? = null + private lateinit var zipballUrl: String + + fun setAbbreviatedOid(abbreviatedOid: String): Builder { + this.abbreviatedOid = abbreviatedOid + return this + } + + fun setAdditions(additions: Int): Builder { + this.additions = additions + return this + } + + fun setAssociatedPullRequests(associatedPullRequests: PullRequestConnection?): Builder { + this.associatedPullRequests = associatedPullRequests + return this + } + + fun setAuthor(author: GitActor?): Builder { + this.author = author + return this + } + + fun setAuthoredByCommitter(authoredByCommitter: Boolean): Builder { + this.authoredByCommitter = authoredByCommitter + return this + } + + fun setAuthoredDate(authoredDate: String): Builder { + this.authoredDate = authoredDate + return this + } + + fun setBlame(blame: Blame): Builder { + this.blame = blame + return this + } + + fun setChangedFiles(changedFiles: Int): Builder { + this.changedFiles = changedFiles + return this + } + + fun setComments(comments: CommitCommentConnection): Builder { + this.comments = comments + return this + } + + fun setCommitResourcePath(commitResourcePath: String): Builder { + this.commitResourcePath = commitResourcePath + return this + } + + fun setCommitUrl(commitUrl: String): Builder { + this.commitUrl = commitUrl + return this + } + + fun setCommittedDate(committedDate: String): Builder { + this.committedDate = committedDate + return this + } + + fun setCommittedViaWeb(committedViaWeb: Boolean): Builder { + this.committedViaWeb = committedViaWeb + return this + } + + fun setCommitter(committer: GitActor?): Builder { + this.committer = committer + return this + } + + fun setDeletions(deletions: Int): Builder { + this.deletions = deletions + return this + } + + fun setDeployments(deployments: DeploymentConnection?): Builder { + this.deployments = deployments + return this + } + + fun setHistory(history: CommitHistoryConnection): Builder { + this.history = history + return this + } + + fun setId(id: String): Builder { + this.id = id + return this + } + + fun setMessage(message: String): Builder { + this.message = message + return this + } + + fun setMessageBody(messageBody: String): Builder { + this.messageBody = messageBody + return this + } + + fun setMessageBodyHTML(messageBodyHTML: String): Builder { + this.messageBodyHTML = messageBodyHTML + return this + } + + fun setMessageHeadline(messageHeadline: String): Builder { + this.messageHeadline = messageHeadline + return this + } + + fun setMessageHeadlineHTML(messageHeadlineHTML: String): Builder { + this.messageHeadlineHTML = messageHeadlineHTML + return this + } + + fun setOid(oid: String): Builder { + this.oid = oid + return this + } + + fun setParents(parents: CommitConnection): Builder { + this.parents = parents + return this + } + + fun setPushedDate(pushedDate: String?): Builder { + this.pushedDate = pushedDate + return this + } + + fun setRepository(repository: Repository): Builder { + this.repository = repository + return this + } + + fun setResourcePath(resourcePath: String): Builder { + this.resourcePath = resourcePath + return this + } + + fun setSignature(signature: GitSignature?): Builder { + this.signature = signature + return this + } + + fun setStatus(status: Status?): Builder { + this.status = status + return this + } + + fun setTarballUrl(tarballUrl: String): Builder { + this.tarballUrl = tarballUrl + return this + } + + fun setTree(tree: Tree): Builder { + this.tree = tree + return this + } + + fun setTreeResourcePath(treeResourcePath: String): Builder { + this.treeResourcePath = treeResourcePath + return this + } + + fun setTreeUrl(treeUrl: String): Builder { + this.treeUrl = treeUrl + return this + } + + fun setUrl(url: String): Builder { + this.url = url + return this + } + + fun setViewerCanSubscribe(viewerCanSubscribe: Boolean): Builder { + this.viewerCanSubscribe = viewerCanSubscribe + return this + } + + fun setViewerSubscription(viewerSubscription: SubscriptionState?): Builder { + this.viewerSubscription = viewerSubscription + return this + } + + fun setZipballUrl(zipballUrl: String): Builder { + this.zipballUrl = zipballUrl + return this + } + + fun build(): Commit { + return Commit(abbreviatedOid, additions, associatedPullRequests, author, authoredByCommitter, authoredDate, blame, changedFiles, comments, commitResourcePath, commitUrl, committedDate, committedViaWeb, committer, deletions, deployments, history, id, message, messageBody, messageBodyHTML, messageHeadline, messageHeadlineHTML, oid, parents, pushedDate, repository, resourcePath, signature, status, tarballUrl, tree, treeResourcePath, treeUrl, url, viewerCanSubscribe, viewerSubscription, zipballUrl) + } + } +} \ No newline at end of file From 4fb7dbf966898aa8ed93eb6b17152901a3b31562 Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Wed, 1 Dec 2021 22:15:38 -0500 Subject: [PATCH 17/23] Delete .dependabot directory --- .dependabot/config.yml | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 .dependabot/config.yml diff --git a/.dependabot/config.yml b/.dependabot/config.yml deleted file mode 100644 index 095db4846..000000000 --- a/.dependabot/config.yml +++ /dev/null @@ -1,36 +0,0 @@ -version: 1 -update_configs: - - package_manager: java:gradle - directory: / - update_schedule: "weekly" - target_branch: "develop" - - - package_manager: java:gradle - directory: /plugins/gradle/graphql-java-codegen-gradle-plugin - update_schedule: "weekly" - target_branch: "develop" - - package_manager: java:gradle - directory: /plugins/gradle/example-client - update_schedule: "weekly" - target_branch: "develop" - - package_manager: java:gradle - directory: /plugins/gradle/example-client-kotlin - update_schedule: "weekly" - target_branch: "develop" - - package_manager: java:gradle - directory: /plugins/gradle/example-server - update_schedule: "weekly" - target_branch: "develop" - - - package_manager: java:maven - directory: /plugins/maven/graphql-java-codegen-maven-plugin - update_schedule: "weekly" - target_branch: "develop" - - package_manager: java:maven - directory: /plugins/maven/example-client - update_schedule: "weekly" - target_branch: "develop" - - package_manager: java:maven - directory: /plugins/maven/example-server - update_schedule: "weekly" - target_branch: "develop" \ No newline at end of file From 7f5b3c8aab14f0995597eeffd466898637229485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=A6=E5=A2=83=E8=BF=B7=E7=A6=BB?= Date: Thu, 2 Dec 2021 11:17:04 +0800 Subject: [PATCH 18/23] Kotlin: fix default value (#882) --- .../templates/kotlin-lang/request.ftl | 2 +- .../kotlin/GraphQLCodegenGitHubTest.java | 13 ++++ .../kt/default/FriendsQueryRequest.kt.txt | 78 +++++++++++++++++++ .../resources/schemas/kt/default.graphqls | 7 ++ 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/expected-classes/kt/default/FriendsQueryRequest.kt.txt create mode 100644 src/test/resources/schemas/kt/default.graphqls diff --git a/src/main/resources/templates/kotlin-lang/request.ftl b/src/main/resources/templates/kotlin-lang/request.ftl index 7354edda1..99b0f5ea5 100755 --- a/src/main/resources/templates/kotlin-lang/request.ftl +++ b/src/main/resources/templates/kotlin-lang/request.ftl @@ -107,7 +107,7 @@ open class ${className}(private val alias: String?) : GraphQLOperationRequest { <#else> <#if MapperUtil.isKotlinPrimitive(field.type)> <#assign default = MapperUtil.defaultValueKotlinPrimitive(field.type)/> - private var ${field.name}: ${field.type} = default + private var ${field.name}: ${field.type} = ${default} <#else> private lateinit var ${field.name}: ${field.type} diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenGitHubTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenGitHubTest.java index 9a3672ab0..3d3040c50 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenGitHubTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenGitHubTest.java @@ -19,6 +19,7 @@ import static java.util.Collections.singletonList; import static org.hamcrest.MatcherAssert.assertThat; + class GraphQLCodegenGitHubTest { private final File outputBuildDir = new File("build/generated"); @@ -187,4 +188,16 @@ void generate_CustomFieldsResolvers() throws Exception { getFileByName(files, "AcceptTopicSuggestionPayloadResolver.kt")); } + @Test + void generate_RequestWithDefaultValue() throws Exception { + mappingConfig.setGenerateBuilder(true); + mappingConfig.setGenerateClient(true); + new KotlinGraphQLCodegen(singletonList("src/test/resources/schemas/kt/default.graphqls"), + outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); + File[] files = Objects.requireNonNull(outputktClassesDir.listFiles()); + assertSameTrimmedContent(new File("src/test/resources/expected-classes/kt/default/" + + "FriendsQueryRequest.kt.txt"), + getFileByName(files, "FriendsQueryRequest.kt")); + } + } \ No newline at end of file diff --git a/src/test/resources/expected-classes/kt/default/FriendsQueryRequest.kt.txt b/src/test/resources/expected-classes/kt/default/FriendsQueryRequest.kt.txt new file mode 100644 index 000000000..394f0f585 --- /dev/null +++ b/src/test/resources/expected-classes/kt/default/FriendsQueryRequest.kt.txt @@ -0,0 +1,78 @@ +package com.github.graphql + +import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation +import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperationRequest +import java.util.Objects + +@javax.annotation.Generated( + value = ["com.kobylynskyi.graphql.codegen.GraphQLCodegen"], + date = "2020-12-31T23:59:59-0500" +) +open class FriendsQueryRequest(private val alias: String?) : GraphQLOperationRequest { + + companion object { + const val OPERATION_NAME: String = "friends" + val OPERATION_TYPE: GraphQLOperation = GraphQLOperation.QUERY + + @JvmStatic fun builder(): Builder = Builder() + } + + private val input: MutableMap = LinkedHashMap() + private val useObjectMapperForInputSerialization: MutableSet = HashSet() + + constructor(): this(null) + + fun setNum(num: Int) { + this.input["num"] = num + } + + override fun getOperationType(): GraphQLOperation = OPERATION_TYPE + + override fun getOperationName(): String = OPERATION_NAME + + override fun getAlias(): String? = alias ?: OPERATION_NAME + + override fun getInput(): MutableMap = input + + override fun getUseObjectMapperForInputSerialization(): MutableSet = useObjectMapperForInputSerialization + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + if (other == null || javaClass != other.javaClass) { + return false + } + val that = other as FriendsQueryRequest + return Objects.equals(operationType, that.operationType) && + Objects.equals(operationName, that.operationName) && + Objects.equals(input, that.input) + } + + override fun hashCode(): Int = Objects.hash(operationType, operationName, input) + + override fun toString(): String = Objects.toString(input) + + class Builder { + + private var `$alias`: String? = null + private var num: Int = 0 + + fun alias(alias: String?): Builder { + this.`$alias` = alias + return this + } + + fun setNum(num: Int): Builder { + this.num = num + return this + } + + fun build(): FriendsQueryRequest { + val obj = FriendsQueryRequest(`$alias`) + obj.setNum(num) + return obj + } + + } +} \ No newline at end of file diff --git a/src/test/resources/schemas/kt/default.graphqls b/src/test/resources/schemas/kt/default.graphqls new file mode 100644 index 000000000..95019f4c6 --- /dev/null +++ b/src/test/resources/schemas/kt/default.graphqls @@ -0,0 +1,7 @@ +type Query { + friends(num: Int!): [Friend] +} + +type Friend { + name: String +} \ No newline at end of file From d6bd6b45322fbd39049af1ab120e4109a1c7f367 Mon Sep 17 00:00:00 2001 From: Kyle Brooks Date: Wed, 1 Dec 2021 19:38:05 -0800 Subject: [PATCH 19/23] [Kotlin] Ability to generate sealed interfaces (#869) Co-authored-by: Kyle --- docs/codegen-options.md | 1 + .../gradle/example-client-kotlin/build.gradle | 1 + .../gradle/GraphQLCodegenGradleTask.java | 12 +++++ .../graphql/codegen/GraphQLCodegenMojo.java | 9 ++++ .../graphql/codegen/GraphQLCodegenKeys.scala | 2 + .../codegen/GraphQLCodegenPlugin.scala | 1 + .../codegen/kotlin/KotlinGraphQLCodegen.java | 3 ++ .../InterfaceDefinitionToDataModelMapper.java | 2 + ...stResponseDefinitionToDataModelMapper.java | 1 + .../TypeDefinitionToDataModelMapper.java | 4 +- .../UnionDefinitionToDataModelMapper.java | 2 + .../codegen/model/DataModelFields.java | 1 + .../model/GraphQLCodegenConfiguration.java | 7 +++ .../graphql/codegen/model/MappingConfig.java | 11 ++++ .../codegen/model/MappingConfigConstants.java | 3 ++ ...MappingConfigDefaultValuesInitializer.java | 3 ++ .../graphql/codegen/model/MappingContext.java | 5 ++ .../templates/kotlin-lang/interface.ftl | 2 +- .../resources/templates/kotlin-lang/union.ftl | 2 +- .../GraphQLCodegenSealedInterfacesTest.java | 50 +++++++++++++++++++ .../kt/Comment_sealed_interfaces.kt.txt | 40 +++++++++++++++ 21 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenSealedInterfacesTest.java create mode 100644 src/test/resources/expected-classes/kt/Comment_sealed_interfaces.kt.txt diff --git a/docs/codegen-options.md b/docs/codegen-options.md index 2538fab1f..375e81b96 100644 --- a/docs/codegen-options.md +++ b/docs/codegen-options.md @@ -57,6 +57,7 @@ See [DirectiveAnnotationsMapping](#option-directiveannotationsmapping)* | | `generatedLanguage` | Enum | GeneratedLanguage.JAVA | Choose which language you want to generate, Java,Scala,Kotlin were supported. Note that due to language features, there are slight differences in default values between languages.| | `generateModelOpenClasses` | Boolean | false | The class type of the generated model. If true, generate normal classes, else generate data classes. It only support in kotlin(```data class```) and scala(```case class```). Maybe we will consider to support Java ```record``` in the future.| | `initializeNullableTypes` | Boolean | false | Adds a default null value to nullable arguments. Only supported in Kotlin. +| `generateSealedInterfaces` | Boolean | false | This applies to generated interfaces on unions and interfaces. If true, generate sealed interfaces, else generate normal ones. It is only supported in Kotlin. | | `typesAsInterfaces` | Set(String) | Empty | Types that must generated as interfaces should be defined here in format: `TypeName` or `@directive`. E.g.: `User`, `@asInterface`. | ### Option `graphqlSchemas` diff --git a/plugins/gradle/example-client-kotlin/build.gradle b/plugins/gradle/example-client-kotlin/build.gradle index 40ae5e753..4a65fc205 100644 --- a/plugins/gradle/example-client-kotlin/build.gradle +++ b/plugins/gradle/example-client-kotlin/build.gradle @@ -57,6 +57,7 @@ task graphqlCodegenKotlinService(type: GraphQLCodegenGradleTask) { apiPackageName = "io.github.dreamylost.api" modelPackageName = "io.github.dreamylost.model" generateModelOpenClasses = true + generateSealedInterfaces = true customAnnotationsMapping = [ "Character": ["@com.fasterxml.jackson.annotation.JsonTypeInfo(use=com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, include=com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY,property = \"__typename\")", "@com.fasterxml.jackson.annotation.JsonSubTypes(value = arrayOf(" + System.lineSeparator() + diff --git a/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java b/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java index 57fbe3215..14c1ca202 100644 --- a/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java +++ b/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java @@ -104,6 +104,7 @@ public class GraphQLCodegenGradleTask extends DefaultTask implements GraphQLCode private GeneratedLanguage generatedLanguage = MappingConfigConstants.DEFAULT_GENERATED_LANGUAGE; private Boolean generateModelOpenClasses = MappingConfigConstants.DEFAULT_GENERATE_MODEL_OPEN_CLASSES; private Boolean initializeNullableTypes = MappingConfigConstants.DEFAULT_INITIALIZE_NULLABLE_TYPES; + private Boolean generateSealedInterfaces = MappingConfigConstants.DEFAULT_GENERATE_SEALED_INTERFACES; public GraphQLCodegenGradleTask() { setGroup("codegen"); @@ -857,4 +858,15 @@ public Boolean isInitializeNullableTypes() { public void setInitializeNullableTypes(Boolean initializeNullableTypes) { this.initializeNullableTypes = initializeNullableTypes; } + + @Input + @Optional + @Override + public Boolean isGenerateSealedInterfaces() { + return generateSealedInterfaces; + } + + public void setGenerateSealedInterfaces(Boolean generateSealedInterfaces) { + this.generateSealedInterfaces = generateSealedInterfaces; + } } diff --git a/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java b/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java index d88b37a0a..5dcc13521 100644 --- a/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java +++ b/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java @@ -212,6 +212,9 @@ public class GraphQLCodegenMojo extends AbstractMojo implements GraphQLCodegenCo @Parameter(defaultValue = MappingConfigConstants.DEFAULT_INITIALIZE_NULLABLE_TYPES_STRING) private boolean initializeNullableTypes; + @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATE_SEALED_INTERFACES_STRING) + private boolean generateSealedInterfaces; + @Override public void execute() throws MojoExecutionException { addCompileSourceRootIfConfigured(); @@ -271,6 +274,7 @@ public void execute() throws MojoExecutionException { mappingConfig.setGeneratedLanguage(generatedLanguage); mappingConfig.setGenerateModelOpenClasses(isGenerateModelOpenClasses()); mappingConfig.setInitializeNullableTypes(isInitializeNullableTypes()); + mappingConfig.setGenerateSealedInterfaces(isGenerateSealedInterfaces()); try { instantiateCodegen(mappingConfig).generate(); @@ -612,6 +616,11 @@ public Boolean isInitializeNullableTypes() { return initializeNullableTypes; } + @Override + public Boolean isGenerateSealedInterfaces() { + return generateSealedInterfaces; + } + public ParentInterfacesConfig getParentInterfaces() { return parentInterfaces; } diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenKeys.scala b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenKeys.scala index 70420c1b1..945702c05 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenKeys.scala +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenKeys.scala @@ -124,6 +124,8 @@ trait GraphQLCodegenKeys { val generateModelOpenClasses = settingKey[Boolean]("The class type of the generated model. If true, generate normal classes, else generate case class.") + val generateSealedInterfaces = settingKey[Boolean]("If true, generate sealed interfaces for GraphQL unions and interfaces, else generate normal interfaces.") + val generateJacksonTypeIdResolver = settingKey[Boolean]("Specifies whether generated union interfaces should be annotated with a custom Jackson type id resolver generated in model package") //for version diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenPlugin.scala b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenPlugin.scala index e8e0c37d3..2a252c0e3 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenPlugin.scala +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenPlugin.scala @@ -71,6 +71,7 @@ class GraphQLCodegenPlugin(configuration: Configuration, private[codegen] val co graphqlJavaCodegenVersion := None, // suffix/prefix/strategies: generateModelOpenClasses := MappingConfigConstants.DEFAULT_GENERATE_MODEL_OPEN_CLASSES, + generateSealedInterfaces := MappingConfigConstants.DEFAULT_GENERATE_SEALED_INTERFACES, generatedLanguage := MappingConfigConstants.DEFAULT_GENERATED_LANGUAGE, apiNamePrefix := None, apiNameSuffix := MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX, diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java index df3fcb64c..6589f9129 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/kotlin/KotlinGraphQLCodegen.java @@ -52,6 +52,9 @@ protected void initDefaultValues(MappingConfig mappingConfig) { if (mappingConfig.isInitializeNullableTypes() == null) { mappingConfig.setInitializeNullableTypes(false); } + if (mappingConfig.isGenerateSealedInterfaces() == null) { + mappingConfig.setGenerateSealedInterfaces(false); + } if (mappingConfig.getGenerateBuilder() == null) { // functional expression mappingConfig.setGenerateBuilder(false); diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java index e25e6cdc4..b21d18965 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InterfaceDefinitionToDataModelMapper.java @@ -15,6 +15,7 @@ import static com.kobylynskyi.graphql.codegen.model.DataModelFields.FIELDS; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_ANNOTATION; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_INFO; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATE_SEALED_INTERFACES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.IMMUTABLE_MODELS; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.IMPLEMENTS; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.JAVA_DOC; @@ -63,6 +64,7 @@ public Map map(MappingContext mappingContext, ExtendedInterfaceT dataModel.put(ENUM_IMPORT_IT_SELF_IN_SCALA, mappingContext.getEnumImportItSelfInScala()); dataModel.put(IMMUTABLE_MODELS, mappingContext.getGenerateImmutableModels()); dataModel.put(PARENT_INTERFACE_PROPERTIES, mappingContext.getParentInterfaceProperties()); + dataModel.put(GENERATE_SEALED_INTERFACES, mappingContext.isGenerateSealedInterfaces()); return dataModel; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java index 39bf24ff7..ade4b4f0e 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java @@ -29,6 +29,7 @@ import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_ANNOTATION; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_INFO; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATE_ALL_METHOD_IN_PROJECTION; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATE_SEALED_INTERFACES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.JAVA_DOC; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.METHOD_NAME; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.OPERATION_NAME; diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java index b72a73a02..e91ded2a5 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java @@ -18,7 +18,6 @@ import java.util.stream.Collectors; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ANNOTATIONS; -import static com.kobylynskyi.graphql.codegen.model.DataModelFields.INITIALIZE_NULLABLE_TYPES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.BUILDER; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.CLASS_NAME; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ENUM_IMPORT_IT_SELF_IN_SCALA; @@ -27,8 +26,10 @@ import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_ANNOTATION; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_INFO; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATE_MODEL_OPEN_CLASSES; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATE_SEALED_INTERFACES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.IMMUTABLE_MODELS; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.IMPLEMENTS; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.INITIALIZE_NULLABLE_TYPES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.JAVA_DOC; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.PACKAGE; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.PARENT_INTERFACE_PROPERTIES; @@ -104,6 +105,7 @@ public Map map(MappingContext mappingContext, dataModel.put(PARENT_INTERFACE_PROPERTIES, mappingContext.getParentInterfaceProperties()); dataModel.put(GENERATE_MODEL_OPEN_CLASSES, mappingContext.isGenerateModelOpenClasses()); dataModel.put(INITIALIZE_NULLABLE_TYPES, mappingContext.isInitializeNullableTypes()); + dataModel.put(GENERATE_SEALED_INTERFACES, mappingContext.isGenerateSealedInterfaces()); return dataModel; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java index a0ea2c4f4..5b94a632a 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnionDefinitionToDataModelMapper.java @@ -12,6 +12,7 @@ import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ENUM_IMPORT_IT_SELF_IN_SCALA; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_ANNOTATION; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_INFO; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATE_SEALED_INTERFACES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.JAVA_DOC; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.PACKAGE; @@ -47,6 +48,7 @@ public Map map(MappingContext mappingContext, ExtendedUnionTypeD dataModel.put(GENERATED_ANNOTATION, mappingContext.getAddGeneratedAnnotation()); dataModel.put(GENERATED_INFO, mappingContext.getGeneratedInformation()); dataModel.put(ENUM_IMPORT_IT_SELF_IN_SCALA, mappingContext.getEnumImportItSelfInScala()); + dataModel.put(GENERATE_SEALED_INTERFACES, mappingContext.isGenerateSealedInterfaces()); return dataModel; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java index 5797ecda4..ec234d2c6 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java @@ -37,6 +37,7 @@ public final class DataModelFields { public static final String SERIALIZATION_LIBRARY = "serializationLibrary"; public static final String GENERATE_MODEL_OPEN_CLASSES = "generateModelOpenClasses"; public static final String INITIALIZE_NULLABLE_TYPES = "initializeNullableTypes"; + public static final String GENERATE_SEALED_INTERFACES = "generateSealedInterfaces"; private DataModelFields() { } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java index f02504562..81ca1ca1e 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java @@ -454,4 +454,11 @@ public interface GraphQLCodegenConfiguration { */ Boolean isInitializeNullableTypes(); + /** + * Specifies whether generate sealed interfaces. + * + * @return false generate sealed interfaces class in kotlin + */ + Boolean isGenerateSealedInterfaces(); + } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java index db376eb35..f8c8d3a9b 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java @@ -79,6 +79,7 @@ public class MappingConfig implements GraphQLCodegenConfiguration, Combinable T getValueOrDefaultToThis(MappingConfig source, Function getValueFunction) { @@ -666,4 +669,12 @@ public void setInitializeNullableTypes(boolean initializeNullableTypes) { this.initializeNullableTypes = initializeNullableTypes; } + public Boolean isGenerateSealedInterfaces() { + return generateSealedInterfaces; + } + + public void setGenerateSealedInterfaces(boolean generateSealedInterfaces) { + this.generateSealedInterfaces = generateSealedInterfaces; + } + } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java index f557e3142..34a978767 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java @@ -71,6 +71,9 @@ public class MappingConfigConstants { //Only supported in kotlin. public static final boolean DEFAULT_INITIALIZE_NULLABLE_TYPES = false; public static final String DEFAULT_INITIALIZE_NULLABLE_TYPES_STRING = "false"; + // Only supported in Kotlin + public static final boolean DEFAULT_GENERATE_SEALED_INTERFACES = false; + public static final String DEFAULT_GENERATE_SEALED_INTERFACES_STRING = "false"; private MappingConfigConstants() { diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java index 1aa446a02..1ab1a3e89 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java @@ -105,6 +105,9 @@ public static void initDefaultValues(MappingConfig mappingConfig) { if (mappingConfig.getGenerateAllMethodInProjection() == null) { mappingConfig.setGenerateAllMethodInProjection(MappingConfigConstants.DEFAULT_GENERATE_ALL_METHOD); } + if (mappingConfig.isGenerateSealedInterfaces() == null) { + mappingConfig.setGenerateSealedInterfaces(MappingConfigConstants.DEFAULT_GENERATE_SEALED_INTERFACES); + } } } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java index 457696056..2ccea8b9e 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java @@ -62,6 +62,11 @@ public Boolean isInitializeNullableTypes() { return config.isInitializeNullableTypes(); } + @Override + public Boolean isGenerateSealedInterfaces() { + return config.isGenerateSealedInterfaces(); + } + @Override public Map getCustomTypesMapping() { return config.getCustomTypesMapping(); diff --git a/src/main/resources/templates/kotlin-lang/interface.ftl b/src/main/resources/templates/kotlin-lang/interface.ftl index 4c512e152..a5f54201e 100755 --- a/src/main/resources/templates/kotlin-lang/interface.ftl +++ b/src/main/resources/templates/kotlin-lang/interface.ftl @@ -46,7 +46,7 @@ import ${import}.* <#list annotations as annotation> @${annotation} -interface ${className}<#if implements?has_content> : <#list implements as interface>${interface}<#if interface_has_next>, { +<#if generateSealedInterfaces>sealed interface ${className}<#if implements?has_content> : <#list implements as interface>${interface}<#if interface_has_next>, { <#if fields?has_content> <#list fields as field> diff --git a/src/main/resources/templates/kotlin-lang/union.ftl b/src/main/resources/templates/kotlin-lang/union.ftl index c10c72156..c4a9ea594 100755 --- a/src/main/resources/templates/kotlin-lang/union.ftl +++ b/src/main/resources/templates/kotlin-lang/union.ftl @@ -19,6 +19,6 @@ package ${package} <#list annotations as annotation> @${annotation} -interface ${className} { +<#if generateSealedInterfaces>sealed interface ${className} { } diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenSealedInterfacesTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenSealedInterfacesTest.java new file mode 100644 index 000000000..0fb0f4b03 --- /dev/null +++ b/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenSealedInterfacesTest.java @@ -0,0 +1,50 @@ +package com.kobylynskyi.graphql.codegen.kotlin; + +import com.kobylynskyi.graphql.codegen.TestUtils; +import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage; +import com.kobylynskyi.graphql.codegen.model.MappingConfig; +import com.kobylynskyi.graphql.codegen.utils.Utils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.Objects; + +import static com.kobylynskyi.graphql.codegen.TestUtils.assertSameTrimmedContent; +import static com.kobylynskyi.graphql.codegen.TestUtils.getFileByName; +import static java.util.Collections.singletonList; + +class GraphQLCodegenSealedInterfacesTest { + private final File outputBuildDir = new File("build/generated"); + private final File outputScalaClassesDir = new File("build/generated/com/github/graphql"); + private final MappingConfig mappingConfig = new MappingConfig(); + + @BeforeEach + void init() { + mappingConfig.setGenerateParameterizedFieldsResolvers(false); + mappingConfig.setPackageName("com.github.graphql"); + mappingConfig.setGeneratedLanguage(GeneratedLanguage.KOTLIN); + mappingConfig.setGenerateToString(true); + mappingConfig.setGenerateApis(true); + mappingConfig.setGenerateClient(true); + mappingConfig.setGenerateEqualsAndHashCode(true); + mappingConfig.setGenerateBuilder(true); + mappingConfig.setGenerateSealedInterfaces(true); + } + + @AfterEach + void cleanup() { + Utils.deleteDir(outputBuildDir); + } + + @Test + void generate_MultipleInterfacesPerType() throws Exception { + new KotlinGraphQLCodegen(singletonList("src/test/resources/schemas/github.graphqls"), + outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); + File[] files = Objects.requireNonNull(outputScalaClassesDir.listFiles()); + + assertSameTrimmedContent(new File("src/test/resources/expected-classes/kt/Comment_sealed_interfaces.kt.txt"), + getFileByName(files, "Comment.kt")); + } +} diff --git a/src/test/resources/expected-classes/kt/Comment_sealed_interfaces.kt.txt b/src/test/resources/expected-classes/kt/Comment_sealed_interfaces.kt.txt new file mode 100644 index 000000000..97d2a15c1 --- /dev/null +++ b/src/test/resources/expected-classes/kt/Comment_sealed_interfaces.kt.txt @@ -0,0 +1,40 @@ +package com.github.graphql + + +@javax.annotation.Generated( + value = ["com.kobylynskyi.graphql.codegen.GraphQLCodegen"], + date = "2020-12-31T23:59:59-0500" +) +sealed interface Comment { + + val author: Actor? + + val authorAssociation: CommentAuthorAssociation + + val body: String + + val bodyHTML: String + + val bodyText: String + + val createdAt: String + + val createdViaEmail: Boolean + + val editor: Actor? + + val id: String + + val includesCreatedEdit: Boolean + + val lastEditedAt: String? + + val publishedAt: String? + + val updatedAt: String + + val userContentEdits: UserContentEditConnection? + + val viewerDidAuthor: Boolean + +} From 97fef9681501a883e49ab4a482f4e5d01e982230 Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Thu, 2 Dec 2021 20:03:00 -0500 Subject: [PATCH 20/23] Add description of useObjectMapperForRequestSerialization to codegen-options.md #912 --- docs/codegen-options.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/codegen-options.md b/docs/codegen-options.md index 375e81b96..ebae25123 100644 --- a/docs/codegen-options.md +++ b/docs/codegen-options.md @@ -59,6 +59,7 @@ See [DirectiveAnnotationsMapping](#option-directiveannotationsmapping)* | | `initializeNullableTypes` | Boolean | false | Adds a default null value to nullable arguments. Only supported in Kotlin. | `generateSealedInterfaces` | Boolean | false | This applies to generated interfaces on unions and interfaces. If true, generate sealed interfaces, else generate normal ones. It is only supported in Kotlin. | | `typesAsInterfaces` | Set(String) | Empty | Types that must generated as interfaces should be defined here in format: `TypeName` or `@directive`. E.g.: `User`, `@asInterface`. | +| `useObjectMapperForRequestSerialization` | Set(String) | Empty | Fields that require serialization using `com.fasterxml.jackson.databind.ObjectMapper#writeValueAsString(Object)`. Values should be defined here in the following format: `GraphqlObjectName.fieldName` or `GraphqlTypeName`. If just type is specified, then all fields of this type will be serialized using ObjectMapper. E.g.: `["Person.createdDateTime", ZonedDateTime"]` | ### Option `graphqlSchemas` From 323efd0f791a089cd1f9d5c889c5c7790ba1eefa Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Sat, 15 Jan 2022 19:46:19 -0500 Subject: [PATCH 21/23] Parameterized field getters in type interface are missing parameters #859 (#913) --- .../mapper/DataModelMapperFactory.java | 6 ++-- .../FieldDefinitionToParameterMapper.java | 7 ++++- .../codegen/model/ParameterDefinition.java | 12 ++++++++ .../templates/java-lang/interface.ftl | 2 +- .../GraphQLCodegenTypesAsInterfacesTest.java | 29 +++++++++++++++---- .../expected-classes/ProfileOwner.java.txt | 6 ++-- .../Foo.java.txt | 16 ++++++++++ .../types-as-interfaces-parametrized.graphqls | 14 +++++++++ 8 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 src/test/resources/expected-classes/types-as-interfaces-parametrized/Foo.java.txt create mode 100644 src/test/resources/schemas/types-as-interfaces-parametrized.graphqls diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java index 7fe3a8825..26fe985a3 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/DataModelMapperFactory.java @@ -23,14 +23,14 @@ public class DataModelMapperFactory { public DataModelMapperFactory(MapperFactory mapperFactory) { this.mapperFactory = mapperFactory; - this.fieldDefToParamMapper = new FieldDefinitionToParameterMapper(mapperFactory); + InputValueDefinitionToParameterMapper inputValueDefToParamMapper = new InputValueDefinitionToParameterMapper( + mapperFactory); + this.fieldDefToParamMapper = new FieldDefinitionToParameterMapper(mapperFactory, inputValueDefToParamMapper); this.enumDefToDataModelMapper = new EnumDefinitionToDataModelMapper(mapperFactory); this.unionDefToDataModelMapper = new UnionDefinitionToDataModelMapper(mapperFactory); this.typeDefToDataModelMapper = new TypeDefinitionToDataModelMapper(mapperFactory, fieldDefToParamMapper); this.interfaceDefToDataModelMapper = new InterfaceDefinitionToDataModelMapper( mapperFactory, fieldDefToParamMapper); - InputValueDefinitionToParameterMapper inputValueDefToParamMapper = new InputValueDefinitionToParameterMapper( - mapperFactory); this.inputDefToDataModelMapper = new InputDefinitionToDataModelMapper( mapperFactory, inputValueDefToParamMapper); this.fieldDefsToResolverDataModelMapper = new FieldDefinitionsToResolverDataModelMapper( diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java index e9848ffb9..2e3603c1d 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java @@ -23,11 +23,14 @@ public class FieldDefinitionToParameterMapper { private final GraphQLTypeMapper graphQLTypeMapper; private final DataModelMapper dataModelMapper; private final AnnotationsMapper annotationsMapper; + private final InputValueDefinitionToParameterMapper inputValueDefinitionToParameterMapper; - public FieldDefinitionToParameterMapper(MapperFactory mapperFactory) { + public FieldDefinitionToParameterMapper(MapperFactory mapperFactory, + InputValueDefinitionToParameterMapper inputValueDefToParamMapper) { this.graphQLTypeMapper = mapperFactory.getGraphQLTypeMapper(); this.dataModelMapper = mapperFactory.getDataModelMapper(); this.annotationsMapper = mapperFactory.getAnnotationsMapper(); + this.inputValueDefinitionToParameterMapper = inputValueDefToParamMapper; } /** @@ -137,6 +140,8 @@ private ParameterDefinition mapField(MappingContext mappingContext, ExtendedFiel parameter.setDeprecated(DeprecatedDefinitionBuilder.build(mappingContext, fieldDef)); parameter.setMandatory(namedDefinition.isMandatory()); parameter.setSerializeUsingObjectMapper(namedDefinition.isSerializeUsingObjectMapper()); + parameter.setInputParameters(inputValueDefinitionToParameterMapper.map( + mappingContext, fieldDef.getInputValueDefinitions(), fieldDef.getName())); return parameter; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/ParameterDefinition.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/ParameterDefinition.java index 98d4a5290..435111613 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/ParameterDefinition.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/ParameterDefinition.java @@ -31,6 +31,10 @@ public class ParameterDefinition { private List javaDoc = new ArrayList<>(); private DeprecatedDefinition deprecated; private boolean serializeUsingObjectMapper; + /** + * If the type is parametrized then input parameters will be defined here + */ + private List inputParameters; /** * Definition of the same type, but defined in the parent */ @@ -124,4 +128,12 @@ public ParameterDefinition getDefinitionInParentType() { public void setDefinitionInParentType(ParameterDefinition definitionInParentType) { this.definitionInParentType = definitionInParentType; } + + public List getInputParameters() { + return inputParameters; + } + + public void setInputParameters(List inputParameters) { + this.inputParameters = inputParameters; + } } diff --git a/src/main/resources/templates/java-lang/interface.ftl b/src/main/resources/templates/java-lang/interface.ftl index 4d55a9a2e..f3957e0b0 100644 --- a/src/main/resources/templates/java-lang/interface.ftl +++ b/src/main/resources/templates/java-lang/interface.ftl @@ -41,7 +41,7 @@ public interface ${className} <#if implements?has_content>extends <#list impleme <#list field.annotations as annotation> @${annotation} - ${field.type} get${field.name?cap_first}(); + ${field.type} get${field.name?cap_first}(<#list field.inputParameters as param><#list param.annotations as paramAnnotation>@${paramAnnotation}<#if param.annotations?has_content> ${param.type} ${param.name}<#if param_has_next>, ); diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTypesAsInterfacesTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTypesAsInterfacesTest.java index 91d063ec6..5eeff536d 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTypesAsInterfacesTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenTypesAsInterfacesTest.java @@ -8,13 +8,13 @@ import org.junit.jupiter.api.Test; import java.io.File; -import java.util.Collections; import java.util.HashSet; import java.util.Objects; import static com.kobylynskyi.graphql.codegen.TestUtils.assertSameTrimmedContent; import static com.kobylynskyi.graphql.codegen.TestUtils.getFileByName; import static java.util.Arrays.asList; +import static java.util.Collections.singleton; import static java.util.Collections.singletonList; class GraphQLCodegenTypesAsInterfacesTest { @@ -26,7 +26,9 @@ class GraphQLCodegenTypesAsInterfacesTest { @BeforeEach void init() { mappingConfig.setPackageName("com.github.graphql"); - mappingConfig.setFieldsWithResolvers(Collections.singleton("@customResolver")); + mappingConfig.setFieldsWithResolvers(singleton("@customResolver")); + mappingConfig.setFieldsWithoutResolvers(singleton("@noResolver")); + mappingConfig.setTypesAsInterfaces(new HashSet<>(singleton("@asInterface"))); } @AfterEach @@ -36,7 +38,7 @@ void cleanup() { @Test void generate_typesAsInterfaces() throws Exception { - mappingConfig.setTypesAsInterfaces(new HashSet<>(asList("@asInterface", "Order"))); + mappingConfig.getTypesAsInterfaces().add("Order"); new JavaGraphQLCodegen(singletonList("src/test/resources/schemas/types-as-interfaces.graphqls"), outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); @@ -68,16 +70,31 @@ void generate_typesAsInterfacesExtendsInterface() throws Exception { assertSameTrimmedContent(new File("src/test/resources/expected-classes/" + "types-as-interfaces-extends-interface/Node.java.txt"), getFileByName(files, "Node.java")); assertSameTrimmedContent(new File("src/test/resources/expected-classes/" + - "types-as-interfaces-extends-interface/Profile.java.txt"), + "types-as-interfaces-extends-interface/Profile.java.txt"), getFileByName(files, "Profile.java")); assertSameTrimmedContent(new File("src/test/resources/expected-classes/" + - "types-as-interfaces-extends-interface/QueryResolver.java.txt"), + "types-as-interfaces-extends-interface/QueryResolver.java.txt"), getFileByName(files, "QueryResolver.java")); assertSameTrimmedContent(new File("src/test/resources/expected-classes/" + "types-as-interfaces-extends-interface/User.java.txt"), getFileByName(files, "User.java")); assertSameTrimmedContent(new File("src/test/resources/expected-classes/" + - "types-as-interfaces-extends-interface/UserCurrentQueryResolver.java.txt"), + "types-as-interfaces-extends-interface/UserCurrentQueryResolver.java.txt"), getFileByName(files, "UserCurrentQueryResolver.java")); } + @Test + void generate_typeAsInterfaceParametrized() throws Exception { + mappingConfig.setGenerateParameterizedFieldsResolvers(true); + + new JavaGraphQLCodegen(singletonList("src/test/resources/schemas/" + + "types-as-interfaces-parametrized.graphqls"), + outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); + + File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); + + assertSameTrimmedContent(new File( + "src/test/resources/expected-classes/types-as-interfaces-parametrized/Foo.java.txt"), + getFileByName(files, "Foo.java")); + } + } diff --git a/src/test/resources/expected-classes/ProfileOwner.java.txt b/src/test/resources/expected-classes/ProfileOwner.java.txt index aecfc03a2..0cb9bf1d6 100644 --- a/src/test/resources/expected-classes/ProfileOwner.java.txt +++ b/src/test/resources/expected-classes/ProfileOwner.java.txt @@ -7,7 +7,7 @@ package com.github.graphql; ) public interface ProfileOwner { - boolean getAnyPinnableItems(); + boolean getAnyPinnableItems(PinnableItemType type); String getEmail(); @@ -25,10 +25,10 @@ public interface ProfileOwner { String getName(); @javax.validation.constraints.NotNull - PinnableItemConnection getPinnableItems(); + PinnableItemConnection getPinnableItems(String after, String before, Integer first, Integer last, @javax.validation.constraints.NotNull java.util.List types); @javax.validation.constraints.NotNull - PinnableItemConnection getPinnedItems(); + PinnableItemConnection getPinnedItems(String after, String before, Integer first, Integer last, @javax.validation.constraints.NotNull java.util.List types); int getPinnedItemsRemaining(); diff --git a/src/test/resources/expected-classes/types-as-interfaces-parametrized/Foo.java.txt b/src/test/resources/expected-classes/types-as-interfaces-parametrized/Foo.java.txt new file mode 100644 index 000000000..554307732 --- /dev/null +++ b/src/test/resources/expected-classes/types-as-interfaces-parametrized/Foo.java.txt @@ -0,0 +1,16 @@ +package com.github.graphql; + + +@javax.annotation.Generated( + value = "com.kobylynskyi.graphql.codegen.GraphQLCodegen", + date = "2020-12-31T23:59:59-0500" +) +public interface Foo { + + @javax.validation.constraints.NotNull + String getSimpleField(); + + @javax.validation.constraints.NotNull + String getParameterizedField(int count); + +} \ No newline at end of file diff --git a/src/test/resources/schemas/types-as-interfaces-parametrized.graphqls b/src/test/resources/schemas/types-as-interfaces-parametrized.graphqls new file mode 100644 index 000000000..67d7ba604 --- /dev/null +++ b/src/test/resources/schemas/types-as-interfaces-parametrized.graphqls @@ -0,0 +1,14 @@ +""" +used with typesAsInterfaces config +""" +directive @asInterface on OBJECT + +""" +used with fieldsWithResolvers config +""" +directive @noResolver on FIELD_DEFINITION + +type Foo @asInterface { + simpleField: String! + parameterizedField(count: Int!): String! @noResolver +} \ No newline at end of file From d6f7d734a9f1f7cdbab58df24d0de0d468ce2dac Mon Sep 17 00:00:00 2001 From: aldib Date: Thu, 20 Jan 2022 16:27:10 +0000 Subject: [PATCH 22/23] =?UTF-8?q?When=20using=20GraphQL=20federation,=20ex?= =?UTF-8?q?ternal=20parties=20can=20extend=20types=20and=20=E2=80=A6=20(#8?= =?UTF-8?q?66)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/codegen-options.md | 3 + .../gradle/example-client-kotlin/build.gradle | 1 + plugins/gradle/example-server/build.gradle | 3 + .../kobylynskyi/product/Application.java | 1 + .../gradle/GraphQLCodegenGradleTask.java | 30 +++ .../graphql/codegen/GraphQLCodegenMojo.java | 27 +++ .../graphql/codegen/GraphQLCodegenKeys.scala | 3 + .../codegen/GraphQLCodegenPlugin.scala | 9 +- .../InputDefinitionToDataModelMapper.java | 17 +- .../TypeDefinitionToDataModelMapper.java | 12 +- .../codegen/mapper/UnknownFieldsSupport.java | 40 ++++ .../codegen/model/DataModelFields.java | 2 + .../model/GraphQLCodegenConfiguration.java | 18 ++ .../graphql/codegen/model/MappingConfig.java | 24 ++ .../codegen/model/MappingConfigConstants.java | 3 + ...MappingConfigDefaultValuesInitializer.java | 6 + .../graphql/codegen/model/MappingContext.java | 12 + .../codegen/GraphQLCodegenDefaultsTest.java | 19 ++ .../unknown-fields/InputWithDefaults.java.txt | 224 ++++++++++++++++++ .../unknown-fields/MyEnum.java.txt | 24 ++ .../unknown-fields/SomeObject.java.txt | 70 ++++++ 21 files changed, 542 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnknownFieldsSupport.java create mode 100644 src/test/resources/expected-classes/unknown-fields/InputWithDefaults.java.txt create mode 100644 src/test/resources/expected-classes/unknown-fields/MyEnum.java.txt create mode 100644 src/test/resources/expected-classes/unknown-fields/SomeObject.java.txt diff --git a/docs/codegen-options.md b/docs/codegen-options.md index ebae25123..bc43da2a2 100644 --- a/docs/codegen-options.md +++ b/docs/codegen-options.md @@ -60,6 +60,9 @@ See [DirectiveAnnotationsMapping](#option-directiveannotationsmapping)* | | `generateSealedInterfaces` | Boolean | false | This applies to generated interfaces on unions and interfaces. If true, generate sealed interfaces, else generate normal ones. It is only supported in Kotlin. | | `typesAsInterfaces` | Set(String) | Empty | Types that must generated as interfaces should be defined here in format: `TypeName` or `@directive`. E.g.: `User`, `@asInterface`. | | `useObjectMapperForRequestSerialization` | Set(String) | Empty | Fields that require serialization using `com.fasterxml.jackson.databind.ObjectMapper#writeValueAsString(Object)`. Values should be defined here in the following format: `GraphqlObjectName.fieldName` or `GraphqlTypeName`. If just type is specified, then all fields of this type will be serialized using ObjectMapper. E.g.: `["Person.createdDateTime", ZonedDateTime"]` | +| `supportUnknownFields` | Boolean | false | Specifies whether api classes should support unknown fields during serialization or deserialization. If `true`, classes will include a property of type [`java.util.Map`](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Map.html) that will store unknown fields.| +| `unknownFieldsPropertyName` | String | userDefinedFields | Specifies the name of the property to be included in api classes to support unknown fields during serialization or deserialization| + ### Option `graphqlSchemas` diff --git a/plugins/gradle/example-client-kotlin/build.gradle b/plugins/gradle/example-client-kotlin/build.gradle index 4a65fc205..8fb52084e 100644 --- a/plugins/gradle/example-client-kotlin/build.gradle +++ b/plugins/gradle/example-client-kotlin/build.gradle @@ -65,4 +65,5 @@ task graphqlCodegenKotlinService(type: GraphQLCodegenGradleTask) { " com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = DroidTO::class, name = \"Droid\")))"], ] modelNameSuffix = "TO" + supportUnknownFields = true } \ No newline at end of file diff --git a/plugins/gradle/example-server/build.gradle b/plugins/gradle/example-server/build.gradle index 2479e6e6d..457d0cd3f 100644 --- a/plugins/gradle/example-server/build.gradle +++ b/plugins/gradle/example-server/build.gradle @@ -48,6 +48,9 @@ graphqlCodegen { } modelNameSuffix = "TO" generateApis = true + supportUnknownFields = true + unknownFieldsPropertyName = "additionalFields" + } repositories { diff --git a/plugins/gradle/example-server/src/main/java/io/github/kobylynskyi/product/Application.java b/plugins/gradle/example-server/src/main/java/io/github/kobylynskyi/product/Application.java index 932bb676d..8f8ec98e0 100644 --- a/plugins/gradle/example-server/src/main/java/io/github/kobylynskyi/product/Application.java +++ b/plugins/gradle/example-server/src/main/java/io/github/kobylynskyi/product/Application.java @@ -6,6 +6,7 @@ @SpringBootApplication public class Application { + public static void main(String[] args) { SpringApplication.run(Application.class, args); } diff --git a/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java b/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java index 14c1ca202..4b032aec0 100644 --- a/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java +++ b/plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java @@ -106,6 +106,9 @@ public class GraphQLCodegenGradleTask extends DefaultTask implements GraphQLCode private Boolean initializeNullableTypes = MappingConfigConstants.DEFAULT_INITIALIZE_NULLABLE_TYPES; private Boolean generateSealedInterfaces = MappingConfigConstants.DEFAULT_GENERATE_SEALED_INTERFACES; + private Boolean supportUnknownFields = MappingConfigConstants.DEFAULT_SUPPORT_UNKNOWN_FIELDS; + private String unknownFieldsPropertyName = MappingConfigConstants.DEFAULT_UNKNOWN_FIELDS_PROPERTY_NAME; + public GraphQLCodegenGradleTask() { setGroup("codegen"); setDescription("Generates Java POJOs and interfaces based on GraphQL schemas"); @@ -182,6 +185,9 @@ public void generate() throws Exception { mappingConfig.setGenerateModelOpenClasses(generateModelOpenClasses); mappingConfig.setInitializeNullableTypes(initializeNullableTypes); + mappingConfig.setSupportUnknownFields(isSupportUnknownFields()); + mappingConfig.setUnknownFieldsPropertyName(getUnknownFieldsPropertyName()); + instantiateCodegen(mappingConfig).generate(); } @@ -869,4 +875,28 @@ public Boolean isGenerateSealedInterfaces() { public void setGenerateSealedInterfaces(Boolean generateSealedInterfaces) { this.generateSealedInterfaces = generateSealedInterfaces; } + + @Input + @Optional + @Override + public Boolean isSupportUnknownFields() { + return supportUnknownFields; + } + + public void setSupportUnknownFields(boolean supportUnknownFields) { + this.supportUnknownFields = supportUnknownFields; + } + + @Input + @Optional + @Override + public String getUnknownFieldsPropertyName() { + return unknownFieldsPropertyName; + } + + public void setUnknownFieldsPropertyName(String unknownFieldsPropertyName) { + this.unknownFieldsPropertyName = unknownFieldsPropertyName; + } + + } diff --git a/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java b/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java index 5dcc13521..e2982fc29 100644 --- a/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java +++ b/plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java @@ -200,6 +200,12 @@ public class GraphQLCodegenMojo extends AbstractMojo implements GraphQLCodegenCo @Parameter private String[] configurationFiles; + @Parameter(defaultValue = MappingConfigConstants.DEFAULT_SUPPORT_UNKNOWN_FIELDS_STRING) + private boolean supportUnknownFields; + + @Parameter(defaultValue = MappingConfigConstants.DEFAULT_UNKNOWN_FIELDS_PROPERTY_NAME) + private String unknownFieldsPropertyName; + /** * The project being built. */ @@ -276,6 +282,9 @@ public void execute() throws MojoExecutionException { mappingConfig.setInitializeNullableTypes(isInitializeNullableTypes()); mappingConfig.setGenerateSealedInterfaces(isGenerateSealedInterfaces()); + mappingConfig.setSupportUnknownFields(isSupportUnknownFields()); + mappingConfig.setUnknownFieldsPropertyName(getUnknownFieldsPropertyName()); + try { instantiateCodegen(mappingConfig).generate(); } catch (Exception e) { @@ -629,6 +638,24 @@ public String[] getConfigurationFiles() { return configurationFiles; } + @Override + public Boolean isSupportUnknownFields() { + return supportUnknownFields; + } + + public void setSupportUnknownFields(boolean supportUnknownFields) { + this.supportUnknownFields = supportUnknownFields; + } + + @Override + public String getUnknownFieldsPropertyName() { + return unknownFieldsPropertyName; + } + + public void setUnknownFieldsPropertyName(String unknownFieldsPropertyName) { + this.unknownFieldsPropertyName = unknownFieldsPropertyName; + } + private static Map> convertToListsMap(Map sourceMap) { if (sourceMap == null) { return new HashMap<>(); diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenKeys.scala b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenKeys.scala index 945702c05..a62a58f6d 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenKeys.scala +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenKeys.scala @@ -135,4 +135,7 @@ trait GraphQLCodegenKeys { //some others for sbt val generateCodegenTargetPath = settingKey[File]("Where to store generated files and add the generated code to the classpath, so that they can be referenced.") + val supportUnknownFields = settingKey[Boolean]("supportUnknownFields") + val unknownFieldsPropertyName = settingKey[String]("unknownFieldsPropertyName") + } diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenPlugin.scala b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenPlugin.scala index 2a252c0e3..1e2833fa4 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenPlugin.scala +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/main/scala/io/github/dreamylost/graphql/codegen/GraphQLCodegenPlugin.scala @@ -117,7 +117,10 @@ class GraphQLCodegenPlugin(configuration: Configuration, private[codegen] val co // parent interfaces configs: parentInterfaces := parentInterfacesConfig, generateAllMethodInProjection := MappingConfigConstants.DEFAULT_GENERATE_ALL_METHOD, - responseProjectionMaxDepth := MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_MAX_DEPTH + responseProjectionMaxDepth := MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_MAX_DEPTH, + + supportUnknownFields := MappingConfigConstants.DEFAULT_SUPPORT_UNKNOWN_FIELDS, + unknownFieldsPropertyName := MappingConfigConstants.DEFAULT_UNKNOWN_FIELDS_PROPERTY_NAME ) private def getMappingConfig(): Def.Initialize[MappingConfig] = Def.setting { @@ -172,6 +175,10 @@ class GraphQLCodegenPlugin(configuration: Configuration, private[codegen] val co mappingConfig.setGeneratedLanguage((generatedLanguage in GraphQLCodegenConfig).value) mappingConfig.setGenerateModelOpenClasses((generateModelOpenClasses in GraphQLCodegenConfig).value) mappingConfig.setGenerateJacksonTypeIdResolver((generateJacksonTypeIdResolver in GraphQLCodegenConfig).value); + + mappingConfig.setSupportUnknownFields((supportUnknownFields in GraphQLCodegenConfig).value) + mappingConfig.setUnknownFieldsPropertyName((unknownFieldsPropertyName in GraphQLCodegenConfig).value) + mappingConfig } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java index f587095cb..ffe6f5819 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java @@ -1,14 +1,15 @@ package com.kobylynskyi.graphql.codegen.mapper; import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.ParameterDefinition; import com.kobylynskyi.graphql.codegen.model.builders.JavaDocBuilder; import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInputObjectTypeDefinition; import java.util.HashMap; +import java.util.List; import java.util.Map; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ANNOTATIONS; -import static com.kobylynskyi.graphql.codegen.model.DataModelFields.INITIALIZE_NULLABLE_TYPES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.BUILDER; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.CLASS_NAME; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ENUM_IMPORT_IT_SELF_IN_SCALA; @@ -18,18 +19,21 @@ import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_INFO; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATE_MODEL_OPEN_CLASSES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.IMMUTABLE_MODELS; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.INITIALIZE_NULLABLE_TYPES; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.JAVA_DOC; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.NAME; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.PACKAGE; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.SUPPORT_UNKNOWN_FIELDS; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.TO_STRING; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.TO_STRING_FOR_REQUEST; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.UNKNOWN_FIELDS_PROPERTY_NAME; /** * Map input type definition to a Freemarker data model * * @author kobylynskyi */ -public class InputDefinitionToDataModelMapper { +public class InputDefinitionToDataModelMapper implements UnknownFieldsSupport { private final AnnotationsMapper annotationsMapper; private final DataModelMapper dataModelMapper; @@ -50,14 +54,17 @@ public InputDefinitionToDataModelMapper(MapperFactory mapperFactory, * @return Freemarker data model of the GraphQL type */ public Map map(MappingContext mappingContext, ExtendedInputObjectTypeDefinition definition) { + List fields = inputValueDefinitionToParameterMapper + .map(mappingContext, definition.getValueDefinitions(), definition.getName()); + createUnknownFields(mappingContext).ifPresent(fields::add); + Map dataModel = new HashMap<>(); // type/enum/input/interface/union classes do not require any imports dataModel.put(PACKAGE, DataModelMapper.getModelPackageName(mappingContext)); dataModel.put(CLASS_NAME, dataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, definition)); dataModel.put(JAVA_DOC, JavaDocBuilder.build(definition)); dataModel.put(NAME, definition.getName()); - dataModel.put(FIELDS, inputValueDefinitionToParameterMapper - .map(mappingContext, definition.getValueDefinitions(), definition.getName())); + dataModel.put(FIELDS, fields); dataModel.put(ANNOTATIONS, annotationsMapper.getAnnotations(mappingContext, definition)); dataModel.put(BUILDER, mappingContext.getGenerateBuilder()); dataModel.put(EQUALS_AND_HASH_CODE, mappingContext.getGenerateEqualsAndHashCode()); @@ -69,6 +76,8 @@ public Map map(MappingContext mappingContext, ExtendedInputObjec dataModel.put(ENUM_IMPORT_IT_SELF_IN_SCALA, mappingContext.getEnumImportItSelfInScala()); dataModel.put(GENERATE_MODEL_OPEN_CLASSES, mappingContext.isGenerateModelOpenClasses()); dataModel.put(INITIALIZE_NULLABLE_TYPES, mappingContext.isInitializeNullableTypes()); + dataModel.put(SUPPORT_UNKNOWN_FIELDS, mappingContext.isSupportUnknownFields()); + dataModel.put(UNKNOWN_FIELDS_PROPERTY_NAME, mappingContext.getUnknownFieldsPropertyName()); return dataModel; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java index e91ded2a5..8936d5f30 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java @@ -33,15 +33,17 @@ import static com.kobylynskyi.graphql.codegen.model.DataModelFields.JAVA_DOC; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.PACKAGE; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.PARENT_INTERFACE_PROPERTIES; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.SUPPORT_UNKNOWN_FIELDS; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.TO_STRING; import static com.kobylynskyi.graphql.codegen.model.DataModelFields.TO_STRING_FOR_REQUEST; +import static com.kobylynskyi.graphql.codegen.model.DataModelFields.UNKNOWN_FIELDS_PROPERTY_NAME; /** * Map type definition to a Freemarker data model * * @author kobylynskyi */ -public class TypeDefinitionToDataModelMapper { +public class TypeDefinitionToDataModelMapper implements UnknownFieldsSupport { private final GraphQLTypeMapper graphQLTypeMapper; private final AnnotationsMapper annotationsMapper; @@ -106,6 +108,8 @@ public Map map(MappingContext mappingContext, dataModel.put(GENERATE_MODEL_OPEN_CLASSES, mappingContext.isGenerateModelOpenClasses()); dataModel.put(INITIALIZE_NULLABLE_TYPES, mappingContext.isInitializeNullableTypes()); dataModel.put(GENERATE_SEALED_INTERFACES, mappingContext.isGenerateSealedInterfaces()); + dataModel.put(SUPPORT_UNKNOWN_FIELDS, mappingContext.isSupportUnknownFields()); + dataModel.put(UNKNOWN_FIELDS_PROPERTY_NAME, mappingContext.getUnknownFieldsPropertyName()); return dataModel; } @@ -132,6 +136,12 @@ private Collection getFields(MappingContext mappingContext, .flatMap(Collection::stream) .forEach(paramDef -> allParameters .merge(paramDef.getName(), paramDef, TypeDefinitionToDataModelMapper::merge)); + + + createUnknownFields(mappingContext).ifPresent( + unknownFields -> allParameters.put(mappingContext.getUnknownFieldsPropertyName(), unknownFields) + ); + return allParameters.values(); } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnknownFieldsSupport.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnknownFieldsSupport.java new file mode 100644 index 000000000..9618ec645 --- /dev/null +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/UnknownFieldsSupport.java @@ -0,0 +1,40 @@ +package com.kobylynskyi.graphql.codegen.mapper; + +import com.kobylynskyi.graphql.codegen.model.MappingContext; +import com.kobylynskyi.graphql.codegen.model.ParameterDefinition; + +import java.util.Arrays; +import java.util.Optional; + +/** + * Utility interface that provides convenience methods to handle unknown fields during the marshaling + * and unmarshalling of a JSON document + * + * @author aldib + */ +public interface UnknownFieldsSupport { + + /** + * Creates an instance of {@link ParameterDefinition} that can be used to generate + * a field of type {@link java.util.Map} to store unknown fields during the marshaling + * and unmarshalling of a JSON document + * + * @param mappingContext The context of the mapping process. + * @return If {@link MappingContext#isSupportUnknownFields()} is true, it returns a monad containing + * the instance of {@link ParameterDefinition}. {@link Optional#empty()} otherwise. + */ + default Optional createUnknownFields(MappingContext mappingContext) { + if (mappingContext.isSupportUnknownFields()) { + ParameterDefinition unknownFields = new ParameterDefinition(); + unknownFields.setName(mappingContext.getUnknownFieldsPropertyName()); + unknownFields.setOriginalName(mappingContext.getUnknownFieldsPropertyName()); + unknownFields.setType("java.util.Map"); + unknownFields.setAnnotations(Arrays.asList( + "com.fasterxml.jackson.annotation.JsonAnyGetter", + "com.fasterxml.jackson.annotation.JsonAnySetter" + )); + return Optional.of(unknownFields); + } + return Optional.empty(); + } +} diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java index ec234d2c6..bfe2f95f9 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java @@ -38,6 +38,8 @@ public final class DataModelFields { public static final String GENERATE_MODEL_OPEN_CLASSES = "generateModelOpenClasses"; public static final String INITIALIZE_NULLABLE_TYPES = "initializeNullableTypes"; public static final String GENERATE_SEALED_INTERFACES = "generateSealedInterfaces"; + public static final String SUPPORT_UNKNOWN_FIELDS = "supportUnknownFields"; + public static final String UNKNOWN_FIELDS_PROPERTY_NAME = "unknownFieldsPropertyName"; private DataModelFields() { } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java index 81ca1ca1e..efc0c4a5f 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java @@ -461,4 +461,22 @@ public interface GraphQLCodegenConfiguration { */ Boolean isGenerateSealedInterfaces(); + /* + * Specifies whether api classes should support unknown fields during serialization or deserialization. + * + * @return true classes will include a property of type {@link java.util.Map} that will store unknown fields. + * @see com.fasterxml.jackson.annotation.JsonAnyGetter + * @see com.fasterxml.jackson.annotation.JsonAnySetter + */ + Boolean isSupportUnknownFields(); + + /** + * Specifies the name of the property to be included in api classes to support unknown + * fields during serialization or deserialization + * + * @return The name of the property to store unknown fields + */ + String getUnknownFieldsPropertyName(); + + } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java index f8c8d3a9b..128901e52 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java @@ -39,6 +39,7 @@ public class MappingConfig implements GraphQLCodegenConfiguration, Combinable fieldsWithResolvers = new HashSet<>(); @@ -191,6 +193,10 @@ public void combine(MappingConfig source) { GraphQLCodegenConfiguration::isInitializeNullableTypes); generateSealedInterfaces = getValueOrDefaultToThis(source, GraphQLCodegenConfiguration::isGenerateSealedInterfaces); + supportUnknownFields = getValueOrDefaultToThis(source, + GraphQLCodegenConfiguration::isSupportUnknownFields); + unknownFieldsPropertyName = getValueOrDefaultToThis(source, + GraphQLCodegenConfiguration::getUnknownFieldsPropertyName); } private T getValueOrDefaultToThis(MappingConfig source, Function getValueFunction) { @@ -649,6 +655,24 @@ public GeneratedLanguage getGeneratedLanguage() { return generatedLanguage; } + @Override + public String getUnknownFieldsPropertyName() { + return unknownFieldsPropertyName; + } + + public void setUnknownFieldsPropertyName(String unknownFieldsPropertyName) { + this.unknownFieldsPropertyName = unknownFieldsPropertyName; + } + + @Override + public Boolean isSupportUnknownFields() { + return supportUnknownFields; + } + + public void setSupportUnknownFields(Boolean supportUnknownFields) { + this.supportUnknownFields = supportUnknownFields; + } + public void setGeneratedLanguage(GeneratedLanguage generatedLanguage) { this.generatedLanguage = generatedLanguage; } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java index 34a978767..df3499cde 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java @@ -75,6 +75,9 @@ public class MappingConfigConstants { public static final boolean DEFAULT_GENERATE_SEALED_INTERFACES = false; public static final String DEFAULT_GENERATE_SEALED_INTERFACES_STRING = "false"; + public static final boolean DEFAULT_SUPPORT_UNKNOWN_FIELDS = false; + public static final String DEFAULT_SUPPORT_UNKNOWN_FIELDS_STRING = "false"; + public static final String DEFAULT_UNKNOWN_FIELDS_PROPERTY_NAME = "userDefinedFields"; private MappingConfigConstants() { } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java index 1ab1a3e89..57f11b675 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigDefaultValuesInitializer.java @@ -108,6 +108,12 @@ public static void initDefaultValues(MappingConfig mappingConfig) { if (mappingConfig.isGenerateSealedInterfaces() == null) { mappingConfig.setGenerateSealedInterfaces(MappingConfigConstants.DEFAULT_GENERATE_SEALED_INTERFACES); } + if (mappingConfig.isSupportUnknownFields() == null) { + mappingConfig.setSupportUnknownFields(MappingConfigConstants.DEFAULT_SUPPORT_UNKNOWN_FIELDS); + } + if (mappingConfig.getUnknownFieldsPropertyName() == null) { + mappingConfig.setUnknownFieldsPropertyName(MappingConfigConstants.DEFAULT_UNKNOWN_FIELDS_PROPERTY_NAME); + } } } diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java index 2ccea8b9e..8b780d4d5 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java @@ -62,6 +62,8 @@ public Boolean isInitializeNullableTypes() { return config.isInitializeNullableTypes(); } + + @Override public Boolean isGenerateSealedInterfaces() { return config.isGenerateSealedInterfaces(); @@ -307,6 +309,16 @@ public Set getTypesAsInterfaces() { return config.getTypesAsInterfaces(); } + @Override + public Boolean isSupportUnknownFields() { + return config.isSupportUnknownFields(); + } + + @Override + public String getUnknownFieldsPropertyName() { + return config.getUnknownFieldsPropertyName(); + } + public ExtendedDocument getDocument() { return document; } diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenDefaultsTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenDefaultsTest.java index d64c706ac..900e8aad4 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenDefaultsTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenDefaultsTest.java @@ -53,6 +53,25 @@ void generate_CheckFiles() throws Exception { } } + @Test + void generate_UnkonwnFields() throws Exception { + mappingConfig.setSupportUnknownFields(true); + mappingConfig.setUnknownFieldsPropertyName("userDefinedFields"); + + new JavaGraphQLCodegen(singletonList("src/test/resources/schemas/defaults.graphqls"), + outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); + + File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); + List generatedFileNames = Arrays.stream(files).map(File::getName).sorted().collect(toList()); + assertEquals(asList("InputWithDefaults.java", "MyEnum.java", "SomeObject.java"), generatedFileNames); + + for (File file : files) { + assertSameTrimmedContent(new File(String.format("src/test/resources/expected-classes/unknown-fields/%s.txt", + file.getName())), + file); + } + } + @Test void generate_CheckFiles_WithPrefixSuffix() throws Exception { mappingConfig.setModelNameSuffix("TO"); diff --git a/src/test/resources/expected-classes/unknown-fields/InputWithDefaults.java.txt b/src/test/resources/expected-classes/unknown-fields/InputWithDefaults.java.txt new file mode 100644 index 000000000..0629ea8a0 --- /dev/null +++ b/src/test/resources/expected-classes/unknown-fields/InputWithDefaults.java.txt @@ -0,0 +1,224 @@ +package com.kobylynskyi.graphql.testdefaults; + + +/** + * This input has all possible types + */ +@javax.annotation.Generated( + value = "com.kobylynskyi.graphql.codegen.GraphQLCodegen", + date = "2020-12-31T23:59:59-0500" +) +public class InputWithDefaults implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + + private Double floatVal = 1.23; + private Boolean booleanVal = false; + private Integer intVal = 42; + private String stringVal = "my-default"; + private MyEnum enumVal = MyEnum.ONE; + @javax.validation.constraints.NotNull + private MyEnum nonNullEnumVal = MyEnum.TWO; + private SomeObject objectWithNullDefault = null; + private SomeObject objectWithNonNullDefault; + private java.util.List intList = java.util.Arrays.asList(1, 2, 3); + private java.util.List intListEmptyDefault = java.util.Collections.emptyList(); + @javax.validation.constraints.NotNull + private java.util.List objectListEmptyDefault = java.util.Collections.emptyList(); + @com.fasterxml.jackson.annotation.JsonAnyGetter + @com.fasterxml.jackson.annotation.JsonAnySetter + private java.util.Map userDefinedFields; + + public InputWithDefaults() { + } + + public InputWithDefaults(Double floatVal, Boolean booleanVal, Integer intVal, String stringVal, MyEnum enumVal, MyEnum nonNullEnumVal, SomeObject objectWithNullDefault, SomeObject objectWithNonNullDefault, java.util.List intList, java.util.List intListEmptyDefault, java.util.List objectListEmptyDefault, java.util.Map userDefinedFields) { + this.floatVal = floatVal; + this.booleanVal = booleanVal; + this.intVal = intVal; + this.stringVal = stringVal; + this.enumVal = enumVal; + this.nonNullEnumVal = nonNullEnumVal; + this.objectWithNullDefault = objectWithNullDefault; + this.objectWithNonNullDefault = objectWithNonNullDefault; + this.intList = intList; + this.intListEmptyDefault = intListEmptyDefault; + this.objectListEmptyDefault = objectListEmptyDefault; + this.userDefinedFields = userDefinedFields; + } + + public Double getFloatVal() { + return floatVal; + } + public void setFloatVal(Double floatVal) { + this.floatVal = floatVal; + } + + public Boolean getBooleanVal() { + return booleanVal; + } + public void setBooleanVal(Boolean booleanVal) { + this.booleanVal = booleanVal; + } + + public Integer getIntVal() { + return intVal; + } + public void setIntVal(Integer intVal) { + this.intVal = intVal; + } + + public String getStringVal() { + return stringVal; + } + public void setStringVal(String stringVal) { + this.stringVal = stringVal; + } + + public MyEnum getEnumVal() { + return enumVal; + } + public void setEnumVal(MyEnum enumVal) { + this.enumVal = enumVal; + } + + public MyEnum getNonNullEnumVal() { + return nonNullEnumVal; + } + public void setNonNullEnumVal(MyEnum nonNullEnumVal) { + this.nonNullEnumVal = nonNullEnumVal; + } + + public SomeObject getObjectWithNullDefault() { + return objectWithNullDefault; + } + public void setObjectWithNullDefault(SomeObject objectWithNullDefault) { + this.objectWithNullDefault = objectWithNullDefault; + } + + public SomeObject getObjectWithNonNullDefault() { + return objectWithNonNullDefault; + } + public void setObjectWithNonNullDefault(SomeObject objectWithNonNullDefault) { + this.objectWithNonNullDefault = objectWithNonNullDefault; + } + + public java.util.List getIntList() { + return intList; + } + public void setIntList(java.util.List intList) { + this.intList = intList; + } + + public java.util.List getIntListEmptyDefault() { + return intListEmptyDefault; + } + public void setIntListEmptyDefault(java.util.List intListEmptyDefault) { + this.intListEmptyDefault = intListEmptyDefault; + } + + public java.util.List getObjectListEmptyDefault() { + return objectListEmptyDefault; + } + public void setObjectListEmptyDefault(java.util.List objectListEmptyDefault) { + this.objectListEmptyDefault = objectListEmptyDefault; + } + + public java.util.Map getUserDefinedFields() { + return userDefinedFields; + } + public void setUserDefinedFields(java.util.Map userDefinedFields) { + this.userDefinedFields = userDefinedFields; + } + + + + public static InputWithDefaults.Builder builder() { + return new InputWithDefaults.Builder(); + } + + public static class Builder { + + private Double floatVal = 1.23; + private Boolean booleanVal = false; + private Integer intVal = 42; + private String stringVal = "my-default"; + private MyEnum enumVal = MyEnum.ONE; + private MyEnum nonNullEnumVal = MyEnum.TWO; + private SomeObject objectWithNullDefault = null; + private SomeObject objectWithNonNullDefault; + private java.util.List intList = java.util.Arrays.asList(1, 2, 3); + private java.util.List intListEmptyDefault = java.util.Collections.emptyList(); + private java.util.List objectListEmptyDefault = java.util.Collections.emptyList(); + private java.util.Map userDefinedFields; + + public Builder() { + } + + public Builder setFloatVal(Double floatVal) { + this.floatVal = floatVal; + return this; + } + + public Builder setBooleanVal(Boolean booleanVal) { + this.booleanVal = booleanVal; + return this; + } + + public Builder setIntVal(Integer intVal) { + this.intVal = intVal; + return this; + } + + public Builder setStringVal(String stringVal) { + this.stringVal = stringVal; + return this; + } + + public Builder setEnumVal(MyEnum enumVal) { + this.enumVal = enumVal; + return this; + } + + public Builder setNonNullEnumVal(MyEnum nonNullEnumVal) { + this.nonNullEnumVal = nonNullEnumVal; + return this; + } + + public Builder setObjectWithNullDefault(SomeObject objectWithNullDefault) { + this.objectWithNullDefault = objectWithNullDefault; + return this; + } + + public Builder setObjectWithNonNullDefault(SomeObject objectWithNonNullDefault) { + this.objectWithNonNullDefault = objectWithNonNullDefault; + return this; + } + + public Builder setIntList(java.util.List intList) { + this.intList = intList; + return this; + } + + public Builder setIntListEmptyDefault(java.util.List intListEmptyDefault) { + this.intListEmptyDefault = intListEmptyDefault; + return this; + } + + public Builder setObjectListEmptyDefault(java.util.List objectListEmptyDefault) { + this.objectListEmptyDefault = objectListEmptyDefault; + return this; + } + + public Builder setUserDefinedFields(java.util.Map userDefinedFields) { + this.userDefinedFields = userDefinedFields; + return this; + } + + + public InputWithDefaults build() { + return new InputWithDefaults(floatVal, booleanVal, intVal, stringVal, enumVal, nonNullEnumVal, objectWithNullDefault, objectWithNonNullDefault, intList, intListEmptyDefault, objectListEmptyDefault, userDefinedFields); + } + + } +} \ No newline at end of file diff --git a/src/test/resources/expected-classes/unknown-fields/MyEnum.java.txt b/src/test/resources/expected-classes/unknown-fields/MyEnum.java.txt new file mode 100644 index 000000000..489176b8f --- /dev/null +++ b/src/test/resources/expected-classes/unknown-fields/MyEnum.java.txt @@ -0,0 +1,24 @@ +package com.kobylynskyi.graphql.testdefaults; + +@javax.annotation.Generated( + value = "com.kobylynskyi.graphql.codegen.GraphQLCodegen", + date = "2020-12-31T23:59:59-0500" +) +public enum MyEnum { + + ONE("ONE"), + TWO("TWO"), + THREE("THREE"); + + private final String graphqlName; + + private MyEnum(String graphqlName) { + this.graphqlName = graphqlName; + } + + @Override + public String toString() { + return this.graphqlName; + } + +} \ No newline at end of file diff --git a/src/test/resources/expected-classes/unknown-fields/SomeObject.java.txt b/src/test/resources/expected-classes/unknown-fields/SomeObject.java.txt new file mode 100644 index 000000000..0b6ecfb65 --- /dev/null +++ b/src/test/resources/expected-classes/unknown-fields/SomeObject.java.txt @@ -0,0 +1,70 @@ +package com.kobylynskyi.graphql.testdefaults; + + +@javax.annotation.Generated( + value = "com.kobylynskyi.graphql.codegen.GraphQLCodegen", + date = "2020-12-31T23:59:59-0500" +) +public class SomeObject implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + + @javax.validation.constraints.NotNull + private String name; + @com.fasterxml.jackson.annotation.JsonAnyGetter + @com.fasterxml.jackson.annotation.JsonAnySetter + private java.util.Map userDefinedFields; + + public SomeObject() { + } + + public SomeObject(String name, java.util.Map userDefinedFields) { + this.name = name; + this.userDefinedFields = userDefinedFields; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public java.util.Map getUserDefinedFields() { + return userDefinedFields; + } + public void setUserDefinedFields(java.util.Map userDefinedFields) { + this.userDefinedFields = userDefinedFields; + } + + + + public static SomeObject.Builder builder() { + return new SomeObject.Builder(); + } + + public static class Builder { + + private String name; + private java.util.Map userDefinedFields; + + public Builder() { + } + + public Builder setName(String name) { + this.name = name; + return this; + } + + public Builder setUserDefinedFields(java.util.Map userDefinedFields) { + this.userDefinedFields = userDefinedFields; + return this; + } + + + public SomeObject build() { + return new SomeObject(name, userDefinedFields); + } + + } +} \ No newline at end of file From 0443f986741e0519ac958445b6af96f39909afc3 Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Sun, 23 Jan 2022 18:02:31 -0500 Subject: [PATCH 23/23] Bump version to 5.4.0 - release --- build.gradle | 2 +- plugins/gradle/README.md | 4 ++-- plugins/gradle/example-client-kotlin/build.gradle | 6 +++--- plugins/gradle/example-client/build.gradle | 4 ++-- plugins/gradle/example-server/build.gradle | 2 +- .../gradle/graphql-java-codegen-gradle-plugin/build.gradle | 2 +- plugins/maven/README.md | 2 +- plugins/maven/example-client/pom.xml | 2 +- plugins/maven/example-server/pom.xml | 2 +- plugins/maven/graphql-java-codegen-maven-plugin/pom.xml | 4 ++-- .../example-client-scala/project/plugins.sbt | 2 +- .../example-client-scala/version.sbt | 2 +- .../example-client/project/plugins.sbt | 2 +- .../graphql-codegen-sbt-plugin/example-client/version.sbt | 2 +- .../graphql-codegen-sbt-plugin/simple/project/plugins.sbt | 2 +- .../sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt | 2 +- plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt | 2 +- 17 files changed, 22 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index c7db7e93d..c1480bbcc 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { id "org.sonarqube" version "3.2.0" } -def graphqlCodegenVersion = '5.3.1-SNAPSHOT' // This variable used in the automatic release process +def graphqlCodegenVersion = '5.4.0' // This variable used in the automatic release process group = "io.github.kobylynskyi" version = graphqlCodegenVersion diff --git a/plugins/gradle/README.md b/plugins/gradle/README.md index 635c913ea..6b33801c4 100644 --- a/plugins/gradle/README.md +++ b/plugins/gradle/README.md @@ -17,7 +17,7 @@ ```groovy plugins { - id "io.github.kobylynskyi.graphql.codegen" version "5.3.0" + id "io.github.kobylynskyi.graphql.codegen" version "5.4.0" } ``` @@ -31,7 +31,7 @@ buildscript { } } dependencies { - classpath "io.github.kobylynskyi.graphql.codegen:graphql-codegen-gradle-plugin:5.3.0" + classpath "io.github.kobylynskyi.graphql.codegen:graphql-codegen-gradle-plugin:5.4.0" } } diff --git a/plugins/gradle/example-client-kotlin/build.gradle b/plugins/gradle/example-client-kotlin/build.gradle index 8fb52084e..d812d21e7 100644 --- a/plugins/gradle/example-client-kotlin/build.gradle +++ b/plugins/gradle/example-client-kotlin/build.gradle @@ -4,10 +4,10 @@ import io.github.kobylynskyi.graphql.codegen.gradle.GraphQLCodegenGradleTask plugins { id 'java' id "org.jetbrains.kotlin.jvm" version "1.3.71" - id "io.github.kobylynskyi.graphql.codegen" version "5.3.1-SNAPSHOT" + id "io.github.kobylynskyi.graphql.codegen" version "5.4.0" } -def graphqlCodegenClientKotlinVersion = '5.3.1-SNAPSHOT' // Variable used in the automatic release process +def graphqlCodegenClientKotlinVersion = '5.4.0' // Variable used in the automatic release process group = 'io.github.dreamylost' version = graphqlCodegenClientKotlinVersion @@ -29,7 +29,7 @@ repositories { dependencies { - implementation "io.github.kobylynskyi:graphql-java-codegen:5.3.1-SNAPSHOT" + implementation "io.github.kobylynskyi:graphql-java-codegen:5.4.0" implementation "javax.validation:validation-api:2.0.1.Final" implementation "com.squareup.okhttp3:okhttp:4.2.2" implementation "com.fasterxml.jackson.core:jackson-core:2.12.0" diff --git a/plugins/gradle/example-client/build.gradle b/plugins/gradle/example-client/build.gradle index 54be21d3f..75fe7d650 100644 --- a/plugins/gradle/example-client/build.gradle +++ b/plugins/gradle/example-client/build.gradle @@ -7,7 +7,7 @@ plugins { // use the latest available version: // https://plugins.gradle.org/plugin/io.github.kobylynskyi.graphql.codegen - id "io.github.kobylynskyi.graphql.codegen" version "5.3.1-SNAPSHOT" + id "io.github.kobylynskyi.graphql.codegen" version "5.4.0" } mainClassName = "io.github.kobylynskyi.order.Application" @@ -22,7 +22,7 @@ dependencies { // use the latest available version: // https://search.maven.org/artifact/io.github.kobylynskyi/graphql-java-codegen - implementation "io.github.kobylynskyi:graphql-java-codegen:5.3.1-SNAPSHOT" + implementation "io.github.kobylynskyi:graphql-java-codegen:5.4.0" implementation "org.apache.httpcomponents:httpclient:4.5.13" implementation "javax.validation:validation-api:2.0.1.Final" diff --git a/plugins/gradle/example-server/build.gradle b/plugins/gradle/example-server/build.gradle index 457d0cd3f..a9c00353d 100644 --- a/plugins/gradle/example-server/build.gradle +++ b/plugins/gradle/example-server/build.gradle @@ -6,7 +6,7 @@ plugins { // // use the latest available version: // https://plugins.gradle.org/plugin/io.github.kobylynskyi.graphql.codegen - id "io.github.kobylynskyi.graphql.codegen" version "5.3.1-SNAPSHOT" + id "io.github.kobylynskyi.graphql.codegen" version "5.4.0" } mainClassName = "io.github.kobylynskyi.product.Application" diff --git a/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle b/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle index 8f0316cf2..b6d387dda 100644 --- a/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle +++ b/plugins/gradle/graphql-java-codegen-gradle-plugin/build.gradle @@ -16,7 +16,7 @@ apply plugin: "java" apply plugin: "idea" apply plugin: "maven-publish" -def graphqlCodegenGradlePluginVersion = '5.3.1-SNAPSHOT' // This variable used in the automatic release process +def graphqlCodegenGradlePluginVersion = '5.4.0' // This variable used in the automatic release process group = "io.github.kobylynskyi" version = graphqlCodegenGradlePluginVersion diff --git a/plugins/maven/README.md b/plugins/maven/README.md index edcd653c8..aa031b287 100644 --- a/plugins/maven/README.md +++ b/plugins/maven/README.md @@ -20,7 +20,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin - 5.3.0 + 5.4.0 diff --git a/plugins/maven/example-client/pom.xml b/plugins/maven/example-client/pom.xml index 2ce80d20d..5b43d3af5 100644 --- a/plugins/maven/example-client/pom.xml +++ b/plugins/maven/example-client/pom.xml @@ -4,7 +4,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin-example-client - 5.3.1-SNAPSHOT + 5.4.0 graphql-codegen-maven-plugin-example-client diff --git a/plugins/maven/example-server/pom.xml b/plugins/maven/example-server/pom.xml index a91294fc8..172346ca7 100644 --- a/plugins/maven/example-server/pom.xml +++ b/plugins/maven/example-server/pom.xml @@ -4,7 +4,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin-example-server - 5.3.1-SNAPSHOT + 5.4.0 graphql-codegen-maven-plugin-example-server diff --git a/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml b/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml index cceb650f9..0e082562b 100644 --- a/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml +++ b/plugins/maven/graphql-java-codegen-maven-plugin/pom.xml @@ -3,7 +3,7 @@ io.github.kobylynskyi graphql-codegen-maven-plugin - 5.3.1-SNAPSHOT + 5.4.0 maven-plugin graphql-codegen-maven-plugin @@ -72,7 +72,7 @@ 3.0.1 3.3.4 - 5.3.1-SNAPSHOT + 5.4.0 diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt index 263ea403c..d557effa1 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.3.1-SNAPSHOT") +addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.4.0") diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt index 0d3be3233..52ab284d7 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client-scala/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.3.1-SNAPSHOT" +version in ThisBuild := "5.4.0" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt index 263ea403c..d557effa1 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.3.1-SNAPSHOT") +addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % "5.4.0") diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt index 0d3be3233..52ab284d7 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/example-client/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.3.1-SNAPSHOT" +version in ThisBuild := "5.4.0" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt index f1514ded5..d898283b9 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/project/plugins.sbt @@ -1,4 +1,4 @@ -sys.props.get("plugin.version").orElse(Some("5.3.1-SNAPSHOT")) match { +sys.props.get("plugin.version").orElse(Some("5.4.0")) match { case Some(x) => addSbtPlugin("io.github.jxnu-liguobin" % "graphql-codegen-sbt-plugin" % x) case _ => sys.error("""|The system property 'plugin.version' is not defined. |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt index 0d3be3233..52ab284d7 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/src/sbt-test/graphql-codegen-sbt-plugin/simple/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.3.1-SNAPSHOT" +version in ThisBuild := "5.4.0" diff --git a/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt b/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt index 0d3be3233..52ab284d7 100644 --- a/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt +++ b/plugins/sbt/graphql-java-codegen-sbt-plugin/version.sbt @@ -1 +1 @@ -version in ThisBuild := "5.3.1-SNAPSHOT" +version in ThisBuild := "5.4.0"