Skip to content

Commit 25a2692

Browse files
committed
#15 - Refactor OpenAPI/Swagger generation adding DocContext
1 parent 78d96fc commit 25a2692

File tree

13 files changed

+448
-300
lines changed

13 files changed

+448
-300
lines changed

src/main/java/io/dinject/javalin/generator/ControllerReader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private List<ExecutableElement> initInterfaceMethods() {
9191
return ifaceMethods;
9292
}
9393

94-
<A extends Annotation> A findAnnotation(Class<A> type) {
94+
private <A extends Annotation> A findAnnotation(Class<A> type) {
9595
A annotation = beanType.getAnnotation(type);
9696
if (annotation != null) {
9797
return annotation;

src/main/java/io/dinject/javalin/generator/ControllerRouteWriter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ private void writeAddRoutes() {
4747
for (MethodReader method : reader.getMethods()) {
4848
method.addRoute(writer);
4949
if (!reader.isDocHidden()) {
50-
method.addMeta(ctx);
50+
method.buildApiDocumentation(ctx);
5151
}
5252
}
5353

src/main/java/io/dinject/javalin/generator/ElementReader.java

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@
77
import io.dinject.controller.FormParam;
88
import io.dinject.controller.Header;
99
import io.dinject.controller.QueryParam;
10-
import io.dinject.javalin.generator.javadoc.Javadoc;
11-
import io.swagger.v3.oas.models.Operation;
12-
import io.swagger.v3.oas.models.media.Schema;
13-
import io.swagger.v3.oas.models.parameters.Parameter;
10+
import io.dinject.javalin.generator.openapi.MethodDocBuilder;
11+
import io.dinject.javalin.generator.openapi.MethodParamDocBuilder;
1412

1513
import javax.lang.model.element.Element;
1614
import javax.lang.model.element.TypeElement;
1715

18-
class ElementReader {
16+
public class ElementReader {
1917

2018
private final ProcessingContext ctx;
2119
private final Element element;
@@ -107,7 +105,7 @@ private String nameFrom(String name, String defaultName) {
107105
return defaultName;
108106
}
109107

110-
String getVarName() {
108+
public String getVarName() {
111109
return varName;
112110
}
113111

@@ -146,38 +144,15 @@ void writeParamName(Append writer) {
146144
}
147145
}
148146

149-
void addMeta(ProcessingContext ctx, Javadoc javadoc, Operation operation) {
147+
/**
148+
* Build the OpenAPI documentation for this parameter.
149+
*/
150+
void buildApiDocumentation(MethodDocBuilder methodDoc) {
150151
if (!isJavalinContext()) {
151-
if (paramType == ParamType.FORM || paramType == ParamType.BODY) {
152-
addMetaRequestBody(ctx, javadoc, operation);
153-
154-
} else {
155-
Parameter param = new Parameter();
156-
param.setName(varName);
157-
param.setDescription(javadoc.getParams().get(paramName));
158-
159-
Schema schema = ctx.toSchema(rawType, element);
160-
if (paramType == ParamType.FORMPARAM) {
161-
ctx.addFormParam(operation, varName, schema);
162-
163-
} else {
164-
param.setSchema(schema);
165-
param.setIn(paramType.getType());
166-
operation.addParametersItem(param);
167-
}
168-
}
152+
new MethodParamDocBuilder(methodDoc, this).build();
169153
}
170154
}
171155

172-
private void addMetaRequestBody(ProcessingContext ctx, Javadoc javadoc, Operation operation) {
173-
174-
Schema schema = ctx.toSchema(rawType, element);
175-
String description = javadoc.getParams().get(paramName);
176-
177-
boolean asForm = (paramType == ParamType.FORM);
178-
ctx.addRequestBody(operation, schema, asForm, description);
179-
}
180-
181156
void writeCtxGet(Append writer, PathSegments segments) {
182157

183158
if (isJavalinContext()) {
@@ -266,4 +241,19 @@ private void writeForm(Append writer, String shortType, String varName, ParamTyp
266241
form.write(writer);
267242
}
268243

244+
public ParamType getParamType() {
245+
return paramType;
246+
}
247+
248+
public String getParamName() {
249+
return paramName;
250+
}
251+
252+
public String getRawType() {
253+
return rawType;
254+
}
255+
256+
public Element getElement() {
257+
return element;
258+
}
269259
}

src/main/java/io/dinject/javalin/generator/MethodParam.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package io.dinject.javalin.generator;
22

3-
import io.dinject.javalin.generator.javadoc.Javadoc;
4-
import io.swagger.v3.oas.models.Operation;
3+
import io.dinject.javalin.generator.openapi.MethodDocBuilder;
54

65
import javax.lang.model.element.VariableElement;
76

8-
class MethodParam {
7+
public class MethodParam {
98

109
private final ElementReader elementParam;
1110

@@ -25,7 +24,7 @@ void buildParamName(Append writer) {
2524
elementParam.writeParamName(writer);
2625
}
2726

28-
void addMeta(ProcessingContext ctx, Javadoc javadoc, Operation operation) {
29-
elementParam.addMeta(ctx, javadoc, operation);
27+
public void buildApiDocumentation(MethodDocBuilder methodDoc) {
28+
elementParam.buildApiDocumentation(methodDoc);
3029
}
3130
}

src/main/java/io/dinject/javalin/generator/MethodReader.java

Lines changed: 48 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@
99
import io.dinject.controller.Produces;
1010
import io.dinject.controller.Put;
1111
import io.dinject.javalin.generator.javadoc.Javadoc;
12-
import io.swagger.v3.oas.annotations.Hidden;
13-
import io.swagger.v3.oas.models.Operation;
14-
import io.swagger.v3.oas.models.PathItem;
15-
import io.swagger.v3.oas.models.responses.ApiResponse;
16-
import io.swagger.v3.oas.models.responses.ApiResponses;
12+
import io.dinject.javalin.generator.openapi.MethodDocBuilder;
1713

1814
import javax.lang.model.element.ExecutableElement;
1915
import javax.lang.model.element.VariableElement;
@@ -26,7 +22,7 @@
2622

2723
import static io.dinject.javalin.generator.Constants.JAVALIN_ROLES;
2824

29-
class MethodReader {
25+
public class MethodReader {
3026

3127
private final ProcessingContext ctx;
3228
private final ControllerReader bean;
@@ -76,12 +72,16 @@ boolean isWebMethod() {
7672
return webMethod != null;
7773
}
7874

75+
public Javadoc getJavadoc() {
76+
return javadoc;
77+
}
78+
7979
private String produces(ControllerReader bean) {
8080
final Produces produces = findAnnotation(Produces.class);
8181
return (produces != null) ? produces.value() : bean.getProduces();
8282
}
8383

84-
<A extends Annotation> A findAnnotation(Class<A> type) {
84+
public <A extends Annotation> A findAnnotation(Class<A> type) {
8585
A annotation = element.getAnnotation(type);
8686
if (annotation != null) {
8787
return annotation;
@@ -120,80 +120,16 @@ void read() {
120120
}
121121
}
122122

123-
void addMeta(ProcessingContext ctx) {
124-
125-
if (webMethod != null && notHidden()) {
126-
127-
Operation operation = new Operation();
128-
//operation.setOperationId();
129-
operation.setSummary(javadoc.getSummary());
130-
operation.setDescription(javadoc.getDescription());
131-
132-
if (javadoc.isDeprecated()) {
133-
operation.setDeprecated(true);
134-
} else if (findAnnotation(Deprecated.class) != null) {
135-
operation.setDeprecated(true);
136-
}
137-
138-
PathItem pathItem = ctx.pathItem(fullPath);
139-
switch (webMethod) {
140-
case GET:
141-
pathItem.setGet(operation);
142-
break;
143-
case PUT:
144-
pathItem.setPut(operation);
145-
break;
146-
case POST:
147-
pathItem.setPost(operation);
148-
break;
149-
case DELETE:
150-
pathItem.setDelete(operation);
151-
break;
152-
case PATCH:
153-
pathItem.setPatch(operation);
154-
break;
155-
}
156-
157-
for (MethodParam param : params) {
158-
param.addMeta(ctx, javadoc, operation);
159-
}
160-
161-
ApiResponses responses = new ApiResponses();
162-
operation.setResponses(responses);
163-
164-
ApiResponse response = new ApiResponse();
165-
response.setDescription(javadoc.getReturnDescription());
166-
167-
if (isVoid) {
168-
if (isEmpty(response.getDescription())) {
169-
response.setDescription("No content");
170-
}
171-
} else {
172-
String contentMediaType = (produces == null) ? MediaType.APPLICATION_JSON : produces;
173-
response.setContent(ctx.createContent(returnType(), contentMediaType));
174-
}
175-
responses.addApiResponse(httpStatusCode(), response);
176-
}
177-
}
178-
179-
private TypeMirror returnType() {
180-
if (actualExecutable != null) {
181-
return actualExecutable.getReturnType();
182-
}
183-
return element.getReturnType();
184-
}
185-
186-
private boolean isEmpty(String value) {
187-
return value == null || value.isEmpty();
188-
}
189-
190123
/**
191-
* Return true if the method is included in documentation.
124+
* Build the OpenAPI documentation for the method / operation.
192125
*/
193-
private boolean notHidden() {
194-
return !ctx.isOpenApiAvailable() || findAnnotation(Hidden.class) == null;
126+
void buildApiDocumentation(ProcessingContext ctx) {
127+
if (webMethod != null) {
128+
new MethodDocBuilder(this, ctx.doc()).build();
129+
}
195130
}
196131

132+
197133
void addRoute(Append writer) {
198134

199135
if (webMethod != null) {
@@ -202,7 +138,7 @@ void addRoute(Append writer) {
202138
segments = PathSegments.parse(fullPath);
203139

204140
writer.append(" ApiBuilder.%s(\"%s\", ctx -> {", webMethod.name().toLowerCase(), segments.fullPath()).eol();
205-
writer.append(" ctx.status(%s);", httpStatusCode()).eol();
141+
writer.append(" ctx.status(%s);", getStatusCode()).eol();
206142

207143
List<PathSegments.Segment> metricSegments = segments.metricSegments();
208144
for (PathSegments.Segment metricSegment : metricSegments) {
@@ -214,7 +150,7 @@ void addRoute(Append writer) {
214150
}
215151
writer.append(" ");
216152

217-
if (isReturnContent()) {
153+
if (!isVoid()) {
218154
writeContextReturn(writer);
219155
}
220156
writer.append("controller.");
@@ -226,7 +162,7 @@ void addRoute(Append writer) {
226162
params.get(i).buildParamName(writer);
227163
}
228164
writer.append(")");
229-
if (isReturnContent()) {
165+
if (!isVoid()) {
230166
writer.append(")");
231167
}
232168
writer.append(";").eol();
@@ -264,14 +200,6 @@ private List<String> roles() {
264200
return methodRoles.isEmpty() ? bean.getRoles() : methodRoles;
265201
}
266202

267-
private String httpStatusCode() {
268-
return Integer.toString(webMethod.statusCode(isVoid));
269-
}
270-
271-
private boolean isReturnContent() {
272-
return !isVoid;
273-
}
274-
275203
private boolean readMethodAnnotation() {
276204

277205
Form form = findAnnotation(Form.class);
@@ -307,4 +235,36 @@ private boolean setWebMethod(WebMethod webMethod, String value) {
307235
this.webMethodPath = value;
308236
return true;
309237
}
238+
239+
public WebMethod getWebMethod() {
240+
return webMethod;
241+
}
242+
243+
public String getFullPath() {
244+
return fullPath;
245+
}
246+
247+
public List<MethodParam> getParams() {
248+
return params;
249+
}
250+
251+
public boolean isVoid() {
252+
return isVoid;
253+
}
254+
255+
public String getProduces() {
256+
return produces;
257+
}
258+
259+
public TypeMirror getReturnType() {
260+
if (actualExecutable != null) {
261+
return actualExecutable.getReturnType();
262+
}
263+
return element.getReturnType();
264+
}
265+
266+
public String getStatusCode() {
267+
return Integer.toString(webMethod.statusCode(isVoid));
268+
}
269+
310270
}

src/main/java/io/dinject/javalin/generator/ParamType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.dinject.javalin.generator;
22

3-
enum ParamType {
3+
public enum ParamType {
44

55
BODY("body", "body"),
66
PATHPARAM("pathParam", "path"),

0 commit comments

Comments
 (0)