Skip to content

Commit 72fe111

Browse files
committed
#135 Refactor extracting methods for MethodReader
1 parent 2c61b48 commit 72fe111

File tree

3 files changed

+88
-112
lines changed

3 files changed

+88
-112
lines changed

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

Lines changed: 66 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
package io.avaje.http.generator.core;
22

3-
import java.lang.annotation.Annotation;
4-
import java.util.ArrayList;
5-
import java.util.Arrays;
6-
import java.util.List;
7-
import java.util.Optional;
8-
import java.util.function.Predicate;
9-
import java.util.stream.Collectors;
10-
import java.util.stream.Stream;
3+
import io.avaje.http.api.*;
4+
import io.avaje.http.generator.core.javadoc.Javadoc;
5+
import io.avaje.http.generator.core.openapi.MethodDocBuilder;
6+
import io.swagger.v3.oas.annotations.tags.Tag;
7+
import io.swagger.v3.oas.annotations.tags.Tags;
118

129
import javax.lang.model.element.Element;
1310
import javax.lang.model.element.ExecutableElement;
@@ -16,53 +13,39 @@
1613
import javax.lang.model.type.TypeKind;
1714
import javax.lang.model.type.TypeMirror;
1815
import javax.validation.Valid;
19-
20-
import io.avaje.http.api.Delete;
21-
import io.avaje.http.api.Form;
22-
import io.avaje.http.api.Get;
23-
import io.avaje.http.api.OpenAPIResponse;
24-
import io.avaje.http.api.OpenAPIResponses;
25-
import io.avaje.http.api.Patch;
26-
import io.avaje.http.api.Post;
27-
import io.avaje.http.api.Produces;
28-
import io.avaje.http.api.Put;
29-
import io.avaje.http.generator.core.javadoc.Javadoc;
30-
import io.avaje.http.generator.core.openapi.MethodDocBuilder;
31-
import io.swagger.v3.oas.annotations.tags.Tag;
32-
import io.swagger.v3.oas.annotations.tags.Tags;
16+
import java.lang.annotation.Annotation;
17+
import java.util.ArrayList;
18+
import java.util.Arrays;
19+
import java.util.List;
20+
import java.util.Optional;
21+
import java.util.function.Predicate;
22+
import java.util.stream.Collectors;
23+
import java.util.stream.Stream;
3324

