title: How to get type annotations & attribute values for VariableElement with Java8?
body: <p>Consider the following code:</p>
  
  <pre><code>public class SimpleTest {
  
      private Map&lt;@JSON Integer,Map&lt;@Frozen Integer,@Enumerated(value = Enumerated.Encoding.NAME, test = "123") String&gt;&gt; map;
  }
  </code></pre>
  
  <p>With the latest JDK8 API for annotation processing, how can I access the list of annotations (<strong>@JSON</strong>, <strong>@Frozen</strong> &amp; <strong>@Enumerated</strong>) and their corresponding attributes (value &amp; test for <strong>@Enumerated</strong>) from the VariableElement ?</p>
  
  <pre><code>final VariableElement mapElm = els.stream().filter(x -&gt; x.getSimpleName().contentEquals("map")).findFirst().get();
  ???
  ???
  </code></pre>
  
  <p>I've tried many tricks, like <code>mapElm.getTypeArguments().get(0)</code> for the <code>@Json Integer</code> but I never succeed to get my hand on the annotation <strong>@JSON</strong>...</p>
  
  <p><strong>Edit</strong>: By accessing internal classes of the JDK, I can have access to those annotations but it's so hacky and sensitive to impl change that I'm wondering whether there is a better way</p>
  
  <pre><code>public static class SimpleEntityCodecFactoryTest {
  
      private Map&lt;@JSON Integer,Map&lt;@Frozen Integer,@Enumerated(value = Enumerated.Encoding.NAME, test = "123") String&gt;&gt; map;
  }
  
  final TypeElement typeElement = elementUtils.getTypeElement(SimpleEntityCodecFactoryTest.class.getCanonicalName());
  final List&lt;VariableElement&gt; els = ElementFilter.fieldsIn(typeElement.getEnclosedElements());
  
  final VariableElement mapElt = els.stream().filter(x -&gt; x.getSimpleName().contentEquals("map")).findFirst().get();
  final com.sun.tools.javac.util.List&lt;Attribute.TypeCompound&gt; typeAttributes = ((Symbol.VarSymbol) mapElt).getMetadata().getTypeAttributes();
  for (Attribute.TypeCompound typeAttribute : typeAttributes) {
      final DeclaredType annotationType = typeAttribute.getAnnotationType();
      System.out.println(format("Accessing annotation '%s' at location : %s",annotationType.toString(),typeAttribute.getPosition().location));
      for (Map.Entry&lt;Symbol.MethodSymbol,Attribute&gt; entry : typeAttribute.getElementValues().entrySet()) {
          final Symbol.MethodSymbol methodSymbol = entry.getKey();
          final Attribute attribute = entry.getValue();
          System.out.println(format("Attribute '%s' for annotation '%s' : %s", methodSymbol.name, annotationType.toString(), attribute.toString()));
      }
  }    
  </code></pre>
  
  <p>The output display:</p>
  
  <pre><code>Accessing annotation 'info.archinnov.achilles.annotations.JSON' at location : TYPE_ARGUMENT(0)
  Accessing annotation 'info.archinnov.achilles.annotations.Frozen' at location : TYPE_ARGUMENT(1),TYPE_ARGUMENT(0)
  Accessing annotation 'info.archinnov.achilles.annotations.Enumerated' at location : TYPE_ARGUMENT(1),TYPE_ARGUMENT(1)
  Attribute 'value' for annotation 'info.archinnov.achilles.annotations.Enumerated' : info.archinnov.achilles.annotations.Enumerated.Encoding.NAME
  Attribute 'test' for annotation 'info.archinnov.achilles.annotations.Enumerated' : "123"
  </code></pre>
  
  <p>The above code is working fine in <strong>IntelliJ</strong>, but because of the dirty cast <strong>((Symbol.VarSymbol) mapElt).getMetadata()</strong>, it is working with <strong>Oracle JDK</strong> but fails miserably with <strong>Eclipse compiler</strong>.</p>
  
  <p>Right now, I don't find any other solution than the dirty cast to access annotations in generic types. Any idea is welcomed</p>
  
  <p><strong>Solution:</strong></p>
  
  <p>Thanks to Werner (<strong>wmdietl</strong>), I can access the nested annotations using the <strong>Tree API</strong> instead of <strong>Elements</strong> or <strong>TypeMirror</strong></p>
  
  <p>However I'm quite stuck because once I get there, it is not possible to convert any subclass of <strong>Tree</strong> back to <strong>Element</strong> or <strong>TypeMirror</strong> (my real target). </p>
  
  <p>All of my annotation processing is using heavily JavaPoet (<a href="https://github.com/square/javapoet" rel="nofollow">https://github.com/square/javapoet</a>) to generate clean source code and this framework only handles TypeMirror, not Tree</p>
  
  <p>In the <a href="https://github.com/typetools/checker-framework/blob/master/javacutil/src/org/checkerframework/javacutil/TreeUtils.java" rel="nofollow">https://github.com/typetools/checker-framework/blob/master/javacutil/src/org/checkerframework/javacutil/TreeUtils.java</a> class, there are some methods to convert <strong>Tree</strong> back to <strong>Element</strong> but it is relying on <strong>InternalUtils</strong>, which I can't use because it won't be compatible with <strong>Eclipse ECJ compiler</strong>.</p>
  
  <p>I  guess I will have to wait for JDK 9 before having an usable Element API that will be compatible with ECJ compiler</p>
  
  <p><strong>Edit</strong>: To make the type annotation work for <strong>Eclipse Compiler</strong>, I had to cast to internal compiler classes like here: <a href="https://github.com/doanduyhai/Achilles/blob/master/achilles-core/src/main/java/info/archinnov/achilles/internals/parser/AnnotationTree.java#L83-L85" rel="nofollow">https://github.com/doanduyhai/Achilles/blob/master/achilles-core/src/main/java/info/archinnov/achilles/internals/parser/AnnotationTree.java#L83-L85</a>. It's ugly but that is the only way for now until JDK9.</p>