/*
 * 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.user.rebind.rpc;

import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JField;
import com.google.gwt.core.ext.typeinfo.JGenericType;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JRealClassType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.JTypeParameter;
import com.google.gwt.core.ext.typeinfo.JWildcardType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.user.client.rpc.GwtTransient;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.google.gwt.user.rebind.rpc.ProblemReport.Priority;
import com.google.gwt.user.rebind.rpc.TypeParameterExposureComputer.TypeParameterFlowInfo;
import com.google.gwt.user.rebind.rpc.TypePaths.TypePath;

import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Map.Entry;

/**
 * Builds a {@link SerializableTypeOracle} for a given set of root types.
 * 
 * <p>
 * There are two goals for this builder. First, discover the set of serializable
 * types that can be serialized if you serialize one of the root types. Second,
 * to make sure that all root types can actually be serialized by GWT.
 * </p>
 * 
 * <p>
 * To find the serializable types, it includes the root types, and then it
 * iteratively traverses the type hierarchy and the fields of any type already
 * deemed serializable. To improve the accuracy of the traversal there is a
 * computations of the exposure of type parameters. When the traversal reaches a
 * parameterized type, these exposure values are used to determine how to treat
 * the arguments.
 * </p>
 * 
 * <p>
 * A type qualifies for serialization if it or one of its subtypes is
 * automatically or manually serializable. Automatic serialization is selected
 * if the type is assignable to {@link IsSerializable} or {@link Serializable}
 * or if the type is a primitive type such as int, boolean, etc. Manual
 * serialization is selected if there exists another type with the same fully
 * qualified name concatenated with "_CustomFieldSerializer". If a type
 * qualifies for both manual and automatic serialization, manual serialization
 * is preferred.
 * </p>
 * 
 * <p>
 * Some types may be marked as "enhanced," either automatically by the presence
 * of a JDO <code>@PersistenceCapable</code> or JPA <code>@Entity</code> tag on
 * the class definition, or manually by extending the 'rpc.enhancedClasses'
 * configuration property in the GWT module XML file. For example, to manually
 * mark the class com.google.myapp.MyPersistentClass as enhanced, use:
 * 
 * <pre>
 * <extend-configuration-property name='rpc.enhancedClasses'
 *     value='com.google.myapp.MyPersistentClass'/>
 * </pre>
 * 
 * <p>
 * Enhanced classes are checked for the presence of additional serializable
 * fields on the server that were not defined in client code as seen by the GWT
 * compiler. If it is possible for an instance of such a class to be transmitted
 * bidrectionally between server and client, a special RPC rule is used. The
 * server-only fields are serialized using standard Java serialization and sent
 * between the client and server as a blob of opaque base-64 encoded binary
 * data. When an instance is sent from client to server, the server instance is
 * populated by invoking setter methods where possible rather than by setting
 * fields directly. This allows APIs such as JDO the opportunity to update the
 * object state properly to take into account changes that may have occurred to
 * the object's state while resident on the client.
 * </p>
 */
public class SerializableTypeOracleBuilder {

  class TypeInfoComputed {
    /**
     * <code>true</code> if the type is assignable to {@link IsSerializable} or
     * {@link java.io.Serializable Serializable}.
     */
    private final boolean autoSerializable;

    /**
     * <code>true</code> if the this type directly implements one of the marker
     * interfaces.
     */
    private final boolean directlyImplementsMarker;

    /**
     * <code>true</code> if the type is automatically or manually serializable
     * and the corresponding checks succeed.
     */
    private boolean fieldSerializable = false;

    /**
     * <code>true</code> if this type might be instantiated.
     */
    private boolean instantiable = false;

    /**
     * <code>true</code> if there are instantiable subtypes assignable to this
     * one.
     */
    private boolean instantiableSubtypes;

    /**
     * All instantiable types found when this type was quaried, including the
     * type itself.
     */
    private Set<JClassType> instantiableTypes = new HashSet<JClassType>();

    /**
     * Custom field serializer or <code>null</code> if there isn't one.
     */
    private final JClassType manualSerializer;

    /**
     * <code>true</code> if this class might be enhanced on the server to
     * contain extra fields.
     */
    private final boolean maybeEnhanced;

    /**
     * Path used to discover this type.
     */
    private final TypePath path;

    /**
     * The state that this type is currently in.
     */
    private TypeState state = TypeState.NOT_CHECKED;

    /**
     * {@link JClassType} associated with this metadata.
     */
    private final JType type;

    public TypeInfoComputed(JType type, TypePath path) {
      this.type = type;
      this.path = path;
      if (type instanceof JClassType) {
        JClassType typeClass = (JClassType) type;
        autoSerializable = SerializableTypeOracleBuilder.isAutoSerializable(typeClass);
        manualSerializer = findCustomFieldSerializer(typeOracle, typeClass);
        directlyImplementsMarker = directlyImplementsMarkerInterface(typeClass);
        maybeEnhanced = hasJdoAnnotation(typeClass)
            || hasJpaAnnotation(typeClass);
      } else {
        autoSerializable = false;
        manualSerializer = null;
        directlyImplementsMarker = false;
        maybeEnhanced = false;
      }
    }

    /**
     * Returns the internal set of instantiable types for this TIC.
     * Modifications to this set are immediately recorded into the TIC as well.
     * TODO(spoon) maybe pass the TIC around instead of the set? then there
     * could be addInstantiableType(JClassType) instead of speccing this to be
     * mutable.
     */
    public Set<JClassType> getInstantiableTypes() {
      return instantiableTypes;
    }

    public JClassType getManualSerializer() {
      return manualSerializer;
    }

    public TypePath getPath() {
      return path;
    }

    public JType getType() {
      return type;
    }

    public boolean hasInstantiableSubtypes() {
      return isInstantiable() || instantiableSubtypes
          || isPendingInstantiable();
    }

    public boolean isAutoSerializable() {
      return autoSerializable;
    }

    public boolean isDeclaredSerializable() {
      return autoSerializable || isManuallySerializable();
    }

    public boolean isDirectlySerializable() {
      return directlyImplementsMarker || isManuallySerializable();
    }

    public boolean isDone() {
      return state == TypeState.CHECK_DONE;
    }

    public boolean isFieldSerializable() {
      return fieldSerializable;
    }

    public boolean isInstantiable() {
      return instantiable;
    }

    public boolean isManuallySerializable() {
      return manualSerializer != null;
    }

    public boolean isPendingInstantiable() {
      return state == TypeState.CHECK_IN_PROGRESS;
    }

    public boolean maybeEnhanced() {
      return maybeEnhanced;
    }

    public void setFieldSerializable() {
      fieldSerializable = true;
    }

