Skip to content

Commit 8ba1efe

Browse files
committed
Support Object schema
1 parent af302eb commit 8ba1efe

File tree

6 files changed

+457
-17
lines changed

6 files changed

+457
-17
lines changed

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import io.dinject.controller.QueryParam;
1010
import io.dinject.javalin.generator.javadoc.Javadoc;
1111
import io.swagger.v3.oas.models.Operation;
12-
import io.swagger.v3.oas.models.media.Schema;
1312
import io.swagger.v3.oas.models.parameters.Parameter;
1413

1514
import javax.lang.model.element.Element;
@@ -18,6 +17,7 @@
1817
class ElementReader {
1918

2019
private final ProcessingContext ctx;
20+
private final Element element;
2121
private final String rawType;
2222
private final TypeHandler typeHandler;
2323
private final String varName;
@@ -28,18 +28,17 @@ class ElementReader {
2828
private ParamType paramType;
2929
private boolean impliedParamType;
3030
private String paramDefault;
31-
// private String docComment;
3231

3332
ElementReader(Element element, ProcessingContext ctx, ParamType defaultType, boolean formMarker) {
3433
this.ctx = ctx;
34+
this.element = element;
3535
this.rawType = element.asType().toString();
3636
this.typeHandler = TypeMap.get(rawType);
3737
this.formMarker = formMarker;
3838

3939
this.varName = element.getSimpleName().toString();
4040
this.snakeName = Util.snakeCase(varName);
4141
this.paramName = varName;
42-
// this.docComment = ctx.getDocComment(element);
4342

4443
readAnnotations(element, defaultType);
4544
}
@@ -142,17 +141,14 @@ void writeParamName(Append writer) {
142141
}
143142
}
144143

145-
void addMeta(Javadoc javadoc, Operation operation) {
144+
void addMeta(ProcessingContext ctx, Javadoc javadoc, Operation operation) {
146145
if (!isJavalinContext()) {
147146

148147
Parameter param = new Parameter();
149148
param.setName(varName);
150149
param.setDescription(javadoc.getParams().get(paramName));
151150
param.setIn(paramType.getType());
152-
153-
Schema schema = new Schema();
154-
schema.setType("string");
155-
param.setSchema(schema);
151+
param.setSchema(ctx.toSchema(element.asType()));
156152

157153
operation.addParametersItem(param);
158154
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ void buildParamName(Append writer) {
2525
elementParam.writeParamName(writer);
2626
}
2727

28-
void addMeta(Javadoc javadoc, Operation operation) {
29-
elementParam.addMeta(javadoc, operation);
28+
void addMeta(ProcessingContext ctx, Javadoc javadoc, Operation operation) {
29+
elementParam.addMeta(ctx, javadoc, operation);
3030
}
3131
}

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import io.swagger.v3.oas.models.Operation;
1212
import io.swagger.v3.oas.models.PathItem;
1313
import io.swagger.v3.oas.models.Paths;
14+
import io.swagger.v3.oas.models.responses.ApiResponse;
15+
import io.swagger.v3.oas.models.responses.ApiResponses;
1416

1517
import javax.lang.model.element.ExecutableElement;
1618
import javax.lang.model.element.VariableElement;
@@ -76,7 +78,7 @@ void read() {
7678
}
7779
}
7880

79-
public void addMeta(ProcessingContext ctx) {
81+
void addMeta(ProcessingContext ctx) {
8082

8183
if (webMethod != null && notHidden()) {
8284

@@ -108,8 +110,17 @@ public void addMeta(ProcessingContext ctx) {
108110
}
109111

110112
for (MethodParam param : params) {
111-
param.addMeta(javadoc, operation);
113+
param.addMeta(ctx, javadoc, operation);
112114
}
115+
116+
ApiResponses responses = new ApiResponses();
117+
operation.setResponses(responses);
118+
119+
ApiResponse response = new ApiResponse();
120+
responses.addApiResponse(ApiResponses.DEFAULT, response);
121+
response.setDescription(javadoc.getReturnDescription());
122+
123+
response.setContent(ctx.createContent(element.getReturnType(), "application/json"));
113124
}
114125
}
115126

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

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

3+
import io.dinject.javalin.generator.openapi.SchemaBuilder;
34
import io.swagger.v3.oas.models.OpenAPI;
5+
import io.swagger.v3.oas.models.media.Content;
6+
import io.swagger.v3.oas.models.media.Schema;
47

58
import javax.annotation.processing.Filer;
69
import javax.annotation.processing.Messager;
710
import javax.annotation.processing.ProcessingEnvironment;
811
import javax.lang.model.element.Element;
912
import javax.lang.model.element.TypeElement;
13+
import javax.lang.model.type.TypeMirror;
1014
import javax.lang.model.util.Elements;
15+
import javax.lang.model.util.Types;
1116
import javax.tools.Diagnostic;
1217
import javax.tools.FileObject;
1318
import javax.tools.JavaFileObject;
@@ -17,11 +22,13 @@
1722
import static io.dinject.javalin.generator.Constants.GENERATED;
1823
import static io.dinject.javalin.generator.Constants.OPENAPIDEFINITION;
1924

20-
class ProcessingContext {
25+
public class ProcessingContext {
2126

2227
private final Messager messager;
2328
private final Filer filer;
24-
private final Elements elementUtils;
29+
private final Types types;
30+
private final Elements elements;
31+
private final SchemaBuilder schemaBuilder;
2532
private final boolean generatedAvailable;
2633
private final boolean openApiAvailable;
2734

@@ -30,7 +37,9 @@ class ProcessingContext {
3037
ProcessingContext(ProcessingEnvironment env) {
3138
this.messager = env.getMessager();
3239
this.filer = env.getFiler();
33-
this.elementUtils = env.getElementUtils();
40+
this.elements = env.getElementUtils();
41+
this.types = env.getTypeUtils();
42+
this.schemaBuilder = new SchemaBuilder(types, elements);//, this);
3443
this.generatedAvailable = isTypeAvailable(GENERATED);
3544
this.openApiAvailable = isTypeAvailable(OPENAPIDEFINITION);
3645
}
@@ -40,7 +49,7 @@ private boolean isTypeAvailable(String canonicalName) {
4049
}
4150

4251
TypeElement getTypeElement(String canonicalName) {
43-
return elementUtils.getTypeElement(canonicalName);
52+
return elements.getTypeElement(canonicalName);
4453
}
4554

4655
boolean isGeneratedAvailable() {
@@ -59,6 +68,10 @@ void logDebug(String msg, Object... args) {
5968
messager.printMessage(Diagnostic.Kind.NOTE, String.format(msg, args));
6069
}
6170

71+
// public void logWarn(String msg, Object... args) {
72+
// messager.printMessage(Diagnostic.Kind.WARNING, String.format(msg, args));
73+
// }
74+
6275
/**
6376
* Create a file writer for the given class name.
6477
*/
@@ -71,7 +84,7 @@ FileObject createResource(String path, String name, Element origin) throws IOExc
7184
}
7285

7386
String getDocComment(Element param) {
74-
return elementUtils.getDocComment(param);
87+
return elements.getDocComment(param);
7588
}
7689

7790
OpenAPI getOpenAPI() {
@@ -80,6 +93,14 @@ OpenAPI getOpenAPI() {
8093

8194
void setOpenAPI(OpenAPI openAPI) {
8295
this.openAPI = openAPI;
96+
this.schemaBuilder.setOpenAPI(openAPI);
97+
}
98+
99+
Schema toSchema(TypeMirror asType) {
100+
return schemaBuilder.toSchema(asType);
83101
}
84102

103+
Content createContent(TypeMirror returnType, String mediaType) {
104+
return schemaBuilder.createContent(returnType, mediaType);
105+
}
85106
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
package io.dinject.javalin.generator.openapi;
2+
3+
import io.swagger.v3.oas.models.media.BooleanSchema;
4+
import io.swagger.v3.oas.models.media.DateSchema;
5+
import io.swagger.v3.oas.models.media.DateTimeSchema;
6+
import io.swagger.v3.oas.models.media.FileSchema;
7+
import io.swagger.v3.oas.models.media.IntegerSchema;
8+
import io.swagger.v3.oas.models.media.NumberSchema;
9+
import io.swagger.v3.oas.models.media.Schema;
10+
import io.swagger.v3.oas.models.media.StringSchema;
11+
12+
import java.io.File;
13+
import java.math.BigDecimal;
14+
import java.math.BigInteger;
15+
import java.net.URI;
16+
import java.net.URL;
17+
import java.sql.Timestamp;
18+
import java.time.Instant;
19+
import java.time.LocalDate;
20+
import java.time.LocalDateTime;
21+
import java.time.OffsetDateTime;
22+
import java.time.ZonedDateTime;
23+
import java.util.HashMap;
24+
import java.util.Map;
25+
import java.util.UUID;
26+
27+
/**
28+
* Helper to translate known Java types to OpenAPI Schema.
29+
*/
30+
class KnownTypes {
31+
32+
interface KnownType {
33+
Schema<?> createSchema();
34+
}
35+
36+
/**
37+
* Map of known types by canonical name.
38+
*/
39+
private final Map<String, KnownType> typeMap = new HashMap<>();
40+
41+
KnownTypes() {
42+
add(new StringType(), String.class);
43+
add(new BoolType(), boolean.class, Boolean.class);
44+
add(new IntegerType(), int.class, Integer.class);
45+
add(new LongType(), long.class, Long.class);
46+
add(new NumberType(), double.class, Double.class, float.class, Float.class, BigDecimal.class, BigInteger.class);
47+
add(new DateType(), LocalDate.class, java.sql.Date.class);
48+
add(new DateTimeType(), Instant.class, OffsetDateTime.class, ZonedDateTime.class, Timestamp.class, java.util.Date.class, LocalDateTime.class);
49+
50+
add(new UUIDType(), UUID.class);
51+
add(new URLType(), URL.class);
52+
add(new URIType(), URI.class);
53+
add(new FileType(), File.class);
54+
}
55+
56+
/**
57+
* Return the OpenAPI Schema for the given Java type or Null.
58+
*/
59+
Schema<?> createSchema(String type) {
60+
final KnownType knownType = typeMap.get(type);
61+
return (knownType != null) ? knownType.createSchema() : null;
62+
}
63+
64+
private void add(KnownType type, Class<?>... keys) {
65+
for (Class<?> key : keys) {
66+
typeMap.put(key.getCanonicalName(), type);
67+
}
68+
}
69+
70+
private class FileType implements KnownType {
71+
@Override
72+
public Schema<?> createSchema() {
73+
return new FileSchema();
74+
}
75+
}
76+
77+
private class StringType implements KnownType {
78+
@Override
79+
public Schema<?> createSchema() {
80+
return new StringSchema();
81+
}
82+
}
83+
84+
private class BoolType implements KnownType {
85+
@Override
86+
public Schema<?> createSchema() {
87+
return new BooleanSchema();
88+
}
89+
}
90+
91+
private class IntegerType implements KnownType {
92+
@Override
93+
public Schema<?> createSchema() {
94+
return new IntegerSchema();
95+
}
96+
}
97+
98+
private class LongType implements KnownType {
99+
@Override
100+
public Schema<?> createSchema() {
101+
return new IntegerSchema().format("int64");
102+
}
103+
}
104+
105+
private class NumberType implements KnownType {
106+
@Override
107+
public Schema<?> createSchema() {
108+
return new NumberSchema();
109+
}
110+
}
111+
112+
private class DateType implements KnownType {
113+
@Override
114+
public Schema<?> createSchema() {
115+
return new DateSchema();
116+
}
117+
}
118+
119+
private class DateTimeType implements KnownType {
120+
@Override
121+
public Schema<?> createSchema() {
122+
return new DateTimeSchema();
123+
}
124+
}
125+
126+
private class UUIDType extends StringBaseType {
127+
private UUIDType() {
128+
super("uuid");
129+
}
130+
}
131+
132+
private class URLType extends StringBaseType {
133+
private URLType() {
134+
super("url");
135+
}
136+
}
137+
138+
private class URIType extends StringBaseType {
139+
private URIType() {
140+
super("uri");
141+
}
142+
}
143+
144+
private class StringBaseType implements KnownType {
145+
private final String format;
146+
147+
private StringBaseType(String format) {
148+
this.format = format;
149+
}
150+
151+
@Override
152+
public Schema<?> createSchema() {
153+
return new StringSchema().format(format);
154+
}
155+
}
156+
}

0 commit comments

Comments
 (0)