Skip to content

Commit e24b81d

Browse files
authored
Merge branch 'avaje:master' into master
2 parents 59997c4 + fc44373 commit e24b81d

File tree

12 files changed

+303
-69
lines changed

12 files changed

+303
-69
lines changed

http-generator-client/src/main/java/io/avaje/http/generator/client/ClientMethodWriter.java

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import javax.lang.model.element.TypeElement;
66
import java.util.Set;
7+
import java.util.stream.Collectors;
78

89
/**
910
* Write code to register Web route for a given controller method.
@@ -22,24 +23,21 @@ class ClientMethodWriter {
2223
private final UType returnType;
2324
private MethodParam bodyHandlerParam;
2425
private String methodGenericParams = "";
26+
private final boolean useJsonb;
2527

26-
ClientMethodWriter(MethodReader method, Append writer, ProcessingContext ctx) {
28+
ClientMethodWriter(MethodReader method, Append writer, ProcessingContext ctx, boolean useJsonb) {
2729
this.method = method;
2830
this.writer = writer;
2931
this.webMethod = method.webMethod();
3032
this.ctx = ctx;
3133
this.returnType = Util.parseType(method.returnType());
34+
this.useJsonb = useJsonb;
3235
}
3336

3437
void addImportTypes(ControllerReader reader) {
3538
reader.addImportTypes(returnType.importTypes());
3639
for (final MethodParam param : method.params()) {
37-
final var type = param.utype();
38-
final var type0 = type.param0();
39-
final var type1 = type.param1();
40-
reader.addImportType(type.mainType().replace("[]", ""));
41-
if (type0 != null) reader.addImportType(type0.replace("[]", ""));
42-
if (type1 != null) reader.addImportType(type1.replace("[]", ""));
40+
reader.addImportTypes(param.utype().importTypes());
4341
}
4442
}
4543

@@ -116,37 +114,51 @@ private void writeEnd() {
116114

117115
private void writeSyncResponse() {
118116
writer.append(" ");
119-
String type0 = returnType.mainType();
120-
String type1 = returnType.param0();
121-
writeResponse(type0, type1);
117+
writeResponse(returnType);
122118
}
123119

124120
private void writeAsyncResponse() {
125121
writer.append(" .async()");
126-
String type0 = returnType.param0();
127-
String type1 = returnType.param1();
128-
writeResponse(type0, type1);
122+
writeResponse(returnType.paramRaw());
129123
}
130124

131125
private void writeCallResponse() {
132126
writer.append(" .call()");
133-
String type0 = returnType.param0();
134-
String type1 = returnType.param1();
135-
writeResponse(type0, type1);
127+
writeResponse(returnType.paramRaw());
136128
}
137129

138-
private void writeResponse(String type0, String type1) {
139-
if (isList(type0)) {
140-
writer.append(".list(%s.class);", Util.shortName(type1)).eol();
141-
} else if (isStream(type0)) {
142-
writer.append(".stream(%s.class);", Util.shortName(type1)).eol();
143-
} else if (isHttpResponse(type0)){
130+
private void writeResponse(UType type) {
131+
final var mainType = type.mainType();
132+
final var param1 = type.paramRaw();
133+
if (isList(mainType)) {
134+
writer.append(".list(");
135+
writeGeneric(param1);
136+
} else if (isStream(mainType)) {
137+
writer.append(".stream(");
138+
writeGeneric(param1);
139+
} else if (isHttpResponse(mainType)) {
144140
writeWithHandler();
145141
} else {
146-
writer.append(".bean(%s.class);", Util.shortName(type0)).eol();
142+
writer.append(".bean(");
143+
writeGeneric(type);
147144
}
148145
}
149146

147+
void writeGeneric(UType type) {
148+
if (useJsonb && type.isGeneric()) {
149+
final var params =
150+
type.importTypes().stream()
151+
.skip(1)
152+
.map(Util::shortName)
153+
.collect(Collectors.joining(".class, "));
154+
155+
writer.append("Types.newParameterizedType(%s.class, %s.class)", Util.shortName(type.mainType()), params);
156+
} else {
157+
writer.append("%s.class", Util.shortName(type.mainType()));
158+
}
159+
writer.append(");").eol();
160+
}
161+
150162
private void writeWithHandler() {
151163
if (bodyHandlerParam != null) {
152164
writer.append(".handler(%s);", bodyHandlerParam.name()).eol();
@@ -268,4 +280,4 @@ private boolean isHttpResponse(String type0) {
268280
return type0.equals("java.net.http.HttpResponse");
269281
}
270282

271-
}
283+
}

http-generator-client/src/main/java/io/avaje/http/generator/client/ClientProcessor.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.avaje.http.api.Client;
44
import io.avaje.http.generator.core.ControllerReader;
5+
import io.avaje.http.generator.core.JsonBUtil;
56
import io.avaje.http.generator.core.ProcessingContext;
67

78
import javax.annotation.processing.AbstractProcessor;
@@ -27,6 +28,16 @@ public class ClientProcessor extends AbstractProcessor {
2728

2829
protected ProcessingContext ctx;
2930

31+
private final boolean useJsonB;
32+
33+
public ClientProcessor() {
34+
useJsonB = JsonBUtil.detectJsonb();
35+
}
36+
37+
public ClientProcessor(boolean useJsonb) {
38+
useJsonB = useJsonb;
39+
}
40+
3041
@Override
3142
public SourceVersion getSupportedSourceVersion() {
3243
return SourceVersion.latest();
@@ -107,7 +118,7 @@ private void writeClient(Element controller) {
107118
}
108119

109120
protected String writeClientAdapter(ProcessingContext ctx, ControllerReader reader) throws IOException {
110-
return new ClientWriter(reader, ctx).write();
121+
return new ClientWriter(reader, ctx, useJsonB).write();
111122
}
112123

113124
}

http-generator-client/src/main/java/io/avaje/http/generator/client/ClientWriter.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@ class ClientWriter extends BaseControllerWriter {
2121
private static final String SUFFIX = "HttpClient";
2222

2323
private final List<ClientMethodWriter> methodList = new ArrayList<>();
24+
private final boolean useJsonb;
2425

25-
ClientWriter(ControllerReader reader, ProcessingContext ctx) throws IOException {
26+
ClientWriter(ControllerReader reader, ProcessingContext ctx, boolean useJsonB) throws IOException {
2627
super(reader, ctx, SUFFIX);
2728
reader.addImportType(HTTP_CLIENT_CONTEXT);
2829
reader.addImportType(HTTP_API_PROVIDER);
30+
this.useJsonb = useJsonB;
2931
readMethods();
32+
if (useJsonB) reader.addImportType("io.avaje.jsonb.Types");
3033
}
3134

3235
@Override
@@ -38,7 +41,7 @@ protected String initPackageName(String originName) {
3841
private void readMethods() {
3942
for (MethodReader method : reader.methods()) {
4043
if (method.isWebMethod()) {
41-
ClientMethodWriter methodWriter = new ClientMethodWriter(method, writer, ctx);
44+
final var methodWriter = new ClientMethodWriter(method, writer, ctx, useJsonb);
4245
methodWriter.addImportTypes(reader);
4346
methodList.add(methodWriter);
4447
}

http-generator-core/src/main/java/io/avaje/http/generator/core/JsonBUtil.java

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,23 @@
33
import java.util.LinkedHashMap;
44
import java.util.Map;
55
import java.util.function.Consumer;
6+
import java.util.stream.Collectors;
67

78
public class JsonBUtil {
89
private JsonBUtil() {}
910

11+
/**
12+
* Return true if avaje-jsonb is detected in the classpath.
13+
*/
14+
public static boolean detectJsonb() {
15+
try {
16+
Class.forName("io.avaje.jsonb.Jsonb");
17+
return true;
18+
} catch (final ClassNotFoundException e) {
19+
return false;
20+
}
21+
}
22+
1023
public static Map<String, UType> jsonTypes(ControllerReader reader) {
1124

1225
final Map<String, UType> jsonTypes = new LinkedHashMap<>();
@@ -37,26 +50,45 @@ private static void addJsonBodyType(MethodReader methodReader, Consumer<UType> a
3750
}
3851

3952
public static void writeJsonbType(UType type, Append writer) {
40-
4153
writer.append(" this.%sJsonType = jsonB.type(", type.shortName());
4254
if (!type.isGeneric()) {
43-
writer.append("%s.class)", PrimitiveUtil.wrap(type.full()));
55+
writer.append("%s.class)", Util.shortName(PrimitiveUtil.wrap(type.full())));
4456
} else {
4557
switch (type.mainType()) {
4658
case "java.util.List":
47-
writer.append("%s.class).list()", type.param0());
59+
writeType(type.paramRaw(), writer);
60+
writer.append(".list()");
4861
break;
4962
case "java.util.Set":
50-
writer.append("%s.class).set()", type.param0());
63+
writeType(type.paramRaw(), writer);
64+
writer.append(".set()");
5165
break;
5266
case "java.util.Map":
53-
writer.append("%s.class).map()", type.param1());
67+
writeType(type.paramRaw(), writer);
68+
writer.append(".map()");
5469
break;
55-
default:
56-
throw new UnsupportedOperationException(
57-
"Only java.util Map, Set and List are supported JsonB Controller Collection Types");
70+
default: {
71+
if (type.mainType().contains("java.util")) {
72+
throw new UnsupportedOperationException("Only java.util Map, Set and List are supported JsonB Controller Collection Types");
73+
}
74+
writeType(type, writer);
75+
}
5876
}
5977
}
6078
writer.append(";").eol();
6179
}
80+
81+
static void writeType(UType type, Append writer) {
82+
if (type.isGeneric()) {
83+
final var params =
84+
type.importTypes().stream()
85+
.skip(1)
86+
.map(Util::shortName)
87+
.collect(Collectors.joining(".class, "));
88+
89+
writer.append("Types.newParameterizedType(%s.class, %s.class))", Util.shortName(type.mainType()), params);
90+
} else {
91+
writer.append("%s.class)", Util.shortName(type.mainType()));
92+
}
93+
}
6294
}

