/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.javac;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.dev.javac.asm.CollectAnnotationData;
import com.google.gwt.dev.javac.asm.CollectAnnotationData.AnnotationData;
import com.google.gwt.dev.javac.asm.CollectClassData;
import com.google.gwt.dev.javac.asm.CollectClassData.AnnotationEnum;
import com.google.gwt.dev.javac.asm.CollectFieldData;
import com.google.gwt.dev.javac.asm.CollectMethodData;
import com.google.gwt.dev.javac.asm.CollectTypeParams;
import com.google.gwt.dev.javac.asm.ResolveClassSignature;
import com.google.gwt.dev.javac.asm.ResolveMethodSignature;
import com.google.gwt.dev.javac.asm.ResolveTypeSignature;
import com.google.gwt.dev.javac.typemodel.JAbstractMethod;
import com.google.gwt.dev.javac.typemodel.JArrayType;
import com.google.gwt.dev.javac.typemodel.JClassType;
import com.google.gwt.dev.javac.typemodel.JField;
import com.google.gwt.dev.javac.typemodel.JGenericType;
import com.google.gwt.dev.javac.typemodel.JMethod;
import com.google.gwt.dev.javac.typemodel.JPackage;
import com.google.gwt.dev.javac.typemodel.JParameterizedType;
import com.google.gwt.dev.javac.typemodel.JRawType;
import com.google.gwt.dev.javac.typemodel.JRealClassType;
import com.google.gwt.dev.javac.typemodel.JTypeParameter;
import com.google.gwt.dev.javac.typemodel.JWildcardType;
import com.google.gwt.dev.javac.typemodel.TypeOracle;
import com.google.gwt.dev.javac.typemodel.TypeOracleUpdater;
import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting;
import com.google.gwt.thirdparty.guava.common.base.Function;
import com.google.gwt.thirdparty.guava.common.collect.Collections2;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Queues;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import com.google.gwt.thirdparty.guava.common.util.concurrent.ThreadFactoryBuilder;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.util.TraceClassVisitor;

import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Builds or rebuilds a {@link com.google.gwt.core.ext.typeinfo.TypeOracle} from a set of
 * compilation units.
 */
public class CompilationUnitTypeOracleUpdater extends TypeOracleUpdater {

  /**
   * A container to hold all the information we need to add one type to the TypeOracle.
   */
  static class TypeData {

    private final byte[] byteCode;
    private CollectClassData classData;
    private final String internalName;

    /**
     * A timestamp as returned from {@link System#currentTimeMillis()}
     */
    private final long lastModifiedTime;
    private final String packageName;
    private final String sourceName;

    protected TypeData(String packageName, String sourceName, String internalName, byte[] byteCode,
        long lastModifiedTime) {
      this.packageName = packageName;
      this.sourceName = sourceName;
      this.internalName = internalName;
      this.byteCode = byteCode;
      this.lastModifiedTime = lastModifiedTime;
    }

    /**
     * Collects data about a class which only needs the bytecode and no TypeOracle data structures.
     * This is used to make the initial shallow identity pass for creating
     * JRealClassType/JGenericType objects.
     */
    synchronized CollectClassData getCollectClassData() {
      if (classData == null) {
        ClassReader reader = new ClassReader(byteCode);
        classData = new CollectClassData();
        ClassVisitor classVisitor = classData;
        if (TRACE_CLASSES) {
          classVisitor = new TraceClassVisitor(classVisitor, new PrintWriter(System.out));
        }
        reader.accept(classVisitor, 0);
      }
      return classData;
    }
  }

  private class CompilationUnitTypeOracleResolver implements Resolver {

    private final TypeOracleBuildContext context;

    public CompilationUnitTypeOracleResolver(TypeOracleBuildContext context) {
      this.context = context;
    }

    @Override
    public void addImplementedInterface(JRealClassType type, JClassType intf) {
      CompilationUnitTypeOracleUpdater.this.addImplementedInterface(type, intf);
    }

    @Override
    public void addThrows(JAbstractMethod method, JClassType exception) {
      CompilationUnitTypeOracleUpdater.this.addThrows(method, exception);
    }

    @Override
    public JRealClassType findByInternalName(String internalName) {
      return CompilationUnitTypeOracleUpdater.this.findByInternalName(internalName);
    }

    @Override
    public TypeOracle getTypeOracle() {
      return CompilationUnitTypeOracleUpdater.this.typeOracle;
    }

    @Override
    public JMethod newMethod(JClassType type, String name,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
        JTypeParameter[] typeParams) {
      return CompilationUnitTypeOracleUpdater.this.newMethod(
          type, name, declaredAnnotations, typeParams);
    }

    @Override
    public void newParameter(JAbstractMethod method, JType argType, String argName,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations, boolean argNamesAreReal) {
      CompilationUnitTypeOracleUpdater.this.newParameter(
          method, argType, argName, declaredAnnotations, argNamesAreReal);
    }

    @Override
    public JRealClassType newRealClassType(JPackage pkg, String enclosingTypeName,
        boolean isLocalType, String simpleSourceName, boolean isInterface) {
      return CompilationUnitTypeOracleUpdater.this.newRealClassType(
          pkg, enclosingTypeName, simpleSourceName, isInterface);
    }

    @Override
    public boolean resolveAnnotations(TreeLogger logger, List<CollectAnnotationData> annotations,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
      return CompilationUnitTypeOracleUpdater.this.resolveAnnotations(
          logger, annotations, declaredAnnotations);
    }

    @Override
    public boolean resolveClass(TreeLogger logger, JRealClassType type) {
      return CompilationUnitTypeOracleUpdater.this.resolveClass(logger, type, context);
    }

    @Override
    public void setReturnType(JAbstractMethod method, JType returnType) {
      CompilationUnitTypeOracleUpdater.this.setReturnType(method, returnType);
    }

    @Override
    public void setSuperClass(JRealClassType type, JClassType superType) {
      CompilationUnitTypeOracleUpdater.this.setSuperClass(type, superType);
    }
  }

