gt:         Elements elements = env.getElementUtils();
context: /*
   * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  package com.sun.tools.internal.jxc.model.nav;
  
  import com.sun.source.tree.CompilationUnitTree;
  import com.sun.source.util.TreePath;
  import com.sun.source.util.Trees;
  import com.sun.xml.internal.bind.v2.model.nav.Navigator;
  import com.sun.xml.internal.bind.v2.runtime.Location;
  
  import javax.annotation.processing.ProcessingEnvironment;
  import javax.lang.model.element.Element;
  import javax.lang.model.element.ElementKind;
  import javax.lang.model.element.ExecutableElement;
  import javax.lang.model.element.Modifier;
  import javax.lang.model.element.TypeElement;
  import javax.lang.model.element.TypeParameterElement;
  import javax.lang.model.element.VariableElement;
  import javax.lang.model.type.ArrayType;
  import javax.lang.model.type.DeclaredType;
  import javax.lang.model.type.PrimitiveType;
  import javax.lang.model.type.TypeKind;
  import javax.lang.model.type.TypeMirror;
  import javax.lang.model.type.TypeVariable;
  import javax.lang.model.type.TypeVisitor;
  import javax.lang.model.type.WildcardType;
  import javax.lang.model.util.ElementFilter;
  import javax.lang.model.util.Elements;
  import javax.lang.model.util.SimpleTypeVisitor6;
  import javax.lang.model.util.Types;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  
  /**
   * {@link Navigator} implementation for annotation processing.
   * TODO: check the spec on how generics are supposed to be handled
   *
   * @author Kohsuke Kawaguchi (kk@kohsuke.org)
   */
  public class ApNavigator implements Navigator<TypeMirror, TypeElement, VariableElement, ExecutableElement> {
  
      private final ProcessingEnvironment env;
  
      private final PrimitiveType primitiveByte;
  
      public ApNavigator(ProcessingEnvironment env) {
          this.env = env;
          this.primitiveByte = env.getTypeUtils().getPrimitiveType(TypeKind.BYTE);
      }
  
      public TypeElement getSuperClass(TypeElement typeElement) {
          if (typeElement.getKind().equals(ElementKind.CLASS)) {
              TypeMirror sup = typeElement.getSuperclass();
              if (!sup.getKind().equals(TypeKind.NONE))
                  return (TypeElement) ((DeclaredType) sup).asElement();
              else
                  return null;
          }
          return env.getElementUtils().getTypeElement(Object.class.getName());
      }
  
      public TypeMirror getBaseClass(TypeMirror type, TypeElement sup) {
          return baseClassFinder.visit(type, sup);
      }
  
      public String getClassName(TypeElement t) {
          return t.getQualifiedName().toString();
      }
  
      public String getTypeName(TypeMirror typeMirror) {
          return typeMirror.toString();
      }
  
      public String getClassShortName(TypeElement t) {
          return t.getSimpleName().toString();
      }
  
      public Collection<VariableElement> getDeclaredFields(TypeElement typeElement) {
          return ElementFilter.fieldsIn(typeElement.getEnclosedElements());
      }
  
      public VariableElement getDeclaredField(TypeElement clazz, String fieldName) {
          for (VariableElement fd : ElementFilter.fieldsIn(clazz.getEnclosedElements())) {
              if (fd.getSimpleName().toString().equals(fieldName))
                  return fd;
          }
          return null;
      }
  
      public Collection<ExecutableElement> getDeclaredMethods(TypeElement typeElement) {
          return ElementFilter.methodsIn(typeElement.getEnclosedElements());
      }
  
      public TypeElement getDeclaringClassForField(VariableElement f) {
          return (TypeElement) f.getEnclosingElement();
      }
  
      public TypeElement getDeclaringClassForMethod(ExecutableElement m) {
          return (TypeElement) m.getEnclosingElement();
      }
  
      public TypeMirror getFieldType(VariableElement f) {
          return f.asType();
      }
  
      public String getFieldName(VariableElement f) {
          return f.getSimpleName().toString();
      }
  
      public String getMethodName(ExecutableElement m) {
          return m.getSimpleName().toString();
      }
  
      public TypeMirror getReturnType(ExecutableElement m) {
          return m.getReturnType();
      }
  
      public TypeMirror[] getMethodParameters(ExecutableElement m) {
          Collection<? extends VariableElement> ps = m.getParameters();
          TypeMirror[] r = new TypeMirror[ps.size()];
          int i=0;
          for (VariableElement p : ps)
              r[i++] = p.asType();
          return r;
      }
  
      public boolean isStaticMethod(ExecutableElement m) {
          return hasModifier(m, Modifier.STATIC);
      }
  
      public boolean isFinalMethod(ExecutableElement m) {
          return hasModifier(m, Modifier.FINAL);
      }
  
      private boolean hasModifier(Element d, Modifier mod) {
          return d.getModifiers().contains(mod);
      }
  
      public boolean isSubClassOf(TypeMirror sub, TypeMirror sup) {
          if(sup==DUMMY)
          // see ref(). if the sub type is known to Annotation Processing,
          // its base class must be known. Thus if the sup is DUMMY,
          // it cannot possibly be the super type.
              return false;
          return env.getTypeUtils().isSubtype(sub,sup);
      }
  
      private String getSourceClassName(Class clazz) {
          Class<?> d = clazz.getDeclaringClass();
          if(d==null)
              return clazz.getName();
          else {
              String shortName = clazz.getName().substring(d.getName().length()+1/*for $*/);
              return getSourceClassName(d)+'.'+shortName;
          }
      }
  
      public TypeMirror ref(Class c) {
          if(c.isArray())
              return env.getTypeUtils().getArrayType( ref(c.getComponentType()) );
          if(c.isPrimitive())
              return getPrimitive(c);
          TypeElement t = env.getElementUtils().getTypeElement(getSourceClassName(c));
          // Annotation Processing only operates on a set of classes used in the compilation,
          // and it won't recognize additional classes (even if they are visible from javac)
          // and return null.
          //
          // this is causing a problem where we check if a type is collection.
          // so until the problem is fixed in Annotation Processing, work around the issue
          // by returning a dummy token
          // TODO: check if this is still valid
          if(t==null)
              return DUMMY;
          return env.getTypeUtils().getDeclaredType(t);
      }
  
      public TypeMirror use(TypeElement t) {
          assert t != null;
          return env.getTypeUtils().getDeclaredType(t);
      }
  
      public TypeElement asDecl(TypeMirror m) {
          m = env.getTypeUtils().erasure(m);
          if (m.getKind().equals(TypeKind.DECLARED)) {
              DeclaredType d = (DeclaredType) m;
              return (TypeElement) d.asElement();
          } else
              return null;
      }
  
      public TypeElement asDecl(Class c) {
          return env.getElementUtils().getTypeElement(getSourceClassName(c));
      }
  
      public TypeMirror erasure(TypeMirror t) {
          Types tu = env.getTypeUtils();
          t = tu.erasure(t);
          if (t.getKind().equals(TypeKind.DECLARED)) {
              DeclaredType dt = (DeclaredType)t;
              if (!dt.getTypeArguments().isEmpty())
                  return tu.getDeclaredType((TypeElement) dt.asElement());
          }
          return t;
      }
  
      public boolean isAbstract(TypeElement clazz) {
          return hasModifier(clazz,Modifier.ABSTRACT);
      }
  
      public boolean isFinal(TypeElement clazz) {
          return hasModifier(clazz,Modifier.FINAL);
      }
  
      public VariableElement[] getEnumConstants(TypeElement clazz) {
          List<? extends Element> elements = env.getElementUtils().getAllMembers(clazz);
          Collection<VariableElement> constants = new HashSet<VariableElement>();
          for (Element element : elements) {
              if (element.getKind().equals(ElementKind.ENUM_CONSTANT)) {
                  constants.add((VariableElement) element);
              }
          }
          return constants.toArray(new VariableElement[constants.size()]);
      }
  
      public TypeMirror getVoidType() {
          return env.getTypeUtils().getNoType(TypeKind.VOID);
      }
  
      public String getPackageName(TypeElement clazz) {
          return env.getElementUtils().getPackageOf(clazz).getQualifiedName().toString();
      }
  
      public TypeElement findClass(String className, TypeElement referencePoint) {
          return env.getElementUtils().getTypeElement(className);
      }
  
      public boolean isBridgeMethod(ExecutableElement method) {
          return method.getModifiers().contains(Modifier.VOLATILE);
      }
  
      public boolean isOverriding(ExecutableElement method, TypeElement base) {
  