http-generator-core/src/main/java/io/avaje/http/generator/core/UType.java

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ static UType parse(TypeMirror type) {
1212
return Util.parseType(type);
1313
}
1414

15+
/**
16+
* Create the UType from the given String.
17+
*/
18+
static UType parse(String type) {
19+
return Util.parse(type);
20+
}
21+
1522
UType VOID = new VoidType();
1623

1724
/**
@@ -48,6 +55,13 @@ default String param1() {
4855
return null;
4956
}
5057

58+
/**
59+
* Return the raw generic parameter if this UType is a Collection.
60+
*/
61+
default UType paramRaw() {
62+
return null;
63+
}
64+
5165
/**
5266
* Return the raw type.
5367
*/
@@ -106,7 +120,9 @@ public String full() {
106120

107121
@Override
108122
public Set<String> importTypes() {
109-
return Collections.singleton(rawType);
123+
return rawType.startsWith("java.lang.") && rawType.indexOf('.') > -1
124+
? Set.of()
125+
: Collections.singleton(rawType.replace("[]", ""));
110126
}
111127

112128
@Override
@@ -130,15 +146,37 @@ public String mainType() {
130146
*/
131147
class Generic implements UType {
132148
final String rawType;
149+
final UType rawParamType;
133150
final List<String> allTypes;
134151
final String shortRawType;
135152
final String shortName;
136153

137154
Generic(String rawTypeInput) {
138-
this.rawType = rawTypeInput.replace(" ",""); // trim whitespace
155+
this.rawType = rawTypeInput.replace(" ", ""); // trim whitespace
139156
this.allTypes = Arrays.asList(rawType.split("[<|>|,]"));
140157
this.shortRawType = shortRawType(rawType, allTypes);
141158
this.shortName = Util.name(shortRawType);
159+
final var paramTypeString = extractRawParam();
160+
this.rawParamType = paramTypeString != null ? UType.parse(paramTypeString) : null;
161+
}
162+
163+
private String extractRawParam() {
164+
switch (mainType()) {
165+
case "java.util.Set":
166+
case "java.util.List":
167+
case "java.util.stream.Stream":
168+
case "java.util.concurrent.CompletableFuture":
169+
case "io.avaje.http.client.HttpCall":
170+
var first = rawType.indexOf("<") + 1;
171+
var end = rawType.lastIndexOf(">");
172+
return rawType.substring(first, end);
173+
case "java.util.Map":
174+
first = rawType.indexOf(",") + 1;
175+
end = rawType.lastIndexOf(">");
176+
return rawType.substring(first, end);
177+
default:
178+
return null;
179+
}
142180
}
143181

144182
private String shortRawType(String rawType, List<String> allTypes) {
@@ -163,7 +201,7 @@ public Set<String> importTypes() {
163201
Set<String> set = new LinkedHashSet<>();
164202
for (String type : allTypes) {
165203
if (!type.startsWith("java.lang.") && type.indexOf('.') > -1) {
166-
set.add(type);
204+
set.add(type.replace("[]", ""));
167205
}
168206
}
169207
return set;
@@ -210,5 +248,10 @@ public String param0() {
210248
public String param1() {
211249
return allTypes.size() < 3 ? null : allTypes.get(2);
212250
}
251+
252+
@Override
253+
public UType paramRaw() {
254+
return rawParamType;
255+
}
213256
}
214257
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private void writeContextReturn() {
103103
} else if (MediaType.TEXT_PLAIN.equalsIgnoreCase(produces)) {
104104
writer.append(" res.writerContext().contentType(io.helidon.common.http.MediaType.TEXT_PLAIN);").eol();
105105
} else {
106-
writer.append( "res.writerContext().contentType(io.helidon.common.http.MediaType.parse(\"%s\"));", produces).eol();
106+
writer.append(" res.writerContext().contentType(io.helidon.common.http.MediaType.parse(\"%s\"));", produces).eol();
107107
}
108108
}
109109

http-generator-javalin/src/main/java/io/avaje/http/generator/javalin/ControllerWriter.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
package io.avaje.http.generator.javalin;
22

3-
import io.avaje.http.generator.core.*;
4-
53
import java.io.IOException;
64
import java.util.Map;
75

6+
import io.avaje.http.generator.core.BaseControllerWriter;
7+
import io.avaje.http.generator.core.Constants;
8+
import io.avaje.http.generator.core.ControllerReader;
9+
import io.avaje.http.generator.core.JsonBUtil;
10+
import io.avaje.http.generator.core.MethodReader;
11+
import io.avaje.http.generator.core.PrimitiveUtil;
12+
import io.avaje.http.generator.core.ProcessingContext;
13+
import io.avaje.http.generator.core.UType;
14+
815
/**
916
* Write Javalin specific Controller WebRoute handling adapter.
1017
*/
@@ -21,7 +28,11 @@ class ControllerWriter extends BaseControllerWriter {
2128
if (useJsonB) {
2229
reader.addImportType("io.avaje.jsonb.Jsonb");
2330
reader.addImportType("io.avaje.jsonb.JsonType");
31+
reader.addImportType("io.avaje.jsonb.Types");
2432
this.jsonTypes = JsonBUtil.jsonTypes(reader);
33+
jsonTypes.values().stream()
34+
.map(UType::importTypes)
35+
.forEach(reader::addImportTypes);
2536
} else {
2637
this.jsonTypes = Map.of();
2738
}
@@ -77,7 +88,8 @@ private void writeClassStart() {
7788
}
7889

7990
for (final UType type : jsonTypes.values()) {
80-
writer.append(" private final JsonType<%s> %sJsonType;", PrimitiveUtil.wrap(type.full()), type.shortName()).eol();
91+
final var typeString = PrimitiveUtil.wrap(type.shortType()).replace(",", ", ");
92+
writer.append(" private final JsonType<%s> %sJsonType;", typeString, type.shortName()).eol();
8193
}
8294
writer.eol();
8395

0 commit comments

Comments
 (0)