    public void setInstantiable(boolean instantiable) {
      this.instantiable = instantiable;
      if (instantiable) {
        fieldSerializable = true;
      }
      state = TypeState.CHECK_DONE;
    }

    public void setInstantiableSubtypes(boolean instantiableSubtypes) {
      this.instantiableSubtypes = instantiableSubtypes;
    }

    public void setPendingInstantiable() {
      state = TypeState.CHECK_IN_PROGRESS;
    }
  }

  private enum TypeState {
    /**
     * The instantiability of a type has been determined.
     */
    CHECK_DONE("Check succeeded"),
    /**
     * The instantiability of a type is being checked.
     */
    CHECK_IN_PROGRESS("Check in progress"),
    /**
     * The instantiability of a type has not been checked.
     */
    NOT_CHECKED("Not checked");

    private final String message;

    TypeState(String message) {
      this.message = message;
    }

    @Override
    public String toString() {
      return message;
    }
  }

  /**
   * Compares {@link JType}s according to their qualified source names.
   */
  static final Comparator<JType> JTYPE_COMPARATOR = new Comparator<JType>() {
    public int compare(JType t1, JType t2) {
      return t1.getQualifiedSourceName().compareTo(t2.getQualifiedSourceName());
    }
  };

  /**
   * No type filtering by default..
   */
  private static final TypeFilter DEFAULT_TYPE_FILTER = new TypeFilter() {
    public String getName() {
      return "Default";
    }

    public boolean isAllowed(JClassType type) {
      return true;
    }
  };

  /**
   * A reference to the annotation class
   * javax.jdo.annotations.PersistenceCapable used by the JDO API. May be null
   * if JDO is not present in the runtime environment.
   */
  private static Class<? extends Annotation> JDO_PERSISTENCE_CAPABLE_ANNOTATION = null;

  /**
   * A reference to the method 'String
   * javax.jdo.annotations.PersistenceCapable.detachable()'.
   */
  private static Method JDO_PERSISTENCE_CAPABLE_DETACHABLE_METHOD;

  /**
   * A reference to the annotation class javax.persistence.Entity used by the
   * JPA API. May be null if JPA is not present in the runtime environment.
   */
  private static Class<? extends Annotation> JPA_ENTITY_ANNOTATION = null;

  static {
    try {
      JDO_PERSISTENCE_CAPABLE_ANNOTATION = Class.forName(
          "javax.jdo.annotations.PersistenceCapable").asSubclass(
          Annotation.class);
      JDO_PERSISTENCE_CAPABLE_DETACHABLE_METHOD = JDO_PERSISTENCE_CAPABLE_ANNOTATION.getDeclaredMethod(
          "detachable", (Class[]) null);
    } catch (ClassNotFoundException e) {
      // Ignore, JDO_PERSISTENCE_CAPABLE_ANNOTATION will be null
    } catch (NoSuchMethodException e) {
      JDO_PERSISTENCE_CAPABLE_ANNOTATION = null;
    }

    try {
      JPA_ENTITY_ANNOTATION = Class.forName("javax.persistence.Entity").asSubclass(
          Annotation.class);
    } catch (ClassNotFoundException e) {
      // Ignore, JPA_ENTITY_CAPABLE_ANNOTATION will be null
    }
  }

  static boolean canBeInstantiated(JClassType type, ProblemReport problems) {
    if (type.isEnum() == null) {
      if (type.isAbstract()) {
        // Abstract types will be picked up if there is an instantiable
        // subtype.
        return false;
      }

      if (!type.isDefaultInstantiable() && !isManuallySerializable(type)) {
        // Warn and return false.
        problems.add(type, type.getParameterizedQualifiedSourceName()
            + " is not default instantiable (it must have a zero-argument "
            + "constructor or no constructors at all) and has no custom "
            + "serializer.", Priority.DEFAULT);
        return false;
      }
    } else {
      /*
       * Enums are always instantiable regardless of abstract or default
       * instantiability.
       */
    }

    return true;
  }

  /**
   * Finds the custom field serializer for a given type.
   * 
   * @param typeOracle
   * @param type
   * @return the custom field serializer for a type or <code>null</code> if
   *         there is not one
   */
  public static JClassType findCustomFieldSerializer(TypeOracle typeOracle,
      JType type) {
    JClassType classOrInterface = type.isClassOrInterface();
    if (classOrInterface == null) {
      return null;
    }

    String customFieldSerializerName = type.getQualifiedSourceName()
        + "_CustomFieldSerializer";
    JClassType customSerializer = typeOracle.findType(customFieldSerializerName);
    if (customSerializer == null) {
      // If the type is in the java.lang or java.util packages then it will be
      // mapped into com.google.gwt.user.client.rpc.core package
      customSerializer = typeOracle.findType("com.google.gwt.user.client.rpc.core."
          + customFieldSerializerName);
    }

    return customSerializer;
  }

  static JRealClassType getBaseType(JClassType type) {
    if (type.isParameterized() != null) {
      return type.isParameterized().getBaseType();
    } else if (type.isRawType() != null) {
      return type.isRawType().getBaseType();
    }

    return (JRealClassType) type;
  }

  /**
   * @param type the type to query
   * @return true if the type is annotated with @PersistenceCapable(...,
   *         detachable="true")
   */
  static boolean hasJdoAnnotation(JClassType type) {
    if (JDO_PERSISTENCE_CAPABLE_ANNOTATION == null) {
      return false;
    }
    Annotation annotation = type.getAnnotation(JDO_PERSISTENCE_CAPABLE_ANNOTATION);
    if (annotation == null) {
      return false;
    }
    try {
      Object value = JDO_PERSISTENCE_CAPABLE_DETACHABLE_METHOD.invoke(
          annotation, (Object[]) null);
      if (value instanceof String) {
        return "true".equalsIgnoreCase((String) value);
      } else {
        return false;
      }
    } catch (IllegalAccessException e) {
      // will return false
    } catch (InvocationTargetException e) {
      // will return false
    }

    return false;
  }

  /**
   * @param type the type to query
   * @return true if the type is annotated with @Entity
   */
  static boolean hasJpaAnnotation(JClassType type) {
    if (JPA_ENTITY_ANNOTATION == null) {
      return false;
    }
    Annotation annotation = type.getAnnotation(JPA_ENTITY_ANNOTATION);
    return annotation != null;
  }

  static boolean isAutoSerializable(JClassType type) {
    try {
      JClassType isSerializable = getIsSerializableMarkerInterface(type);
      JClassType serializable = getSerializableMarkerInterface(type);
      return type.isAssignableTo(isSerializable)
          || type.isAssignableTo(serializable);
    } catch (NotFoundException e) {
      return false;
    }
  }