  /**
   * This context keeps common data so we don't have to pass it around between methods for one pass
   * of {@link CompilationUnitTypeOracleUpdater#addNewTypesDontIndex(TreeLogger, Collection,
   * MethodArgNamesLookup)} .
   */
  protected class TypeOracleBuildContext {
    protected final MethodArgNamesLookup allMethodArgs;

    private final Map<String, CollectClassData> classDataByInternalName = Maps.newHashMap();

    private final Map<JRealClassType, CollectClassData> classDataByType = Maps.newHashMap();

    private final Resolver resolver = new CompilationUnitTypeOracleResolver(this);

    protected TypeOracleBuildContext(MethodArgNamesLookup allMethodArgs) {
      this.allMethodArgs = allMethodArgs;
    }
  }

  /**
   * Pairs of bits to convert from ASM Opcodes.* to Shared.* bitfields.
   */
  private static final int[] ASM_TO_SHARED_MODIFIERS =
      new int[] {Opcodes.ACC_PUBLIC, Shared.MOD_PUBLIC, //
          Opcodes.ACC_PRIVATE, Shared.MOD_PRIVATE, //
          Opcodes.ACC_PROTECTED, Shared.MOD_PROTECTED, //
          Opcodes.ACC_STATIC, Shared.MOD_STATIC, //
          Opcodes.ACC_FINAL, Shared.MOD_FINAL, //
          Opcodes.ACC_ABSTRACT, Shared.MOD_ABSTRACT, //
          Opcodes.ACC_VOLATILE, Shared.MOD_VOLATILE, //
          Opcodes.ACC_TRANSIENT, Shared.MOD_TRANSIENT, //
      };

  private static final JTypeParameter[] NO_TYPE_PARAMETERS = new JTypeParameter[0];

  /**
   * Turn on to trace class processing.
   */
  private static final boolean TRACE_CLASSES = false;

  /**
   * Suppress some warnings related to missing valiation.jar on classpath.
   */
  private static boolean warnedMissingValidationJar = false;

  private static JTypeParameter[] collectTypeParams(String signature) {
    if (signature != null) {
      List<JTypeParameter> params = Lists.newArrayList();
      SignatureReader reader = new SignatureReader(signature);
      reader.accept(new CollectTypeParams(params));
      return params.toArray(new JTypeParameter[params.size()]);
    }
    return NO_TYPE_PARAMETERS;
  }

  private static JTypeParameter[] getTypeParametersForClass(CollectClassData classData) {
    JTypeParameter[] typeParams = null;
    if (classData.getSignature() != null) {
      // TODO(jat): do we need to consider generic types w/ method type
      // params for local classes?
      typeParams = collectTypeParams(classData.getSignature());
    }
    return typeParams;
  }

  private static Class<?> getWrapperClass(Class<?> primitiveClass) {
    assert primitiveClass.isPrimitive();
    if (primitiveClass.equals(Integer.TYPE)) {
      return Integer.class;
    } else if (primitiveClass.equals(Boolean.TYPE)) {
      return Boolean.class;
    } else if (primitiveClass.equals(Byte.TYPE)) {
      return Byte.class;
    } else if (primitiveClass.equals(Character.TYPE)) {
      return Character.class;
    } else if (primitiveClass.equals(Short.TYPE)) {
      return Short.class;
    } else if (primitiveClass.equals(Long.TYPE)) {
      return Long.class;
    } else if (primitiveClass.equals(Float.TYPE)) {
      return Float.class;
    } else if (primitiveClass.equals(Double.TYPE)) {
      return Double.class;
    } else {
      throw new IllegalArgumentException(primitiveClass.toString() + " not a primitive class");
    }
  }

  /**
   * Returns whether this name is the special package-info type name.
   */
  private static boolean isPackageInfoTypeName(String simpleSourceName) {
    return "package-info".equals(simpleSourceName);
  }

  /**
   * Returns true if this class is a non-static class inside a generic class.
   */
  // TODO(jat): do we need to consider the entire hierarchy?
  private static boolean nonStaticInsideGeneric(
      CollectClassData classData, CollectClassData enclosingClassData) {
    if (enclosingClassData == null || (classData.getAccess() & Opcodes.ACC_STATIC) != 0) {
      return false;
    }
    return getTypeParametersForClass(enclosingClassData) != null;
  }

  /**
   * Returns the original type or its raw type if it is generic
   */
  private static JType possiblySubstituteRawType(JType type) {
    if (type != null) {
      JGenericType genericType = (JGenericType) type.isGenericType();
      if (genericType != null) {
        type = genericType.getRawType();
      }
    }
    return type;
  }

  private final Set<String> resolvedTypeSourceNames = Sets.newHashSet();
  private final Map<String, JRealClassType> typesByInternalName = Maps.newHashMap();
  /**
   * An executor service to parallelize some of the update process.
   */
  private static ExecutorService executor =
      new ThreadPoolExecutor(0, Runtime.getRuntime().availableProcessors(), 60L, TimeUnit.SECONDS,
          Queues.<Runnable>newLinkedBlockingQueue(),
          // Make sure this executor lets the whole process terminate correctly even if there
          // are still live threads.
          new ThreadFactoryBuilder().setDaemon(true).build());

  public CompilationUnitTypeOracleUpdater(TypeOracle typeOracle) {
    super(typeOracle);
  }

