8
8
import static java .util .stream .Collectors .toMap ;
9
9
10
10
import java .io .IOException ;
11
+ import java .nio .file .Files ;
12
+ import java .nio .file .StandardOpenOption ;
11
13
import java .util .HashMap ;
14
+ import java .util .HashSet ;
12
15
import java .util .Map ;
13
16
import java .util .Map .Entry ;
14
17
import java .util .Set ;
27
30
28
31
@ GenerateAPContext
29
32
@ GenerateModuleInfoReader
30
- @ SupportedOptions ({"useJavax" , "useSingleton" , "instrumentRequests" ,"disableDirectWrites" ,"disableJsonB" })
33
+ @ SupportedOptions ({
34
+ "useJavax" ,
35
+ "useSingleton" ,
36
+ "instrumentRequests" ,
37
+ "disableDirectWrites" ,
38
+ "disableJsonB"
39
+ })
31
40
public abstract class BaseProcessor extends AbstractProcessor {
32
41
42
+ private static final String HTTP_CONTROLLERS_TXT = "testAPI/controllers.txt" ;
33
43
protected String contextPathString ;
34
44
35
45
protected Map <String , String > packagePaths = new HashMap <>();
36
46
47
+ private final Set <String > clientFQNs = new HashSet <>();
48
+
37
49
@ Override
38
50
public SourceVersion getSupportedSourceVersion () {
39
51
return SourceVersion .latest ();
40
52
}
41
53
42
54
@ Override
43
55
public Set <String > getSupportedAnnotationTypes () {
44
- return Set .of (PathPrism .PRISM_TYPE , ControllerPrism .PRISM_TYPE , OpenAPIDefinitionPrism .PRISM_TYPE );
56
+ return Set .of (
57
+ PathPrism .PRISM_TYPE , ControllerPrism .PRISM_TYPE , OpenAPIDefinitionPrism .PRISM_TYPE );
45
58
}
46
59
47
60
@ Override
48
61
public synchronized void init (ProcessingEnvironment processingEnv ) {
49
62
super .init (processingEnv );
50
63
APContext .init (processingEnv );
51
64
ProcessingContext .init (processingEnv , providePlatformAdapter ());
65
+
66
+ try {
67
+ var txtFilePath = APContext .getBuildResource (HTTP_CONTROLLERS_TXT );
68
+
69
+ if (txtFilePath .toFile ().exists ()) {
70
+ Files .lines (txtFilePath ).forEach (clientFQNs ::add );
71
+ }
72
+ if (APContext .isTestCompilation ()) {
73
+ for (var path : clientFQNs ) {
74
+ TestClientWriter .writeActual (path );
75
+ }
76
+ }
77
+ } catch (IOException e ) {
78
+ e .printStackTrace ();
79
+ // not worth failing over
80
+ }
52
81
}
53
82
54
83
/** Provide the platform specific adapter to use for Javalin, Helidon etc. */
@@ -82,19 +111,34 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
82
111
readSecuritySchemes (round );
83
112
}
84
113
85
- for (final Element controller : round .getElementsAnnotatedWith (typeElement (ControllerPrism .PRISM_TYPE ))) {
114
+ for (final var controller :
115
+ ElementFilter .typesIn (
116
+ round .getElementsAnnotatedWith (typeElement (ControllerPrism .PRISM_TYPE )))) {
86
117
writeAdapter (controller );
87
118
}
88
119
89
120
if (round .processingOver ()) {
90
121
writeOpenAPI ();
91
122
ProcessingContext .validateModule ();
123
+
124
+ if (!APContext .isTestCompilation ()) {
125
+ try {
126
+ Files .write (
127
+ APContext .getBuildResource (HTTP_CONTROLLERS_TXT ),
128
+ clientFQNs ,
129
+ StandardOpenOption .CREATE ,
130
+ StandardOpenOption .WRITE );
131
+ } catch (IOException e ) {
132
+ // not worth failing over
133
+ }
134
+ }
92
135
}
93
136
return false ;
94
137
}
95
138
96
139
private void readOpenApiDefinition (RoundEnvironment round ) {
97
- for (final Element element : round .getElementsAnnotatedWith (typeElement (OpenAPIDefinitionPrism .PRISM_TYPE ))) {
140
+ for (final Element element :
141
+ round .getElementsAnnotatedWith (typeElement (OpenAPIDefinitionPrism .PRISM_TYPE ))) {
98
142
doc ().readApiDefinition (element );
99
143
}
100
144
}
@@ -103,16 +147,19 @@ private void readTagDefinitions(RoundEnvironment round) {
103
147
for (final Element element : round .getElementsAnnotatedWith (typeElement (TagPrism .PRISM_TYPE ))) {
104
148
doc ().addTagDefinition (element );
105
149
}
106
- for (final Element element : round .getElementsAnnotatedWith (typeElement (TagsPrism .PRISM_TYPE ))) {
150
+ for (final Element element :
151
+ round .getElementsAnnotatedWith (typeElement (TagsPrism .PRISM_TYPE ))) {
107
152
doc ().addTagsDefinition (element );
108
153
}
109
154
}
110
155
111
156
private void readSecuritySchemes (RoundEnvironment round ) {
112
- for (final Element element : round .getElementsAnnotatedWith (typeElement (SecuritySchemePrism .PRISM_TYPE ))) {
157
+ for (final Element element :
158
+ round .getElementsAnnotatedWith (typeElement (SecuritySchemePrism .PRISM_TYPE ))) {
113
159
doc ().addSecurityScheme (element );
114
160
}
115
- for (final Element element : round .getElementsAnnotatedWith (typeElement (SecuritySchemesPrism .PRISM_TYPE ))) {
161
+ for (final Element element :
162
+ round .getElementsAnnotatedWith (typeElement (SecuritySchemesPrism .PRISM_TYPE ))) {
116
163
doc ().addSecuritySchemes (element );
117
164
}
118
165
}
@@ -121,31 +168,42 @@ private void writeOpenAPI() {
121
168
doc ().writeApi ();
122
169
}
123
170
124
- private void writeAdapter (Element controller ) {
125
- if (controller instanceof TypeElement ) {
126
- final var packageFQN = elements ().getPackageOf (controller ).getQualifiedName ().toString ();
127
- final var contextPath = Util .combinePath (contextPathString , packagePath (packageFQN ));
128
- final var reader = new ControllerReader ((TypeElement ) controller , contextPath );
129
- reader .read (true );
130
- try {
131
- writeControllerAdapter (reader );
132
- } catch (final Throwable e ) {
133
- logError (reader .beanType (), "Failed to write $Route class " + e );
171
+ private void writeAdapter (TypeElement controller ) {
172
+ final var packageFQN = elements ().getPackageOf (controller ).getQualifiedName ().toString ();
173
+ final var contextPath = Util .combinePath (contextPathString , packagePath (packageFQN ));
174
+ final var reader = new ControllerReader (controller , contextPath );
175
+ reader .read (true );
176
+ try {
177
+
178
+ writeControllerAdapter (reader );
179
+ writeClientAdapter (reader );
180
+
181
+ } catch (final Throwable e ) {
182
+ logError (reader .beanType (), "Failed to write $Route class " + e );
183
+ }
184
+ }
185
+
186
+ private void writeClientAdapter (ControllerReader reader ) {
187
+
188
+ try {
189
+ if (reader .beanType ().getInterfaces ().isEmpty ()
190
+ && "java.lang.Object" .equals (reader .beanType ().getSuperclass ().toString ())) {
191
+ new TestClientWriter (reader ).write ();
192
+ clientFQNs .add (reader .beanType ().getQualifiedName ().toString () + "TestAPI" );
134
193
}
194
+ } catch (final IOException e ) {
195
+ logError (reader .beanType (), "Failed to write $Route class " + e );
135
196
}
136
197
}
137
198
138
199
private String packagePath (String packageFQN ) {
139
200
return packagePaths .entrySet ().stream ()
140
- .filter (k -> packageFQN .startsWith (k .getKey ()))
141
- .map (Entry ::getValue )
142
- .reduce (Util ::combinePath )
143
- .orElse (null );
201
+ .filter (k -> packageFQN .startsWith (k .getKey ()))
202
+ .map (Entry ::getValue )
203
+ .reduce (Util ::combinePath )
204
+ .orElse (null );
144
205
}
145
206
146
- /**
147
- * Write the adapter code for the given controller.
148
- */
207
+ /** Write the adapter code for the given controller. */
149
208
public abstract void writeControllerAdapter (ControllerReader reader ) throws IOException ;
150
-
151
209
}
0 commit comments