88import static java .util .stream .Collectors .toMap ;
99
1010import java .io .IOException ;
11+ import java .nio .file .Files ;
12+ import java .nio .file .StandardOpenOption ;
1113import java .util .HashMap ;
14+ import java .util .HashSet ;
1215import java .util .Map ;
1316import java .util .Map .Entry ;
1417import java .util .Set ;
2730
2831@ GenerateAPContext
2932@ GenerateModuleInfoReader
30- @ SupportedOptions ({"useJavax" , "useSingleton" , "instrumentRequests" ,"disableDirectWrites" ,"disableJsonB" })
33+ @ SupportedOptions ({
34+ "useJavax" ,
35+ "useSingleton" ,
36+ "instrumentRequests" ,
37+ "disableDirectWrites" ,
38+ "disableJsonB"
39+ })
3140public abstract class BaseProcessor extends AbstractProcessor {
3241
42+ private static final String HTTP_CONTROLLERS_TXT = "controllers.txt" ;
43+
3344 protected String contextPathString ;
3445
3546 protected Map <String , String > packagePaths = new HashMap <>();
3647
48+ private final Set <String > controllerFQNs = new HashSet <>();
49+
3750 @ Override
3851 public SourceVersion getSupportedSourceVersion () {
3952 return SourceVersion .latest ();
4053 }
4154
4255 @ Override
4356 public Set <String > getSupportedAnnotationTypes () {
44- return Set .of (PathPrism .PRISM_TYPE , ControllerPrism .PRISM_TYPE , OpenAPIDefinitionPrism .PRISM_TYPE );
57+ return Set .of (
58+ PathPrism .PRISM_TYPE , ControllerPrism .PRISM_TYPE , OpenAPIDefinitionPrism .PRISM_TYPE );
4559 }
4660
4761 @ Override
4862 public synchronized void init (ProcessingEnvironment processingEnv ) {
4963 super .init (processingEnv );
5064 APContext .init (processingEnv );
5165 ProcessingContext .init (processingEnv , providePlatformAdapter ());
66+
67+ try {
68+ var txtFilePath = APContext .getBuildResource (HTTP_CONTROLLERS_TXT );
69+
70+ if (txtFilePath .toFile ().exists ()) {
71+ Files .lines (txtFilePath ).forEach (controllerFQNs ::add );
72+ }
73+ if (APContext .isTestCompilation ()) {
74+ System .out .println ("Trying to read: " + controllerFQNs + "from path:" + txtFilePath );
75+ controllerFQNs .stream ().map (APContext ::typeElement ).forEach (this ::writeClientAdapter );
76+ }
77+ } catch (IOException e ) {
78+ e .printStackTrace ();
79+ // not worth failing over
80+ }
5281 }
5382
5483 /** Provide the platform specific adapter to use for Javalin, Helidon etc. */
@@ -82,19 +111,34 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
82111 readSecuritySchemes (round );
83112 }
84113
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 )))) {
86117 writeAdapter (controller );
87118 }
88119
89120 if (round .processingOver ()) {
90121 writeOpenAPI ();
91122 ProcessingContext .validateModule ();
123+
124+ if (!APContext .isTestCompilation ()) {
125+ try {
126+ Files .write (
127+ APContext .getBuildResource (HTTP_CONTROLLERS_TXT ),
128+ controllerFQNs ,
129+ StandardOpenOption .CREATE ,
130+ StandardOpenOption .WRITE );
131+ } catch (IOException e ) {
132+ // not worth failing over
133+ }
134+ }
92135 }
93136 return false ;
94137 }
95138
96139 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 ))) {
98142 doc ().readApiDefinition (element );
99143 }
100144 }
@@ -103,16 +147,19 @@ private void readTagDefinitions(RoundEnvironment round) {
103147 for (final Element element : round .getElementsAnnotatedWith (typeElement (TagPrism .PRISM_TYPE ))) {
104148 doc ().addTagDefinition (element );
105149 }
106- for (final Element element : round .getElementsAnnotatedWith (typeElement (TagsPrism .PRISM_TYPE ))) {
150+ for (final Element element :
151+ round .getElementsAnnotatedWith (typeElement (TagsPrism .PRISM_TYPE ))) {
107152 doc ().addTagsDefinition (element );
108153 }
109154 }
110155
111156 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 ))) {
113159 doc ().addSecurityScheme (element );
114160 }
115- for (final Element element : round .getElementsAnnotatedWith (typeElement (SecuritySchemesPrism .PRISM_TYPE ))) {
161+ for (final Element element :
162+ round .getElementsAnnotatedWith (typeElement (SecuritySchemesPrism .PRISM_TYPE ))) {
116163 doc ().addSecuritySchemes (element );
117164 }
118165 }
@@ -121,39 +168,46 @@ private void writeOpenAPI() {
121168 doc ().writeApi ();
122169 }
123170
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-
132- writeControllerAdapter (reader );
133- TypeElement typeElement = (TypeElement ) controller ;
134- if (APContext .isTestCompilation ()
135- && typeElement .getInterfaces ().isEmpty ()
136- && "java.lang.Object" .equals (typeElement .getSuperclass ().toString ())) {
137- new TestClientWriter (reader ).write ();
138- }
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+ controllerFQNs .add (controller .getQualifiedName ().toString ());
180+
181+ } catch (final Throwable e ) {
182+ logError (reader .beanType (), "Failed to write $Route class " + e );
183+ }
184+ }
139185
140- } catch (final Throwable e ) {
141- logError (reader .beanType (), "Failed to write $Route class " + e );
186+ private void writeClientAdapter (TypeElement controller ) {
187+ final var packageFQN = elements ().getPackageOf (controller ).getQualifiedName ().toString ();
188+ final var contextPath = Util .combinePath (contextPathString , packagePath (packageFQN ));
189+ final var reader = new ControllerReader (controller , contextPath );
190+ reader .read (true );
191+ try {
192+ if (controller .getInterfaces ().isEmpty ()
193+ && "java.lang.Object" .equals (controller .getSuperclass ().toString ())) {
194+ new TestClientWriter (reader ).write ();
142195 }
196+ writeControllerAdapter (reader );
197+
198+ } catch (final Throwable e ) {
199+ logError (reader .beanType (), "Failed to write $Route class " + e );
143200 }
144201 }
145202
146203 private String packagePath (String packageFQN ) {
147204 return packagePaths .entrySet ().stream ()
148- .filter (k -> packageFQN .startsWith (k .getKey ()))
149- .map (Entry ::getValue )
150- .reduce (Util ::combinePath )
151- .orElse (null );
205+ .filter (k -> packageFQN .startsWith (k .getKey ()))
206+ .map (Entry ::getValue )
207+ .reduce (Util ::combinePath )
208+ .orElse (null );
152209 }
153210
154- /**
155- * Write the adapter code for the given controller.
156- */
211+ /** Write the adapter code for the given controller. */
157212 public abstract void writeControllerAdapter (ControllerReader reader ) throws IOException ;
158-
159213}
0 commit comments