  /**
   * Adds new units to an existing TypeOracle but does not yet index their type hierarchy.<br />
   *
   * It is ok for this function to recursive since no repeated or invalid type indexing will result.
   *
   * @param logger logger to use
   * @param typeDataList collection of data need to build types. (Doesn't retain references to
   *          TypeData instances.)
   * @param argsLookup Allows the caller to pass the method argument names which are not normally
   *          available in bytecode.
   */
  void addNewTypesDontIndex(
      TreeLogger logger, Collection<TypeData> typeDataList, MethodArgNamesLookup argsLookup) {
    Event typeOracleUpdaterEvent = SpeedTracerLogger.start(CompilerEventType.TYPE_ORACLE_UPDATER);

    // First collect all class data.
    Event visitClassFileEvent = SpeedTracerLogger.start(
        CompilerEventType.TYPE_ORACLE_UPDATER, "phase", "Visit Class Files");
    TypeOracleBuildContext context = getContext(argsLookup);

    for (TypeData typeData : typeDataList) {
      CollectClassData classData = typeData.getCollectClassData();
      // skip any classes that can't be referenced by name outside of
      // their local scope, such as anonymous classes and method-local classes
      if (classData.hasNoExternalName()) {
        continue;
      }
      // skip classes that have been previously added
      if (typesByInternalName.containsKey(classData.getInternalName())) {
        continue;
      }
      context.classDataByInternalName.put(typeData.internalName, classData);
    }
    visitClassFileEvent.end();

    Event identityEvent = SpeedTracerLogger.start(
        CompilerEventType.TYPE_ORACLE_UPDATER, "phase", "Establish Identity");
    // Perform a shallow pass to establish identity for new and old types.
    Set<JRealClassType> unresolvedTypes = Sets.newLinkedHashSet();
    for (TypeData typeData : typeDataList) {
      CollectClassData classData = context.classDataByInternalName.get(typeData.internalName);
      if (classData == null) {
        // ignore classes that were skipped earlier
        continue;
      }
      if (typesByInternalName.containsKey(classData.getInternalName())) {
        // skip classes that have been previously added
        continue;
      }
      JRealClassType type = createType(typeData, unresolvedTypes, context);
      if (type != null) {
        assert Name.isInternalName(typeData.internalName);
        typesByInternalName.put(typeData.internalName, type);
        context.classDataByType.put(type, classData);
      }
    }
    identityEvent.end();

    Event resolveEnclosingEvent = SpeedTracerLogger.start(
        CompilerEventType.TYPE_ORACLE_UPDATER, "phase", "Resolve Enclosing Classes");
    // Hook up enclosing types
    TreeLogger branch = logger.branch(TreeLogger.SPAM, "Resolving enclosing classes");
    for (Iterator<JRealClassType> unresolvedTypesIterator = unresolvedTypes.iterator();
        unresolvedTypesIterator.hasNext();) {
      JRealClassType unresolvedType = unresolvedTypesIterator.next();
      if (!resolveEnclosingClass(branch, unresolvedType, context)) {
        // already logged why it failed, don't try and use it further
        unresolvedTypesIterator.remove();
      }
    }
    resolveEnclosingEvent.end();

    Event resolveUnresolvedEvent = SpeedTracerLogger.start(
        CompilerEventType.TYPE_ORACLE_UPDATER, "phase", "Resolve Unresolved Types");
    // Resolve unresolved types.
    for (JRealClassType unresolvedType : unresolvedTypes) {
      branch =
          logger.branch(TreeLogger.SPAM, "Resolving " + unresolvedType.getQualifiedSourceName());
      if (!resolveClass(branch, unresolvedType, context)) {
        // already logged why it failed.
        // TODO: should we do anything else here?
      }
    }
    resolveUnresolvedEvent.end();

    // no longer needed
    context = null;
    typeOracleUpdaterEvent.end();
  }

  private static void prefechTypeData(Collection<TypeData> typeDataList) {
    // Parse bytecode in parallel by calling {@code TypeData.getCollectClassData()} in parallel.
    try {
      executor.<Void>invokeAll(Collections2.transform(typeDataList,
          new Function<TypeData, Callable<Void>>() {
            @Override
            public Callable<Void> apply(final TypeData typeData) {
              return new Callable<Void>() {
                @Override
                public Void call() {
                  typeData.getCollectClassData();
                  return null;
                }
              };
            }
          }));
    } catch (InterruptedException e) {
      // InterruptedException can be safely ignored here as the threads interrupted are only
      // precomputing data in parallel that will otherwise be computed later sequentially if
      // the threads are aborted.
      // Anyway restore the thread interrupted state just in case.
      Thread.currentThread().interrupt();
    }
  }

  /**
   * Adds new units to an existing TypeOracle and indexes their type hierarchy.
   */
  public void addNewUnits(TreeLogger logger, Collection<CompilationUnit> compilationUnits) {
    addNewTypesDontIndex(logger, compilationUnits);
    indexTypes();
  }

  @VisibleForTesting
  void indexTypes() {
    Event finishEvent =
        SpeedTracerLogger.start(CompilerEventType.TYPE_ORACLE_UPDATER, "phase", "Finish");
    super.finish();
    finishEvent.end();
  }

  protected void addNewTypesDontIndex(TreeLogger logger,
      Collection<CompilationUnit> compilationUnits) {
    Collection<TypeData> typeDataList = Lists.newArrayList();

    // Create method args data for types to add
    MethodArgNamesLookup argsLookup = new MethodArgNamesLookup();
    for (CompilationUnit compilationUnit : compilationUnits) {
      argsLookup.mergeFrom(compilationUnit.getMethodArgs());
    }

    // Create list including byte code for each type to add
    // TODO(rluble): this process can be done in parallel. Probably best to merge this for
    // loop with the one in prefetchTypeData.
    for (CompilationUnit compilationUnit : compilationUnits) {
      for (CompiledClass compiledClass : compilationUnit.getCompiledClasses()) {
        TypeData typeData = new TypeData(compiledClass.getPackageName(),
            compiledClass.getSourceName(), compiledClass.getInternalName(),
            compiledClass.getBytes(), compiledClass.getUnit().getLastModified());
        typeDataList.add(typeData);
      }
    }

    prefechTypeData(typeDataList);

    // Add the new types to the type oracle build in progress.
    addNewTypesDontIndex(logger, typeDataList, argsLookup);
  }

  @VisibleForTesting
  public Resolver getMockResolver() {
    return new CompilationUnitTypeOracleResolver(
        new TypeOracleBuildContext(new MethodArgNamesLookup()));
  }

  public TypeOracle getTypeOracle() {
    return typeOracle;
  }

  @VisibleForTesting
  public Map<String, JRealClassType> getTypesByInternalName() {
    return typesByInternalName;
  }

  /**
   * Returns the type corresponding to the given internal name.<br />
   *
   * Implementations are free to service requests eagerly or lazily.
   */
  protected JRealClassType findByInternalName(String internalName) {
    assert Name.isInternalName(internalName);
    return typesByInternalName.get(internalName);
  }