3425
public class MethodReader {
3526

3627
private final ProcessingContext ctx;
3728
private final ControllerReader bean;
3829
private final ExecutableElement element;
39-
4030
private final boolean isVoid;
4131
private final List<MethodParam> params = new ArrayList<>();
42-
4332
private final Javadoc javadoc;
44-
45-
private WebMethod webMethod;
46-
private String webMethodPath;
47-
48-
private boolean formMarker;
49-
5033
/**
5134
* Holds enum Roles that are required for the method.
5235
*/
5336
private final List<String> methodRoles;
54-
5537
private final String produces;
56-
5738
private final List<OpenAPIResponse> apiResponses;
58-
5939
private final ExecutableType actualExecutable;
6040
private final List<? extends TypeMirror> actualParams;
61-
6241
private final PathSegments pathSegments;
6342
private final boolean hasValid;
6443
private final List<ExecutableElement> superMethods;
6544

45+
private WebMethod webMethod;
46+
private String webMethodPath;
47+
private boolean formMarker;
48+
6649
MethodReader(ControllerReader bean, ExecutableElement element, ExecutableType actualExecutable, ProcessingContext ctx) {
6750
this.ctx = ctx;
6851
this.bean = bean;
@@ -74,52 +57,50 @@ public class MethodReader {
7457
this.produces = produces(bean);
7558
initWebMethodViaAnnotation();
7659

77-
this.superMethods =
78-
ctx.getSuperMethods(element.getEnclosingElement(), element.getSimpleName().toString());
79-
80-
superMethods.stream().forEach(m -> methodRoles.addAll(Util.findRoles(m)));
81-
82-
this.apiResponses = getApiResponses();
83-
this.javadoc =
84-
Optional.of(Javadoc.parse(ctx.docComment(element)))
85-
.filter(Predicate.not(Javadoc::isEmpty))
86-
.orElseGet(
87-
() ->
88-
superMethods.stream()
89-
.map(e -> Javadoc.parse(ctx.docComment(e)))
90-
.filter(Predicate.not(Javadoc::isEmpty))
91-
.findFirst()
92-
.orElse(Javadoc.parse("")));
60+
this.superMethods = ctx.superMethods(element.getEnclosingElement(), element.getSimpleName().toString());
61+
superMethods.forEach(m -> methodRoles.addAll(Util.findRoles(m)));
9362

94-
if (isWebMethod()) {
63+
this.apiResponses = buildApiResponses();
64+
this.javadoc = buildJavadoc(element, ctx);
9565

96-
Class<Annotation> jakartaValidAnnotation;
66+
if (isWebMethod()) {
67+
Class<Annotation> jakartaValidAnnotation;
9768
try {
9869
jakartaValidAnnotation = jakartaValidAnnotation();
9970
} catch (final ClassNotFoundException e) {
10071
jakartaValidAnnotation = null;
10172
}
102-
103-
final var jakartaAnnotation = jakartaValidAnnotation;
104-
105-
this.hasValid =
106-
findAnnotation(Valid.class) != null
107-
|| (jakartaValidAnnotation != null && findAnnotation(jakartaValidAnnotation) != null)
108-
|| superMethods.stream()
109-
.map(
110-
e ->
111-
findAnnotation(Valid.class, e) != null
112-
|| (jakartaAnnotation != null
113-
&& findAnnotation(jakartaAnnotation, e) != null))
114-
.anyMatch(b -> b);
115-
73+
this.hasValid = hasValid(jakartaValidAnnotation);
11674
this.pathSegments = PathSegments.parse(Util.combinePath(bean.path(), webMethodPath));
11775
} else {
11876
this.hasValid = false;
11977
this.pathSegments = null;
12078
}
12179
}
12280

81+
private Javadoc buildJavadoc(ExecutableElement element, ProcessingContext ctx) {
82+
return Optional.of(Javadoc.parse(ctx.docComment(element)))
83+
.filter(Predicate.not(Javadoc::isEmpty))
84+
.orElseGet(() -> superMethods.stream()
85+
.map(e -> Javadoc.parse(ctx.docComment(e)))
86+
.filter(Predicate.not(Javadoc::isEmpty))
87+
.findFirst()
88+
.orElse(Javadoc.parse("")));
89+
}
90+
91+
private boolean hasValid(Class<Annotation> jakartaValidAnnotation) {
92+
return findAnnotation(Valid.class) != null
93+
|| (jakartaValidAnnotation != null && findAnnotation(jakartaValidAnnotation) != null)
94+
|| superMethodHasValid(jakartaValidAnnotation);
95+
}
96+
97+
private boolean superMethodHasValid(Class<Annotation> jakartaAnnotation) {
98+
return superMethods.stream()
99+
.anyMatch(e ->
100+
findAnnotation(Valid.class, e) != null
101+
|| (jakartaAnnotation != null && findAnnotation(jakartaAnnotation, e) != null));
102+
}
103+
123104
@SuppressWarnings("unchecked")
124105
private static Class<Annotation> jakartaValidAnnotation() throws ClassNotFoundException {
125106
return (Class<Annotation>) Class.forName(Valid.class.getCanonicalName().replace("javax", "jakarta"));
@@ -175,31 +156,30 @@ private String produces(ControllerReader bean) {
175156
return (produces != null) ? produces.value() : bean.produces();
176157
}
177158

178-
private List<OpenAPIResponse> getApiResponses() {
159+
private List<OpenAPIResponse> buildApiResponses() {
179160
final var container =
180-
Optional.ofNullable(findAnnotation(OpenAPIResponses.class)).stream()
181-
.map(OpenAPIResponses::value)
182-
.flatMap(Arrays::stream);
161+
Optional.ofNullable(findAnnotation(OpenAPIResponses.class)).stream()
162+
.map(OpenAPIResponses::value)
163+
.flatMap(Arrays::stream);
183164

184165
final var methodResponses =
185-
Stream.concat(
186-
container, Arrays.stream(element.getAnnotationsByType(OpenAPIResponse.class)));
166+
Stream.concat(
167+
container, Arrays.stream(element.getAnnotationsByType(OpenAPIResponse.class)));
187168

188169
final var superMethodResponses =
189-
superMethods.stream()
190-
.flatMap(
191-
m ->
192-
Stream.concat(
193-
Optional.ofNullable(findAnnotation(OpenAPIResponses.class, m)).stream()
194-
.map(OpenAPIResponses::value)
195-
.flatMap(Arrays::stream),
196-
Arrays.stream(m.getAnnotationsByType(OpenAPIResponse.class))));
170+
superMethods.stream()
171+
.flatMap(
172+
method ->
173+
Stream.concat(
174+
Optional.ofNullable(findAnnotation(OpenAPIResponses.class, method)).stream()
175+
.map(OpenAPIResponses::value)
176+
.flatMap(Arrays::stream),
177+
Arrays.stream(method.getAnnotationsByType(OpenAPIResponse.class))));
197178

198179
return Stream.concat(methodResponses, superMethodResponses).collect(Collectors.toList());
199180
}
200181

201182
public <A extends Annotation> A findAnnotation(Class<A> type) {
202-
203183
return findAnnotation(type, element);
204184
}
205185

@@ -208,28 +188,27 @@ public <A extends Annotation> A findAnnotation(Class<A> type, ExecutableElement
208188
if (annotation != null) {
209189
return annotation;
210190
}
211-
212191
return bean.findMethodAnnotation(type, elem);
213192
}
214193

215194
private List<String> addTagsToList(Element element, List<String> list) {
216-
if (element == null)
195+
if (element == null) {
217196
return list;
218-
197+
}
219198
if (element.getAnnotation(Tag.class) != null) {
220199
list.add(element.getAnnotation(Tag.class).name());
221200
}
222201
if (element.getAnnotation(Tags.class) != null) {
223-
for (Tag tag : element.getAnnotation(Tags.class).value())
202+
for (Tag tag : element.getAnnotation(Tags.class).value()) {
224203
list.add(tag.name());
204+
}
225205
}
226206
return list;
227207
}
228208

229209
public List<String> tags() {
230210
final var tags = addTagsToList(element, new ArrayList<>());
231-
superMethods.forEach(e -> addTagsToList(e, tags));
232-
211+
superMethods.forEach(method -> addTagsToList(method, tags));
233212
return addTagsToList(element.getEnclosingElement(), tags);
234213
}
235214

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

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package io.avaje.http.generator.core;
22

3-
import java.io.IOException;
4-
import java.util.List;
5-
import java.util.Objects;
6-
import java.util.stream.Collectors;
3+
import io.avaje.http.generator.core.openapi.DocContext;
74

85
import javax.annotation.processing.Filer;
96
import javax.annotation.processing.Messager;
@@ -20,8 +17,10 @@
2017
import javax.tools.FileObject;
2118
import javax.tools.JavaFileObject;
2219
import javax.tools.StandardLocation;
23-
24-
import io.avaje.http.generator.core.openapi.DocContext;
20+
import java.io.IOException;
21+
import java.util.List;
22+
import java.util.Objects;
23+
import java.util.stream.Collectors;
2524

2625
public class ProcessingContext {
2726

@@ -120,23 +119,21 @@ public TypeMirror asMemberOf(DeclaredType declaredType, Element element) {
120119
return types.asMemberOf(declaredType, element);
121120
}
122121

123-
public List<ExecutableElement> getSuperMethods(Element element, String methodName) {
124-
122+
public List<ExecutableElement> superMethods(Element element, String methodName) {
125123
return types.directSupertypes(element.asType()).stream()
126-
.filter(t -> !t.toString().contains("java.lang.Object"))
127-
.map(
128-
superType -> {
129-
final var superClass = (TypeElement) types.asElement(superType);
130-
for (final ExecutableElement method :
131-
ElementFilter.methodsIn(elements.getAllMembers(superClass))) {
132-
if (method.getSimpleName().contentEquals(methodName)) {
133-
return method;
134-
}
135-
}
136-
return null;
137-
})
138-
.filter(Objects::nonNull)
139-
.collect(Collectors.toList());
124+
.filter(type -> !type.toString().contains("java.lang.Object"))
125+
.map(
126+
superType -> {
127+
final var superClass = (TypeElement) types.asElement(superType);
128+
for (final ExecutableElement method : ElementFilter.methodsIn(elements.getAllMembers(superClass))) {
129+
if (method.getSimpleName().contentEquals(methodName)) {
130+
return method;
131+
}
132+
}
133+
return null;
134+
})
135+
.filter(Objects::nonNull)
136+
.collect(Collectors.toList());
140137
}
141138

142139
public PlatformAdapter platform() {

tests/test-javalin-jsonb/src/main/resources/public/openapi.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
{
22
"openapi" : "3.0.1",
33
"info" : {
4-
"title" : "Example service",
4+
"title" : "Example service showing off the Path extension method of controller",
55
"description" : "Example Javalin controllers with Java and Maven",
66
"version" : ""
77
},
88
"tags" : [
99
{
1010
"name" : "tag1",
11-
"description" : "it's somethin"
11+
"description" : "this is added to openapi tags"
1212
},
1313
{
1414
"name" : "tag1",
15-
"description" : "this is added to openapi tags"
15+
"description" : "it's somethin"
1616
}
1717
],
1818
"paths" : {

0 commit comments

Comments
 (0)