Skip to content

Commit 9e85c13

Browse files
authored
Handle java-reserved names in client generated classes #237 (#238)
1 parent f05b793 commit 9e85c13

34 files changed

+1039
-22
lines changed

src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionToParameterMapper.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ private static ParameterDefinition mapField(MappingContext mappingContext, Exten
6969
String parentTypeName) {
7070
ParameterDefinition parameter = new ParameterDefinition();
7171
parameter.setName(MapperUtils.capitalizeIfRestricted(fieldDef.getName()));
72+
parameter.setOriginalName(fieldDef.getName());
7273
parameter.setType(getJavaType(mappingContext, fieldDef.getType(), fieldDef.getName(), parentTypeName).getName());
7374
parameter.setAnnotations(getAnnotations(mappingContext, fieldDef.getType(), fieldDef.getName(), parentTypeName, false));
7475
parameter.setJavaDoc(fieldDef.getJavaDoc());
@@ -88,11 +89,11 @@ private static ProjectionParameterDefinition mapProjectionField(MappingContext m
8889
ExtendedFieldDefinition fieldDef,
8990
ExtendedDefinition<?, ?> parentTypeDef) {
9091
ProjectionParameterDefinition parameter = new ProjectionParameterDefinition();
91-
parameter.setName(MapperUtils.capitalizeIfRestricted(fieldDef.getName()));
92-
parameter.setMethodName(parameter.getName());
92+
parameter.setName(fieldDef.getName());
93+
parameter.setMethodName(MapperUtils.capitalizeMethodNameIfRestricted(parameter.getName()));
9394
String nestedType = getNestedTypeName(fieldDef.getType());
9495
if (mappingContext.getTypesUnionsInterfacesNames().contains(nestedType)) {
95-
parameter.setType(nestedType + mappingContext.getResponseProjectionSuffix());
96+
parameter.setType(Utils.capitalize(nestedType + mappingContext.getResponseProjectionSuffix()));
9697
}
9798
if (!Utils.isEmpty(fieldDef.getInputValueDefinitions())) {
9899
parameter.setParametrizedInputClassName(

src/main/java/com/kobylynskyi/graphql/codegen/mapper/FieldDefinitionsToResolverDataModelMapper.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ private static OperationDefinition map(MappingContext mappingContext, ExtendedFi
139139
String javaType = GraphqlTypeToJavaTypeMapper.getJavaType(
140140
mappingContext, resolvedField.getType(), resolvedField.getName(), parentTypeName).getName();
141141
OperationDefinition operation = new OperationDefinition();
142-
operation.setName(resolvedField.getName());
142+
operation.setName(MapperUtils.capitalizeIfRestricted(resolvedField.getName()));
143+
operation.setOriginalName(resolvedField.getName());
143144
operation.setType(GraphqlTypeToJavaTypeMapper.wrapIntoAsyncIfRequired(mappingContext, javaType, parentTypeName));
144145
operation.setAnnotations(GraphqlTypeToJavaTypeMapper.getAnnotations(mappingContext,
145146
resolvedField.getType(), resolvedField.getName(), parentTypeName, false));
@@ -158,7 +159,7 @@ private static List<ParameterDefinition> getOperationParameters(MappingContext m
158159
if (!Utils.isGraphqlOperation(parentTypeName)) {
159160
String parentObjectParamType = GraphqlTypeToJavaTypeMapper.getJavaType(mappingContext, new TypeName(parentTypeName));
160161
String parentObjectParamName = MapperUtils.capitalizeIfRestricted(Utils.uncapitalize(parentObjectParamType));
161-
parameters.add(new ParameterDefinition(parentObjectParamType, parentObjectParamName, null, emptyList(), emptyList(), resolvedField.isDeprecated()));
162+
parameters.add(new ParameterDefinition(parentObjectParamType, parentObjectParamName, parentObjectParamName, null, emptyList(), emptyList(), resolvedField.isDeprecated()));
162163
}
163164

164165
// 2. Next parameters are input values

src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputValueDefinitionToParameterMapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public static List<ParameterDefinition> map(MappingContext mappingContext, List<
4747
private static ParameterDefinition map(MappingContext mappingContext, InputValueDefinition inputValueDefinition, String parentTypeName) {
4848
ParameterDefinition parameter = new ParameterDefinition();
4949
parameter.setName(MapperUtils.capitalizeIfRestricted(inputValueDefinition.getName()));
50+
parameter.setOriginalName(inputValueDefinition.getName());
5051
parameter.setType(getJavaType(mappingContext, inputValueDefinition.getType()));
5152
parameter.setDefaultValue(DefaultValueMapper.map(mappingContext, inputValueDefinition.getDefaultValue(), inputValueDefinition.getType()));
5253
parameter.setAnnotations(getAnnotations(mappingContext, inputValueDefinition.getType(), inputValueDefinition.getName(), parentTypeName, false));

src/main/java/com/kobylynskyi/graphql/codegen/mapper/MapperUtils.java

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import java.util.function.Function;
2424
import java.util.stream.Collectors;
2525

26-
class MapperUtils {
26+
public class MapperUtils {
2727

2828
private static final Set<String> JAVA_RESTRICTED_KEYWORDS = new HashSet<>(Arrays.asList(
2929
"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue",
@@ -32,25 +32,48 @@ class MapperUtils {
3232
"private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch",
3333
"synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while"));
3434

35+
private static final Set<String> JAVA_RESTRICTED_METHOD_NAMES = new HashSet<>(Arrays.asList(
36+
"getClass", "notify", "notifyAll", "wait"));
37+
3538
private MapperUtils() {
3639
}
3740

3841
/**
3942
* Capitalize field name if it is Java-restricted.
4043
* Examples:
41-
* * class -> Class
42-
* * int -> Int
44+
* * 'class' becomes 'Class'
45+
* * 'int' becomes 'Int'
4346
*
4447
* @param fieldName any string
4548
* @return capitalized value if it is restricted in Java, same value as parameter otherwise
4649
*/
47-
static String capitalizeIfRestricted(String fieldName) {
50+
public static String capitalizeIfRestricted(String fieldName) {
4851
if (JAVA_RESTRICTED_KEYWORDS.contains(fieldName)) {
4952
return Utils.capitalize(fieldName);
5053
}
5154
return fieldName;
5255
}
5356

57+
/**
58+
* Capitalize method name if it is Java-restricted.
59+
* Examples:
60+
* * 'getClass' becomes 'GetClass'
61+
* * 'wait' becomes 'Wait'
62+
* * 'this' becomes 'This'
63+
*
64+
* @param methodName any string
65+
* @return capitalized value if it is restricted in Java, same value as parameter otherwise
66+
*/
67+
public static String capitalizeMethodNameIfRestricted(String methodName) {
68+
if (JAVA_RESTRICTED_KEYWORDS.contains(methodName)) {
69+
return Utils.capitalize(methodName);
70+
}
71+
if (JAVA_RESTRICTED_METHOD_NAMES.contains(methodName)) {
72+
return Utils.capitalize(methodName);
73+
}
74+
return methodName;
75+
}
76+
5477
/**
5578
* Generates a model class name including prefix and suffix (if any)
5679
*

src/main/java/com/kobylynskyi/graphql/codegen/mapper/RequestResponseDefinitionToDataModelMapper.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.FIELDS;
2626
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_INFO;
2727
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.JAVA_DOC;
28+
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.METHOD_NAME;
2829
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.OPERATION_NAME;
2930
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.OPERATION_TYPE;
3031
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.PACKAGE;
@@ -118,6 +119,7 @@ public static Map<String, Object> mapResponse(MappingContext mappingContext,
118119
dataModel.put(JAVA_DOC, operationDef.getJavaDoc());
119120
dataModel.put(DEPRECATED, operationDef.isDeprecated());
120121
dataModel.put(OPERATION_NAME, operationDef.getName());
122+
dataModel.put(METHOD_NAME, MapperUtils.capitalizeMethodNameIfRestricted(operationDef.getName()));
121123
dataModel.put(RETURN_TYPE_NAME, javaType);
122124
dataModel.put(GENERATED_INFO, mappingContext.getGeneratedInformation());
123125
return dataModel;
@@ -277,7 +279,7 @@ private static ProjectionParameterDefinition getChildDefinition(MappingContext m
277279
ProjectionParameterDefinition parameter = new ProjectionParameterDefinition();
278280
parameter.setName("...on " + childName);
279281
parameter.setMethodName("on" + childName);
280-
parameter.setType(childName + mappingContext.getResponseProjectionSuffix());
282+
parameter.setType(Utils.capitalize(childName + mappingContext.getResponseProjectionSuffix()));
281283
return parameter;
282284
}
283285

src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public final class DataModelFields {
2424
public static final String ANNOTATIONS = "annotations";
2525
public static final String OPERATION_TYPE = "operationType";
2626
public static final String OPERATION_NAME = "operationName";
27+
public static final String METHOD_NAME = "methodName";
2728
public static final String RETURN_TYPE_NAME = "returnTypeName";
2829
public static final String GENERATED_INFO = "generatedInfo";
2930

src/main/java/com/kobylynskyi/graphql/codegen/model/OperationDefinition.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@
1010
*/
1111
public class OperationDefinition {
1212

13+
/**
14+
* Normalized name using {@link com.kobylynskyi.graphql.codegen.mapper.MapperUtils#capitalizeIfRestricted(String) MapperUtils.capitalizeIfRestricted() }
15+
*/
1316
private String name;
17+
/**
18+
* Original name that appears in GraphQL schema
19+
*/
20+
private String originalName;
1421
private String type;
1522
private List<String> annotations = new ArrayList<>();
1623
private List<ParameterDefinition> parameters = new ArrayList<>();
@@ -25,6 +32,14 @@ public void setName(String name) {
2532
this.name = name;
2633
}
2734

35+
public String getOriginalName() {
36+
return originalName;
37+
}
38+
39+
public void setOriginalName(String originalName) {
40+
this.originalName = originalName;
41+
}
42+
2843
public String getType() {
2944
return type;
3045
}

src/main/java/com/kobylynskyi/graphql/codegen/model/ParameterDefinition.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,17 @@
1515
public class ParameterDefinition {
1616

1717
public static final ParameterDefinition DATA_FETCHING_ENVIRONMENT = new ParameterDefinition(
18-
DataFetchingEnvironment.class.getName(), "env", null, emptyList(), emptyList(), false);
18+
DataFetchingEnvironment.class.getName(), "env", "env", null, emptyList(), emptyList(), false);
1919

2020
private String type;
21+
/**
22+
* Normalized name using {@link com.kobylynskyi.graphql.codegen.mapper.MapperUtils#capitalizeIfRestricted(String) MapperUtils.capitalizeIfRestricted() }
23+
*/
2124
private String name;
25+
/**
26+
* Original name that appears in GraphQL schema
27+
*/
28+
private String originalName;
2229
private String defaultValue;
2330
private List<String> annotations = new ArrayList<>();
2431
private List<String> javaDoc = new ArrayList<>();
@@ -27,12 +34,11 @@ public class ParameterDefinition {
2734
public ParameterDefinition() {
2835
}
2936

30-
public ParameterDefinition(String type, String name, String defaultValue,
31-
List<String> annotations,
32-
List<String> javaDoc,
33-
boolean deprecated) {
37+
public ParameterDefinition(String type, String name, String originalName, String defaultValue,
38+
List<String> annotations, List<String> javaDoc, boolean deprecated) {
3439
this.type = type;
3540
this.name = name;
41+
this.originalName = originalName;
3642
this.defaultValue = defaultValue;
3743
this.annotations = annotations;
3844
this.javaDoc = javaDoc;
@@ -55,6 +61,14 @@ public void setName(String name) {
5561
this.name = name;
5662
}
5763

64+
public String getOriginalName() {
65+
return originalName;
66+
}
67+
68+
public void setOriginalName(String originalName) {
69+
this.originalName = originalName;
70+
}
71+
5872
public String getDefaultValue() {
5973
return defaultValue;
6074
}

src/main/resources/templates/javaClassGraphqlParametrizedInput.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public class ${className} implements GraphQLParametrizedInput {
103103
<#if fields?has_content>
104104
<#list fields as field>
105105
if (${field.name} != null) {
106-
joiner.add("${field.name}: " + GraphQLRequestSerializer.getEntry(${field.name}));
106+
joiner.add("${field.originalName}: " + GraphQLRequestSerializer.getEntry(${field.name}));
107107
}
108108
</#list>
109109
</#if>

src/main/resources/templates/javaClassGraphqlRequest.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public class ${className} implements GraphQLOperationRequest {
4949
@Deprecated
5050
</#if>
5151
public void set${field.name?cap_first}(${field.type} ${field.name}) {
52-
this.input.put("${field.name}", ${field.name});
52+
this.input.put("${field.originalName}", ${field.name});
5353
}
5454

5555
</#list>

0 commit comments

Comments
 (0)