  private Annotation createAnnotation(TreeLogger logger,
      Class<? extends Annotation> annotationClass, AnnotationData annotationData) {
    // Make a copy before we mutate the collection.
    Map<String, Object> values = Maps.newHashMap(annotationData.getValues());
    logger =
        logger.branch(TreeLogger.TRACE, "Resolving annotation for " + annotationClass.getName());
    for (Map.Entry<String, Object> entry : values.entrySet()) {
      Method method = null;
      Throwable caught = null;
      try {
        method = annotationClass.getMethod(entry.getKey());
        entry.setValue(resolveAnnotationValue(logger, method.getReturnType(), entry.getValue()));
      } catch (SecurityException e) {
        caught = e;
      } catch (NoSuchMethodException e) {
        caught = e;
      }
      if (caught != null) {
        logger.log(TreeLogger.WARN,
            "Exception resolving " + annotationClass.getCanonicalName() + "." + entry.getKey() +
            " : " + caught.getMessage());
        return null;
      }
    }
    return AnnotationProxyFactory.create(annotationClass, values);
  }

  /**
   * Doesn't retain a reference to the TypeData.
   */
  private JRealClassType createType(
      TypeData typeData, CollectClassData collectClassData, CollectClassData enclosingClassData) {
    int access = collectClassData.getAccess();
    String simpleName = Shared.getShortName(typeData.sourceName);
    JRealClassType type = null;
    String packageName = typeData.packageName;
    JPackage pkg = typeOracle.getOrCreatePackage(packageName);
    boolean isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
    assert !collectClassData.hasNoExternalName();
    String enclosingSimpleName = null;
    if (enclosingClassData != null) {
      enclosingSimpleName = enclosingClassData.getNestedSourceName();
    }
    if ((access & Opcodes.ACC_ANNOTATION) != 0) {
      type = newAnnotationType(pkg, enclosingSimpleName, simpleName);
    } else if ((access & Opcodes.ACC_ENUM) != 0) {
      type = newEnumType(pkg, enclosingSimpleName, simpleName);
    } else {
      JTypeParameter[] typeParams = getTypeParametersForClass(collectClassData);
      if ((typeParams != null && typeParams.length > 0)
          || nonStaticInsideGeneric(collectClassData, enclosingClassData)) {
        type = new JGenericType(
            typeOracle, pkg, enclosingSimpleName, simpleName, isInterface, typeParams);
      } else {
        type = newRealClassType(pkg, enclosingSimpleName, simpleName, isInterface);
      }
    }

    type.addModifierBits(mapBits(ASM_TO_SHARED_MODIFIERS, access));
    if (isInterface) {
      // Always add implicit modifiers on interfaces.
      type.addModifierBits(Shared.MOD_STATIC | Shared.MOD_ABSTRACT);
    }
    type.addLastModifiedTime(typeData.lastModifiedTime);

    return type;
  }

  /**
   * Doesn't retain a reference to the TypeData.
   */
  private JRealClassType createType(
      TypeData typeData, Set<JRealClassType> unresolvedTypes, TypeOracleBuildContext context) {
    CollectClassData classData = context.classDataByInternalName.get(typeData.internalName);
    String enclosingClassInternalName = classData.getEnclosingInternalName();
    CollectClassData enclosingClassData = null;
    if (enclosingClassInternalName != null) {
      enclosingClassData = context.classDataByInternalName.get(enclosingClassInternalName);
      if (enclosingClassData == null) {
        // if our enclosing class was skipped, skip this one too
        return null;
      }
    }
    JRealClassType realClassType = createType(typeData, classData, enclosingClassData);
    unresolvedTypes.add(realClassType);
    return realClassType;
  }

  private Class<? extends Annotation> getAnnotationClass(
      TreeLogger logger, AnnotationData annotationData) {
    Type type = Type.getType(annotationData.getDesc());
    String binaryName = type.getClassName();
    try {
      Class<?> clazz =
          Class.forName(binaryName, false, Thread.currentThread().getContextClassLoader());
      if (!Annotation.class.isAssignableFrom(clazz)) {
        logger.log(TreeLogger.ERROR, "Type " + binaryName + " is not an annotation");
        return null;
      }
      return clazz.asSubclass(Annotation.class);
    } catch (ClassNotFoundException e) {
      TreeLogger.Type level = TreeLogger.WARN;
      if (shouldSuppressUnresolvableAnnotation(logger, binaryName)) {
        level = TreeLogger.DEBUG;
      }
      logger.log(level, "Ignoring unresolvable annotation type " + binaryName);
      return null;
    }
  }

  @SuppressWarnings("unused")
  private Class<?> getClassLiteralForPrimitive(Type type) {
    switch (type.getSort()) {
      case Type.BOOLEAN:
        return Boolean.TYPE;
      case Type.BYTE:
        return Byte.TYPE;
      case Type.CHAR:
        return Character.TYPE;
      case Type.SHORT:
        return Short.TYPE;
      case Type.INT:
        return Integer.TYPE;
      case Type.LONG:
        return Long.TYPE;
      case Type.FLOAT:
        return Float.TYPE;
      case Type.DOUBLE:
        return Double.TYPE;
      case Type.VOID:
        return Void.TYPE;
      default:
        assert false : "Unexpected primitive type " + type;
        return null;
    }
  }

  /**
   * Returns a new build context to use for the duration of one addNewTypesDontIndex() invocation.
   */
  protected TypeOracleBuildContext getContext(MethodArgNamesLookup argsLookup) {
    return new TypeOracleBuildContext(argsLookup);
  }

  /**
   * Map a bitset onto a different bitset.
   *
   * @param mapping int array containing a sequence of from/to pairs, each from entry should have
   *          exactly one bit set
   * @param input bitset to map
   * @return mapped bitset
   */
  private int mapBits(int[] mapping, int input) {
    int output = 0;
    for (int i = 0; i < mapping.length; i += 2) {
      if ((input & mapping[i]) != 0) {
        output |= mapping[i + 1];
      }
    }
    return output;
  }