  /**
   * Returns <code>true</code> if this type is part of the standard java
   * packages.
   */
  static boolean isInStandardJavaPackage(String className) {
    if (className.startsWith("java.")) {
      return true;
    }

    if (className.startsWith("javax.")) {
      return true;
    }

    return false;
  }

  static void recordTypeParametersIn(JType type, Set<JTypeParameter> params) {
    JTypeParameter isTypeParameter = type.isTypeParameter();
    if (isTypeParameter != null) {
      params.add(isTypeParameter);
    }

    JArrayType isArray = type.isArray();
    if (isArray != null) {
      recordTypeParametersIn(isArray.getComponentType(), params);
    }

    JWildcardType isWildcard = type.isWildcard();
    if (isWildcard != null) {
      for (JClassType bound : isWildcard.getUpperBounds()) {
        recordTypeParametersIn(bound, params);
      }
    }

    JParameterizedType isParameterized = type.isParameterized();
    if (isParameterized != null) {
      for (JClassType arg : isParameterized.getTypeArgs()) {
        recordTypeParametersIn(arg, params);
      }
    }
  }

  /**
   * Return <code>true</code> if a class's fields should be considered for
   * serialization. If it returns <code>false</code> then none of the fields of
   * this class should be serialized.
   */
  static boolean shouldConsiderFieldsForSerialization(JClassType type,
      TypeFilter filter, ProblemReport problems) {
    if (!isAllowedByFilter(filter, type, problems)) {
      return false;
    }

    if (!isDeclaredSerializable(type)) {
      problems.add(type, type.getParameterizedQualifiedSourceName()
          + " is not assignable to '" + IsSerializable.class.getName()
          + "' or '" + Serializable.class.getName()
          + "' nor does it have a custom field serializer", Priority.DEFAULT);
      return false;
    }

    if (isManuallySerializable(type)) {
      JClassType manualSerializer = findCustomFieldSerializer(type.getOracle(),
          type);
      assert (manualSerializer != null);

      List<String> fieldProblems = CustomFieldSerializerValidator.validate(
          manualSerializer, type);
      if (!fieldProblems.isEmpty()) {
        for (String problem : fieldProblems) {
          problems.add(type, problem, Priority.FATAL);
        }
        return false;
      }
    } else {
      assert (isAutoSerializable(type));

      if (!isAccessibleToSerializer(type)) {
        // Class is not visible to a serializer class in the same package
        problems.add(type, type.getParameterizedQualifiedSourceName()
            + " is not accessible from a class in its same package; it "
            + "will be excluded from the set of serializable types",
            Priority.DEFAULT);
        return false;
      }

      if (type.isMemberType() && !type.isStatic()) {
        // Non-static member types cannot be serialized
        problems.add(type, type.getParameterizedQualifiedSourceName()
            + " is nested but "
            + "not static; it will be excluded from the set of serializable "
            + "types", Priority.DEFAULT);
        return false;
      }
    }

    return true;
  }

  /**
   * Returns <code>true</code> if the field qualifies for serialization without
   * considering its type.
   */
  static boolean shouldConsiderForSerialization(TreeLogger logger,
      boolean suppressNonStaticFinalFieldWarnings, JField field) {
    if (field.isStatic() || field.isTransient()) {
      return false;
    }

    if (field.isAnnotationPresent(GwtTransient.class)) {
      return false;
    }

    if (field.isFinal()) {
      Type logLevel;
      if (isManuallySerializable(field.getEnclosingType())) {
        /*
         * If the type has a custom serializer, assume the programmer knows
         * best.
         */
        logLevel = TreeLogger.DEBUG;
      } else {
        logLevel = TreeLogger.WARN;
      }
      logger.branch(suppressNonStaticFinalFieldWarnings ? TreeLogger.DEBUG
          : logLevel, "Field '" + field.toString()
          + "' will not be serialized because it is final", null);
      return false;
    }

    return true;
  }

  private static boolean directlyImplementsMarkerInterface(JClassType type) {
    try {
      return TypeHierarchyUtils.directlyImplementsInterface(type,
          getIsSerializableMarkerInterface(type))
          || TypeHierarchyUtils.directlyImplementsInterface(type,
              getSerializableMarkerInterface(type));
    } catch (NotFoundException e) {
      return false;
    }
  }

  private static JArrayType getArrayType(TypeOracle typeOracle, int rank,
      JType component) {
    assert (rank > 0);

    JArrayType array = null;
    JType currentComponent = component;
    for (int i = 0; i < rank; ++i) {
      array = typeOracle.getArrayType(currentComponent);
      currentComponent = array;
    }

    return array;
  }

  private static JClassType getIsSerializableMarkerInterface(JClassType type)
      throws NotFoundException {
    return type.getOracle().getType(IsSerializable.class.getName());
  }

  private static JClassType getSerializableMarkerInterface(JClassType type)
      throws NotFoundException {
    return type.getOracle().getType(Serializable.class.getName());
  }

  /**
   * Returns <code>true</code> if a serializer class could access this type.
   */
  private static boolean isAccessibleToSerializer(JClassType type) {
    if (type.isPrivate()) {
      return false;
    }

    if (isInStandardJavaPackage(type.getQualifiedSourceName())) {
      if (!type.isPublic()) {
        return false;
      }
    }

    if (type.isMemberType()) {
      return isAccessibleToSerializer(type.getEnclosingType());
    }

    return true;
  }

  private static boolean isAllowedByFilter(TypeFilter filter,
      JClassType classType, ProblemReport problems) {
    if (!filter.isAllowed(classType)) {
      problems.add(classType, classType.getParameterizedQualifiedSourceName()
          + " is excluded by type filter ", Priority.AUXILIARY);
      return false;
    }

    return true;
  }

  private static boolean isDeclaredSerializable(JClassType type) {
    return isAutoSerializable(type) || isManuallySerializable(type);
  }

  private static boolean isDirectlySerializable(JClassType type) {
    return directlyImplementsMarkerInterface(type)
        || isManuallySerializable(type);
  }

  private static boolean isManuallySerializable(JClassType type) {
    return findCustomFieldSerializer(type.getOracle(), type) != null;
  }

  private static void logSerializableTypes(TreeLogger logger,
      Set<JClassType> fieldSerializableTypes) {
    TreeLogger localLogger = logger.branch(TreeLogger.DEBUG, "Identified "
        + fieldSerializableTypes.size() + " serializable type"
        + ((fieldSerializableTypes.size() == 1) ? "" : "s"), null);

    for (JClassType fieldSerializableType : fieldSerializableTypes) {
      localLogger.branch(TreeLogger.DEBUG,
          fieldSerializableType.getParameterizedQualifiedSourceName(), null);
    }
  }

  private boolean alreadyCheckedObject;

  /**
   * Cache of the {@link JClassType} for {@link Collection}.
   */
  private final JGenericType collectionClass;

