Skip to content

Commit c31eab5

Browse files
committed
now doesn't generate Duplicate JsonTypes
1 parent 00a02ff commit c31eab5

File tree

4 files changed

+134
-110
lines changed

4 files changed

+134
-110
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ tests/test-nima/.classpath
1414
tests/test-nima/.factorypath
1515
tests/test-nima/.project
1616
*.class
17+
tests/test-nima-jsonb/.classpath

http-generator-nima/src/main/java/io/avaje/http/generator/helidon/nima/ControllerMethodWriter.java

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package io.avaje.http.generator.helidon.nima;
22

3-
import io.avaje.http.api.MediaType;
4-
import io.avaje.http.generator.core.*;
5-
63
import java.util.List;
4+
import java.util.Map;
75
import java.util.Optional;
86

7+
import io.avaje.http.api.MediaType;
8+
import io.avaje.http.generator.core.Append;
9+
import io.avaje.http.generator.core.MethodParam;
10+
import io.avaje.http.generator.core.MethodReader;
11+
import io.avaje.http.generator.core.ParamType;
12+
import io.avaje.http.generator.core.PathSegments;
13+
import io.avaje.http.generator.core.ProcessingContext;
14+
import io.avaje.http.generator.core.WebMethod;
15+
916
/**
1017
* Write code to register Web route for a given controller method.
1118
*/
@@ -16,13 +23,20 @@ class ControllerMethodWriter {
1623
private final WebMethod webMethod;
1724
private final ProcessingContext ctx;
1825
private final boolean useJsonB;
19-
20-
ControllerMethodWriter(MethodReader method, Append writer, ProcessingContext ctx, boolean useJsonB) {
26+
private final Map<String, JsonbType> jsonTypes;
27+
28+
ControllerMethodWriter(
29+
MethodReader method,
30+
Append writer,
31+
ProcessingContext ctx,
32+
boolean useJsonB,
33+
Map<String, JsonbType> jsonTypes) {
2134
this.method = method;
2235
this.writer = writer;
23-
this.webMethod = method.getWebMethod();
36+
webMethod = method.getWebMethod();
2437
this.ctx = ctx;
2538
this.useJsonB = useJsonB;
39+
this.jsonTypes=jsonTypes;
2640
}
2741

2842
void writeRule() {
@@ -36,11 +50,20 @@ void writeHandler(boolean requestScoped) {
3650
final var bodyType = method.getBodyType();
3751
if (bodyType != null) {
3852
if (useJsonB) {
53+
54+
final var jsonbType =
55+
method.getParams().stream()
56+
.filter(MethodParam::isBody)
57+
.findFirst()
58+
.orElseThrow()
59+
.getUType()
60+
.full()
61+
.transform(jsonTypes::get);
3962
writer
40-
.append(
41-
" var %s = %sBodyJsonType.fromJson(req.content().inputStream());",
42-
method.getBodyName(), method.simpleName())
43-
.eol();
63+
.append(
64+
" var %s = %sJsonType.fromJson(req.content().inputStream());",
65+
method.getBodyName(), jsonbType.fieldName())
66+
.eol();
4467

4568
} else {
4669
// use default helidon content negotiation
@@ -103,7 +126,11 @@ void writeHandler(boolean requestScoped) {
103126
if (!method.isVoid()) {
104127
writeContextReturn();
105128
if (producesJson()) {
106-
writer.append(" %sReturnedJsonType.toJson(result, res.outputStream());", method.simpleName()).eol();
129+
130+
final var jsonbType = method.getReturnType().toString().transform(jsonTypes::get);
131+
writer
132+
.append(" %sJsonType.toJson(result, res.outputStream());", jsonbType.fieldName())
133+
.eol();
107134
} else {
108135
writer.append(" res.send(result);").eol();
109136
}
Lines changed: 92 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package io.avaje.http.generator.helidon.nima;
22

33
import java.io.IOException;
4+
import java.util.HashMap;
45
import java.util.List;
6+
import java.util.Map;
57
import java.util.Optional;
68

79
import javax.lang.model.type.DeclaredType;
@@ -12,19 +14,25 @@
1214
import io.avaje.http.generator.core.MethodParam;
1315
import io.avaje.http.generator.core.MethodReader;
1416
import io.avaje.http.generator.core.ProcessingContext;
17+
import io.avaje.http.generator.core.UType;
1518

1619
/** Write Helidon specific web route adapter (a Helidon Service). */
1720
class ControllerWriter extends BaseControllerWriter {
1821

1922
private static final String AT_GENERATED = "@Generated(\"avaje-helidon-nima-generator\")";
2023
private final boolean useJsonB;
24+
private final Map<String, JsonbType> jsonTypes;
2125

22-
ControllerWriter(ControllerReader reader, ProcessingContext ctx, boolean jsonB) throws IOException {
26+
ControllerWriter(ControllerReader reader, ProcessingContext ctx, boolean jsonB)
27+
throws IOException {
2328
super(reader, ctx);
24-
this.useJsonB = jsonB;
29+
useJsonB = jsonB;
2530
if (useJsonB) {
2631
reader.addImportType("io.avaje.jsonb.Jsonb");
2732
reader.addImportType("io.avaje.jsonb.JsonType");
33+
jsonTypes = new HashMap<>();
34+
} else {
35+
jsonTypes = null;
2836
}
2937
reader.addImportType("io.helidon.common.http.HttpMediaType");
3038
reader.addImportType("io.helidon.common.parameters.Parameters");
@@ -46,7 +54,7 @@ void write() {
4654
private List<ControllerMethodWriter> getWriterMethods() {
4755
return reader.getMethods().stream()
4856
.filter(MethodReader::isWebMethod)
49-
.map(it -> new ControllerMethodWriter(it, writer, ctx, useJsonB))
57+
.map(it -> new ControllerMethodWriter(it, writer, ctx, useJsonB, jsonTypes))
5058
.toList();
5159
}
5260

@@ -88,17 +96,16 @@ private void writeClassStart() {
8896
writer.append(" private final Validator validator;").eol();
8997
}
9098

91-
List<MethodReader> jsonMethods;
9299
if (useJsonB) {
93-
jsonMethods =
100+
101+
final var jsonMethods =
94102
reader.getMethods().stream()
95103
.filter(MethodReader::isWebMethod)
96104
.filter(m -> !"byte[]".equals(m.getReturnType().toString()))
97-
.filter(m -> m.getProduces() == null || m.getProduces().toLowerCase().contains("json"))
105+
.filter(
106+
m -> m.getProduces() == null || m.getProduces().toLowerCase().contains("json"))
98107
.toList();
99108
writeJsonBTypeFields(jsonMethods);
100-
} else {
101-
jsonMethods = null;
102109
}
103110
writer.eol();
104111

@@ -115,126 +122,112 @@ private void writeClassStart() {
115122
writer.append(" this.validator = validator;").eol();
116123
}
117124
if (useJsonB) {
118-
writeJsonBTypeAssignments(jsonMethods);
125+
writeJsonBTypeAssignments();
119126
}
120127
writer.append(" }").eol().eol();
121128
}
122129

123130
public void writeJsonBTypeFields(List<MethodReader> jsonMethods) {
124131
for (final MethodReader methodReader : jsonMethods) {
125-
// body types
126-
if (methodReader.getBodyType() != null) {
127-
methodReader.getParams().stream()
128-
.filter(MethodParam::isBody)
129-
.forEach(
130-
param ->
131-
writer
132-
.append(
133-
" private final JsonType<%s> %sBodyJsonType;",
134-
param.getUType().full(), methodReader.simpleName())
135-
.eol());
136-
}
137132

133+
writeFieldJsonBodyType(methodReader);
138134
if (methodReader.isVoid()) {
139135
continue;
140136
}
141-
142-
// return types
143-
if (methodReader.getReturnType() instanceof final DeclaredType fullType) {
144-
final var typeArgs = fullType.getTypeArguments();
145-
final var typeArgSize = typeArgs.size();
146-
147-
writer.append(" private final JsonType<");
148-
switch (typeArgSize) {
149-
case 1 -> {
150-
if (fullType.toString().contains("java.util.Set"))
151-
writer.append("java.util.Set<%s>>", typeArgs.get(0));
152-
else writer.append("java.util.List<%s>>", typeArgs.get(0));
153-
}
154-
case 2 -> writer.append("java.util.Map<String, %s>>", typeArgs.get(1));
155-
default -> writer.append("%s>", fullType);
156-
}
157-
writer.append(" %sReturnedJsonType;", methodReader.simpleName()).eol();
158-
} else {
159-
throw new UnsupportedOperationException("Only Objects are supported with Jsonb Return Types");
160-
}
137+
writeFieldJsonReturnType(methodReader);
161138
}
162-
}
163-
164-
public void writeJsonBTypeAssignments(List<MethodReader> jsonMethods) {
165-
for (final MethodReader methodReader : jsonMethods) {
166-
// body types
167-
writeBodyJsonType(methodReader);
168-
if (methodReader.isVoid()) {
169-
continue;
170-
}
171-
writeReturnJsonType(methodReader);
172-
}
173-
}
174-
175-
private void writeBodyJsonType(MethodReader methodReader) {
139+
} public void writeFieldJsonBodyType(MethodReader methodReader) {
140+
// body types
176141
if (methodReader.getBodyType() != null) {
177142
methodReader.getParams().stream()
178143
.filter(MethodParam::isBody)
179144
.forEach(
180-
p -> {
181-
final var type = p.getUType();
182-
final var jsonType =
183-
Optional.ofNullable(type.param1())
184-
.or(() -> Optional.ofNullable(type.param0()))
185-
.orElseGet(type::full);
186-
writer.append(
187-
" this.%sBodyJsonType = jsonB.type(%s.class)",
188-
methodReader.simpleName(), jsonType);
189-
190-
if (type.param0() != null) {
191-
writer.append(".");
192-
switch (type.mainType()) {
193-
case "java.util.List" -> writer.append("list");
194-
case "java.util.Map" -> writer.append("map");
195-
case "java.util.Set" -> writer.append("set");
196-
default -> throw new UnsupportedOperationException(
197-
"Only java.util Map, Set and List are supported JsonB Controller Body Return Types");
198-
}
199-
writer.append("()");
200-
}
201-
writer.append(";").eol();
145+
param -> {
146+
final var fullType = param.getUType().full();
147+
jsonTypes.computeIfAbsent(
148+
fullType,
149+
k -> {
150+
final var baseType = getBaseType(param.getUType());
151+
final var fieldName = createFieldName(baseType, k);
152+
writer.append("private final JsonType<%s> %sJsonType;", k, fieldName).eol();
153+
return new JsonbType(baseType, fieldName);
154+
});
202155
});
203156
}
204157
}
205158

206-
void writeReturnJsonType(MethodReader methodReader) {
159+
public void writeFieldJsonReturnType(MethodReader methodReader) {
160+
161+
// return types
207162
if (methodReader.getReturnType() instanceof final DeclaredType fullType) {
208-
final var typeArgs = fullType.getTypeArguments();
209-
final var typeArgSize = typeArgs.size();
210-
final var jsonType =
211-
switch (typeArgSize) {
212-
case 1 -> typeArgs.get(0);
213-
case 2 -> typeArgs.get(1);
214-
default -> fullType;
215-
};
216-
217-
writer.append(
218-
" this.%sReturnedJsonType = jsonB.type(%s.class)",
219-
methodReader.simpleName(), jsonType);
220-
final var returnType = fullType.toString();
221-
if (typeArgSize != 0) {
222-
writer.append(".");
163+
final var fullTypeString = fullType.toString();
164+
jsonTypes.computeIfAbsent(
165+
fullTypeString,
166+
k -> {
167+
final var baseType = getBaseType(fullType);
168+
final var fieldName = createFieldName(baseType, k);
169+
writer.append("private final JsonType<%s> %sJsonType;", k, fieldName).eol();
170+
return new JsonbType(baseType, fieldName);
171+
});
172+
} else {
173+
throw new UnsupportedOperationException("Only Objects are supported with Jsonb Return Types");
174+
}
175+
}
176+
177+
public void writeJsonBTypeAssignments() {
178+
for (final var entry : jsonTypes.entrySet()) {
179+
final var fullType = entry.getKey();
180+
final var element = entry.getValue();
181+
final var fieldName = element.fieldName();
182+
final var baseType = element.baseType();
223183

224-
switch (returnType.substring(0, 13)) {
184+
writer.append(" this.%sJsonType = jsonB.type(%s.class)", fieldName, baseType);
185+
186+
if (fullType.contains("<")) {
187+
writer.append(".");
188+
switch (fullType.substring(0, 13)) {
225189
case "java.util.Lis" -> writer.append("list");
226190
case "java.util.Map" -> writer.append("map");
227191
case "java.util.Set" -> writer.append("set");
228192
default -> throw new UnsupportedOperationException(
229-
"Only java.util Map, Set and List are supported JsonB Controller Collection Return Types");
193+
"Only java.util Map, Set and List are supported JsonB Controller Collection Types");
230194
}
231-
232195
writer.append("()");
233196
}
234197
writer.append(";").eol();
235-
236-
} else {
237-
throw new UnsupportedOperationException("Only Objects and Strings are supported with Jsonb Controller Return Types");
238198
}
239199
}
200+
201+
public static String getBaseType(UType type) {
202+
203+
return Optional.ofNullable(type.param1())
204+
.or(() -> Optional.ofNullable(type.param0()))
205+
.orElseGet(type::full);
206+
}
207+
208+
private static String getBaseType(DeclaredType type) {
209+
final var typeArgs = type.getTypeArguments();
210+
return switch (typeArgs.size()) {
211+
case 1 -> typeArgs.get(0).toString();
212+
213+
case 2 -> typeArgs.get(1).toString();
214+
default -> type.toString();
215+
};
216+
}
217+
218+
private static String createFieldName(String baseType, String fullType) {
219+
final var shortType =
220+
baseType
221+
.substring(baseType.lastIndexOf('.') + 1)
222+
.transform(str -> str.substring(0, 1).toLowerCase() + str.substring(1));
223+
224+
if (shortType.length() <= 13) return shortType;
225+
226+
return switch (fullType.substring(0, 13)) {
227+
case "java.util.Lis" -> "List";
228+
case "java.util.Map" -> "Map";
229+
case "java.util.Set" -> "Set";
230+
default -> "";
231+
};
232+
}
240233
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package io.avaje.http.generator.helidon.nima;
2+
3+
public record JsonbType(String baseType, String fieldName) {}

0 commit comments

Comments
 (0)