  private boolean resolveAnnotation(TreeLogger logger, CollectAnnotationData annotationVisitor,
      Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
    AnnotationData annotationData = annotationVisitor.getAnnotation();
    Class<? extends Annotation> annotationClass = getAnnotationClass(logger, annotationData);
    if (annotationClass == null) {
      return false;
    }
    Annotation annotation = createAnnotation(logger, annotationClass, annotationData);
    if (annotation == null) {
      return false;
    }
    declaredAnnotations.put(annotationClass, annotation);
    return true;
  }

  private boolean resolveAnnotations(TreeLogger logger,
      List<CollectAnnotationData> annotationVisitors,
      Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
    boolean succeeded = true;
    if (annotationVisitors != null) {
      for (CollectAnnotationData annotationVisitor : annotationVisitors) {
        succeeded &= resolveAnnotation(logger, annotationVisitor, declaredAnnotations);
      }
    }
    return succeeded;
  }

  @SuppressWarnings("unchecked")
  private Object resolveAnnotationValue(TreeLogger logger, Class<?> expectedType, Object value) {
    if (expectedType.isArray()) {
      Class<?> componentType = expectedType.getComponentType();
      if (!value.getClass().isArray()) {
        logger.log(TreeLogger.WARN, "Annotation error: expected array of "
            + componentType.getCanonicalName() + ", got " + value.getClass().getCanonicalName());
        return null;
      }
      if (componentType.isPrimitive()) {
        // primitive arrays are already resolvedTypes
        return value;
      }
      // resolve each element in the array
      int n = Array.getLength(value);
      Object newArray = Array.newInstance(componentType, n);
      for (int i = 0; i < n; ++i) {
        Object valueElement = Array.get(value, i);
        Object resolvedValue = resolveAnnotationValue(logger, componentType, valueElement);
        if (resolvedValue == null || !componentType.isAssignableFrom(resolvedValue.getClass())) {
          logger.log(TreeLogger.ERROR,
              "Annotation error: expected " + componentType + ", got " + resolvedValue);
        } else {
          Array.set(newArray, i, resolvedValue);
        }
      }
      return newArray;
    } else if (expectedType.isEnum()) {
      if (!(value instanceof AnnotationEnum)) {
        logger.log(
            TreeLogger.ERROR, "Annotation error: expected an enum value," + " but got " + value);
        return null;
      }
      AnnotationEnum annotEnum = (AnnotationEnum) value;
      Class<? extends Enum> enumType = expectedType.asSubclass(Enum.class);
      try {
        return Enum.valueOf(enumType, annotEnum.getValue());
      } catch (IllegalArgumentException e) {
        logger.log(TreeLogger.WARN, "Unable to resolve annotation value '" + annotEnum.getValue()
            + "' within enum type '" + enumType.getName() + "'");
        return null;
      }
    } else if (Annotation.class.isAssignableFrom(expectedType)) {
      if (!(value instanceof AnnotationData)) {
        logger.log(TreeLogger.WARN, "Annotation error: expected annotation type "
            + expectedType.getCanonicalName() + ", got " + value.getClass().getCanonicalName());
        return null;
      }
      AnnotationData annotData = (AnnotationData) value;
      Class<? extends Annotation> annotationClass = getAnnotationClass(logger, annotData);
      if (!expectedType.isAssignableFrom(annotationClass)) {
        logger.log(TreeLogger.WARN, "Annotation error: expected " + expectedType.getCanonicalName()
            + ", got " + annotationClass.getCanonicalName());
        return null;
      }
      return createAnnotation(logger, annotationClass, annotData);
    } else if (expectedType.isPrimitive()) {
      Class<?> wrapper = getWrapperClass(expectedType);
      return wrapper.cast(value);
    } else {
      if (expectedType.isAssignableFrom(value.getClass())) {
        return value;
      }
      if (Class.class.equals(expectedType)) {
        if (!(value instanceof Type)) {
          logger.log(TreeLogger.WARN,
              "Annotation error: expected a class " + "literal, but received " + value);
          return null;
        }
        Type valueType = (Type) value;
        // See if we can use a binary only class here
        try {
          return forName(valueType.getClassName());
        } catch (ClassNotFoundException e) {
          logger.log(
              TreeLogger.WARN, "Annotation error: cannot resolve " + valueType.getClassName());
          return null;
        }
      }
      // TODO(jat) asserts about other acceptable types
      return value;
    }
  }

  private static final Map<String, Class<?>> BUILT_IN_PRIMITIVE_MAP;

  static {
    ImmutableMap.Builder<String, Class<?>> builder = ImmutableMap.<String, Class<?>>builder()
        .put("Z",  boolean.class)
        .put("B", byte.class)
        .put("C", char.class)
        .put("S", short.class)
        .put("I", int.class)
        .put("F", float.class)
        .put("D", double.class)
        .put("J", long.class)
        .put("V", void.class);

    for (Class c : new Class[] { void.class, boolean.class, byte.class, char.class,
        short.class, int.class, float.class, double.class, long.class }) {
      builder.put(c.getName(), c);
    }
    BUILT_IN_PRIMITIVE_MAP = builder.build();
  }

  public static Class forName(String name) throws ClassNotFoundException {
    Class c = BUILT_IN_PRIMITIVE_MAP.get(name);
    if (c == null) {
      c = Class.forName(name, false, Thread.currentThread().getContextClassLoader());
    }
    return c;
  }

  private JType resolveArray(Type type) {
    assert type.getSort() == Type.ARRAY;
    JType resolvedType = resolveType(type.getElementType());
    int dimensions = type.getDimensions();
    for (int i = 0; i < dimensions; ++i) {
      resolvedType = typeOracle.getArrayType(resolvedType);
    }
    return resolvedType;
  }

