/*
 * Copyright 2010 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.web.bindery.requestfactory.server;

import com.google.web.bindery.autobean.shared.ValueCodex;
import com.google.gwt.dev.asm.AnnotationVisitor;
import com.google.gwt.dev.asm.ClassReader;
import com.google.gwt.dev.asm.ClassVisitor;
import com.google.gwt.dev.asm.MethodVisitor;
import com.google.gwt.dev.asm.Opcodes;
import com.google.gwt.dev.asm.Type;
import com.google.gwt.dev.asm.commons.EmptyVisitor;
import com.google.gwt.dev.asm.commons.Method;
import com.google.gwt.dev.asm.signature.SignatureReader;
import com.google.gwt.dev.asm.signature.SignatureVisitor;
import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.Name.BinaryName;
import com.google.gwt.dev.util.Name.SourceOrBinaryName;
import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.InstanceRequest;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.google.web.bindery.requestfactory.shared.ProxyForName;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.RequestFactory;
import com.google.web.bindery.requestfactory.shared.Service;
import com.google.web.bindery.requestfactory.shared.ServiceName;
import com.google.web.bindery.requestfactory.shared.SkipInterfaceValidation;
import com.google.web.bindery.requestfactory.shared.ValueProxy;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
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.logging.Level;
import java.util.logging.Logger;

/**
 * Encapsulates validation logic to determine if a {@link RequestFactory}
 * interface, its {@link RequestContext}, and associated {@link EntityProxy}
 * interfaces match their domain counterparts. This implementation examines the
 * classfiles directly in order to avoid the need to load the types into the
 * JVM.
 * <p>
 * This class is amenable to being used as a unit test:
 * 
 * <pre>
 * public void testRequestFactory() {
 *   Logger logger = Logger.getLogger("");
 *   RequestFactoryInterfaceValidator v = new RequestFactoryInterfaceValidator(
 *     logger, new ClassLoaderLoader(MyRequestContext.class.getClassLoader()));
 *   v.validateRequestContext(MyRequestContext.class.getName());
 *   assertFalse(v.isPoisoned());
 * }
 * </pre>
 * This class also has a {@code main} method and can be used as a build-time
 * tool:
 * 
 * <pre>
 * java -cp gwt-servlet.jar:your-code.jar \
 *   com.google.web.bindery.requestfactory.server.RequestFactoryInterfaceValidator \
 *   com.example.MyRequestFactory
 * </pre>
 */
public class RequestFactoryInterfaceValidator {
  /**
   * An implementation of {@link Loader} that uses a {@link ClassLoader} to
   * retrieve the class files.
   */
  public static class ClassLoaderLoader implements Loader {
    private final ClassLoader loader;

    public ClassLoaderLoader(ClassLoader loader) {
      this.loader = loader;
    }

    public boolean exists(String resource) {
      return loader.getResource(resource) != null;
    }

    public InputStream getResourceAsStream(String resource) {
      return loader.getResourceAsStream(resource);
    }
  }

  /**
   * Abstracts the mechanism by which class files are loaded.
   * 
   * @see ClassLoaderLoader
   */
  public interface Loader {
    /**
     * Returns true if the specified resource can be loaded.
     * 
     * @param resource a resource name (e.g. <code>com/example/Foo.class</code>)
     */
    boolean exists(String resource);

    /**
     * Returns an InputStream to access the specified resource, or
     * <code>null</code> if no such resource exists.
     * 
     * @param resource a resource name (e.g. <code>com/example/Foo.class</code>)
     */
    InputStream getResourceAsStream(String resource);
  }

  /**
   * Improves error messages by providing context for the user.
   * <p>
   * Visible for testing.
   */
  static class ErrorContext {
    private final Logger logger;
    private final ErrorContext parent;
    private Type currentType;
    private Method currentMethod;
    private RequestFactoryInterfaceValidator validator;

    public ErrorContext(Logger logger) {
      this.logger = logger;
      this.parent = null;
    }

    protected ErrorContext(ErrorContext parent) {
      this.logger = parent.logger;
      this.parent = parent;
      this.validator = parent.validator;
    }

    public void poison(String msg, Object... args) {
      poison();
      logger.logp(Level.SEVERE, currentType(), currentMethod(),
          String.format(msg, args));
      validator.poisoned = true;
    }

    public void poison(String msg, Throwable t) {
      poison();
      logger.logp(Level.SEVERE, currentType(), currentMethod(), msg, t);
      validator.poisoned = true;
    }

    public ErrorContext setMethod(Method method) {
      ErrorContext toReturn = fork();
      toReturn.currentMethod = method;
      return toReturn;
    }

    public ErrorContext setType(Type type) {
      ErrorContext toReturn = fork();
      toReturn.currentType = type;
      return toReturn;
    }

    public void spam(String msg, Object... args) {
      logger.logp(Level.FINEST, currentType(), currentMethod(),
          String.format(msg, args));
    }

    protected ErrorContext fork() {
      return new ErrorContext(this);
    }

    void setValidator(RequestFactoryInterfaceValidator validator) {
      assert this.validator == null : "Cannot set validator twice";
      this.validator = validator;
    }

    private String currentMethod() {
      if (currentMethod != null) {
        return print(currentMethod);
      }
      if (parent != null) {
        return parent.currentMethod();
      }
      return null;
    }

    private String currentType() {
      if (currentType != null) {
        return print(currentType);
      }
      if (parent != null) {
        return parent.currentType();
      }
      return null;
    }

    /**
     * Populate {@link RequestFactoryInterfaceValidator#badTypes} with the
     * current context.
     */
    private void poison() {
      if (currentType != null) {
        validator.badTypes.add(currentType.getClassName());
      }
      if (parent != null) {
        parent.poison();
      }
    }
  }

  /**
   * Used internally as a placeholder for types that cannot be mapped to a
   * domain object.
   */
  interface MissingDomainType {
  }

  /**
   * Collects the ProxyFor or Service annotation from an EntityProxy or
   * RequestContext type.
   */
  private class DomainMapper extends EmptyVisitor {
    private final ErrorContext logger;
    private String domainInternalName;
    private List<Class<? extends Annotation>> found = new ArrayList<Class<? extends Annotation>>();
    private String locatorInternalName;

