1
1
package io .avaje .http .generator .jex ;
2
2
3
- import static io .avaje .http .generator .core .ProcessingContext .isAssignable2Interface ;
4
- import static io .avaje .http .generator .core .ProcessingContext .logError ;
5
- import static io .avaje .http .generator .core .ProcessingContext .platform ;
6
-
7
- import java .io .IOException ;
8
3
import java .util .List ;
9
4
10
5
import io .avaje .http .generator .core .*;
11
- import io .avaje .http .generator .core .openapi .MediaType ;
6
+
7
+ import javax .lang .model .type .TypeMirror ;
8
+
9
+ import static io .avaje .http .generator .core .ProcessingContext .*;
12
10
13
11
/**
14
12
* Write code to register Web route for a given controller method.
@@ -17,13 +15,15 @@ class ControllerMethodWriter {
17
15
18
16
private final MethodReader method ;
19
17
private final Append writer ;
18
+ private final ControllerReader reader ;
20
19
private final WebMethod webMethod ;
21
20
private final boolean instrumentContext ;
22
21
private final boolean isFilter ;
23
22
24
- ControllerMethodWriter (MethodReader method , Append writer ) {
23
+ ControllerMethodWriter (MethodReader method , Append writer , ControllerReader reader ) {
25
24
this .method = method ;
26
25
this .writer = writer ;
26
+ this .reader = reader ;
27
27
this .webMethod = method .webMethod ();
28
28
this .instrumentContext = method .instrumentContext ();
29
29
this .isFilter = webMethod == CoreWebMethod .FILTER ;
@@ -47,11 +47,19 @@ void writeRouting() {
47
47
} else if (isFilter ) {
48
48
writer .append (" routing.filter(this::_%s)" , method .simpleName ());
49
49
} else {
50
- writer .append (
51
- " routing.%s(\" %s\" , this::_%s)" ,
52
- webMethod .name ().toLowerCase (), fullPath , method .simpleName ());
50
+ writer .append (" routing.%s(\" %s\" , " , webMethod .name ().toLowerCase (), fullPath );
51
+ var hxRequest = method .hxRequest ();
52
+ if (hxRequest != null ) {
53
+ writeHxHandler (hxRequest );
54
+ } else {
55
+ writer .append ("this::_%s)" , method .simpleName ());
56
+ }
53
57
}
58
+ writeRoles ();
59
+ writer .append (";" ).eol ();
60
+ }
54
61
62
+ private void writeRoles () {
55
63
List <String > roles = method .roles ();
56
64
if (!roles .isEmpty ()) {
57
65
writer .append (".withRoles(" );
@@ -63,11 +71,88 @@ void writeRouting() {
63
71
}
64
72
writer .append (")" );
65
73
}
66
- writer .append (";" ).eol ();
67
74
}
68
75
69
- void writeHandler (boolean requestScoped ) {
76
+ private void writeHxHandler (HxRequestPrism hxRequest ) {
77
+ writer .append ("HxHandler.builder(this::_%s)" , method .simpleName ());
78
+ if (hasValue (hxRequest .target ())) {
79
+ writer .append (".target(\" %s\" )" , hxRequest .target ());
80
+ }
81
+ if (hasValue (hxRequest .triggerId ())) {
82
+ writer .append (".trigger(\" %s\" )" , hxRequest .triggerId ());
83
+ } else if (hasValue (hxRequest .value ())) {
84
+ writer .append (".trigger(\" %s\" )" , hxRequest .value ());
85
+ }
86
+ if (hasValue (hxRequest .triggerName ())) {
87
+ writer .append (".triggerName(\" %s\" )" , hxRequest .triggerName ());
88
+ } else if (hasValue (hxRequest .value ())) {
89
+ writer .append (".triggerName(\" %s\" )" , hxRequest .value ());
90
+ }
91
+ writer .append (".build())" );
92
+ }
70
93
94
+ private static boolean hasValue (String value ) {
95
+ return value != null && !value .isBlank ();
96
+ }
97
+
98
+ enum ResponseMode {
99
+ Void ,
100
+ Json ,
101
+ Text ,
102
+ Templating ,
103
+ InputStream ,
104
+ Other
105
+ }
106
+
107
+ ResponseMode responseMode () {
108
+ if (method .isVoid () || isFilter ) {
109
+ return ResponseMode .Void ;
110
+ }
111
+ if (isInputStream (method .returnType ())) {
112
+ return ResponseMode .InputStream ;
113
+ }
114
+ if (producesJson ()) {
115
+ return ResponseMode .Json ;
116
+ }
117
+ if (useTemplating ()) {
118
+ return ResponseMode .Templating ;
119
+ }
120
+ if (producesText ()) {
121
+ return ResponseMode .Text ;
122
+ }
123
+ return ResponseMode .Other ;
124
+ }
125
+
126
+ private boolean isInputStream (TypeMirror type ) {
127
+ return isAssignable2Interface (type .toString (), "java.io.InputStream" );
128
+ }
129
+
130
+ private boolean producesJson () {
131
+ return // useJsonB
132
+ !disabledDirectWrites ()
133
+ && !"byte[]" .equals (method .returnType ().toString ())
134
+ && (method .produces () == null || method .produces ().toLowerCase ().contains ("json" ));
135
+ }
136
+
137
+ private boolean producesText () {
138
+ return (method .produces () != null && method .produces ().toLowerCase ().contains ("text" ));
139
+ }
140
+
141
+ private boolean useContentCache () {
142
+ return method .hasContentCache ();
143
+ }
144
+
145
+ private boolean useTemplating () {
146
+ return reader .html ()
147
+ && !"byte[]" .equals (method .returnType ().toString ())
148
+ && (method .produces () == null || method .produces ().toLowerCase ().contains ("html" ));
149
+ }
150
+
151
+ private boolean usesFormParams () {
152
+ return method .params ().stream ().anyMatch (p -> p .isForm () || ParamType .FORMPARAM .equals (p .paramType ()));
153
+ }
154
+
155
+ void writeHandler (boolean requestScoped ) {
71
156
if (method .isErrorMethod ()) {
72
157
writer .append (" private void _%s(Context ctx, %s ex) {" , method .simpleName (), method .exceptionShortName ());
73
158
} else if (isFilter ) {
@@ -77,7 +162,6 @@ void writeHandler(boolean requestScoped) {
77
162
}
78
163
79
164
writer .eol ();
80
-
81
165
write (requestScoped );
82
166
writer .append (" }" ).eol ().eol ();
83
167
}
@@ -105,6 +189,23 @@ private void write(boolean requestScoped) {
105
189
param .writeValidate (writer );
106
190
}
107
191
}
192
+ final var withFormParams = usesFormParams ();
193
+ final ResponseMode responseMode = responseMode ();
194
+ final boolean withContentCache = responseMode == ResponseMode .Templating && useContentCache ();
195
+ if (withContentCache ) {
196
+ writer .append (" var key = contentCache.key(ctx" );
197
+ if (withFormParams ) {
198
+ writer .append (", ctx.formParamMap()" );
199
+ }
200
+ writer .append (");" ).eol ();
201
+ writer .append (" var cacheContent = contentCache.content(key);" ).eol ();
202
+ writer .append (" if (cacheContent != null) {" ).eol ();
203
+ writeContextReturn (responseMode );
204
+ writer .append (" res.send(cacheContent);" ).eol ();
205
+ writer .append (" return;" ).eol ();
206
+ writer .append (" }" ).eol ();
207
+ }
208
+
108
209
writer .append (" " );
109
210
if (!method .isVoid ()) {
110
211
writer .append ("var result = " );
@@ -138,26 +239,39 @@ private void write(boolean requestScoped) {
138
239
}
139
240
writer .append (";" ).eol ();
140
241
if (!method .isVoid ()) {
141
- writer .append (" if (result != null) {" ).eol ();
142
- writer .append (" " );
143
- writeContextReturn ();
144
- writer .append ("result);" ).eol ();
145
- writer .append (" }" ).eol ();
242
+ TypeMirror typeMirror = method .returnType ();
243
+ boolean includeNoContent = !typeMirror .getKind ().isPrimitive ();
244
+ String indent = includeNoContent ? " " : " " ;
245
+ if (includeNoContent ) {
246
+ writer .append (" if (result != null) {" ).eol ();
247
+ }
248
+ if (responseMode == ResponseMode .Templating ) {
249
+ writer .append (indent ).append ("var content = renderer.render(result);" ).eol ();
250
+ if (withContentCache ) {
251
+ writer .append (indent ).append ("contentCache.contentPut(key, content);" ).eol ();
252
+ }
253
+ writer .append (indent );
254
+ writeContextReturn (responseMode );
255
+ writer .append ("content);" ).eol ();
256
+ } else {
257
+ writer .append (indent );
258
+ writeContextReturn (responseMode );
259
+ writer .append ("result);" ).eol ();
260
+ }
261
+ if (includeNoContent ) {
262
+ writer .append (" }" ).eol ();
263
+ }
146
264
}
147
265
}
148
266
149
- private void writeContextReturn () {
267
+ private void writeContextReturn (ResponseMode responseMode ) {
150
268
final var produces = method .produces ();
151
- if (produces == null || produces .equalsIgnoreCase (MediaType .APPLICATION_JSON .getValue ())) {
152
- writer .append ("ctx.json(" );
153
- } else if (produces .equalsIgnoreCase (MediaType .TEXT_HTML .getValue ())) {
154
- writer .append ("ctx.html(" );
155
- } else if (produces .equalsIgnoreCase (MediaType .TEXT_PLAIN .getValue ())) {
156
- writer .append ("ctx.text(" );
157
- } else if (JsonBUtil .isJsonMimeType (produces )) {
158
- writer .append ("ctx.contentType(\" %s\" ).json(" , produces );
159
- } else {
160
- writer .append ("ctx.contentType(\" %s\" ).write(" , produces );
269
+ switch (responseMode ) {
270
+ case Void : break ;
271
+ case Json : writer .append ("ctx.json(" ); break ;
272
+ case Text : writer .append ("ctx.text(" ); break ;
273
+ case Templating : writer .append ("ctx.html(" ); break ;
274
+ default : writer .append ("ctx.contentType(\" %s\" ).write(" , produces );
161
275
}
162
276
}
163
277
0 commit comments