  // TODO(stalcup): refactor this recursive resolveFoo() process. At the moment there is a recursive
  // tree of resolveFoo() calls. Most of them return a boolean, but some do not. Some of the
  // booleans are read and acted upon, some are not. Some functions do their own logging and some
  // return a false to indicate that the caller should log. Sometimes the boolean return value is an
  // indication of whether logging should occur and other times it's an indication of whether
  // exploration should continue. It's a mess. Some ideas that would probably make this more sane:
  // be consistent about SPAM logging throughout and WARN logging only at the tip, and process types
  // in a queue instead of with recursion.
  private boolean resolveClass(
      TreeLogger logger, JRealClassType unresolvedType, TypeOracleBuildContext context) {
    assert unresolvedType != null;
    // Avoid cycles and useless computation.
    if (resolvedTypeSourceNames.contains(unresolvedType.getQualifiedSourceName())) {
      return true;
    }
    resolvedTypeSourceNames.add(unresolvedType.getQualifiedSourceName());

    // Make sure our enclosing type is resolved first.
    if (unresolvedType.getEnclosingType() != null
        && !resolveClass(logger, unresolvedType.getEnclosingType(), context)) {
      return false;
    }

    // Build a search list for type parameters to find their definition,
    // resolving enclosing classes as we go up.
    TypeParameterLookup typeParamLookup = new TypeParameterLookup();
    typeParamLookup.pushEnclosingScopes(unresolvedType);

    CollectClassData classData = context.classDataByType.get(unresolvedType);
    assert classData != null;
    int access = classData.getAccess();

    assert (!classData.getClassType().hasNoExternalName());

    logger = logger.branch(
        TreeLogger.SPAM, "Found type '" + unresolvedType.getQualifiedSourceName() + "'", null);

    // Handle package-info classes.
    if (isPackageInfoTypeName(unresolvedType.getSimpleSourceName())) {
      return resolvePackage(logger, unresolvedType, classData.getAnnotations());
    }

    // Resolve annotations
    Map<Class<? extends Annotation>, Annotation> declaredAnnotations = Maps.newHashMap();
    resolveAnnotations(logger, classData.getAnnotations(), declaredAnnotations);
    addAnnotations(unresolvedType, declaredAnnotations);

    String signature = classData.getSignature();

    /*
     * Note: Byte code from the OpenJDK compiler doesn't contain a type signature for non-static
     * inner classes of parameterized types that do not contain new parameters (but JDT compiled
     * byte code does). That can cause some differences in the way generic types are represented in
     * the type oracle.
     *
     * These differences also show up when using java.lang.reflect to look at types.
     */
    boolean isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
    if (signature != null) {
      // If we have a signature, use it for superclass and interfaces
      SignatureReader reader = new SignatureReader(signature);
      ResolveClassSignature classResolver = new ResolveClassSignature(
          context.resolver, logger, unresolvedType, typeParamLookup);
      reader.accept(classResolver);
      classResolver.finish();

      if (unresolvedType.getSuperclass() != null
          && !resolveClass(logger, unresolvedType.getSuperclass(), context)) {
        logger.log(TreeLogger.WARN,
            "Unable to resolve supertype " + unresolvedType.getSuperclass().getName());
        return false;
      }
    } else {
      // Set the super type for non-interfaces
      if (!isInterface) {
        String superInternalName = classData.getSuperInternalName();
        assert Name.isInternalName(superInternalName);
        if (superInternalName != null) {
          JClassType superType = findByInternalName(superInternalName);
          if (superType == null || !resolveClass(logger, superType, context)) {
            logger.log(TreeLogger.WARN, "Unable to resolve supertype " + superInternalName);
            return false;
          }
          setSuperClass(unresolvedType, (JClassType) possiblySubstituteRawType(superType));
        }
      }

      // Set interfaces
      for (String interfaceInternalName : classData.getInterfaceInternalNames()) {
        JClassType interfaceType = findByInternalName(interfaceInternalName);
        if (interfaceType == null || !resolveClass(logger, interfaceType, context)) {
          logger.log(TreeLogger.WARN, "Unable to resolve interface " + interfaceInternalName);
          return false;
        }
        addImplementedInterface(
            unresolvedType, (JClassType) possiblySubstituteRawType(interfaceType));
      }
    }
    if (!isInterface && unresolvedType.getSuperclass() == null) {
      // Only Object or interfaces should not have a superclass
      assert "java/lang/Object".equals(classData.getInternalName());
    }

    // Process methods
    for (CollectMethodData method : classData.getMethods()) {
      TreeLogger branch = logger.branch(TreeLogger.SPAM, "Resolving method " + method.getName());
      // TODO(rluble): Allow the users to ask for Java 8 features. For now these are filtered out.
      if (isInterface && isJava8InterfaceMethod(method)) {
        logger.log(TreeLogger.Type.SPAM, "Ignoring Java 8 interface method " + method.getName());
        continue;
      }
      if (!resolveMethod(branch, unresolvedType, method, typeParamLookup, context)) {
        // Already logged.
        return false;
      }
    }

    // Process fields
    // Track the next enum ordinal across resolveField calls.
    int[] nextEnumOrdinal = new int[] {0};
    for (CollectFieldData field : classData.getFields()) {
      TreeLogger branch = logger.branch(TreeLogger.SPAM, "Resolving field " + field.getName());
      if (!resolveField(branch, unresolvedType, field, typeParamLookup, nextEnumOrdinal, context)) {
        // Already logged.
        return false;
      }
    }
    return true;
  }

  private boolean isJava8InterfaceMethod(CollectMethodData method) {
    // (Normal) interface methods are abstract. Java 8 introduced the ability to declare default
    // methods and static methods both of which are exposed as non abstract methods.
    return (method.getAccess() & Opcodes.ACC_ABSTRACT) == 0;
  }

