Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plugins/gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ apply plugin: "io.github.kobylynskyi.graphql.codegen"
| `generateRequests` | Boolean | False | Specifies whether client-side classes should be generated for each query, mutation and subscription. This includes: `Request` class (contains input data) and `ResponseProjection` class (contains response fields). |
| `requestSuffix` | String | Request | Sets the suffix for `Request` classes. |
| `responseProjectionSuffix` | String | ResponseProjection | Sets the suffix for `ResponseProjection` classes. |
| `parametrizedInputSuffix` | String | ParametrizedInput | Sets the suffix for `ParametrizedInput` classes. |
| `parentInterfaces` | *See [parentInterfaces](#option-parentinterfaces)* | Empty | Block to define parent interfaces for generated interfaces (query / mutation / subscription / type resolver) |


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class GraphQLCodegenGradleTask extends DefaultTask implements GraphQLCode
private Boolean generateRequests;
private String requestSuffix;
private String responseProjectionSuffix;
private String parametrizedInputSuffix;
private final ParentInterfacesConfig parentInterfaces = new ParentInterfacesConfig();
private String jsonConfigurationFile;

Expand Down Expand Up @@ -84,6 +85,7 @@ public void generate() throws Exception {
mappingConfig.setGenerateRequests(generateRequests);
mappingConfig.setRequestSuffix(requestSuffix);
mappingConfig.setResponseProjectionSuffix(responseProjectionSuffix);
mappingConfig.setParametrizedInputSuffix(parametrizedInputSuffix);
mappingConfig.setResolverParentInterface(getResolverParentInterface());
mappingConfig.setQueryResolverParentInterface(getQueryResolverParentInterface());
mappingConfig.setMutationResolverParentInterface(getMutationResolverParentInterface());
Expand Down Expand Up @@ -408,6 +410,17 @@ public void setResponseProjectionSuffix(String responseProjectionSuffix) {
this.responseProjectionSuffix = responseProjectionSuffix;
}

@Input
@Optional
@Override
public String getParametrizedInputSuffix() {
return parametrizedInputSuffix;
}

public void setParametrizedInputSuffix(String parametrizedInputSuffix) {
this.parametrizedInputSuffix = parametrizedInputSuffix;
}

@Nested
@Optional
public ParentInterfacesConfig getParentInterfaces() {
Expand Down
1 change: 1 addition & 0 deletions plugins/maven/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ You can run the plugin manually with `mvn generate-sources`. It will be run auto
| `generateRequests` | Boolean | False | Specifies whether client-side classes should be generated for each query, mutation and subscription. This includes: `Request` class (contains input data) and `ResponseProjection` class (contains response fields). |
| `requestSuffix` | String | Request | Sets the suffix for `Request` classes. |
| `responseProjectionSuffix` | String | ResponseProjection | Sets the suffix for `ResponseProjection` classes. |
| `parametrizedInputSuffix` | String | ParametrizedInput | Sets the suffix for `ParametrizedInput` classes. |
| `parentInterfaces` | *See [parentInterfaces](#option-parentinterfaces)* | Empty | Block to define parent interfaces for generated interfaces (query / mutation / subscription / type resolver) |


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ public class GraphQLCodegenMojo extends AbstractMojo implements GraphQLCodegenCo
@Parameter(defaultValue = MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_SUFFIX)
private String responseProjectionSuffix;

@Parameter(defaultValue = MappingConfigConstants.DEFAULT_PARAMETRIZED_INPUT_SUFIX)
private String parametrizedInputSuffix;

@Parameter
private String jsonConfigurationFile;

Expand Down Expand Up @@ -138,6 +141,7 @@ public void execute() throws MojoExecutionException {
mappingConfig.setGenerateRequests(generateRequests);
mappingConfig.setRequestSuffix(requestSuffix);
mappingConfig.setResponseProjectionSuffix(responseProjectionSuffix);
mappingConfig.setParametrizedInputSuffix(parametrizedInputSuffix);
mappingConfig.setResolverParentInterface(getResolverParentInterface());
mappingConfig.setQueryResolverParentInterface(getQueryResolverParentInterface());
mappingConfig.setMutationResolverParentInterface(getMutationResolverParentInterface());
Expand Down Expand Up @@ -409,6 +413,19 @@ public String getResponseProjectionSuffix() {
return responseProjectionSuffix;
}

public void setResponseProjectionSuffix(String responseProjectionSuffix) {
this.responseProjectionSuffix = responseProjectionSuffix;
}

@Override
public String getParametrizedInputSuffix() {
return parametrizedInputSuffix;
}

public void setParametrizedInputSuffix(String parametrizedInputSuffix) {
this.parametrizedInputSuffix = parametrizedInputSuffix;
}

public ParentInterfacesConfig getParentInterfaces() {
return parentInterfaces;
}
Expand Down Expand Up @@ -437,10 +454,6 @@ public String getResolverParentInterface() {
return parentInterfaces.getResolver();
}

public void setResponseProjectionSuffix(String responseProjectionSuffix) {
this.responseProjectionSuffix = responseProjectionSuffix;
}

public String getJsonConfigurationFile() {
return jsonConfigurationFile;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class FreeMarkerTemplatesRegistry {
static Template requestTemplate;
static Template interfaceTemplate;
static Template operationsTemplate;
static Template parametrizedInputTemplate;
static Template responseProjectionTemplate;

static {
Expand All @@ -32,6 +33,7 @@ class FreeMarkerTemplatesRegistry {
requestTemplate = configuration.getTemplate("templates/javaClassGraphqlRequest.ftl");
interfaceTemplate = configuration.getTemplate("templates/javaClassGraphqlInterface.ftl");
operationsTemplate = configuration.getTemplate("templates/javaClassGraphqlOperations.ftl");
parametrizedInputTemplate = configuration.getTemplate("templates/javaClassGraphqlParametrizedInput.ftl");
responseProjectionTemplate = configuration.getTemplate("templates/javaClassGraphqlResponseProjection.ftl");
} catch (IOException e) {
throw new UnableToLoadFreeMarkerTemplateException(e);
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegen.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.kobylynskyi.graphql.codegen.model.MappingContext;
import com.kobylynskyi.graphql.codegen.model.definitions.*;
import com.kobylynskyi.graphql.codegen.supplier.MappingConfigSupplier;
import com.kobylynskyi.graphql.codegen.utils.Utils;
import graphql.language.FieldDefinition;
import graphql.language.ScalarTypeExtensionDefinition;
import lombok.Getter;
Expand Down Expand Up @@ -64,6 +65,9 @@ private void initDefaultValues(MappingConfig mappingConfig) {
if (mappingConfig.getResponseProjectionSuffix() == null) {
mappingConfig.setResponseProjectionSuffix(MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_SUFFIX);
}
if (mappingConfig.getParametrizedInputSuffix() == null) {
mappingConfig.setParametrizedInputSuffix(MappingConfigConstants.DEFAULT_PARAMETRIZED_INPUT_SUFIX);
}
if (mappingConfig.getGenerateToString() == null) {
mappingConfig.setGenerateToString(MappingConfigConstants.DEFAULT_TO_STRING);
}
Expand Down Expand Up @@ -179,6 +183,13 @@ private List<File> generateType(MappingContext mappingContext, ExtendedObjectTyp
if (Boolean.TRUE.equals(mappingConfig.getGenerateRequests())) {
Map<String, Object> responseProjDataModel = TypeDefinitionToDataModelMapper.mapResponseProjection(mappingContext, definition);
generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.responseProjectionTemplate, responseProjDataModel, outputDir));

for (ExtendedFieldDefinition fieldDefinition : definition.getFieldDefinitions()) {
if (!Utils.isEmpty(fieldDefinition.getInputValueDefinitions())) {
Map<String, Object> fieldProjDataModel = TypeDefinitionToDataModelMapper.mapParametrizedInput(mappingContext, fieldDefinition, definition);
generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.parametrizedInputTemplate, fieldProjDataModel, outputDir));
}
}
}
return generatedFiles;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.kobylynskyi.graphql.codegen.model.MappingContext;
import com.kobylynskyi.graphql.codegen.model.ParameterDefinition;
import com.kobylynskyi.graphql.codegen.model.ProjectionParameterDefinition;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition;
import com.kobylynskyi.graphql.codegen.utils.Utils;

Expand Down Expand Up @@ -38,14 +39,16 @@ public static List<ParameterDefinition> mapFields(MappingContext mappingContext,
/**
* Map field definition to a Freemarker-understandable data model type
*
* @param mappingContext Global mapping context
* @param fieldDefinitions List of GraphQL field definitions
* @param mappingContext Global mapping context
* @param fieldDefinitions List of GraphQL field definitions
* @param parentTypeDefinition Parent GraphQL type definition
* @return Freemarker data model of the GraphQL field definition
*/
public static List<ProjectionParameterDefinition> mapProjectionFields(MappingContext mappingContext,
List<ExtendedFieldDefinition> fieldDefinitions) {
List<ExtendedFieldDefinition> fieldDefinitions,
ExtendedDefinition<?, ?> parentTypeDefinition) {
return fieldDefinitions.stream()
.map(fieldDef -> mapProjectionField(mappingContext, fieldDef))
.map(fieldDef -> mapProjectionField(mappingContext, fieldDef, parentTypeDefinition))
.collect(toList());
}

Expand Down Expand Up @@ -73,16 +76,22 @@ private static ParameterDefinition mapField(MappingContext mappingContext, Exten
*
* @param mappingContext Global mapping context
* @param fieldDef GraphQL field definition
* @param parentTypeDef GraphQL definition which is a parent to provided field definition
* @return Freemarker-understandable format of parameter (field)
*/
private static ProjectionParameterDefinition mapProjectionField(MappingContext mappingContext,
ExtendedFieldDefinition fieldDef) {
ExtendedFieldDefinition fieldDef,
ExtendedDefinition<?, ?> parentTypeDef) {
ProjectionParameterDefinition parameter = new ProjectionParameterDefinition();
parameter.setName(MapperUtils.capitalizeIfRestricted(fieldDef.getName()));
String nestedType = getNestedTypeName(fieldDef.getType());
if (mappingContext.getTypeNames().contains(nestedType)) {
parameter.setType(nestedType + mappingContext.getResponseProjectionSuffix());
}
if (!Utils.isEmpty(fieldDef.getInputValueDefinitions())) {
parameter.setParametrizedInputClassName(
MapperUtils.getParametrizedInputClassName(mappingContext, fieldDef, parentTypeDef));
}
parameter.setDeprecated(fieldDef.isDeprecated());
return parameter;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ static String getClassNameWithPrefixAndSuffix(MappingContext mappingContext, Str
return classNameBuilder.toString();
}

/**
* Generates a class name for ParametrizedInput
*
* @param mappingContext Global mapping context
* @param fieldDefinition GraphQL field definition for a field that has parametrized input
* @param parentTypeDefinition GraphQL definition which is a parent for fieldDefinition
* @return Class name of parametrized input
*/
static String getParametrizedInputClassName(MappingContext mappingContext,
ExtendedFieldDefinition fieldDefinition,
ExtendedDefinition<?, ?> parentTypeDefinition) {
return Utils.capitalize(parentTypeDefinition.getName()) +
Utils.capitalize(fieldDefinition.getName()) +
mappingContext.getParametrizedInputSuffix();
}

/**
* Get java package name for api class.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.kobylynskyi.graphql.codegen.model.ParameterDefinition;
import com.kobylynskyi.graphql.codegen.model.ProjectionParameterDefinition;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDocument;
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.model.definitions.ExtendedUnionTypeDefinition;
Expand Down Expand Up @@ -68,6 +69,31 @@ public static Map<String, Object> mapResponseProjection(MappingContext mappingCo
return dataModel;
}

/**
* Map field definition to a Freemarker data model of Parametrized Input.
*
* @param mappingContext Global mapping context
* @param fieldDefinition GraphQL field definition
* @param parentTypeDefinition GraphQL parent type definition
* @return Freemarker data model of the GraphQL Parametrized Input
*/
public static Map<String, Object> mapParametrizedInput(MappingContext mappingContext,
ExtendedFieldDefinition fieldDefinition,
ExtendedObjectTypeDefinition parentTypeDefinition) {
Map<String, Object> dataModel = new HashMap<>();
// ParametrizedInput classes are sharing the package with the model classes, so no imports are needed
dataModel.put(PACKAGE, MapperUtils.getModelPackageName(mappingContext));
dataModel.put(CLASS_NAME, MapperUtils.getParametrizedInputClassName(mappingContext, fieldDefinition, parentTypeDefinition));
dataModel.put(JAVA_DOC, Collections.singletonList(String.format("Parametrized input for field %s in type %s",
fieldDefinition.getName(), parentTypeDefinition.getName())));
dataModel.put(FIELDS, InputValueDefinitionToParameterMapper.map(
mappingContext, fieldDefinition.getInputValueDefinitions(), parentTypeDefinition.getName()));
dataModel.put(BUILDER, mappingContext.getGenerateBuilder());
dataModel.put(EQUALS_AND_HASH_CODE, mappingContext.getGenerateEqualsAndHashCode());
// dataModel.put(TO_STRING, mappingConfig.getGenerateToString()); always generated for serialization purposes
return dataModel;
}

/**
* Get merged attributes from the type and attributes from the interface.
*
Expand Down Expand Up @@ -124,11 +150,11 @@ private static Collection<ProjectionParameterDefinition> getProjectionFields(Map
Map<String, ProjectionParameterDefinition> allParameters = new LinkedHashMap<>();

// includes parameters from the base definition and extensions
FieldDefinitionToParameterMapper.mapProjectionFields(mappingContext, typeDefinition.getFieldDefinitions())
FieldDefinitionToParameterMapper.mapProjectionFields(mappingContext, typeDefinition.getFieldDefinitions(), typeDefinition)
.forEach(p -> allParameters.put(p.getName(), p));
// includes parameters from the interface
getInterfacesOfType(typeDefinition, mappingContext.getDocument()).stream()
.map(i -> FieldDefinitionToParameterMapper.mapProjectionFields(mappingContext, i.getFieldDefinitions()))
.map(i -> FieldDefinitionToParameterMapper.mapProjectionFields(mappingContext, i.getFieldDefinitions(), i))
.flatMap(Collection::stream)
.filter(paramDef -> !allParameters.containsKey(paramDef.getName()))
.forEach(paramDef -> allParameters.put(paramDef.getName(), paramDef));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@ public interface GraphQLCodegenConfiguration {
*/
String getResponseProjectionSuffix();

/**
* The suffix for `ParametrizedInput` classes.
*
* @return The suffix for `ParametrizedInput` classes.
*/
String getParametrizedInputSuffix();

/**
* Interface that will be added as "extend" to all generated api Query interfaces.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public class MappingConfig implements GraphQLCodegenConfiguration, Combinable<Ma
private Boolean generateRequests;
private String requestSuffix;
private String responseProjectionSuffix;
private String parametrizedInputSuffix;

@Override
public void combine(MappingConfig source) {
Expand Down Expand Up @@ -92,6 +93,7 @@ public void combine(MappingConfig source) {
this.generateRequests = source.generateRequests != null ? source.generateRequests : this.generateRequests;
this.requestSuffix = source.requestSuffix != null ? source.requestSuffix : this.requestSuffix;
this.responseProjectionSuffix = source.responseProjectionSuffix != null ? source.responseProjectionSuffix : this.responseProjectionSuffix;
this.parametrizedInputSuffix = source.parametrizedInputSuffix != null ? source.parametrizedInputSuffix : this.parametrizedInputSuffix;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ public class MappingConfigConstants {
public static final String DEFAULT_GENERATE_REQUESTS_STRING = "false";
public static final String DEFAULT_REQUEST_SUFFIX = "Request";
public static final String DEFAULT_RESPONSE_PROJECTION_SUFFIX = "ResponseProjection";
public static final String DEFAULT_PARAMETRIZED_INPUT_SUFIX = "ParametrizedInput";
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ public String getResponseProjectionSuffix() {
return config.getResponseProjectionSuffix();
}

@Override
public String getParametrizedInputSuffix() {
return config.getParametrizedInputSuffix();
}

@Override
public String getQueryResolverParentInterface() {
return config.getQueryResolverParentInterface();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ public class ProjectionParameterDefinition {
private String type;
private String name;
private boolean deprecated;
private String parametrizedInputClassName;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.kobylynskyi.graphql.codegen.model.graphql;

/**
* The implementation class should contain the input values of the field definition.
*/
public interface GraphQLParametrizedInput {

}
Loading