  private Set<String> enhancedClasses = null;

  private PrintWriter logOutputWriter;

  /**
   * Cache of the {@link JClassType} for {@link Map}.
   */
  private final JGenericType mapClass;

  private final Map<JClassType, TreeLogger> rootTypes = new LinkedHashMap<JClassType, TreeLogger>();

  /**
   * If <code>true</code> we will not warn if a serializable type contains a
   * non-static final field. We warn because these fields are not serialized.
   */
  private final boolean suppressNonStaticFinalFieldWarnings;

  private final TypeConstrainer typeConstrainer;
  private TypeFilter typeFilter = DEFAULT_TYPE_FILTER;

  private final TypeOracle typeOracle;

  private final TypeParameterExposureComputer typeParameterExposureComputer = new TypeParameterExposureComputer(
      typeFilter);

  /**
   * The set of type parameters that appear in one of the root types.
   * TODO(spoon): It would be cleaner to delete this field, and instead to have
   * {@link #addRootType(TreeLogger, JType)} replace parameters with wildcard
   * types. Then the root types would not contain any parameters.
   */
  private Set<JTypeParameter> typeParametersInRootTypes = new HashSet<JTypeParameter>();

  /**
   * Map of {@link JType} to {@link TypeInfoComputed}.
   */
  private final Map<JType, TypeInfoComputed> typeToTypeInfoComputed = new HashMap<JType, TypeInfoComputed>();

  /**
   * Constructs a builder.
   * 
   * @param logger
   * @param propertyOracle
   * @param typeOracle
   * 
   * @throws UnableToCompleteException if we fail to find one of our special
   *           types
   */
  public SerializableTypeOracleBuilder(TreeLogger logger,
      PropertyOracle propertyOracle, TypeOracle typeOracle)
      throws UnableToCompleteException {
    this.typeOracle = typeOracle;
    typeConstrainer = new TypeConstrainer(typeOracle);

    try {
      collectionClass = typeOracle.getType(Collection.class.getName()).isGenericType();
      mapClass = typeOracle.getType(Map.class.getName()).isGenericType();
    } catch (NotFoundException e) {
      logger.log(TreeLogger.ERROR, null, e);
      throw new UnableToCompleteException();
    }

    suppressNonStaticFinalFieldWarnings = Shared.shouldSuppressNonStaticFinalFieldWarnings(
        logger, propertyOracle);
    enhancedClasses = Shared.getEnhancedTypes(propertyOracle);
  }

  public void addRootType(TreeLogger logger, JType type) {
    if (type.isPrimitive() != null) {
      return;
    }

    JClassType clazz = (JClassType) type;
    if (!rootTypes.containsKey(clazz)) {
      recordTypeParametersIn(type, typeParametersInRootTypes);

      rootTypes.put(clazz, logger);
    } else {
      logger.log(TreeLogger.TRACE, clazz.getParameterizedQualifiedSourceName()
          + " is already a root type.");
    }
  }

  /**
   * Builds a {@link SerializableTypeOracle} for a given set of root types.
   * 
   * @param logger
   * @return a {@link SerializableTypeOracle} for the specified set of root
   *         types
   * 
   * @throws UnableToCompleteException if there was not at least one
   *           instantiable type assignable to each of the specified root types
   */
  public SerializableTypeOracle build(TreeLogger logger)
      throws UnableToCompleteException {
    alreadyCheckedObject = false;

    boolean allSucceeded = true;

    for (Entry<JClassType, TreeLogger> entry : rootTypes.entrySet()) {
      ProblemReport problems = new ProblemReport();
      problems.setContextType(entry.getKey());
      boolean entrySucceeded = computeTypeInstantiability(entry.getValue(),
          entry.getKey(), TypePaths.createRootPath(entry.getKey()), problems).hasInstantiableSubtypes();
      if (!entrySucceeded) {
        problems.report(logger, TreeLogger.ERROR, TreeLogger.INFO);
      } else {
        if (problems.hasFatalProblems()) {
          entrySucceeded = false;
          problems.reportFatalProblems(logger, TreeLogger.ERROR);
        }
        // if entrySucceeded, there may still be "warning" problems, but too
        // often they're expected (e.g. non-instantiable subtypes of List), so
        // we log them at DEBUG.
        // TODO(fabbott): we could blacklist or graylist those types here, so
        // instantiation during code generation would flag them for us.
        problems.report(logger, TreeLogger.DEBUG, TreeLogger.DEBUG);
      }

      allSucceeded &= entrySucceeded;
    }

    if (!allSucceeded) {
      throw new UnableToCompleteException();
    }

    for (TypeInfoComputed tic : typeToTypeInfoComputed.values()) {
      assert (!tic.isPendingInstantiable());
    }

    pruneUnreachableTypes();

    logReachableTypes(logger);

    Set<JClassType> possiblyInstantiatedTypes = new TreeSet<JClassType>(
        JTYPE_COMPARATOR);

    Set<JClassType> fieldSerializableTypes = new TreeSet<JClassType>(
        JTYPE_COMPARATOR);

    for (TypeInfoComputed tic : typeToTypeInfoComputed.values()) {
      if (!(tic.getType() instanceof JClassType)) {
        continue;
      }
      JClassType type = (JClassType) tic.getType();

      type = type.getErasedType();

      if (tic.isInstantiable()) {
        assert (!type.isAbstract() || type.isEnum() != null);

        possiblyInstantiatedTypes.add(type);
      }

      if (tic.isFieldSerializable()) {
        assert (type.isInterface() == null);

        fieldSerializableTypes.add(type);
      }

      if (tic.maybeEnhanced()
          || (enhancedClasses != null
          && enhancedClasses.contains(type.getQualifiedSourceName()))) {
        type.setEnhanced();
      }
    }

    logSerializableTypes(logger, fieldSerializableTypes);

    return new SerializableTypeOracleImpl(fieldSerializableTypes,
        possiblyInstantiatedTypes);
  }

  /**
   * Set the {@link PrintWriter} which will receive a detailed log of the types
   * which were examined in order to determine serializability.
   */
  public void setLogOutputWriter(PrintWriter logOutputWriter) {
    this.logOutputWriter = logOutputWriter;
  }

  public void setTypeFilter(TypeFilter typeFilter) {
    this.typeFilter = typeFilter;
    typeParameterExposureComputer.setTypeFilter(typeFilter);
  }

