I'm implementing an annotation processor to make sure that the elements marked with an annotation are instances of a class that implements a certain interface, or are uses of types that implement a certain interface:
@Documented
@Target(value = { ElementType.PARAMETER, ElementType.TYPE_USE })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface AuditSubject {
}
public interface Auditable {
// methods that provide data for writing a log entry...
}
public class Report implements Auditable {
}
For the annotated elements, a log entry must be created after method execution (using AOP). Examples:
@CreateLogEntry
public Result persist(@AuditSubject Report newReport) {
// A log entry must be created based on the incoming 'newReport' instance.
}
@CreateLogEntry
public UpdateResult<@AuditSubject Report> update(Report update) {
// A log entry must be created based on the updated report, which is not the same instance as 'update' but an equivalent one.
}
@CreateLogEntry
public Result persistBatch(List<@AuditSubject Report> batch) {
// A log entry must be created for each element in 'batch' after this method's execution.
}
The log entries must be created provided that Report
implements Auditable
; if it does not, a runtime exception is thrown (Yikes, I forgot to implement the interface!). Thus the annotation processor helps to catch programmer mistakes at compile time. So far I've been successful in checking all uses in parameters, but not in type uses. The relevant code from the annotation processor is as follows:
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element annotated : roundEnv.getElementsAnnotatedWith(AuditSubject.class)) {
// Only prints elements with ElementKind.PARAMETER)!
this.messager.printMessage(Kind.NOTE, TextUtils.replaceParams("annotated: {} ; Kind : {} ; enclosing : {}", annotated, annotated.getKind(), annotated.getEnclosingElement()));
if (annotated.getKind() == ElementKind.PARAMETER) {
// Code here works as expected, raises errors for annotated parameters of classes that don't implement Auditable.
} else if (annotated.getKind() == ElementKind.WHAT_TO_USE) {
// What ElementKind do I need to use here?
}
}
return false;
}
Only annotated elements with kind ElementKind.PARAMETER
are recognized (the first line in the loop of process() only prints a single line for 'newReport'
) How can I check that the annotated types implement Auditable
? There's no "ElementKind.TYPE_USE
" constant to use. I haven't been able to find any relevant information on this matter. Thanks for your attention.