If MyAnnotation
is the annotation which your processor supports, then you'd just write something like this:
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment env) {
if (shouldClaim(annotations)) {
for (Element e : env.getElementsAnnotatedWith(MyAnnotation.class)) {
MyAnnotation a = e.getAnnotation(MyAnnotation.class);
String str1 = a.strNumberOne();
String str2 = a.strNumberTwo();
String str3 = a.strNumberThree();
// Add them to a List or whatever you need.
}
return true;
}
return false;
}
private boolean shouldClaim(Set<? extends TypeElement> annotations) {
Set<String> supported = getSupportedAnnotationTypes();
for (TypeElement a : annotations) {
if (supported.contains(a.getQualifiedName().toString()))
return true;
}
return false;
}
The logic of the shouldClaim
method is explained by the documentation for process
. It would be more complicated if your annotation supports e.g. *
or a type of the form name.*
, but in general you don't. (See getSupportedAnnotationTypes
for a description of what those mean.)
If MyAnnotation
isn't the annotation which your processor supports, then you would need to go through getElementValuesWithDefaults
if it's a type declared in the package you're compiling. Because annotation processing happens during compilation, class files don't exist yet for the source files being compiled, which is why we use the Element
API instead.
Element
represents a declaration of some kind, for example a class, method or variable. TypeElement
represents a class, interface, enum or annotation type declaration. TypeElement
is similar to Class
in terms of what we can do with it, except that we can use a TypeElement
for a class which is not necessarily compiled.
To get annotation values through the element API, you'd do something like this:
Elements elements = processingEnv.getElementUtils();
TypeElement myAnnotation = elements.getTypeElement("com.example.MyAnnotation");
for (Element e : env.getElementsAnnotatedWith(myAnnotation)) {
for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
DeclaredType annotationType = mirror.getAnnotationType();
Element annotationDecl = annotationType.asElement();
if (myAnnotation.equals(annotationDecl)) {
Map<? extends ExecutableElement, ? extends AnnotationValue> values =
elements.getAnnotationValuesWithDefaults(mirror);
String str1 = (String) getValue(values, "strNumberOne");
String str2 = (String) getValue(values, "strNumberTwo");
String str3 = (String) getValue(values, "strNumberThree");
// ...
}
}
}
private Object getValue(Map<? extends ExecutableElement,
? extends AnnotationValue> values,
String name) {
for (Map.Entry<? extends ExecutableElement,
? extends AnnotationValue> e : values.entrySet()) {
if (name.contentEquals(e.getKey().getSimpleName()))
return e.getValue().getValue();
}
return null;
}
That's a pain, but we only need to use the element API if the annotation we're interested in is one of the classes being compiled.
We might also want to find the AnnotationMirror
and/or AnnotationValue
to cause a message of some kind on a particular element using one of the Messager.printMessage
overloads which takes one of the aforementioned objects as an argument.