  /**
   * This method determines information about serializing a type with GWT. To do
   * so, it must traverse all subtypes as well as all field types of those
   * types, transitively.
   * 
   * It returns a {@link TypeInfoComputed} with the information found.
   * 
   * As a side effect, all types needed--plus some--to serialize this type are
   * accumulated in {@link #typeToTypeInfoComputed}. In particular, there will
   * be an entry for any type that has been validated by this method, as a
   * shortcircuit to avoid recomputation.
   * 
   * The method is exposed using default access to enable testing.
   */
  TypeInfoComputed computeTypeInstantiability(TreeLogger logger, JType type,
      TypePath path, ProblemReport problems) {
    assert (type != null);
    if (type.isPrimitive() != null) {
      TypeInfoComputed tic = getTypeInfoComputed(type, path, true);
      tic.setInstantiableSubtypes(true);
      tic.setInstantiable(false);
      return tic;
    }

    assert (type instanceof JClassType);

    JClassType classType = (JClassType) type;

    TypeInfoComputed tic = getTypeInfoComputed(classType, path, false);
    if (tic != null && tic.isDone()) {
      // we have an answer already; use it.
      return tic;
    }

    TreeLogger localLogger = logger.branch(TreeLogger.DEBUG,
        classType.getParameterizedQualifiedSourceName(), null);

    JTypeParameter isTypeParameter = classType.isTypeParameter();
    if (isTypeParameter != null) {
      if (typeParametersInRootTypes.contains(isTypeParameter)) {
        return computeTypeInstantiability(localLogger,
            isTypeParameter.getFirstBound(),
            TypePaths.createTypeParameterInRootPath(path, isTypeParameter),
            problems);
      }

      /*
       * This type parameter was not in a root type and therefore it is the
       * caller's responsibility to deal with it. We assume that it is
       * indirectly instantiable here.
       */
      tic = getTypeInfoComputed(classType, path, true);
      tic.setInstantiableSubtypes(true);
      tic.setInstantiable(false);
      return tic;
    }

    JWildcardType isWildcard = classType.isWildcard();
    if (isWildcard != null) {
      boolean success = true;
      for (JClassType bound : isWildcard.getUpperBounds()) {
        success &= computeTypeInstantiability(localLogger, bound, path,
            problems).hasInstantiableSubtypes();
      }
      tic = getTypeInfoComputed(classType, path, true);
      tic.setInstantiableSubtypes(success);
      tic.setInstantiable(false);
      return tic;
    }

    JArrayType isArray = classType.isArray();
    if (isArray != null) {
      TypeInfoComputed arrayTic = checkArrayInstantiable(localLogger, isArray,
          path, problems);
      assert getTypeInfoComputed(classType, path, false) != null;
      return arrayTic;
    }

    if (classType == typeOracle.getJavaLangObject()) {
      /*
       * Report an error if the type is or erases to Object since this violates
       * our restrictions on RPC. Should be fatal, but I worry users may have
       * Object-using code they can't readily get out of the class hierarchy.
       */
      problems.add(classType,
          "In order to produce smaller client-side code, 'Object' is not "
              + "allowed; please use a more specific type", Priority.DEFAULT);
      tic = getTypeInfoComputed(classType, path, true);
      tic.setInstantiable(false);
      return tic;
    }

    if (classType.isRawType() != null) {
      localLogger.log(
          TreeLogger.DEBUG,
          "Type '"
              + classType.getQualifiedSourceName()
              + "' should be parameterized to help the compiler produce the smallest code size possible for your module",
          null);
    }

    JClassType originalType = (JClassType) type;

    // TreeLogger subtypesLogger = localLogger.branch(TreeLogger.DEBUG,
    // "Analyzing subclasses:", null);
    tic = getTypeInfoComputed(classType, path, true);
    boolean anySubtypes = checkSubtypes(localLogger, originalType,
        tic.getInstantiableTypes(), path, problems);
    if (!tic.isDone()) {
      tic.setInstantiableSubtypes(anySubtypes);
      tic.setInstantiable(false);
    }
    return tic;
  }

  int getTypeParameterExposure(JGenericType type, int index) {
    return getFlowInfo(type, index).getExposure();
  }

  /**
   * Returns <code>true</code> if the fields of the type should be considered
   * for serialization.
   * 
   * Default access to allow for testing.
   */
  boolean shouldConsiderFieldsForSerialization(JClassType type,
      ProblemReport problems) {
    return shouldConsiderFieldsForSerialization(type, typeFilter, problems);
  }

  /**
   * Consider any subtype of java.lang.Object which qualifies for serialization.
   * 
   * @param logger
   */
  private void checkAllSubtypesOfObject(TreeLogger logger, TypePath parent,
      ProblemReport problems) {
    if (alreadyCheckedObject) {
      return;
    }
    alreadyCheckedObject = true;

    /*
     * This will pull in the world and the set of serializable types will be
     * larger than it needs to be. We exclude types that do not qualify for
     * serialization to avoid generating false errors due to types that do not
     * qualify for serialization and have no serializable subtypes.
     */
    TreeLogger localLogger = logger.branch(TreeLogger.WARN,
        "Checking all subtypes of Object which qualify for serialization", null);
    JClassType[] allTypes = typeOracle.getJavaLangObject().getSubtypes();
    for (JClassType cls : allTypes) {
      if (isDeclaredSerializable(cls)) {
        computeTypeInstantiability(localLogger, cls,
            TypePaths.createSubtypePath(parent, cls,
                typeOracle.getJavaLangObject()), problems);
      }
    }
  }

  private TypeInfoComputed checkArrayInstantiable(TreeLogger logger,
      JArrayType array, TypePath path, ProblemReport problems) {

    JType leafType = array.getLeafType();
    JWildcardType leafWild = leafType.isWildcard();
    if (leafWild != null) {
      JArrayType arrayType = getArrayType(typeOracle, array.getRank(),
          leafWild.getUpperBound());
      return checkArrayInstantiable(logger, arrayType, path, problems);
    }

    JClassType leafClass = leafType.isClassOrInterface();
    JTypeParameter isLeafTypeParameter = leafType.isTypeParameter();
    if (isLeafTypeParameter != null
        && !typeParametersInRootTypes.contains(isLeafTypeParameter)) {
      // Don't deal with non root type parameters, but make a TIC entry to
      // save time if it recurs. We assume they're indirectly instantiable.
      TypeInfoComputed tic = getTypeInfoComputed(array, path, true);
      tic.setInstantiableSubtypes(true);
      tic.setInstantiable(false);
      return tic;
    }

    if (!isAllowedByFilter(array, problems)) {
      // Don't deal with filtered out types either, but make a TIC entry to
      // save time if it recurs. We assume they're not instantiable.
      TypeInfoComputed tic = getTypeInfoComputed(array, path, true);
      tic.setInstantiable(false);
      return tic;
    }

    TypeInfoComputed tic = getTypeInfoComputed(array, path, true);
    if (tic.isDone()) {
      return tic;
    } else if (tic.isPendingInstantiable()) {
      return tic;
    }
    tic.setPendingInstantiable();

    TreeLogger branch = logger.branch(TreeLogger.DEBUG,
        "Analyzing component type:", null);

    TypeInfoComputed leafTic = computeTypeInstantiability(branch, leafType,
        TypePaths.createArrayComponentPath(array, path), problems);
    boolean succeeded = leafTic.hasInstantiableSubtypes();
    if (succeeded) {
      if (leafClass == null) {
        assert leafType.isPrimitive() != null;
        markArrayTypesInstantiable(leafType, array.getRank(), path);
      } else {
        TreeLogger covariantArrayLogger = logger.branch(TreeLogger.DEBUG,
            "Covariant array types");

        /*
         * Compute covariant arrays for arrays of reference types.
         */
        for (JClassType instantiableType : TypeHierarchyUtils.getAllTypesBetweenRootTypeAndLeaves(
            leafClass, leafTic.getInstantiableTypes())) {
          if (!isAccessibleToSerializer(instantiableType)) {
            // Skip types that are not accessible from a serializer
            continue;
          }

          covariantArrayLogger.branch(
              TreeLogger.DEBUG,
              getArrayType(typeOracle, array.getRank(), instantiableType).getParameterizedQualifiedSourceName());

          markArrayTypesInstantiable(instantiableType, array.getRank(), path);
        }
      }
    }

    tic.setInstantiable(succeeded);
    return tic;
  }