  private boolean resolveClass(
      TreeLogger logger, JType unresolvedType, TypeOracleBuildContext context) {
    if (!(unresolvedType instanceof JClassType)) {
      // non-classes are already resolvedTypes
      return true;
    }
    if (unresolvedType instanceof JRealClassType) {
      return resolveClass(logger, (JRealClassType) unresolvedType, context);
    }
    if (unresolvedType instanceof JArrayType) {
      return resolveClass(logger, ((JArrayType) unresolvedType).getComponentType(), context);
    }
    if (unresolvedType instanceof JParameterizedType) {
      return resolveClass(logger, ((JParameterizedType) unresolvedType).getBaseType(), context);
    }
    if (unresolvedType instanceof JRawType) {
      return resolveClass(logger, ((JRawType) unresolvedType).getBaseType(), context);
    }
    if (unresolvedType instanceof JTypeParameter) {
      JTypeParameter typeParam = (JTypeParameter) unresolvedType;
      if (!resolveClass(logger, typeParam.getDeclaringClass(), context)) {
        return false;
      }
      for (JClassType bound : typeParam.getBounds()) {
        if (!resolveClass(logger, bound, context)) {
          return false;
        }
      }
      return true;
    }
    if (unresolvedType instanceof JWildcardType) {
      JWildcardType wildcard = (JWildcardType) unresolvedType;
      for (JClassType bound : wildcard.getUpperBounds()) {
        if (!resolveClass(logger, bound, context)) {
          return false;
        }
      }
      for (JClassType bound : wildcard.getLowerBounds()) {
        if (!resolveClass(logger, bound, context)) {
          return false;
        }
      }
      return true;
    }
    return false;
  }

  private boolean resolveEnclosingClass(
      TreeLogger logger, JRealClassType unresolvedType, TypeOracleBuildContext context) {
    assert unresolvedType != null;
    if (unresolvedType.getEnclosingType() != null) {
      return true;
    }

    // Find our enclosing class and set it
    CollectClassData classData = context.classDataByType.get(unresolvedType);
    assert classData != null;
    String enclosingClassInternalName = classData.getEnclosingInternalName();
    JRealClassType enclosingType = null;
    if (enclosingClassInternalName != null) {
      enclosingType = findByInternalName(enclosingClassInternalName);
      // Ensure enclosing classes are resolved
      if (enclosingType != null) {
        if (!resolveEnclosingClass(logger, enclosingType, context)) {
          return false;
        }
        if (enclosingType.isGenericType() != null
            && (classData.getAccess() & (Opcodes.ACC_STATIC | Opcodes.ACC_INTERFACE)) != 0) {
          // If the inner class doesn't have access to it's enclosing type's
          // type variables, the enclosing type must be the raw type instead
          // of the generic type.
          JGenericType genericType = enclosingType.isGenericType();
          setEnclosingType(unresolvedType, genericType.getRawType());
        } else {
          setEnclosingType(unresolvedType, enclosingType);
        }
      }
    }
    return true;
  }

  private boolean resolveField(TreeLogger logger, JRealClassType unresolvedType,
      CollectFieldData field, TypeParameterLookup typeParamLookup, int[] nextEnumOrdinal,
      TypeOracleBuildContext context) {
    Map<Class<? extends Annotation>, Annotation> declaredAnnotations = Maps.newHashMap();
    resolveAnnotations(logger, field.getAnnotations(), declaredAnnotations);
    String name = field.getName();
    JField jfield;
    if ((field.getAccess() & Opcodes.ACC_ENUM) != 0) {
      assert (unresolvedType.isEnum() != null);
      jfield = newEnumConstant(unresolvedType, name, declaredAnnotations, nextEnumOrdinal[0]++);
    } else {
      JField newField = newField(unresolvedType, name, declaredAnnotations);
      jfield = newField;
    }

    // Get modifiers.
    addModifierBits(jfield, mapBits(ASM_TO_SHARED_MODIFIERS, field.getAccess()));

    String signature = field.getSignature();
    JType fieldJType;
    if (signature != null) {
      SignatureReader reader = new SignatureReader(signature);
      JType[] fieldTypeRef = new JType[1];
      reader.acceptType(new ResolveTypeSignature(
          context.resolver, logger, fieldTypeRef, typeParamLookup, null));
      fieldJType = fieldTypeRef[0];
      if (fieldJType == null) {
        logger.log(TreeLogger.ERROR, "Unable to resolve type in field signature " + signature);
        return false;
      }
    } else {
      Type fieldType = Type.getType(field.getDesc());
      fieldJType = resolveType(fieldType);
      if (fieldJType == null) {
        logger.log(TreeLogger.ERROR, "Unable to resolve type " + fieldType.getInternalName()
            + " of field " + field.getName());
        return false;
      }
    }
    setFieldType(jfield, fieldJType);
    return true;
  }

  private boolean resolveMethod(TreeLogger logger, JRealClassType unresolvedType,
      CollectMethodData methodData, TypeParameterLookup typeParamLookup,
      TypeOracleBuildContext context) {
    Map<Class<? extends Annotation>, Annotation> declaredAnnotations = Maps.newHashMap();
    resolveAnnotations(logger, methodData.getAnnotations(), declaredAnnotations);
    String name = methodData.getName();

    if ("<clinit>".equals(name) || (methodData.getAccess() & Opcodes.ACC_SYNTHETIC) != 0) {
      // Ignore the following and leave them out of TypeOracle:
      // - static initializers
      // - synthetic methods
      return true;
    }

    if (unresolvedType.isEnum() != null && "<init>".equals(name)) {
      // Leave enum constructors out of TypeOracle
      return true;
    }

    JAbstractMethod method;

    // Declare the type parameters. We will pass them into the constructors for
    // JConstructor/JMethod/JAnnotatedMethod. Then, we'll do a second pass to
    // resolve the bounds on each JTypeParameter object.
    JTypeParameter[] typeParams = collectTypeParams(methodData.getSignature());

    typeParamLookup.pushScope(typeParams);
    boolean hasReturnType = true;
    if ("<init>".equals(name)) {
      name = unresolvedType.getSimpleSourceName();
      method = newConstructor(unresolvedType, name, declaredAnnotations, typeParams);
      hasReturnType = false;
    } else {
      if (unresolvedType.isAnnotation() != null) {
        // TODO(jat): actually resolve the default annotation value.
        method = newAnnotationMethod(unresolvedType, name, declaredAnnotations, typeParams, null);
      } else {
        method = newMethod(unresolvedType, name, declaredAnnotations, typeParams);
      }
    }

    addModifierBits(method, mapBits(ASM_TO_SHARED_MODIFIERS, methodData.getAccess()));
    if (unresolvedType.isInterface() != null) {
      // Always add implicit modifiers on interface methods.
      addModifierBits(method, Shared.MOD_PUBLIC | Shared.MOD_ABSTRACT);
    }

    if ((methodData.getAccess() & Opcodes.ACC_VARARGS) != 0) {
      setVarArgs(method);
    }

    String signature = methodData.getSignature();
    if (signature != null) {
      // If we have a signature, use it for superclass and interfaces
      SignatureReader reader = new SignatureReader(signature);
      ResolveMethodSignature methodResolver = new ResolveMethodSignature(context.resolver, logger,
          method, typeParamLookup, hasReturnType, methodData, methodData.getArgTypes(),
          methodData.getArgNames(), methodData.hasActualArgNames(), context.allMethodArgs);
      reader.accept(methodResolver);
      if (!methodResolver.finish()) {
        logger.log(TreeLogger.ERROR, "Failed to resolve.");
        return false;
      }
    } else {
      if (hasReturnType) {
        Type returnType = Type.getReturnType(methodData.getDesc());
        JType returnJType = resolveType(returnType);
        if (returnJType == null) {
          logger.log(TreeLogger.ERROR,
              "Unable to resolve return type " + returnType.getInternalName());
          return false;
        }
        setReturnType(method, returnJType);
      }

      if (!resolveParameters(logger, method, methodData, context)) {
        // Already logged.
        return false;
      }
    }
    // The signature might not actually include the exceptions if they don't
    // include a type variable, so resolveThrows is always used (it does
    // nothing if there are already exceptions defined)
    if (!resolveThrows(logger, method, methodData)) {
      // Already logged.
      return false;
    }
    typeParamLookup.popScope();
    return true;
  }

