Skip to content

Commit 1e8debd

Browse files
lmartellottoLaura Martellotto
authored andcommitted
Field aliases support for client generator #173 (#174)
Co-authored-by: Laura Martellotto <[email protected]>
1 parent d27a739 commit 1e8debd

File tree

13 files changed

+447
-83
lines changed

13 files changed

+447
-83
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.kobylynskyi.graphql.codegen.model.graphql;
2+
3+
import java.util.Objects;
4+
import java.util.StringJoiner;
5+
6+
/**
7+
* Class which contains all information about a field which should
8+
* be returned back to the client.
9+
*/
10+
public class GraphQLResponseField {
11+
12+
private final String name;
13+
private String alias;
14+
private GraphQLParametrizedInput parameters;
15+
private GraphQLResponseProjection projection;
16+
17+
public GraphQLResponseField(String name) {
18+
this.name = name;
19+
}
20+
21+
public GraphQLResponseField alias(String alias) {
22+
this.alias = alias;
23+
return this;
24+
}
25+
26+
public GraphQLResponseField parameters(GraphQLParametrizedInput parameters) {
27+
this.parameters = parameters;
28+
return this;
29+
}
30+
31+
public GraphQLResponseField projection(GraphQLResponseProjection projection) {
32+
this.projection = projection;
33+
return this;
34+
}
35+
36+
public String getName() {
37+
return name;
38+
}
39+
40+
public String getAlias() {
41+
return alias;
42+
}
43+
44+
public GraphQLParametrizedInput getParameters() {
45+
return parameters;
46+
}
47+
48+
public GraphQLResponseProjection getProjection() {
49+
return projection;
50+
}
51+
52+
@Override
53+
public String toString() {
54+
StringJoiner joiner = new StringJoiner(" ");
55+
56+
if (getAlias() != null) {
57+
joiner.add(getAlias()).add(":");
58+
}
59+
joiner.add(getName());
60+
if (getParameters() != null) {
61+
joiner.add(getParameters().toString());
62+
}
63+
if (getProjection() != null) {
64+
joiner.add(getProjection().toString());
65+
}
66+
67+
return joiner.toString();
68+
}
69+
70+
@Override
71+
public boolean equals(Object obj) {
72+
if (this == obj) {
73+
return true;
74+
}
75+
if (obj == null || getClass() != obj.getClass()) {
76+
return false;
77+
}
78+
final GraphQLResponseField that = (GraphQLResponseField) obj;
79+
return Objects.equals(name, that.name)
80+
&& Objects.equals(alias, that.alias)
81+
&& Objects.equals(parameters, that.parameters)
82+
&& Objects.equals(projection, that.projection);
83+
}
84+
85+
@Override
86+
public int hashCode() {
87+
return Objects.hash(name, alias, parameters, projection);
88+
}
89+
}
Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.kobylynskyi.graphql.codegen.model.graphql;
22

3-
import java.util.LinkedHashMap;
4-
import java.util.Map;
3+
import java.util.ArrayList;
4+
import java.util.List;
55
import java.util.StringJoiner;
66

77
/**
@@ -10,26 +10,15 @@
1010
*/
1111
public abstract class GraphQLResponseProjection {
1212

13-
protected final Map<String, Object> fields = new LinkedHashMap<>();
14-
protected final Map<String, GraphQLParametrizedInput> parametrizedInputs = new LinkedHashMap<>();
13+
protected final List<GraphQLResponseField> fields = new ArrayList<>();
1514

1615
@Override
1716
public String toString() {
1817
if (fields.isEmpty()) {
1918
return "";
2019
}
2120
StringJoiner joiner = new StringJoiner(" ", "{ ", " }");
22-
for (Map.Entry<String, Object> property : fields.entrySet()) {
23-
joiner.add(property.getKey());
24-
GraphQLParametrizedInput parametrizedInput = parametrizedInputs.get(property.getKey());
25-
if (parametrizedInput != null) {
26-
joiner.add(parametrizedInput.toString());
27-
}
28-
if (property.getValue() != null) {
29-
joiner.add(" ").add(property.getValue().toString());
30-
}
31-
}
21+
fields.forEach(field -> joiner.add(field.toString()));
3222
return joiner.toString();
3323
}
34-
3524
}

src/main/resources/templates/javaClassGraphqlResponseProjection.ftl

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
package ${package};
33

