I have built an annotation processor that is triggered with the com.foo.FooEntity
annotation. There is a need to be able to create more stereotypes that would trigger that annotation processor as well.
For instance, a controller should also trigger this annotation processor. I am wondering if there is a way to place the @FooEntity
annotation on it. Something like:
@FooEntity
@Target(TYPE)
@Retention(RUNTIME)
public @interface Controller {}
And use this so that this class triggers annotation processing
@Controller
public class MyController { ... }
Of course, the idea here is that I want to add new stereotypes without having to touch the annotation processor itself.
I don't think there is a way to configure a processor to process @FooEntity
as well as annotations meta-annotated with @FooEntity
(@Controller
in this case). What you could do instead is have a processor that supports any annotation (@SupportedAnnotationTypes("*")
) and then implement some further logic within the processor itself in order to decide which annotations you do want to process. Here is such an implementation based on my understanding of the problem:
package acme.annotation.processing;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.TypeElement;
import acme.annotation.FooEntity;
@SupportedAnnotationTypes("*")
public class FooEntityExtendedProcessor extends AbstractProcessor {
private void log(String msg) {
System.out.println(msg);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
log("Initially I was asked to process:" + annotations.toString());
Set<TypeElement> fooAnnotations = new HashSet<>();
for (TypeElement elem : annotations) {
if (isFoo(elem)) fooAnnotations.add(elem);
}
if (fooAnnotations.size() > 0) {
log("... but I am now going to process:" + fooAnnotations.toString());
processInternal(fooAnnotations, roundEnv);
} else {
log("... but none of those was my business!");
}
// always return false so that other processors get a chance to process the annotations not consumed here
return false;
}
private void processInternal(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// TODO: do your foo processing here
}
private boolean isFoo(TypeElement elem) {
if (elem.getQualifiedName().toString().equals("acme.annotation.FooEntity")
|| elem.getAnnotation(FooEntity.class) != null) {
return true;
} else {
return false;
}
}
}
A sample run would give you:
Initially I was asked to process:[acme.annotation.FooEntity, skriptor.annotation.ScriptArg, java.lang.Override, skriptor.annotation.ScriptCodeRT, skriptor.annotation.ScriptCode, skriptor.annotation.ScriptObject, javax.ws.rs.Path, javax.ws.rs.GET, acme.annotation.Controller, com.sun.jersey.spi.resource.Singleton, skriptor.annotation.ScriptImport, javax.ws.rs.ext.Provider, javax.ws.rs.Produces, javax.annotation.PostConstruct]
... but I am now going to process:[acme.annotation.Controller, acme.annotation.FooEntity]