Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle TypeMirror and Class gracefully

I'm just getting into javax AnnotationProcessing over here, and have run into an ugly case. I'll illustrate it in a series of pseudo-code lines that describe my learning process:

MyAnnotation ann = elementIfound.getAnnotation(MyAnnotation.class);
// Class<?> clazz = ann.getCustomClass();  // Can throw MirroredTypeException!
// Classes within the compilation unit don't exist in this form at compile time!

// Search web and find this alternative...

// Inspect all AnnotationMirrors
for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
  if (mirror.getAnnotationType().toString().equals(annotationType.getName())) {
    // Inspect all methods on the Annotation class
    for (Entry<? extends ExecutableElement,? extends AnnotationValue> entry : mirror.getElementValues().entrySet()) {
      if (entry.getKey().getSimpleName().toString().equals(paramName)) {
        return (TypeMirror) entry.getValue();
      }
    }
    return null;
  }
}
return null;

The problem is that now I'm finding out that if the client code contains a core class like java.lang.String or java.lang.Object as a Class parameter, this line:

return (TypeMirror) entry.getValue();

...results in a ClassCastException, because the AnnotationProcessor environment is kind enough to actually retrieve the Class object in this case.

I've figured out how to do everything I need to do with TypeMirror in the absence of Class - do I need to handle both of them in my code now? Is there a way to obtain a TypeMirror from a Class object? Because I can't find one

like image 346
torquestomp Avatar asked Jul 15 '13 20:07

torquestomp


1 Answers

The solution I went with for this problem was to use the ProcessingEnvironment to cast the resultant Class objects to TypeMirrors, in the cases when I got classes instead of TypeMirrors. This seems to work fairly well.

AnnotationValue annValue = entry.getValue();
if (annValue instanceof TypeMirror) {
  return (TypeMirror) annValue;
}
else {
  String valString = annValue.getValue().toString();
  TypeElement elem = processingEnv.getElementUtils().getTypeElement(valString);
  return elem.asType();
}
like image 66
torquestomp Avatar answered Sep 30 '22 16:09

torquestomp