  /**
   * Returns <code>true</code> if the declared fields of this type are all
   * instantiable. As a side-effect it fills in {@link TypeInfoComputed} for all
   * necessary types.
   */
  private boolean checkDeclaredFields(TreeLogger logger,
      TypeInfoComputed typeInfo, TypePath parent, ProblemReport problems) {

    JClassType classOrInterface = (JClassType) typeInfo.getType();
    if (classOrInterface.isEnum() != null) {
      // The fields of an enum are never serialized; they are always okay.
      return true;
    }

    JClassType baseType = getBaseType(classOrInterface);

    boolean allSucceeded = true;
    // TODO: Propagating the constraints will produce better results as long
    // as infinite expansion can be avoided in the process.
    JField[] fields = baseType.getFields();
    if (fields.length > 0) {
      TreeLogger localLogger = logger.branch(TreeLogger.DEBUG,
          "Analyzing the fields of type '"
              + classOrInterface.getParameterizedQualifiedSourceName()
              + "' that qualify for serialization", null);

      for (JField field : fields) {
        if (!shouldConsiderForSerialization(localLogger,
            suppressNonStaticFinalFieldWarnings, field)) {
          continue;
        }

        TreeLogger fieldLogger = localLogger.branch(TreeLogger.DEBUG,
            field.toString(), null);
        JType fieldType = field.getType();

        TypePath path = TypePaths.createFieldPath(parent, field);
        if (typeInfo.isManuallySerializable()
            && fieldType.getLeafType() == typeOracle.getJavaLangObject()) {
          checkAllSubtypesOfObject(fieldLogger.branch(TreeLogger.WARN,
              "Object was reached from a manually serializable type", null),
              path, problems);
        } else {
          allSucceeded &= computeTypeInstantiability(fieldLogger, fieldType,
              path, problems).hasInstantiableSubtypes();
        }
      }
    }

    boolean succeeded = allSucceeded || typeInfo.isManuallySerializable();
    if (succeeded) {
      typeInfo.setFieldSerializable();
    }

    return succeeded;
  }

  private boolean checkSubtype(TreeLogger logger, JClassType classOrInterface,
      JClassType originalType, TypePath parent, ProblemReport problems) {
    if (classOrInterface.isEnum() != null) {
      // The fields of an enum are never serialized; they are always okay.
      return true;
    }

    JParameterizedType isParameterized = classOrInterface.isParameterized();
    if (isParameterized != null) {
      if (isRawMapOrRawCollection(classOrInterface)) {
        /*
         * Backwards compatibility. Raw collections or maps force all object
         * subtypes to be considered.
         */
        checkAllSubtypesOfObject(logger, parent, problems);
      } else {
        TreeLogger paramsLogger = logger.branch(TreeLogger.DEBUG,
            "Checking parameters of '"
                + isParameterized.getParameterizedQualifiedSourceName() + "'");

        for (JTypeParameter param : isParameterized.getBaseType().getTypeParameters()) {
          if (!checkTypeArgument(paramsLogger, isParameterized.getBaseType(),
              param.getOrdinal(),
              isParameterized.getTypeArgs()[param.getOrdinal()], parent,
              problems)) {
            return false;
          }
        }
      }
    }

    // Check all super type fields first (recursively).
    JClassType superType = classOrInterface.getSuperclass();
    if (superType != null && superType.isRawType() != null) {
      superType = superType.isRawType().asParameterizedByWildcards();
    }

    if (superType != null && isDeclaredSerializable(superType)) {
      superType = constrainTypeBy(superType, originalType);
      if (superType == null) {
        return false;
      }

      boolean superTypeOk = false;
      superTypeOk = checkSubtype(logger, superType, originalType,
          TypePaths.createSupertypePath(parent, superType, classOrInterface),
          problems);

      /*
       * If my super type did not check out, then I am not instantiable and we
       * should error out... UNLESS I amdirectly serializable myself, in which
       * case it's ok for me to be the root of a new instantiable hierarchy.
       */
      if (!superTypeOk && !isDirectlySerializable(classOrInterface)) {
        return false;
      }
    }

    TypeInfoComputed tic = getTypeInfoComputed(classOrInterface, parent, true);
    return checkDeclaredFields(logger, tic, parent, problems);
  }