    public DomainMapper(ErrorContext logger) {
      this.logger = logger;
      logger.spam("Finding domain mapping annotation");
    }

    public String getDomainInternalName() {
      return domainInternalName;
    }

    public String getLocatorInternalName() {
      return locatorInternalName;
    }

    @Override
    public void visit(int version, int access, String name, String signature,
        String superName, String[] interfaces) {
      if ((access & Opcodes.ACC_INTERFACE) == 0) {
        logger.poison("Type must be an interface");
      }
    }

    /**
     * This method examines one annotation at a time.
     */
    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      // Set to true if the annotation should have class literal values
      boolean expectClasses = false;
      // Set to true if the annonation has string values
      boolean expectNames = false;

      if (desc.equals(Type.getDescriptor(ProxyFor.class))) {
        expectClasses = true;
        found.add(ProxyFor.class);
      } else if (desc.equals(Type.getDescriptor(ProxyForName.class))) {
        expectNames = true;
        found.add(ProxyForName.class);
      } else if (desc.equals(Type.getDescriptor(Service.class))) {
        expectClasses = true;
        found.add(Service.class);
      } else if (desc.equals(Type.getDescriptor(ServiceName.class))) {
        expectNames = true;
        found.add(ServiceName.class);
      }

      if (expectClasses) {
        return new EmptyVisitor() {
          @Override
          public void visit(String name, Object value) {
            if ("value".equals(name)) {
              domainInternalName = ((Type) value).getInternalName();
            } else if ("locator".equals(name)) {
              locatorInternalName = ((Type) value).getInternalName();
            }
          }
        };
      }

      if (expectNames) {
        return new EmptyVisitor() {
          @Override
          public void visit(String name, Object value) {
            String sourceName;
            boolean locatorRequired = "locator".equals(name);
            boolean valueRequired = "value".equals(name);
            if (valueRequired || locatorRequired) {
              sourceName = (String) value;
            } else {
              return;
            }

            /*
             * The input is a source name, so we need to convert it to an
             * internal name. We'll do this by substituting dollar signs for the
             * last slash in the name until there are no more slashes.
             */
            StringBuffer desc = new StringBuffer(sourceName.replace('.', '/'));
            while (!loader.exists(desc.toString() + ".class")) {
              logger.spam("Did not find " + desc.toString());
              int idx = desc.lastIndexOf("/");
              if (idx == -1) {
                if (locatorRequired) {
                  logger.poison("Cannot find locator named %s", value);
                } else if (valueRequired) {
                  logger.poison("Cannot find domain type named %s", value);
                }
                return;
              }
              desc.setCharAt(idx, '$');
            }

            if (locatorRequired) {
              locatorInternalName = desc.toString();
              logger.spam(locatorInternalName);
            } else if (valueRequired) {
              domainInternalName = desc.toString();
              logger.spam(domainInternalName);
            } else {
              throw new RuntimeException("Should not reach here");
            }
          }
        };
      }
      return null;
    }

