From 92e276b688753fc514ae241cc99f2f6097f7ab31 Mon Sep 17 00:00:00 2001 From: Bogdan Kobylynskyi <92bogdan@gmail.com> Date: Wed, 30 Sep 2020 16:41:12 -0500 Subject: [PATCH] Generate parametrized input class for interfaces #327 (#330) --- .../graphql/codegen/GraphQLCodegen.java | 24 +++++++---- ...stResponseDefinitionToDataModelMapper.java | 2 +- .../GraphQLCodegenFieldsResolversTest.java | 13 ++++++ .../GraphQLCodegenModelsForRootTypesTest.java | 4 +- .../ProductLinkCodeParametrizedInput.java.txt | 41 +++++++++++++++++++ .../parametrized-input-client.graphqls | 15 +++++++ 6 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 src/test/resources/expected-classes/request/ProductLinkCodeParametrizedInput.java.txt create mode 100644 src/test/resources/schemas/parametrized-input-client.graphqls diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegen.java b/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegen.java index 026fe265..ae84e744 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegen.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegen.java @@ -279,8 +279,7 @@ public class GraphQLCodegen { for (ExtendedInterfaceTypeDefinition definition : document.getInterfaceDefinitions()) { generateFieldResolver(context, definition.getFieldDefinitions(), definition).ifPresent(generatedFiles::add); } - System.out.println(String.format("Generated %d definition classes in folder %s", - generatedFiles.size(), outputDir.getAbsolutePath())); + System.out.printf("Generated %d definition classes in folder %s%n", generatedFiles.size(), outputDir.getAbsolutePath()); return generatedFiles; } @@ -304,6 +303,13 @@ public class GraphQLCodegen { if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) { Map responseProjDataModel = RequestResponseDefinitionToDataModelMapper.mapResponseProjection(mappingContext, definition); generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.responseProjectionTemplate, responseProjDataModel, outputDir)); + + for (ExtendedFieldDefinition fieldDefinition : definition.getFieldDefinitions()) { + if (!Utils.isEmpty(fieldDefinition.getInputValueDefinitions())) { + Map fieldProjDataModel = RequestResponseDefinitionToDataModelMapper.mapParametrizedInput(mappingContext, fieldDefinition, definition); + generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.parametrizedInputTemplate, fieldProjDataModel, outputDir)); + } + } } return generatedFiles; } @@ -398,12 +404,14 @@ public class GraphQLCodegen { private Optional generateFieldResolver(MappingContext mappingContext, List fieldDefinitions, ExtendedDefinition parentDefinition) { - List fieldDefsWithResolvers = fieldDefinitions.stream() - .filter(fieldDef -> FieldDefinitionToParameterMapper.generateResolversForField(mappingContext, fieldDef, parentDefinition)) - .collect(toList()); - if (!fieldDefsWithResolvers.isEmpty()) { - Map dataModel = FieldDefinitionsToResolverDataModelMapper.mapToTypeResolver(mappingContext, fieldDefsWithResolvers, parentDefinition.getName()); - return Optional.of(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.operationsTemplate, dataModel, outputDir)); + if (Boolean.TRUE.equals(mappingConfig.getGenerateApis())) { + List fieldDefsWithResolvers = fieldDefinitions.stream() + .filter(fieldDef -> FieldDefinitionToParameterMapper.generateResolversForField(mappingContext, fieldDef, parentDefinition)) + .collect(toList()); + if (!fieldDefsWithResolvers.isEmpty()) { + Map dataModel = FieldDefinitionsToResolverDataModelMapper.mapToTypeResolver(mappingContext, fieldDefsWithResolvers, parentDefinition.getName()); + return Optional.of(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.operationsTemplate, dataModel, outputDir)); + } } return Optional.empty(); } 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 6251d9b9..a4452314 100644 --- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java +++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java @@ -64,7 +64,7 @@ public class RequestResponseDefinitionToDataModelMapper { */ public static Map mapParametrizedInput(MappingContext mappingContext, ExtendedFieldDefinition fieldDefinition, - ExtendedObjectTypeDefinition parentTypeDefinition) { + ExtendedDefinition parentTypeDefinition) { String className = MapperUtils.getParametrizedInputClassName(mappingContext, fieldDefinition, parentTypeDefinition); Map dataModel = new HashMap<>(); // ParametrizedInput classes are sharing the package with the model classes, so no imports are needed diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFieldsResolversTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFieldsResolversTest.java index e75c4d86..48add0c5 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFieldsResolversTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenFieldsResolversTest.java @@ -50,6 +50,19 @@ class GraphQLCodegenFieldsResolversTest { getFileByName(files, "CommitResolver.java")); } + @Test + void generate_ParametrizedFieldsInInterface() throws Exception { + mappingConfig.setGenerateClient(true); + mappingConfig.setGenerateApis(false); + + new GraphQLCodegen(singletonList("src/test/resources/schemas/parametrized-input-client.graphqls"), + outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate(); + + File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); + assertSameTrimmedContent(new File("src/test/resources/expected-classes/request/ProductLinkCodeParametrizedInput.java.txt"), + getFileByName(files, "ProductLinkCodeParametrizedInput.java")); + } + @Test void generate_CustomFieldsResolvers() throws Exception { mappingConfig.setModelNamePrefix("Github"); diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenModelsForRootTypesTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenModelsForRootTypesTest.java index c47c877e..3dda5324 100644 --- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenModelsForRootTypesTest.java +++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphQLCodegenModelsForRootTypesTest.java @@ -70,8 +70,8 @@ class GraphQLCodegenModelsForRootTypesTest { File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); List generatedFileNames = Arrays.stream(files).map(File::getName).sorted().collect(toList()); - assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventPropertyResolver.java", "EventStatus.java", - "Mutation.java", "MutationResolver.java", "Query.java", "QueryResolver.java", "Subscription.java"), + assertEquals(Arrays.asList("Event.java", "EventProperty.java", "EventStatus.java", + "Mutation.java", "Query.java", "Subscription.java"), generatedFileNames); } diff --git a/src/test/resources/expected-classes/request/ProductLinkCodeParametrizedInput.java.txt b/src/test/resources/expected-classes/request/ProductLinkCodeParametrizedInput.java.txt new file mode 100644 index 00000000..6f51a4c6 --- /dev/null +++ b/src/test/resources/expected-classes/request/ProductLinkCodeParametrizedInput.java.txt @@ -0,0 +1,41 @@ +package com.github.graphql; + +import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLParametrizedInput; +import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLRequestSerializer; +import java.util.StringJoiner; + +/** + * Parametrized input for field linkCode in type Product + */ +@javax.annotation.Generated( + value = "com.kobylynskyi.graphql.codegen.GraphQLCodegen", + date = "2020-12-31T23:59:59-0500" +) +public class ProductLinkCodeParametrizedInput implements GraphQLParametrizedInput { + + @javax.validation.constraints.NotNull + private String pid; + + public ProductLinkCodeParametrizedInput() { + } + + public ProductLinkCodeParametrizedInput(String pid) { + this.pid = pid; + } + + public ProductLinkCodeParametrizedInput pid(String pid) { + this.pid = pid; + return this; + } + + + @Override + public String toString() { + StringJoiner joiner = new StringJoiner(", ", "(", ")"); + if (pid != null) { + joiner.add("pid: " + GraphQLRequestSerializer.getEntry(pid)); + } + return joiner.toString(); + } + +} \ No newline at end of file diff --git a/src/test/resources/schemas/parametrized-input-client.graphqls b/src/test/resources/schemas/parametrized-input-client.graphqls new file mode 100644 index 00000000..3b54aa97 --- /dev/null +++ b/src/test/resources/schemas/parametrized-input-client.graphqls @@ -0,0 +1,15 @@ +type Query { + product( + companyId: ID! + ): Product! +} + +interface Product { + linkCode( + pid: ID! + ): LinkCode +} + +type LinkCode { + html: String +} -- GitLab