  /**
   * Returns <code>true</code> if this type or one of its subtypes is
   * instantiable relative to a known base type.
   */
  private boolean checkSubtypes(TreeLogger logger, JClassType originalType,
      Set<JClassType> instSubtypes, TypePath path, ProblemReport problems) {
    JClassType baseType = getBaseType(originalType);
    TreeLogger computationLogger = logger.branch(TreeLogger.DEBUG,
        "Finding possibly instantiable subtypes");
    List<JClassType> candidates = getPossiblyInstantiableSubtypes(
        computationLogger, baseType, problems);
    boolean anySubtypes = false;

    TreeLogger verificationLogger = logger.branch(TreeLogger.DEBUG,
        "Verifying instantiability");
    for (JClassType candidate : candidates) {
      if (getBaseType(candidate) == baseType
          && originalType.isRawType() == null) {
        // Don't rely on the constrainer when we have perfect information.
        candidate = originalType;
      } else {
        candidate = constrainTypeBy(candidate, originalType);
        if (candidate == null) {
          continue;
        }
      }

      if (!isAllowedByFilter(candidate, problems)) {
        continue;
      }

      TypePath subtypePath = TypePaths.createSubtypePath(path, candidate,
          originalType);
      TypeInfoComputed tic = getTypeInfoComputed(candidate, subtypePath, true);
      if (tic.isDone()) {
        if (tic.isInstantiable()) {
          anySubtypes = true;
          instSubtypes.add(candidate);
        }
        continue;
      } else if (tic.isPendingInstantiable()) {
        anySubtypes = true;
        instSubtypes.add(candidate);
        continue;
      }
      tic.setPendingInstantiable();

      TreeLogger subtypeLogger = verificationLogger.branch(TreeLogger.DEBUG,
          candidate.getParameterizedQualifiedSourceName());
      boolean instantiable = checkSubtype(subtypeLogger, candidate,
          originalType, subtypePath, problems);
      anySubtypes |= instantiable;
      tic.setInstantiable(instantiable);

      if (instantiable) {
        subtypeLogger.branch(TreeLogger.DEBUG, "Is instantiable");
      }

      // Note we are leaving hasInstantiableSubtypes() as false which might be
      // wrong but it is only used by arrays and thus it will never be looked at
      // for this tic.
      if (instantiable && instSubtypes != null) {
        instSubtypes.add(candidate);
      }
    }

    return anySubtypes;
  }

  /**
   * Check the argument to a parameterized type to see if it will make the type
   * it is applied to be serializable. As a side effect, populates
   * {@link #typeToTypeInfoComputed} in the same way as
   * {@link #checkTypeInstantiable(TreeLogger, JType, boolean)}.
   * 
   * @param logger
   * @param baseType - The generic type the parameter is on
   * @param paramIndex - The index of the parameter in the generic type
   * @param typeArg - An upper bound on the actual argument being applied to the
   *          generic type
   * 
   * @return Whether the a parameterized type can be serializable if
   *         <code>baseType</code> is the base type and the
   *         <code>paramIndex</code>th type argument is a subtype of
   *         <code>typeArg</code>.
   */
  private boolean checkTypeArgument(TreeLogger logger, JGenericType baseType,
      int paramIndex, JClassType typeArg, TypePath parent,
      ProblemReport problems) {
    JWildcardType isWildcard = typeArg.isWildcard();
    if (isWildcard != null) {
      return checkTypeArgument(logger, baseType, paramIndex,
          isWildcard.getUpperBound(), parent, problems);
    }

    JArrayType typeArgAsArray = typeArg.isArray();
    if (typeArgAsArray != null) {
      JTypeParameter parameterOfTypeArgArray = typeArgAsArray.getLeafType().isTypeParameter();
      if (parameterOfTypeArgArray != null) {
        JGenericType declaringClass = parameterOfTypeArgArray.getDeclaringClass();
        if (declaringClass != null) {
          TypeParameterFlowInfo flowInfoForArrayParam = getFlowInfo(
              declaringClass, parameterOfTypeArgArray.getOrdinal());
          TypeParameterFlowInfo otherFlowInfo = getFlowInfo(baseType,
              paramIndex);
          if (otherFlowInfo.getExposure() >= 0
              && otherFlowInfo.isTransitivelyAffectedBy(flowInfoForArrayParam)) {
            problems.add(baseType, "Cannot serialize type '"
                + baseType.getParameterizedQualifiedSourceName()
                + "' when given an argument of type '"
                + typeArg.getParameterizedQualifiedSourceName()
                + "' because it appears to require serializing arrays "
                + "of unbounded dimension", Priority.DEFAULT);
            return false;
          }
        }
      }
    }

    TypePath path = TypePaths.createTypeArgumentPath(parent, baseType,
        paramIndex, typeArg);
    int exposure = getTypeParameterExposure(baseType, paramIndex);
    switch (exposure) {
      case TypeParameterExposureComputer.EXPOSURE_DIRECT: {
        TreeLogger branch = logger.branch(
            TreeLogger.DEBUG,
            "Checking type argument "
                + paramIndex
                + " of type '"
                + baseType.getParameterizedQualifiedSourceName()
                + "' because it is directly exposed in this type or in one of its subtypes");
        return computeTypeInstantiability(branch, typeArg, path, problems).hasInstantiableSubtypes()
            || mightNotBeExposed(baseType, paramIndex);
      }
      case TypeParameterExposureComputer.EXPOSURE_NONE:
        // Ignore this argument
        logger.log(Type.DEBUG, "Ignoring type argument " + paramIndex
            + " of type '" + baseType.getParameterizedQualifiedSourceName()
            + "' because it is not exposed in this or any subtype");
        return true;

      default: {
        assert (exposure >= TypeParameterExposureComputer.EXPOSURE_MIN_BOUNDED_ARRAY);
        problems.add(
            getArrayType(typeOracle, exposure, typeArg),
            "Checking type argument "
                + paramIndex
                + " of type '"
                + baseType.getParameterizedQualifiedSourceName()
                + "' because it is exposed as an array with a maximum dimension of "
                + exposure + " in this type or one of its subtypes",
            Priority.AUXILIARY);
        return computeTypeInstantiability(logger,
            getArrayType(typeOracle, exposure, typeArg), path, problems).hasInstantiableSubtypes()
            || mightNotBeExposed(baseType, paramIndex);
      }
    }
  }

  /**
   * If <code>type</code>'s base class does not inherit from
   * <code>superType</code>'s base class, then return <code>type</code>
   * unchanged. If it does, then return a subtype of <code>type</code> that
   * includes all values in both <code>type</code> and <code>superType</code>.
   * If there are definitely no such values, return <code>null</code>.
   */
  private JClassType constrainTypeBy(JClassType type, JClassType superType) {
    return typeConstrainer.constrainTypeBy(type, superType);
  }

  private TypeParameterFlowInfo getFlowInfo(JGenericType type, int index) {
    return typeParameterExposureComputer.computeTypeParameterExposure(type,
        index);
  }