  private JRealClassType resolveObject(Type type) {
    assert type.getSort() == Type.OBJECT;
    String internalName = type.getInternalName();
    assert Name.isInternalName(internalName);
    JRealClassType classType = findByInternalName(internalName);
    return classType;
  }

  private boolean resolvePackage(TreeLogger logger, JRealClassType unresolvedType,
      List<CollectAnnotationData> annotationVisitors) {
    Map<Class<? extends Annotation>, Annotation> declaredAnnotations = Maps.newHashMap();
    resolveAnnotations(logger, annotationVisitors, declaredAnnotations);
    addAnnotations(unresolvedType.getPackage(), declaredAnnotations);
    return true;
  }

  private boolean resolveParameters(TreeLogger logger, JAbstractMethod method,
      CollectMethodData methodData, TypeOracleBuildContext context) {
    Type[] argTypes = methodData.getArgTypes();
    boolean argNamesAreReal = methodData.hasActualArgNames();
    String[] argNames = methodData.getArgNames();
    if (!argNamesAreReal) {
      String[] lookupNames = context.allMethodArgs.lookup(method, methodData);
      if (lookupNames != null) {
        argNames = lookupNames;
        argNamesAreReal = true;
      }
    }
    List<CollectAnnotationData>[] paramAnnot = methodData.getArgAnnotations();
    for (int i = 0; i < argTypes.length; ++i) {
      Type argType = argTypes[i];
      JType argJType = resolveType(argType);
      if (argJType == null) {
        logger.log(TreeLogger.ERROR, "Unable to resolve type " + argType.getInternalName()
            + " of argument " + methodData.getArgNames()[i]);
        return false;
      }
      // Try to resolve annotations, ignore any that fail.
      Map<Class<? extends Annotation>, Annotation> declaredAnnotations = Maps.newHashMap();
      resolveAnnotations(logger, paramAnnot[i], declaredAnnotations);

      newParameter(method, argJType, argNames[i], declaredAnnotations, argNamesAreReal);
    }
    return true;
  }

  private boolean resolveThrows(TreeLogger logger, JAbstractMethod method,
      CollectMethodData methodData) {
    if (method.getThrows().length == 0) {
      for (String exceptionName : methodData.getExceptions()) {
        Type exceptionType = Type.getObjectType(exceptionName);
        JType exceptionJType = resolveType(exceptionType);
        if (exceptionJType == null) {
          logger.log(TreeLogger.ERROR,
              "Unable to resolve type " + exceptionType.getInternalName() + " of thrown exception");
          return false;
        }
        addThrows(method, (JClassType) exceptionJType);
      }
    }
    return true;
  }

  /**
   * Returns a primitive, an array, or a JRealClassType.
   */
  private JType resolveType(Type type) {
    // Check for primitives.
    switch (type.getSort()) {
      case Type.BOOLEAN:
        return JPrimitiveType.BOOLEAN;
      case Type.BYTE:
        return JPrimitiveType.BYTE;
      case Type.CHAR:
        return JPrimitiveType.CHAR;
      case Type.SHORT:
        return JPrimitiveType.SHORT;
      case Type.INT:
        return JPrimitiveType.INT;
      case Type.LONG:
        return JPrimitiveType.LONG;
      case Type.FLOAT:
        return JPrimitiveType.FLOAT;
      case Type.DOUBLE:
        return JPrimitiveType.DOUBLE;
      case Type.VOID:
        return JPrimitiveType.VOID;
      case Type.ARRAY:
        return resolveArray(type);
      case Type.OBJECT:
        JRealClassType resolvedType = resolveObject(type);
        return possiblySubstituteRawType(resolvedType);
      default:
        assert false : "Unexpected type " + type;
        return null;
    }
  }

  /**
   * Suppress multiple validation related messages and replace with a hint.
   */
  // TODO(zundel): Can be removed when javax.validation is included in the JRE
  private boolean shouldSuppressUnresolvableAnnotation(TreeLogger logger, String sourceName) {
    if (sourceName.startsWith("javax.validation.")
        || sourceName.startsWith("com.google.gwt.validation.")) {
      if (!warnedMissingValidationJar) {
        warnedMissingValidationJar = true;
        logger.log(TreeLogger.WARN, "Detected warnings related to '" + sourceName + "'. "
            + "  Is validation-<version>.jar on the classpath?");
        logger.log(TreeLogger.INFO, "Specify -logLevel DEBUG to see all errors.");
        // Show the first error that matches
        return false;
      }
      // Suppress subsequent errors that match
      return true;
    }
    return false;
  }
}
