Skip to content

Commit 295a23e

Browse files
authored
Add Sigma Lambda Generator (#498)
* start * complete generator * rename routing * test * fix compilation * Update HealthController.java * Update pom.xml
1 parent 9a6cad8 commit 295a23e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1853
-0
lines changed

http-generator-sigma/pom.xml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>io.avaje</groupId>
6+
<artifactId>avaje-http-parent</artifactId>
7+
<version>2.8-RC1</version>
8+
</parent>
9+
10+
<artifactId>avaje-http-sigma-generator</artifactId>
11+
12+
<properties>
13+
<maven.compiler.release>17</maven.compiler.release>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
</properties>
16+
<dependencies>
17+
18+
<dependency>
19+
<groupId>io.avaje</groupId>
20+
<artifactId>avaje-http-generator-core</artifactId>
21+
<version>${project.version}</version>
22+
</dependency>
23+
24+
<dependency>
25+
<groupId>io.avaje</groupId>
26+
<artifactId>avaje-prisms</artifactId>
27+
<version>${avaje.prisms.version}</version>
28+
<scope>provided</scope>
29+
</dependency>
30+
</dependencies>
31+
</project>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Remove from module-info all content after: // SHADED:
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package io.avaje.http.generator.sigma;
2+
3+
import static io.avaje.http.generator.core.ProcessingContext.*;
4+
5+
import java.util.List;
6+
7+
import io.avaje.http.generator.core.*;
8+
import io.avaje.http.generator.core.openapi.MediaType;
9+
10+
/** Write code to register Web route for a given controller method. */
11+
class ControllerMethodWriter {
12+
13+
private final MethodReader method;
14+
private final Append writer;
15+
private final WebMethod webMethod;
16+
private final boolean instrumentContext;
17+
private final boolean customMethod;
18+
19+
ControllerMethodWriter(MethodReader method, Append writer) {
20+
this.method = method;
21+
this.writer = writer;
22+
final var webM = method.webMethod();
23+
this.webMethod = webM == CoreWebMethod.FILTER ? SigmaWebMethod.BEFORE : webM;
24+
this.instrumentContext = method.instrumentContext();
25+
customMethod = !(webMethod instanceof CoreWebMethod);
26+
}
27+
28+
void write() {
29+
final var segments = method.pathSegments();
30+
final var fullPath = segments.fullPath();
31+
32+
writeMethod(fullPath);
33+
34+
final var params = writeParams(segments);
35+
writer.append(" ");
36+
if (!method.isVoid() && !customMethod) {
37+
writer.append("var result = ");
38+
}
39+
40+
if (instrumentContext) {
41+
method.writeContext(writer, "ctx", "ctx");
42+
}
43+
44+
writer.append("controller.");
45+
46+
writer.append(method.simpleName()).append("(");
47+
for (var i = 0; i < params.size(); i++) {
48+
if (i > 0) {
49+
writer.append(", ");
50+
}
51+
final var param = params.get(i);
52+
if (isAssignable2Interface(param.utype().mainType(), "java.lang.Exception")) {
53+
writer.append("ex");
54+
} else {
55+
param.buildParamName(writer);
56+
}
57+
}
58+
59+
if (instrumentContext) {
60+
writer.append(")");
61+
}
62+
63+
writer.append(");").eol();
64+
if (!method.isVoid() && !customMethod) {
65+
writeContextReturn();
66+
writer.eol();
67+
}
68+
69+
writer.append(" }");
70+
writer.append(");").eol().eol();
71+
}
72+
73+
private void writeMethod(final String fullPath) {
74+
if (method.isErrorMethod()) {
75+
writer
76+
.append(" router.exception(%s.class, (ex, ctx) -> {", method.exceptionShortName())
77+
.eol();
78+
} else {
79+
var methodName = webMethod.name().toLowerCase().replace("_m", "M");
80+
writer.append(" router.%s(\"%s\", ctx -> {", methodName, fullPath).eol();
81+
}
82+
if (!customMethod) {
83+
int statusCode = method.statusCode();
84+
if (statusCode > 0) {
85+
writer.append(" ctx.status(%d);", statusCode).eol();
86+
}
87+
}
88+
}
89+
90+
private List<MethodParam> writeParams(final PathSegments segments) {
91+
final var matrixSegments = segments.matrixSegments();
92+
for (final PathSegments.Segment matrixSegment : matrixSegments) {
93+
matrixSegment.writeCreateSegment(writer, platform());
94+
}
95+
96+
final var params = method.params();
97+
for (final MethodParam param : params) {
98+
if (!isAssignable2Interface(param.utype().mainType(), "java.lang.Exception")) {
99+
param.writeCtxGet(writer, segments);
100+
}
101+
}
102+
if (method.includeValidate()) {
103+
for (final MethodParam param : params) {
104+
param.writeValidate(writer);
105+
}
106+
}
107+
return params;
108+
}
109+
110+
private void writeContextReturn() {
111+
var produces = method.produces();
112+
boolean applicationJson =
113+
produces == null || MediaType.APPLICATION_JSON.getValue().equalsIgnoreCase(produces);
114+
if (applicationJson || JsonBUtil.isJsonMimeType(produces)) {
115+
if (applicationJson) {
116+
writer.append(" ctx.json(result);");
117+
} else {
118+
writer.append(" ctx.contentType(\"%s\").result(result);", produces);
119+
}
120+
} else if (MediaType.TEXT_HTML.getValue().equalsIgnoreCase(produces)) {
121+
writer.append(" ctx.html(result);");
122+
} else if (MediaType.TEXT_PLAIN.getValue().equalsIgnoreCase(produces)) {
123+
writer.append(" ctx.text(result);");
124+
} else {
125+
writer.append(" ctx.contentType(\"%s\").result(%s);", produces);
126+
}
127+
}
128+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package io.avaje.http.generator.sigma;
2+
3+
import static io.avaje.http.generator.core.ProcessingContext.diAnnotation;
4+
5+
import java.io.IOException;
6+
7+
import io.avaje.http.generator.core.BaseControllerWriter;
8+
import io.avaje.http.generator.core.ControllerReader;
9+
import io.avaje.http.generator.core.MethodReader;
10+
11+
/**
12+
* Write Sigma specific Controller WebRoute handling adapter.
13+
*/
14+
class ControllerWriter extends BaseControllerWriter {
15+
16+
private static final String AT_GENERATED = "@Generated(\"avaje-sigma-generator\")";
17+
18+
ControllerWriter(ControllerReader reader) throws IOException {
19+
super(reader);
20+
reader.addImportType("io.avaje.sigma.HttpService");
21+
reader.addImportType("io.avaje.sigma.Router");
22+
}
23+
24+
void write() {
25+
writePackage();
26+
writeImports();
27+
writeClassStart();
28+
writeAddRoutes();
29+
writeClassEnd();
30+
}
31+
32+
private void writeAddRoutes() {
33+
writer.append(" @Override").eol();
34+
writer.append(" public void setup(Router router) {").eol().eol();
35+
36+
37+
for (final MethodReader method : reader.methods()) {
38+
if (method.isWebMethod()) {
39+
writeForMethod(method);
40+
}
41+
}
42+
writer.append(" }").eol().eol();
43+
}
44+
45+
private void writeForMethod(MethodReader method) {
46+
new ControllerMethodWriter(method, writer).write();
47+
if (!reader.isDocHidden()) {
48+
method.buildApiDocumentation();
49+
}
50+
}
51+
52+
private void writeClassStart() {
53+
writer.append(AT_GENERATED).eol();
54+
writer.append(diAnnotation()).eol();
55+
writer
56+
.append("public class ")
57+
.append(shortName)
58+
.append("$Route implements HttpService {")
59+
.eol()
60+
.eol();
61+
62+
var controllerName = "controller";
63+
var controllerType = shortName;
64+
writer.append(" private final %s %s;", controllerType, controllerName).eol();
65+
66+
if (reader.isIncludeValidator()) {
67+
writer.append(" private final Validator validator;").eol();
68+
}
69+
70+
if (instrumentContext) {
71+
writer.append(" private final RequestContextResolver resolver;").eol();
72+
}
73+
writer.eol();
74+
75+
writer.append(" public %s$Route(%s %s", shortName, controllerType, controllerName);
76+
if (reader.isIncludeValidator()) {
77+
writer.append(", Validator validator");
78+
}
79+
if (instrumentContext) {
80+
writer.append(", RequestContextResolver resolver");
81+
}
82+
writer.append(") {").eol();
83+
writer.append(" this.%s = %s;", controllerName, controllerName).eol();
84+
if (reader.isIncludeValidator()) {
85+
writer.append(" this.validator = validator;").eol();
86+
}
87+
if (instrumentContext) {
88+
writer.append(" this.resolver = resolver;").eol();
89+
}
90+
writer.append(" }").eol().eol();
91+
}
92+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package io.avaje.http.generator.sigma;
2+
3+
import java.util.List;
4+
import java.util.Optional;
5+
import java.util.function.Function;
6+
7+
import javax.lang.model.element.Element;
8+
9+
import io.avaje.http.generator.core.Append;
10+
import io.avaje.http.generator.core.Constants;
11+
import io.avaje.http.generator.core.ControllerReader;
12+
import io.avaje.http.generator.core.CustomWebMethod;
13+
import io.avaje.http.generator.core.ParamType;
14+
import io.avaje.http.generator.core.PlatformAdapter;
15+
import io.avaje.http.generator.core.UType;
16+
17+
class SigmaAdapter implements PlatformAdapter {
18+
19+
static final String CONTEXT = "io.avaje.sigma.HttpContext";
20+
21+
@Override
22+
public boolean isContextType(String rawType) {
23+
return CONTEXT.equals(rawType);
24+
}
25+
26+
@Override
27+
public String platformVariable(String rawType) {
28+
return "ctx";
29+
}
30+
31+
@Override
32+
public boolean isBodyMethodParam() {
33+
return false;
34+
}
35+
36+
@Override
37+
public String bodyAsClass(UType type) {
38+
if ("java.lang.String".equals(type.full())) {
39+
return "ctx.body()";
40+
} else {
41+
return "ctx.bodyAsClass(" + type.mainType() + ".class)";
42+
}
43+
}
44+
45+
@Override
46+
public String indent() {
47+
return " ";
48+
}
49+
50+
@Override
51+
public void writeReadParameter(Append writer, ParamType paramType, String paramName) {
52+
writer.append("ctx.%s(\"%s\")", paramType, paramName);
53+
}
54+
55+
@Override
56+
public void writeReadParameter(Append writer, ParamType paramType, String paramName, String paramDefault) {
57+
writer.append("withDefault(ctx.%s(\"%s\"), \"%s\")", paramType, paramName, paramDefault);
58+
}
59+
60+
@Override
61+
public void writeReadMapParameter(Append writer, ParamType paramType) {
62+
63+
switch (paramType) {
64+
case QUERYPARAM:
65+
writer.append("ctx.queryParamMap()");
66+
break;
67+
case FORM:
68+
case FORMPARAM:
69+
writer.append("ctx.formParamMap()");
70+
break;
71+
default:
72+
throw new UnsupportedOperationException(
73+
"Only Query/Form Params have Map<String, List<String>> supported in Javalin");
74+
}
75+
}
76+
77+
@Override
78+
public void writeReadCollectionParameter(Append writer, ParamType paramType, String paramName) {
79+
switch (paramType) {
80+
case QUERYPARAM:
81+
writer.append("ctx.queryParams(\"%s\")", paramName);
82+
break;
83+
case HEADER:
84+
writer.append("ctx.headers(\"%s\")", paramName);
85+
break;
86+
case FORMPARAM:
87+
writer.append("ctx.formParams(\"%s\")", paramName);
88+
break;
89+
default:
90+
throw new UnsupportedOperationException(
91+
"Only MultiValue Form/Query Params are supported in Javalin");
92+
}
93+
}
94+
95+
@Override
96+
public void writeReadCollectionParameter(
97+
Append writer, ParamType paramType, String paramName, List<String> paramDefault) {
98+
99+
switch (paramType) {
100+
case QUERYPARAM:
101+
writer.append(
102+
"withDefault(ctx.queryParams(\"%s\"), java.util.List.of(\"%s\"))",
103+
paramName, String.join(",", paramDefault));
104+
break;
105+
case HEADER:
106+
writer.append(
107+
"withDefault(ctx.headers(\"%s\"), java.util.List.of(\"%s\"))",
108+
paramName, String.join(",", paramDefault));
109+
break;
110+
case FORMPARAM:
111+
writer.append(
112+
"withDefault(ctx.formParams(\"%s\"), java.util.List.of(\"%s\"))",
113+
paramName, String.join(",", paramDefault));
114+
break;
115+
default:
116+
throw new UnsupportedOperationException(
117+
"Only MultiValue Form/Header/Query Params are supported in Javalin");
118+
}
119+
}
120+
121+
@Override
122+
public void writeAcceptLanguage(Append writer) {
123+
writer.append("ctx.header(\"%s\")", Constants.ACCEPT_LANGUAGE);
124+
}
125+
126+
@Override
127+
public List<Function<Element, Optional<CustomWebMethod>>> customHandlers() {
128+
129+
return List.of();
130+
}
131+
132+
@Override
133+
public void controllerRoles(List<String> roles, ControllerReader controller) {
134+
135+
}
136+
137+
@Override
138+
public void methodRoles(List<String> roles, ControllerReader controller) {
139+
140+
}
141+
}

0 commit comments

Comments
 (0)