    @Override
    public void visitEnd() {
      // Only allow one annotation
      if (found.size() > 1) {
        StringBuilder sb = new StringBuilder();
        for (Class<?> clazz : found) {
          sb.append(" @").append(clazz.getSimpleName());
        }
        logger.poison("Redundant domain mapping annotations present:%s",
            sb.toString());
      }
    }
  }

  /**
   * Collects information about domain objects. This visitor is intended to be
   * iteratively applied to collect all methods in a type hierarchy.
   */
  private class MethodsInHierarchyCollector extends EmptyVisitor {
    private final ErrorContext logger;
    private Set<RFMethod> methods = new LinkedHashSet<RFMethod>();
    private Set<String> seen = new HashSet<String>();

    private MethodsInHierarchyCollector(ErrorContext logger) {
      this.logger = logger;
    }

    public Set<RFMethod> exec(String internalName) {
      RequestFactoryInterfaceValidator.this.visit(logger, internalName, this);

      Map<RFMethod, RFMethod> toReturn = new HashMap<RFMethod, RFMethod>();
      // Return most-derived methods
      for (RFMethod method : methods) {
        RFMethod key = new RFMethod(method.getName(), Type.getMethodDescriptor(
            Type.VOID_TYPE, method.getArgumentTypes()));

        RFMethod compareTo = toReturn.get(key);
        if (compareTo == null) {
          toReturn.put(key, method);
        } else if (isAssignable(logger, compareTo.getReturnType(),
            method.getReturnType())) {
          toReturn.put(key, method);
        }
      }

      return new HashSet<RFMethod>(toReturn.values());
    }

    @Override
    public void visit(int version, int access, String name, String signature,
        String superName, String[] interfaces) {
      if (!seen.add(name)) {
        return;
      }
      if (!objectType.getInternalName().equals(superName)) {
        RequestFactoryInterfaceValidator.this.visit(logger, superName, this);
      }
      if (interfaces != null) {
        for (String intf : interfaces) {
          RequestFactoryInterfaceValidator.this.visit(logger, intf, this);
        }
      }
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc,
        String signature, String[] exceptions) {
      // Ignore initializers
      if ("<clinit>".equals(name) || "<init>".equals(name)) {
        return null;
      }
      final RFMethod method = new RFMethod(name, desc);
      method.setDeclaredStatic((access & Opcodes.ACC_STATIC) != 0);
      method.setDeclaredSignature(signature);
      methods.add(method);

      return new EmptyVisitor() {
        @Override
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
          if (desc.equals(Type.getDescriptor(SkipInterfaceValidation.class))) {
            method.setValidationSkipped(true);
          }
          return null;
        }
      };
    }
  }

  private static class RFMethod extends Method {
    private boolean isDeclaredStatic;
    private String signature;
    private boolean isValidationSkipped;

    public RFMethod(String name, String desc) {
      super(name, desc);
    }

    public String getSignature() {
      return signature;
    }

    public boolean isDeclaredStatic() {
      return isDeclaredStatic;
    }

    public boolean isValidationSkipped() {
      return isValidationSkipped;
    }

    public void setDeclaredSignature(String signature) {
      this.signature = signature;
    }

    public void setDeclaredStatic(boolean value) {
      isDeclaredStatic = value;
    }

    public void setValidationSkipped(boolean isValidationSkipped) {
      this.isValidationSkipped = isValidationSkipped;
    }

    @Override
    public String toString() {
      return (isDeclaredStatic ? "static " : "") + super.toString();
    }
  }

  private class SupertypeCollector extends EmptyVisitor {
    private final ErrorContext logger;
    private final Set<String> seen = new HashSet<String>();
    private final List<Type> supers = new ArrayList<Type>();

    public SupertypeCollector(ErrorContext logger) {
      this.logger = logger;
    }

    public List<Type> exec(Type type) {
      RequestFactoryInterfaceValidator.this.visit(logger,
          type.getInternalName(), this);
      return supers;
    }

    @Override
    public void visit(int version, int access, String name, String signature,
        String superName, String[] interfaces) {
      if (!seen.add(name)) {
        return;
      }
      supers.add(Type.getObjectType(name));
      if (!objectType.getInternalName().equals(name)) {
        RequestFactoryInterfaceValidator.this.visit(logger, superName, this);
      }
      if (interfaces != null) {
        for (String intf : interfaces) {
          RequestFactoryInterfaceValidator.this.visit(logger, intf, this);
        }
      }
    }
  }

  /**
   * Return all types referenced by a method signature.
   */
  private static class TypesInSignatureCollector extends SignatureAdapter {
    private final Set<Type> found = new HashSet<Type>();

    public Type[] getFound() {
      return found.toArray(new Type[found.size()]);
    }

    @Override
    public SignatureVisitor visitArrayType() {
      return this;
    }

    @Override
    public SignatureVisitor visitClassBound() {
      return this;
    }

    @Override
    public void visitClassType(String name) {
      found.add(Type.getObjectType(name));
    }

    @Override
    public SignatureVisitor visitExceptionType() {
      return this;
    }

    @Override
    public SignatureVisitor visitInterface() {
      return this;
    }

    @Override
    public SignatureVisitor visitInterfaceBound() {
      return this;
    }

    @Override
    public SignatureVisitor visitParameterType() {
      return this;
    }

    @Override
    public SignatureVisitor visitReturnType() {
      return this;
    }

    @Override
    public SignatureVisitor visitSuperclass() {
      return this;
    }

    @Override
    public SignatureVisitor visitTypeArgument(char wildcard) {
      return this;
    }
  }

  static final Set<Class<?>> VALUE_TYPES = ValueCodex.getAllValueTypes();

  public static void main(String[] args) {
    if (args.length == 0) {
      System.err.println("Usage: java -cp gwt-servlet.jar:your-code.jar "
          + RequestFactoryInterfaceValidator.class.getCanonicalName()
          + " com.example.MyRequestFactory");
      System.exit(1);
    }
    RequestFactoryInterfaceValidator validator = new RequestFactoryInterfaceValidator(
        Logger.getLogger(RequestFactoryInterfaceValidator.class.getName()),
        new ClassLoaderLoader(Thread.currentThread().getContextClassLoader()));
    validator.validateRequestFactory(args[0]);
    System.exit(validator.isPoisoned() ? 1 : 0);
  }

  static String messageCouldNotFindMethod(Type domainType,
      List<? extends Method> methods) {
    StringBuilder sb = new StringBuilder();
    sb.append(String.format(
        "Could not find matching method in %s.\nPossible matches:\n",
        print(domainType)));
    for (Method domainMethod : methods) {
      sb.append("  ").append(print(domainMethod)).append("\n");
    }
    return sb.toString();
  }

  private static String print(Method method) {
    StringBuilder sb = new StringBuilder();
    sb.append(print(method.getReturnType())).append(" ").append(
        method.getName()).append("(");
    for (Type t : method.getArgumentTypes()) {
      sb.append(print(t)).append(" ");
    }
    sb.append(")");
    return sb.toString();
  }

  private static String print(Type type) {
    return SourceOrBinaryName.toSourceName(type.getClassName());
  }

  /**
   * A set of binary type names that are known to be bad.
   */
  private final Set<String> badTypes = new HashSet<String>();
  /**
   * The type {@link BaseProxy}.
   */
  private final Type baseProxyIntf = Type.getType(BaseProxy.class);
  /**
   * Maps client types (e.g. FooProxy) to server domain types (e.g. Foo).
   */
  private final Map<Type, Type> clientToDomainType = new HashMap<Type, Type>();
  /**
   * Maps client types (e.g. FooProxy or FooContext) to their locator types
   * (e.g. FooLocator or FooServiceLocator).
   */
  private final Map<Type, Type> clientToLocatorMap = new HashMap<Type, Type>();
  /**
   * Maps domain types (e.g Foo) to client proxy types (e.g. FooAProxy,
   * FooBProxy).
   */
  private final Map<Type, List<Type>> domainToClientType = new HashMap<Type, List<Type>>();
  /**
   * The type {@link EntityProxy}.
   */
  private final Type entityProxyIntf = Type.getType(EntityProxy.class);
  /**
   * The type {@link Enum}.
   */
  private final Type enumType = Type.getType(Enum.class);
  /**
   * A placeholder type for client types that could not be resolved to a domain
   * type.
   */
  private final Type errorType = Type.getType(MissingDomainType.class);
  /**
   * The type {@link InstanceRequest}.
   */
  private final Type instanceRequestIntf = Type.getType(InstanceRequest.class);
  private final Loader loader;
  /**
   * A cache of all methods defined in a type hierarchy.
   */
  private final Map<Type, Set<RFMethod>> methodsInHierarchy = new HashMap<Type, Set<RFMethod>>();
  /**
   * The type {@link Object}.
   */
  private final Type objectType = Type.getObjectType("java/lang/Object");
  private final ErrorContext parentLogger;
  private boolean poisoned;
  /**
   * The type {@link Request}.
   */
  private final Type requestIntf = Type.getType(Request.class);
  /**
   * The type {@link RequestContext}.
   */
  private final Type requestContextIntf = Type.getType(RequestContext.class);
  /**
   * A map of a type to all types that it could be assigned to.
   */
  private final Map<Type, List<Type>> supertypes = new HashMap<Type, List<Type>>();

  /**
   * The type {@link ValueProxy}.
   */
  private final Type valueProxyIntf = Type.getType(ValueProxy.class);

  /**
   * A set to prevent re-validation of a type.
   */
  private final Set<String> validatedTypes = new HashSet<String>();

  /**
   * Contains vaue types (e.g. Integer).
   */
  private final Set<Type> valueTypes = new HashSet<Type>();

  /**
   * Maps a domain object to the type returned from its getId method.
   */
  private final Map<Type, Type> unresolvedKeyTypes = new HashMap<Type, Type>();

  {
    for (Class<?> clazz : VALUE_TYPES) {
      valueTypes.add(Type.getType(clazz));
    }
  }

  public RequestFactoryInterfaceValidator(Logger logger, Loader loader) {
    this.parentLogger = new ErrorContext(logger);
    parentLogger.setValidator(this);
    this.loader = loader;
  }

  /**
   * Visible for testing.
   */
  RequestFactoryInterfaceValidator(ErrorContext errorContext, Loader loader) {
    this.parentLogger = errorContext;
    this.loader = loader;
    errorContext.setValidator(this);
  }

  /**
   * Reset the poisoned status of the validator so that it may be reused without
   * destroying cached state.
   */
  public void antidote() {
    poisoned = false;
  }

  /**
   * Returns true if validation failed.
   */
  public boolean isPoisoned() {
    return poisoned;
  }

  /**
   * This method checks an EntityProxy interface against its peer domain object
   * to determine if the server code would be able to process a request using
   * the methods defined in the EntityProxy interface. It does not perform any
   * checks as to whether or not the EntityProxy could actually be generated by
   * the Generator.
   * <p>
   * This method may be called repeatedly on a single instance of the validator.
   * Doing so will amortize type calculation costs.
   * <p>
   * Checks implemented:
   * <ul>
   * <li> <code>binaryName</code> implements EntityProxy</li>
   * <li><code>binaryName</code> has a {@link ProxyFor} or {@link ProxyForName}
   * annotation</li>
   * <li>The domain object has getId() and getVersion() methods</li>
   * <li>All property methods in the EntityProxy can be mapped onto an
   * equivalent domain method (unless validation is skipped for the method)</li>
   * <li>All referenced proxy types are valid</li>
   * </ul>
   * 
   * @param binaryName the binary name (e.g. {@link Class#getName()}) of the
   *          EntityProxy subtype
   */
  public void validateEntityProxy(String binaryName) {
    validateProxy(binaryName, entityProxyIntf, true);
  }

  /**
   * Determine if the specified type implements a proxy interface and apply the
   * appropriate validations. This can be used as a general-purpose entry method
   * when writing unit tests.
   * 
   * @param binaryName the binary name (e.g. {@link Class#getName()}) of the
   *          EntityProxy or ValueProxy subtype
   */
  public void validateProxy(String binaryName) {
    /*
     * Don't call fastFail() here or the proxy may not be validated, since
     * validateXProxy delegates to validateProxy() which would re-check.
     */
    Type proxyType = Type.getObjectType(BinaryName.toInternalName(binaryName));
    if (isAssignable(parentLogger, entityProxyIntf, proxyType)) {
      validateEntityProxy(binaryName);
    } else if (isAssignable(parentLogger, valueProxyIntf, proxyType)) {
      validateValueProxy(binaryName);
    } else {
      parentLogger.poison("%s is neither an %s nor a %s", print(proxyType),
          print(entityProxyIntf), print(valueProxyIntf));
    }
  }

  /**
   * This method checks a RequestContext interface against its peer domain
   * domain object to determine if the server code would be able to process a
   * request using the the methods defined in the RequestContext interface. It
   * does not perform any checks as to whether or not the RequestContext could
   * actually be generated by the Generator.
   * <p>
   * This method may be called repeatedly on a single instance of the validator.
   * Doing so will amortize type calculation costs.
   * <p>
   * Checks implemented:
   * <ul>
   * <li> <code>binaryName</code> implements RequestContext</li>
   * <li><code>binaryName</code> has a {@link Service} or {@link ServiceName}
   * annotation</li>
   * <li>All service methods in the RequestContext can be mapped onto an
   * equivalent domain method (unless validation is skipped for the method)</li>
   * <li>All referenced EntityProxy types are valid</li>
   * </ul>
   * 
   * @param binaryName the binary name (e.g. {@link Class#getName()}) of the
   *          RequestContext subtype
   * @see #validateEntityProxy(String)
   */
  public void validateRequestContext(String binaryName) {
    if (fastFail(binaryName)) {
      return;
    }

    Type requestContextType = Type.getObjectType(BinaryName.toInternalName(binaryName));
    final ErrorContext logger = parentLogger.setType(requestContextType);

    // Quick sanity check for calling code
    if (!isAssignable(logger, requestContextIntf, requestContextType)) {
      logger.poison("%s is not a %s", print(requestContextType),
          RequestContext.class.getSimpleName());
      return;
    }

    Type domainServiceType = getDomainType(logger, requestContextType);
    if (domainServiceType == errorType) {
      logger.poison(
          "The type %s must be annotated with a @%s or @%s annotation",
          BinaryName.toSourceName(binaryName), Service.class.getSimpleName(),
          ServiceName.class.getSimpleName());
      return;
    }

    for (RFMethod method : getMethodsInHierarchy(logger, requestContextType)) {
      // Ignore methods in RequestContext itself
      if (findCompatibleMethod(logger, requestContextIntf, method, false, true,
          true) != null) {
        continue;
      }

      // Check the client method against the domain
      checkClientMethodInDomain(logger, method, domainServiceType,
          !clientToLocatorMap.containsKey(requestContextType));
      maybeCheckReferredProxies(logger, method);
    }

    checkUnresolvedKeyTypes(logger);
  }

  /**
   * This method checks a RequestFactory interface.
   * <p>
   * This method may be called repeatedly on a single instance of the validator.
   * Doing so will amortize type calculation costs. It does not perform any
   * checks as to whether or not the RequestContext could actually be generated
   * by the Generator.
   * <p>
   * Checks implemented:
   * <ul>
   * <li> <code>binaryName</code> implements RequestFactory</li>
   * <li>All referenced RequestContext types are valid</li>
   * </ul>
   * 
   * @param binaryName the binary name (e.g. {@link Class#getName()}) of the
   *          RequestContext subtype
   * @see #validateRequestContext(String)
   */
  public void validateRequestFactory(String binaryName) {
    if (fastFail(binaryName)) {
      return;
    }

    Type requestFactoryType = Type.getObjectType(BinaryName.toInternalName(binaryName));
    ErrorContext logger = parentLogger.setType(requestFactoryType);

    // Quick sanity check for calling code
    if (!isAssignable(logger, Type.getType(RequestFactory.class),
        requestFactoryType)) {
      logger.poison("%s is not a %s", print(requestFactoryType),
          RequestFactory.class.getSimpleName());
      return;
    }

    // Validate each RequestContext method in the RF
    for (Method contextMethod : getMethodsInHierarchy(logger,
        requestFactoryType)) {
      Type returnType = contextMethod.getReturnType();
      if (isAssignable(logger, requestContextIntf, returnType)) {
        validateRequestContext(returnType.getClassName());
      }
    }
  }

  /**
   * This method checks a ValueProxy interface against its peer domain object to
   * determine if the server code would be able to process a request using the
   * methods defined in the ValueProxy interface. It does not perform any checks
   * as to whether or not the ValueProxy could actually be generated by the
   * Generator.
   * <p>
   * This method may be called repeatedly on a single instance of the validator.
   * Doing so will amortize type calculation costs.
   * <p>
   * Checks implemented:
   * <ul>
   * <li> <code>binaryName</code> implements ValueProxy</li>
   * <li><code>binaryName</code> has a {@link ProxyFor} or {@link ProxyForName}
   * annotation</li>
   * <li>All property methods in the EntityProxy can be mapped onto an
   * equivalent domain method (unless validation is skipped for the method)</li>
   * <li>All referenced proxy types are valid</li>
   * </ul>
   * 
   * @param binaryName the binary name (e.g. {@link Class#getName()}) of the
   *          EntityProxy subtype
   */
  public void validateValueProxy(String binaryName) {
    validateProxy(binaryName, valueProxyIntf, false);
  }

  /**
   * Given the binary name of a domain type, return the BaseProxy type that is
   * assignable to {@code clientType}. This method allows multiple proxy types
   * to be assigned to a domain type for use in different contexts (e.g. API
   * slices). If there are multiple client types mapped to
   * {@code domainTypeBinaryName} and assignable to {@code clientTypeBinaryName}
   * , the first matching type will be returned.
   */
  String getEntityProxyTypeName(String domainTypeBinaryName,
      String clientTypeBinaryName) {
    Type key = Type.getObjectType(BinaryName.toInternalName(domainTypeBinaryName));
    List<Type> found = domainToClientType.get(key);

    /*
     * If nothing was found look for proxyable supertypes the domain object can
     * be upcast to.
     */
    if (found == null || found.isEmpty()) {
      List<Type> types = getSupertypes(parentLogger, key);
      for (Type type : types) {
        if (objectType.equals(type)) {
          break;
        }

        found = domainToClientType.get(type);
        if (found != null && !found.isEmpty()) {
          break;
        }
      }
    }

    if (found == null || found.isEmpty()) {
      return null;
    }

    Type typeToReturn = null;

    // Common case
    if (found.size() == 1) {
      typeToReturn = found.get(0);
    } else {
      // Search for the first assignable type
      Type assignableTo = Type.getObjectType(BinaryName.toInternalName(clientTypeBinaryName));
      for (Type t : found) {
        if (isAssignable(parentLogger, assignableTo, t)) {
          typeToReturn = t;
          break;
        }
      }
    }

    return typeToReturn == null ? null : typeToReturn.getClassName();
  }

  /**
   * Record the mapping of a domain type to a client type. Proxy types will be
   * added to {@link #domainToClientType}.
   */
  private void addToDomainMap(ErrorContext logger, Type domainType,
      Type clientType) {
    clientToDomainType.put(clientType, domainType);

    if (isAssignable(logger, baseProxyIntf, clientType)) {
      maybeCheckProxyType(logger, clientType);
      List<Type> list = domainToClientType.get(domainType);
      if (list == null) {
        list = new ArrayList<Type>();
        domainToClientType.put(domainType, list);
      }
      list.add(clientType);
    }
  }

  /**
   * Check that a given method RequestContext method declaration can be mapped
   * to the server's domain type.
   */
  private void checkClientMethodInDomain(ErrorContext logger, RFMethod method,
      Type domainServiceType, boolean requireStaticMethodsForRequestType) {
    logger = logger.setMethod(method);

    // Create a "translated" method declaration to search for
    // Request<BlahProxy> foo(int a, BarProxy bar) -> Blah foo(int a, Bar bar);
    Type returnType = getReturnType(logger, method);
    Method searchFor = createDomainMethod(logger, new Method(method.getName(),
        returnType, method.getArgumentTypes()));

    RFMethod found = findCompatibleServiceMethod(logger, domainServiceType,
        searchFor, !method.isValidationSkipped());

    if (found != null) {
      boolean isInstance = isAssignable(logger, instanceRequestIntf,
          method.getReturnType());
      if (isInstance && found.isDeclaredStatic()) {
        logger.poison("The method %s is declared to return %s, but the"
            + " service method is static", method.getName(),
            InstanceRequest.class.getCanonicalName());
      } else if (requireStaticMethodsForRequestType && !isInstance
          && !found.isDeclaredStatic()) {
        logger.poison("The method %s is declared to return %s, but the"
            + " service method is not static", method.getName(),
            Request.class.getCanonicalName());
      }
    }
  }

  /**
   * Check that the domain object has <code>getId()</code> and
   * <code>getVersion</code> methods.
   */
  private void checkIdAndVersion(ErrorContext logger, Type domainType) {
    if (objectType.equals(domainType)) {
      return;
    }
    logger = logger.setType(domainType);
    String findMethodName = "find"
        + BinaryName.getShortClassName(domainType.getClassName());
    Type keyType = null;
    RFMethod findMethod = null;

    boolean foundFind = false;
    boolean foundId = false;
    boolean foundVersion = false;
    for (RFMethod method : getMethodsInHierarchy(logger, domainType)) {
      if ("getId".equals(method.getName())
          && method.getArgumentTypes().length == 0) {
        foundId = true;
        keyType = method.getReturnType();
        if (!isResolvedKeyType(logger, keyType)) {
          unresolvedKeyTypes.put(domainType, keyType);
        }
      } else if ("getVersion".equals(method.getName())
          && method.getArgumentTypes().length == 0) {
        foundVersion = true;
        if (!isResolvedKeyType(logger, method.getReturnType())) {
          unresolvedKeyTypes.put(domainType, method.getReturnType());
        }
      } else if (findMethodName.equals(method.getName())
          && method.getArgumentTypes().length == 1) {
        foundFind = true;
        findMethod = method;
      }
      if (foundFind && foundId && foundVersion) {
        break;
      }
    }
    if (!foundId) {
      logger.poison("There is no getId() method in type %s", print(domainType));
    }
    if (!foundVersion) {
      logger.poison("There is no getVersion() method in type %s",
          print(domainType));
    }

    if (foundFind) {
      if (keyType != null
          && !isAssignable(logger, findMethod.getArgumentTypes()[0], keyType)) {
        logger.poison("The key type returned by %s getId()"
            + " cannot be used as the argument to %s(%s)", print(keyType),
            findMethod.getName(), print(findMethod.getArgumentTypes()[0]));
      }
    } else {
      logger.poison("There is no %s method in type %s that returns %2$s",
          findMethodName, print(domainType));
    }
  }

  /**
   * Ensure that the given property method on an EntityProxy exists on the
   * domain object.
   */
  private void checkPropertyMethod(ErrorContext logger,
      RFMethod clientPropertyMethod, Type domainType) {
    logger = logger.setMethod(clientPropertyMethod);

    findCompatiblePropertyMethod(logger, domainType,
        createDomainMethod(logger, clientPropertyMethod),
        !clientPropertyMethod.isValidationSkipped());
  }

  private void checkUnresolvedKeyTypes(ErrorContext logger) {
    unresolvedKeyTypes.values().removeAll(domainToClientType.keySet());
    if (unresolvedKeyTypes.isEmpty()) {
      return;
    }

    for (Map.Entry<Type, Type> type : unresolvedKeyTypes.entrySet()) {
      logger.setType(type.getKey()).poison(
          "The domain type %s uses  a non-simple key type (%s)"
              + " in its getId() or getVersion() method that"
              + " does not have a proxy mapping.", print(type.getKey()),
          print(type.getValue()));
    }
  }

  /**
   * Convert a method declaration using client types (e.g. FooProxy) to domain
   * types (e.g. Foo).
   */
  private Method createDomainMethod(ErrorContext logger, Method clientMethod) {
    Type[] args = clientMethod.getArgumentTypes();
    for (int i = 0, j = args.length; i < j; i++) {
      args[i] = getDomainType(logger, args[i]);
    }
    Type returnType = getDomainType(logger, clientMethod.getReturnType());
    return new Method(clientMethod.getName(), returnType, args);
  }

  /**
   * Common checks to quickly determine if a type needs to be checked.
   */
  private boolean fastFail(String binaryName) {
    if (!Name.isBinaryName(binaryName)) {
      parentLogger.poison("%s is not a binary name", binaryName);
      return true;
    }

    // Allow the poisoned flag to be reset without losing data
    if (badTypes.contains(binaryName)) {
      parentLogger.poison("Type type %s was previously marked as bad",
          binaryName);
      return true;
    }

    // Don't revalidate the same type
    if (!validatedTypes.add(binaryName)) {
      return true;
    }
    return false;
  }

  /**
   * Finds a compatible method declaration in <code>domainType</code>'s
   * hierarchy that is assignment-compatible with the given Method.
   */
  private RFMethod findCompatibleMethod(final ErrorContext logger,
      Type domainType, Method searchFor, boolean mustFind,
      boolean allowOverloads, boolean boxReturnTypes) {
    String methodName = searchFor.getName();
    Type[] clientArgs = searchFor.getArgumentTypes();
    Type clientReturnType = searchFor.getReturnType();
    if (boxReturnTypes) {
      clientReturnType = maybeBoxType(clientReturnType);
    }
    // Pull all methods out of the domain type
    Map<String, List<RFMethod>> domainLookup = new LinkedHashMap<String, List<RFMethod>>();
    for (RFMethod method : getMethodsInHierarchy(logger, domainType)) {
      List<RFMethod> list = domainLookup.get(method.getName());
      if (list == null) {
        list = new ArrayList<RFMethod>();
        domainLookup.put(method.getName(), list);
      }
      list.add(method);
    }

    // Find the matching method in the domain object
    List<RFMethod> methods = domainLookup.get(methodName);
    if (methods == null) {
      if (mustFind) {
        logger.poison("Could not find any methods named %s in %s", methodName,
            print(domainType));
      }
      return null;
    }
    if (methods.size() > 1 && !allowOverloads) {
      StringBuilder sb = new StringBuilder();
      sb.append(String.format("Method overloads found in type %s named %s:\n",
          print(domainType), methodName));
      for (RFMethod method : methods) {
        sb.append("  ").append(print(method)).append("\n");
      }
      logger.poison(sb.toString());
      return null;
    }

    // Check each overloaded name
    for (RFMethod domainMethod : methods) {
      Type[] domainArgs = domainMethod.getArgumentTypes();
      Type domainReturnType = domainMethod.getReturnType();
      if (boxReturnTypes) {
        /*
         * When looking for the implementation of a Request<Integer>, we want to
         * match either int or Integer, so we'll box the domain method's return
         * type.
         */
        domainReturnType = maybeBoxType(domainReturnType);
      }

      /*
       * Make sure the client args can be passed into the domain args and the
       * domain return type into the client return type.
       */
      if (isAssignable(logger, domainArgs, clientArgs)
          && isAssignable(logger, clientReturnType, domainReturnType)) {

        logger.spam("Mapped client method " + print(searchFor) + " to "
            + print(domainMethod));
        return domainMethod;
      }
    }
    if (mustFind) {
      logger.poison(messageCouldNotFindMethod(domainType, methods));
    }
    return null;
  }

  /**
   * Finds a compatible method declaration in <code>domainType</code>'s
   * hierarchy that is assignment-compatible with the given Method.
   */
  private RFMethod findCompatiblePropertyMethod(final ErrorContext logger,
      Type domainType, Method searchFor, boolean mustFind) {
    return findCompatibleMethod(logger, domainType, searchFor, mustFind, false,
        false);
  }

  /**
   * Finds a compatible method declaration in <code>domainType</code>'s
   * hierarchy that is assignment-compatible with the given Method.
   */
  private RFMethod findCompatibleServiceMethod(final ErrorContext logger,
      Type domainType, Method searchFor, boolean mustFind) {
    return findCompatibleMethod(logger, domainType, searchFor, mustFind, false,
        true);
  }

  /**
   * This looks like it should be a utility method somewhere else, but I can't
   * find it.
   */
  private Type getBoxedType(Type primitive) {
    switch (primitive.getSort()) {
      case Type.BOOLEAN:
        return Type.getType(Boolean.class);
      case Type.BYTE:
        return Type.getType(Byte.class);
      case Type.CHAR:
        return Type.getType(Character.class);
      case Type.DOUBLE:
        return Type.getType(Double.class);
      case Type.FLOAT:
        return Type.getType(Float.class);
      case Type.INT:
        return Type.getType(Integer.class);
      case Type.LONG:
        return Type.getType(Long.class);
      case Type.SHORT:
        return Type.getType(Short.class);
      case Type.VOID:
        return Type.getType(Void.class);
    }
    throw new RuntimeException(primitive.getDescriptor()
        + " is not a primitive type");
  }

  /**
   * Convert the type used in a client-side EntityProxy or RequestContext
   * declaration to the equivalent domain type. Value types and supported
   * collections are a pass-through. EntityProxy types will be resolved to their
   * domain object type. RequestContext types will be resolved to their service
   * object.
   */
  private Type getDomainType(ErrorContext logger, Type clientType) {
    Type domainType = clientToDomainType.get(clientType);
    if (domainType != null) {
      return domainType;
    }
    if (isValueType(logger, clientType) || isCollectionType(logger, clientType)) {
      domainType = clientType;
    } else if (entityProxyIntf.equals(clientType)
        || valueProxyIntf.equals(clientType)) {
      domainType = objectType;
    } else {
      logger = logger.setType(clientType);
      DomainMapper pv = new DomainMapper(logger);
      visit(logger, clientType.getInternalName(), pv);
      if (pv.getDomainInternalName() == null) {
        logger.poison("%s has no mapping to a domain type (e.g. @%s or @%s)",
            print(clientType), ProxyFor.class.getSimpleName(),
            Service.class.getSimpleName());
        domainType = errorType;
      } else {
        domainType = Type.getObjectType(pv.getDomainInternalName());
      }
      if (pv.getLocatorInternalName() != null) {
        Type locatorType = Type.getObjectType(pv.getLocatorInternalName());
        clientToLocatorMap.put(clientType, locatorType);
      }
    }
    addToDomainMap(logger, domainType, clientType);
    maybeCheckProxyType(logger, clientType);
    return domainType;
  }

  /**
   * Collect all of the methods defined within a type hierarchy.
   */
  private Set<RFMethod> getMethodsInHierarchy(ErrorContext logger,
      Type domainType) {
    Set<RFMethod> toReturn = methodsInHierarchy.get(domainType);
    if (toReturn == null) {
      logger = logger.setType(domainType);
      toReturn = new MethodsInHierarchyCollector(logger).exec(domainType.getInternalName());
      methodsInHierarchy.put(domainType, Collections.unmodifiableSet(toReturn));
    }
    return toReturn;
  }

  /**
   * Examines a generic RequestContext method declaration and determines the
   * expected domain return type. This implementation is limited in that it will
   * not attempt to resolve type bounds since that would essentially require
   * implementing TypeOracle. In the case where the type bound cannot be
   * resolved, this method will return Object's type.
   */
  private Type getReturnType(ErrorContext logger, RFMethod method) {
    logger = logger.setMethod(method);
    final String[] returnType = {objectType.getInternalName()};
    String signature = method.getSignature();

    final int expectedCount;
    if (method.getReturnType().equals(instanceRequestIntf)) {
      expectedCount = 2;
    } else if (method.getReturnType().equals(requestIntf)) {
      expectedCount = 1;
    } else {
      logger.spam("Punting on " + signature);
      return Type.getObjectType(returnType[0]);
    }

    // TODO(bobv): If a class-based TypeOracle is built, use that instead
    new SignatureReader(signature).accept(new SignatureAdapter() {
      @Override
      public SignatureVisitor visitReturnType() {
        return new SignatureAdapter() {
          int count;

          @Override
          public SignatureVisitor visitTypeArgument(char wildcard) {
            if (++count == expectedCount) {
              return new SignatureAdapter() {
                @Override
                public void visitClassType(String name) {
                  returnType[0] = name;
                }
              };
            }
            return super.visitTypeArgument(wildcard);
          }
        };
      }
    });

    logger.spam("Extracted " + returnType[0]);
    return Type.getObjectType(returnType[0]);
  }

  private List<Type> getSupertypes(ErrorContext logger, Type type) {
    if (type.getSort() != Type.OBJECT) {
      return Collections.emptyList();
    }
    List<Type> toReturn = supertypes.get(type);
    if (toReturn != null) {
      return toReturn;
    }

    logger = logger.setType(type);

    toReturn = new SupertypeCollector(logger).exec(type);
    supertypes.put(type, Collections.unmodifiableList(toReturn));
    return toReturn;
  }

  private boolean isAssignable(ErrorContext logger, Type possibleSupertype,
      Type possibleSubtype) {
    // Fast-path for same type
    if (possibleSupertype.equals(possibleSubtype)) {
      return true;
    }

    // Supertype calculation is cached
    List<Type> allSupertypes = getSupertypes(logger, possibleSubtype);
    return allSupertypes.contains(possibleSupertype);
  }

  private boolean isAssignable(ErrorContext logger, Type[] possibleSupertypes,
      Type[] possibleSubtypes) {
    // Check the same number of types
    if (possibleSupertypes.length != possibleSubtypes.length) {
      return false;
    }
    for (int i = 0, j = possibleSupertypes.length; i < j; i++) {
      if (!isAssignable(logger, possibleSupertypes[i], possibleSubtypes[i])) {
        return false;
      }
    }
    return true;
  }

  private boolean isCollectionType(
      @SuppressWarnings("unused") ErrorContext logger, Type type) {
    // keeping the logger arg just for internal consistency for our small minds
    return "java/util/List".equals(type.getInternalName())
        || "java/util/Set".equals(type.getInternalName());
  }

  /**
   * Keep in sync with {@code ReflectiveServiceLayer.isKeyType()}.
   */
  private boolean isResolvedKeyType(ErrorContext logger, Type type) {
    if (isValueType(logger, type)) {
      return true;
    }

    // We have already seen a mapping for the key type
    if (domainToClientType.containsKey(type)) {
      return true;
    }

    return false;
  }

  private boolean isValueType(ErrorContext logger, Type type) {
    if (type.getSort() != Type.OBJECT) {
      return true;
    }
    if (valueTypes.contains(type)) {
      return true;
    }
    logger = logger.setType(type);
    if (isAssignable(logger, enumType, type)) {
      return true;
    }
    return false;
  }

  private Type maybeBoxType(Type maybePrimitive) {
    if (maybePrimitive.getSort() == Type.OBJECT) {
      return maybePrimitive;
    }
    return getBoxedType(maybePrimitive);
  }

  /**
   * Examine an array of Types and call {@link #validateEntityProxy(String)} or
   * {@link #validateValueProxy(String)} if the type is a proxy.
   */
  private void maybeCheckProxyType(ErrorContext logger, Type... types) {
    for (Type type : types) {
      if (isAssignable(logger, entityProxyIntf, type)) {
        validateEntityProxy(type.getClassName());
      } else if (isAssignable(logger, valueProxyIntf, type)) {
        validateValueProxy(type.getClassName());
      } else if (isAssignable(logger, baseProxyIntf, type)) {
        logger.poison(
            "Invalid type hierarchy for %s. Only types derived from %s or %s may be used.",
            print(type), print(entityProxyIntf), print(valueProxyIntf));
      }
    }
  }

  /**
   * Examine the arguments and return value of a method and check any
   * EntityProxies referred.
   */
  private void maybeCheckReferredProxies(ErrorContext logger, RFMethod method) {
    if (method.getSignature() != null) {
      TypesInSignatureCollector collector = new TypesInSignatureCollector();
      SignatureReader reader = new SignatureReader(method.getSignature());
      reader.accept(collector);
      maybeCheckProxyType(logger, collector.getFound());
    } else {
      Type[] argTypes = method.getArgumentTypes();
      Type returnType = getReturnType(logger, method);

      // Check EntityProxy args ond return types against the domain
      maybeCheckProxyType(logger, argTypes);
      maybeCheckProxyType(logger, returnType);
    }
  }

  private void validateProxy(String binaryName, Type expectedType,
      boolean requireId) {
    if (fastFail(binaryName)) {
      return;
    }

    Type proxyType = Type.getObjectType(BinaryName.toInternalName(binaryName));
    ErrorContext logger = parentLogger.setType(proxyType);

    // Quick sanity check for calling code
    if (!isAssignable(logger, expectedType, proxyType)) {
      parentLogger.poison("%s is not a %s", print(proxyType),
          print(expectedType));
      return;
    }

    // Find the domain type
    Type domainType = getDomainType(logger, proxyType);
    if (domainType == errorType) {
      logger.poison(
          "The type %s must be annotated with a @%s or @%s annotation",
          BinaryName.toSourceName(binaryName), ProxyFor.class.getSimpleName(),
          ProxyForName.class.getSimpleName());
      return;
    }

    // Check for getId() and getVersion() in domain if no locator is specified
    if (requireId) {
      Type locatorType = clientToLocatorMap.get(proxyType);
      if (locatorType == null) {
        checkIdAndVersion(logger, domainType);
      }
    }

    // Collect all methods in the client proxy type
    Set<RFMethod> clientPropertyMethods = getMethodsInHierarchy(logger,
        proxyType);

    // Find the equivalent domain getter/setter method
    for (RFMethod clientPropertyMethod : clientPropertyMethods) {
      // Ignore stableId(). Can't use descriptor due to overrides
      if ("stableId".equals(clientPropertyMethod.getName())
          && clientPropertyMethod.getArgumentTypes().length == 0) {
        continue;
      }
      checkPropertyMethod(logger, clientPropertyMethod, domainType);
      maybeCheckReferredProxies(logger, clientPropertyMethod);
    }
  }

  /**
   * Load the classfile for the given binary name and apply the provided
   * visitor.
   * 
   * @return <code>true</code> if the visitor was successfully visited
   */
  private boolean visit(ErrorContext logger, String internalName,
      ClassVisitor visitor) {
    assert Name.isInternalName(internalName) : "internalName";
    logger.spam("Visiting " + internalName);
    InputStream inputStream = null;
    try {
      inputStream = loader.getResourceAsStream(internalName + ".class");
      if (inputStream == null) {
        logger.poison("Could not find class file for " + internalName);
        return false;
      }
      ClassReader reader = new ClassReader(inputStream);
      reader.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG
          | ClassReader.SKIP_FRAMES);
      return true;
    } catch (IOException e) {
      logger.poison("Unable to open " + internalName, e);
    } finally {
      if (inputStream != null) {
        try {
          inputStream.close();
        } catch (IOException ignored) {
        }
      }
    }
    return false;
  }
}