44
</#if>
5+
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLResponseField;
56
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLResponseProjection;
67
<#if equalsAndHashCode>
78
import java.util.Objects;
@@ -31,14 +32,22 @@ public class ${className} extends GraphQLResponseProjection {
3132
@Deprecated
3233
</#if>
3334
public ${className} ${field.name}(<#if field.type?has_content>${field.type} subProjection</#if>) {
34-
fields.put("${field.name}", <#if field.type?has_content>subProjection<#else>null</#if>);
35+
return ${field.name}(<#if field.parametrizedInputClassName?has_content>(String)</#if>null<#if field.type?has_content>, subProjection</#if>);
36+
}
37+
38+
public ${className} ${field.name}(String alias<#if field.type?has_content>, ${field.type} subProjection</#if>) {
39+
fields.add(new GraphQLResponseField("${field.name}").alias(alias)<#if field.type?has_content>.projection(subProjection)</#if>);
3540
return this;
3641
}
3742

3843
<#if field.parametrizedInputClassName?has_content>
3944
public ${className} ${field.name}(${field.parametrizedInputClassName} input<#if field.type?has_content>, ${field.type} subProjection</#if>) {
40-
parametrizedInputs.put("${field.name}", input);
41-
return ${field.name}(<#if field.type?has_content>subProjection</#if>);
45+
return ${field.name}(null, input<#if field.type?has_content>, subProjection</#if>);
46+
}
47+
48+
public ${className} ${field.name}(String alias, ${field.parametrizedInputClassName} input<#if field.type?has_content>, ${field.type} subProjection</#if>) {
49+
fields.add(new GraphQLResponseField("${field.name}").alias(alias).parameters(input)<#if field.type?has_content>.projection(subProjection)</#if>);
50+
return this;
4251
}
4352

4453
</#if>
@@ -53,12 +62,12 @@ public class ${className} extends GraphQLResponseProjection {
5362
return false;
5463
}
5564
final ${className} that = (${className}) obj;
56-
return Objects.equals(fields, that.fields) && Objects.equals(parametrizedInputs, that.parametrizedInputs);
65+
return Objects.equals(fields, that.fields);
5766
}
5867

5968
@Override
6069
public int hashCode() {
61-
return Objects.hash(fields, parametrizedInputs);
70+
return Objects.hash(fields);
6271
}
6372
</#if>
6473

src/test/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequestSerializerTest.java

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,39 @@ void serialize_withResponseProjection(String name, Function<GraphQLRequest, Stri
9999
assertEquals(expectedQueryDecorator.apply(expectedQueryStr), serializedQuery);
100100
}
101101

102+
@ParameterizedTest(name = "{0}")
103+
@MethodSource("provideAllSerializers")
104+
void serialize_withResponseProjectionAndAlias(String name, Function<GraphQLRequest, String> serializer, Function<String, String> expectedQueryDecorator) {
105+
EventsByCategoryAndStatusQueryRequest request = new EventsByCategoryAndStatusQueryRequest.Builder()
106+
.setCategoryId("categoryIdValue1")
107+
.setStatus(Status.OPEN)
108+
.build();
109+
GraphQLRequest graphQLRequest = new GraphQLRequest(request,
110+
new EventResponseProjection()
111+
.id("myId")
112+
.active("myActive")
113+
.properties("myProps", new EventPropertyResponseProjection()
114+
.floatVal("myFloatVal")
115+
.child("myChild", new EventPropertyResponseProjection()
116+
.intVal("myIntVal")
117+
.parent("myParent", new EventResponseProjection()
118+
.id("myId")))
119+
.booleanVal("myBooleanVal"))
120+
.status("myStatus")
121+
);
122+
String serializedQuery = serializer.apply(graphQLRequest).replaceAll(" +", " ").trim();
123+
String expectedQueryStr = "query { " +
124+
"eventsByCategoryAndStatus(categoryId: \"categoryIdValue1\", status: OPEN){ " +
125+
"myId : id " +
126+
"myActive : active " +
127+
"myProps : properties { " +
128+
"myFloatVal : floatVal myChild : child { myIntVal : intVal myParent : parent { myId : id } } myBooleanVal : booleanVal } " +
129+
"myStatus : status " +
130+
"} " +
131+
"}";
132+
assertEquals(expectedQueryDecorator.apply(expectedQueryStr), serializedQuery);
133+
}
134+
102135
@ParameterizedTest(name = "{0}")
103136
@MethodSource("provideAllSerializers")
104137
void serialize_withResponseProjectionAndParametrizedInput(String name, Function<GraphQLRequest, String> serializer, Function<String, String> expectedQueryDecorator) {
@@ -134,8 +167,44 @@ void serialize_withResponseProjectionAndParametrizedInput(String name, Function<
134167
"status " +
135168
"} " +
136169
"}";
137-
System.out.println(expectedQueryDecorator.apply(expectedQueryStr));
138-
System.out.println(serializedQuery);
170+
assertEquals(expectedQueryDecorator.apply(expectedQueryStr), serializedQuery);
171+
}
172+
173+
@ParameterizedTest(name = "{0}")
174+
@MethodSource("provideAllSerializers")
175+
void serialize_withResponseProjectionAndParametrizedInputAndAlias(String name, Function<GraphQLRequest, String> serializer, Function<String, String> expectedQueryDecorator) {
176+
EventsByCategoryAndStatusQueryRequest request = new EventsByCategoryAndStatusQueryRequest.Builder()
177+
.setCategoryId("categoryIdValue1")
178+
.setStatus(Status.OPEN)
179+
.build();
180+
GraphQLRequest graphQLRequest = new GraphQLRequest(request,
181+
new EventResponseProjection()
182+
.id()
183+
.active()
184+
.properties(new EventPropertyResponseProjection()
185+
.floatVal()
186+
.child("myChild", new EventPropertyChildParametrizedInput()
187+
.last(-10)
188+
.first(+10),
189+
new EventPropertyResponseProjection()
190+
.intVal()
191+
.parent("myParent", new EventPropertyParentParametrizedInput()
192+
.withStatus(Status.OPEN),
193+
new EventResponseProjection()
194+
.id()))
195+
.booleanVal())
196+
.status()
197+
);
198+
String serializedQuery = serializer.apply(graphQLRequest).replaceAll(" +", " ").trim();
199+
String expectedQueryStr = "query { " +
200+
"eventsByCategoryAndStatus(categoryId: \"categoryIdValue1\", status: OPEN){ " +
201+
"id " +
202+
"active " +
203+
"properties { " +
204+
"floatVal myChild : child (first: 10, last: -10) { intVal myParent : parent (withStatus: OPEN) { id } } booleanVal } " +
205+
"status " +
206+
"} " +
207+
"}";
139208
assertEquals(expectedQueryDecorator.apply(expectedQueryStr), serializedQuery);
140209
}
141210

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.kobylynskyi.graphql.codegen.model.graphql.data;
22

3+
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLResponseField;
34
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLResponseProjection;
45

56
/**
@@ -11,43 +12,75 @@ public EventPropertyResponseProjection() {
1112
}
1213

1314
public EventPropertyResponseProjection floatVal() {
14-
fields.put("floatVal", null);
15+
return floatVal(null);
16+
}
17+
18+
public EventPropertyResponseProjection floatVal(String alias) {
19+
fields.add(new GraphQLResponseField("floatVal").alias(alias));
1520
return this;
1621
}
1722

1823
public EventPropertyResponseProjection booleanVal() {
19-
fields.put("booleanVal", null);
24+
return booleanVal(null);
25+
}
26+
27+
public EventPropertyResponseProjection booleanVal(String alias) {
28+
fields.add(new GraphQLResponseField("booleanVal").alias(alias));
2029
return this;
2130
}
2231

2332
public EventPropertyResponseProjection intVal() {
24-
fields.put("intVal", null);
33+
return intVal(null);
34+
}
35+
36+
public EventPropertyResponseProjection intVal(String alias) {
37+
fields.add(new GraphQLResponseField("intVal").alias(alias));
2538
return this;
2639
}
2740

2841
public EventPropertyResponseProjection stringVal() {
29-
fields.put("stringVal", null);
42+
return stringVal(null);
43+
}
44+
45+
public EventPropertyResponseProjection stringVal(String alias) {
46+
fields.add(new GraphQLResponseField("stringVal").alias(alias));
3047
return this;
3148
}
3249

3350
public EventPropertyResponseProjection child(EventPropertyResponseProjection subProjection) {
34-
fields.put("child", subProjection);
51+
return child((String) null, subProjection);
52+
}
53+
54+
public EventPropertyResponseProjection child(String alias, EventPropertyResponseProjection subProjection) {
55+
fields.add(new GraphQLResponseField("child").alias(alias).projection(subProjection));
3556
return this;
3657
}
3758

3859
public EventPropertyResponseProjection child(EventPropertyChildParametrizedInput input, EventPropertyResponseProjection subProjection) {
39-
parametrizedInputs.put("child", input);
40-
return child(subProjection);
60+
return child(null, input, subProjection);
61+
}
62+
63+
public EventPropertyResponseProjection child(String alias, EventPropertyChildParametrizedInput input, EventPropertyResponseProjection subProjection) {
64+
fields.add(new GraphQLResponseField("child").alias(alias).parameters(input).projection(subProjection));
65+
return this;
4166
}
4267

4368
public EventPropertyResponseProjection parent(EventResponseProjection subProjection) {
44-
fields.put("parent", subProjection);
69+
return parent((String) null, subProjection);
70+
}
71+
72+
public EventPropertyResponseProjection parent(String alias, EventResponseProjection subProjection) {
73+
fields.add(new GraphQLResponseField("parent").alias(alias).projection(subProjection));
4574
return this;
4675
}
4776

4877
public EventPropertyResponseProjection parent(EventPropertyParentParametrizedInput input, EventResponseProjection subProjection) {
49-
parametrizedInputs.put("parent", input);
50-
return parent(subProjection);
78+
return parent(null, input, subProjection);
79+
}
80+
81+
public EventPropertyResponseProjection parent(String alias, EventPropertyParentParametrizedInput input, EventResponseProjection subProjection) {
82+
fields.add(new GraphQLResponseField("parent").alias(alias).parameters(input).projection(subProjection));
83+
return this;
5184
}
5285

5386
}

0 commit comments

Comments
 (0)