  /**
   * Returns the subtypes of a given base type as parameterized by wildcards.
   */
  private List<JClassType> getPossiblyInstantiableSubtypes(TreeLogger logger,
      JClassType baseType, ProblemReport problems) {
    assert (baseType == getBaseType(baseType));

    List<JClassType> possiblyInstantiableTypes = new ArrayList<JClassType>();
    if (baseType == typeOracle.getJavaLangObject()) {
      return possiblyInstantiableTypes;
    }

    List<JClassType> candidates = new ArrayList<JClassType>();
    candidates.add(baseType);
    List<JClassType> subtypes = Arrays.asList(baseType.getSubtypes());
    candidates.addAll(subtypes);

    for (JClassType subtype : candidates) {
      JClassType subtypeBase = getBaseType(subtype);
      if (maybeInstantiable(logger, subtypeBase, problems)) {
        /*
         * Convert the generic type into a parameterization that only includes
         * wildcards.
         */
        JGenericType isGeneric = subtype.isGenericType();
        if (isGeneric != null) {
          subtype = isGeneric.asParameterizedByWildcards();
        } else {
          assert (subtype instanceof JRealClassType);
        }

        possiblyInstantiableTypes.add(subtype);
      }
    }

    if (possiblyInstantiableTypes.size() == 0) {
      String possibilities[] = new String[candidates.size()];
      for (int i = 0; i < possibilities.length; i++) {
        JClassType subtype = candidates.get(i);
        String worstMessage = problems.getWorstMessageForType(subtype);
        if (worstMessage == null) {
          possibilities[i] = "   subtype "
              + subtype.getParameterizedQualifiedSourceName()
              + " is not instantiable";
        } else {
          // message with have the form "FQCN some-problem-description"
          possibilities[i] = "   subtype " + worstMessage;
        }
      }
      problems.add(baseType, baseType.getParameterizedQualifiedSourceName()
          + " has no available instantiable subtypes.", Priority.DEFAULT,
          possibilities);
    }
    return possiblyInstantiableTypes;
  }

  private TypeInfoComputed getTypeInfoComputed(JType type, TypePath path,
      boolean createIfNeeded) {
    TypeInfoComputed tic = typeToTypeInfoComputed.get(type);
    if (tic == null && createIfNeeded) {
      tic = new TypeInfoComputed(type, path);
      typeToTypeInfoComputed.put(type, tic);
    }
    return tic;
  }

  private boolean isAllowedByFilter(JClassType classType, ProblemReport problems) {
    return isAllowedByFilter(typeFilter, classType, problems);
  }

  /**
   * Returns <code>true</code> if the type is Collection<? extends Object> or
   * Map<? extends Object, ? extends Object>.
   */
  private boolean isRawMapOrRawCollection(JClassType type) {
    if (type.asParameterizationOf(collectionClass) == collectionClass.asParameterizedByWildcards()) {
      return true;
    }

    if (type.asParameterizationOf(mapClass) == mapClass.asParameterizedByWildcards()) {
      return true;
    }

    return false;
  }

  private void logPath(TreeLogger logger, TypePath path) {
    if (path == null) {
      return;
    }

    logger.log(TreeLogger.DEBUG, path.toString());
    logPath(logger, path.getParent());
  }

  private void logReachableTypes(TreeLogger logger) {
    if (logOutputWriter != null) {
      // Route the TreeLogger output to an output stream.
      PrintWriterTreeLogger printWriterTreeLogger = new PrintWriterTreeLogger(
          logOutputWriter);
      printWriterTreeLogger.setMaxDetail(TreeLogger.ALL);
      logger = printWriterTreeLogger;
    }

    logger.log(TreeLogger.DEBUG, "Reachable types computed on: "
        + new Date().toString());
    Set<JType> keySet = typeToTypeInfoComputed.keySet();
    JType[] types = keySet.toArray(new JType[0]);
    Arrays.sort(types, JTYPE_COMPARATOR);

    for (JType type : types) {
      TypeInfoComputed tic = typeToTypeInfoComputed.get(type);
      assert (tic != null);

      TreeLogger typeLogger = logger.branch(TreeLogger.DEBUG,
          tic.getType().getParameterizedQualifiedSourceName());
      TreeLogger serializationStatus = typeLogger.branch(TreeLogger.DEBUG,
          "Serialization status");
      if (tic.isInstantiable()) {
        serializationStatus.branch(TreeLogger.DEBUG, "Instantiable");
      } else {
        if (tic.isFieldSerializable()) {
          serializationStatus.branch(TreeLogger.DEBUG, "Field serializable");
        } else {
          serializationStatus.branch(TreeLogger.DEBUG, "Not serializable");
        }
      }

      TreeLogger pathLogger = typeLogger.branch(TreeLogger.DEBUG, "Path");

      logPath(pathLogger, tic.getPath());
      logger.log(TreeLogger.DEBUG, "");
    }

    if (logOutputWriter != null) {
      logOutputWriter.flush();
    }
  }

  /**
   * Mark arrays of <code>leafType</code> as instantiable, for arrays of
   * dimension up to <code>maxRank</code>.
   */
  private void markArrayTypesInstantiable(JType leafType, int maxRank,
      TypePath path) {
    for (int rank = 1; rank <= maxRank; ++rank) {
      JArrayType covariantArray = getArrayType(typeOracle, rank, leafType);

      TypeInfoComputed covariantArrayTic = getTypeInfoComputed(covariantArray,
          path, true);
      covariantArrayTic.setInstantiable(true);
    }
  }

  private boolean maybeInstantiable(TreeLogger logger, JClassType type,
      ProblemReport problems) {
    boolean success = canBeInstantiated(type, problems)
        && shouldConsiderFieldsForSerialization(type, problems);
    if (success) {
      logger.log(TreeLogger.DEBUG, type.getParameterizedQualifiedSourceName()
          + " might be instantiable");
    }
    return success;
  }

  private boolean mightNotBeExposed(JGenericType baseType, int paramIndex) {
    TypeParameterFlowInfo flowInfo = getFlowInfo(baseType, paramIndex);
    return flowInfo.getMightNotBeExposed() || isManuallySerializable(baseType);
  }

  /**
   * Remove serializable types that were visited due to speculative paths but
   * are not really needed for serialization.
   * 
   * NOTE: This is currently much more limited than it should be. For example, a
   * path sensitive prune could remove instantiable types also.
   */
  private void pruneUnreachableTypes() {
    /*
     * Record all supertypes of any instantiable type, whether or not they are
     * field serialziable.
     */
    Set<JType> supersOfInstantiableTypes = new LinkedHashSet<JType>();
    for (TypeInfoComputed tic : typeToTypeInfoComputed.values()) {
      if (tic.isInstantiable() && tic.getType() instanceof JClassType) {
        JClassType type = (JClassType) tic.getType().getErasedType();
        JClassType sup = type;
        while (sup != null) {
          supersOfInstantiableTypes.add(sup.getErasedType());
          sup = sup.getErasedType().getSuperclass();
        }
      }
    }

    /*
     * Record any field serializable type that is not in the supers of any
     * instantiable type.
     */
    Set<JType> toKill = new LinkedHashSet<JType>();
    for (TypeInfoComputed tic : typeToTypeInfoComputed.values()) {
      if (tic.isFieldSerializable()
          && !supersOfInstantiableTypes.contains(tic.getType().getErasedType())) {
        toKill.add(tic.getType());
      }
    }

    /*
     * Remove any field serializable supers that cannot be reached from an
     * instantiable type.
     */
    for (JType type : toKill) {
      typeToTypeInfoComputed.remove(type);
    }
  }
}
