/**
 * Copyright (C) 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.inject.spi;

import static com.google.inject.internal.MoreTypes.getRawType;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.inject.ConfigurationException;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.Annotations;
import com.google.inject.internal.Errors;
import com.google.inject.internal.ErrorsException;
import com.google.inject.internal.Nullability;
import com.google.inject.internal.util.Classes;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * A constructor, field or method that can receive injections. Typically this is a member with the
 * {@literal @}{@link Inject} annotation. For non-private, no argument constructors, the member may
 * omit the annotation.
 *
 * @author crazybob@google.com (Bob Lee)
 * @since 2.0
 */
public final class InjectionPoint {
  
  private static final Logger logger = Logger.getLogger(InjectionPoint.class.getName());

  private final boolean optional;
  private final Member member;
  private final TypeLiteral<?> declaringType;
  private final ImmutableList<Dependency<?>> dependencies;

  InjectionPoint(TypeLiteral<?> declaringType, Method method, boolean optional) {
    this.member = method;
    this.declaringType = declaringType;
    this.optional = optional;
    this.dependencies = forMember(method, declaringType, method.getParameterAnnotations());
  }

  InjectionPoint(TypeLiteral<?> declaringType, Constructor<?> constructor) {
    this.member = constructor;
    this.declaringType = declaringType;
    this.optional = false;
    this.dependencies = forMember(
        constructor, declaringType, constructor.getParameterAnnotations());
  }

  InjectionPoint(TypeLiteral<?> declaringType, Field field, boolean optional) {
    this.member = field;
    this.declaringType = declaringType;
    this.optional = optional;

    Annotation[] annotations = field.getAnnotations();

    Errors errors = new Errors(field);
    Key<?> key = null;
    try {
      key = Annotations.getKey(declaringType.getFieldType(field), field, annotations, errors);
    } catch (ConfigurationException e) {
      errors.merge(e.getErrorMessages());
    } catch (ErrorsException e) {
      errors.merge(e.getErrors());
    }
    errors.throwConfigurationExceptionIfErrorsExist();

    this.dependencies = ImmutableList.<Dependency<?>>of(
        newDependency(key, Nullability.allowsNull(annotations), -1));
  }

  private ImmutableList<Dependency<?>> forMember(Member member, TypeLiteral<?> type,
      Annotation[][] paramterAnnotations) {
    Errors errors = new Errors(member);
    Iterator<Annotation[]> annotationsIterator = Arrays.asList(paramterAnnotations).iterator();

    List<Dependency<?>> dependencies = Lists.newArrayList();
    int index = 0;

    for (TypeLiteral<?> parameterType : type.getParameterTypes(member)) {
      try {
        Annotation[] parameterAnnotations = annotationsIterator.next();
        Key<?> key = Annotations.getKey(parameterType, member, parameterAnnotations, errors);
        dependencies.add(newDependency(key, Nullability.allowsNull(parameterAnnotations), index));
        index++;
      } catch (ConfigurationException e) {
        errors.merge(e.getErrorMessages());
      } catch (ErrorsException e) {
        errors.merge(e.getErrors());
      }
    }

    errors.throwConfigurationExceptionIfErrorsExist();
    return ImmutableList.copyOf(dependencies);
  }

  // This metohd is necessary to create a Dependency<T> with proper generic type information
  private <T> Dependency<T> newDependency(Key<T> key, boolean allowsNull, int parameterIndex) {
    return new Dependency<T>(this, key, allowsNull, parameterIndex);
  }

  /**
   * Returns the injected constructor, field, or method.
   */
  public Member getMember() {
    // TODO: Don't expose the original member (which probably has setAccessible(true)).
    return member;
  }

  /**
   * Returns the dependencies for this injection point. If the injection point is for a method or
   * constructor, the dependencies will correspond to that member's parameters. Field injection
   * points always have a single dependency for the field itself.
   *
   * @return a possibly-empty list
   */
  public List<Dependency<?>> getDependencies() {
    return dependencies;
  }

  /**
   * Returns true if this injection point shall be skipped if the injector cannot resolve bindings
   * for all required dependencies. Both explicit bindings (as specified in a module), and implicit
   * bindings ({@literal @}{@link com.google.inject.ImplementedBy ImplementedBy}, default
   * constructors etc.) may be used to satisfy optional injection points.
   */
  public boolean isOptional() {
    return optional;
  }
  
  /**
   * Returns true if the element is annotated with {@literal @}{@link Toolable}.
   * 
   * @since 3.0
   */
  public boolean isToolable() {
    return ((AnnotatedElement)member).isAnnotationPresent(Toolable.class);
  }

  /**
   * Returns the generic type that defines this injection point. If the member exists on a
   * parameterized type, the result will include more type information than the member's {@link
   * Member#getDeclaringClass() raw declaring class}.
   * 
   * @since 3.0
   */
  public TypeLiteral<?> getDeclaringType() {
    return declaringType;
  }

  @Override public boolean equals(Object o) {
    return o instanceof InjectionPoint
        && member.equals(((InjectionPoint) o).member)
        && declaringType.equals(((InjectionPoint) o).declaringType);
  }

  @Override public int hashCode() {
    return member.hashCode() ^ declaringType.hashCode();
  }

  @Override public String toString() {
    return Classes.toString(member);
  }

  /**
   * Returns a new injection point for the specified constructor. If the declaring type of {@code
   * constructor} is parameterized (such as {@code List<T>}), prefer the overload that includes a
   * type literal.
   *
   * @param constructor any single constructor present on {@code type}.
   * 
   * @since 3.0
   */
  public static <T> InjectionPoint forConstructor(Constructor<T> constructor) {
    return new InjectionPoint(TypeLiteral.get(constructor.getDeclaringClass()), constructor);
  }

  /**
   * Returns a new injection point for the specified constructor of {@code type}.
   *
   * @param constructor any single constructor present on {@code type}.
   * @param type the concrete type that defines {@code constructor}.
   * 
   * @since 3.0
   */
  public static <T> InjectionPoint forConstructor(
      Constructor<T> constructor, TypeLiteral<? extends T> type) {
    if (type.getRawType() != constructor.getDeclaringClass()) {
      new Errors(type)
          .constructorNotDefinedByType(constructor, type)
          .throwConfigurationExceptionIfErrorsExist();
    }

    return new InjectionPoint(type, constructor);
  }

  /**
   * Returns a new injection point for the injectable constructor of {@code type}.
   *
   * @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
   *     or a no-arguments constructor that is not private.
   * @throws ConfigurationException if there is no injectable constructor, more than one injectable
   *     constructor, or if parameters of the injectable constructor are malformed, such as a
   *     parameter with multiple binding annotations.
   */
  public static InjectionPoint forConstructorOf(TypeLiteral<?> type) {
    Class<?> rawType = getRawType(type.getType());
    Errors errors = new Errors(rawType);

    Constructor<?> injectableConstructor = null;
    for (Constructor<?> constructor : rawType.getDeclaredConstructors()) {

      boolean optional;
      Inject guiceInject = constructor.getAnnotation(Inject.class);
      if (guiceInject == null) {
        javax.inject.Inject javaxInject = constructor.getAnnotation(javax.inject.Inject.class);
        if (javaxInject == null) {
          continue;
        }
        optional = false;
      } else {
        optional = guiceInject.optional();
      }

      if (optional) {
        errors.optionalConstructor(constructor);
      }

      if (injectableConstructor != null) {
        errors.tooManyConstructors(rawType);
      }

      injectableConstructor = constructor;
      checkForMisplacedBindingAnnotations(injectableConstructor, errors);
    }

    errors.throwConfigurationExceptionIfErrorsExist();

    if (injectableConstructor != null) {
      return new InjectionPoint(type, injectableConstructor);
    }

    // If no annotated constructor is found, look for a no-arg constructor instead.
    try {
      Constructor<?> noArgConstructor = rawType.getDeclaredConstructor();

      // Disallow private constructors on non-private classes (unless they have @Inject)
      if (Modifier.isPrivate(noArgConstructor.getModifiers())
          && !Modifier.isPrivate(rawType.getModifiers())) {
        errors.missingConstructor(rawType);
        throw new ConfigurationException(errors.getMessages());
      }

      checkForMisplacedBindingAnnotations(noArgConstructor, errors);
      return new InjectionPoint(type, noArgConstructor);
    } catch (NoSuchMethodException e) {
      errors.missingConstructor(rawType);
      throw new ConfigurationException(errors.getMessages());
    }
  }

  /**
   * Returns a new injection point for the injectable constructor of {@code type}.
   *
   * @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
   *     or a no-arguments constructor that is not private.
   * @throws ConfigurationException if there is no injectable constructor, more than one injectable
   *     constructor, or if parameters of the injectable constructor are malformed, such as a
   *     parameter with multiple binding annotations.
   */
  public static InjectionPoint forConstructorOf(Class<?> type) {
    return forConstructorOf(TypeLiteral.get(type));
  }

  /**
   * Returns all static method and field injection points on {@code type}.
   *
   * @return a possibly empty set of injection points. The set has a specified iteration order. All
   *      fields are returned and then all methods. Within the fields, supertype fields are returned
   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
   * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
   *      a field with multiple binding annotations. The exception's {@link
   *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
   *      of the valid injection points.
   */
  public static Set<InjectionPoint> forStaticMethodsAndFields(TypeLiteral<?> type) {
    Errors errors = new Errors();
    
    Set<InjectionPoint> result;
    
    if (type.getRawType().isInterface()) {
      errors.staticInjectionOnInterface(type.getRawType());
      result = null;
    } else {
      result = getInjectionPoints(type, true, errors);
    }
    
    if (errors.hasErrors()) {
      throw new ConfigurationException(errors.getMessages()).withPartialValue(result);
    }
    return result;
  }

  /**
   * Returns all static method and field injection points on {@code type}.
   *
   * @return a possibly empty set of injection points. The set has a specified iteration order. All
   *      fields are returned and then all methods. Within the fields, supertype fields are returned
   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
   * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
   *      a field with multiple binding annotations. The exception's {@link
   *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
   *      of the valid injection points.
   */
  public static Set<InjectionPoint> forStaticMethodsAndFields(Class<?> type) {
    return forStaticMethodsAndFields(TypeLiteral.get(type));
  }

  /**
   * Returns all instance method and field injection points on {@code type}.
   *
   * @return a possibly empty set of injection points. The set has a specified iteration order. All
   *      fields are returned and then all methods. Within the fields, supertype fields are returned
   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
   * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
   *      a field with multiple binding annotations. The exception's {@link
   *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
   *      of the valid injection points.
   */
  public static Set<InjectionPoint> forInstanceMethodsAndFields(TypeLiteral<?> type) {
    Errors errors = new Errors();
    Set<InjectionPoint> result = getInjectionPoints(type, false, errors);
    if (errors.hasErrors()) {
      throw new ConfigurationException(errors.getMessages()).withPartialValue(result);
    }
    return result;
  }

  /**
   * Returns all instance method and field injection points on {@code type}.
   *
   * @return a possibly empty set of injection points. The set has a specified iteration order. All
   *      fields are returned and then all methods. Within the fields, supertype fields are returned
   *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
   * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
   *      a field with multiple binding annotations. The exception's {@link
   *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
   *      of the valid injection points.
   */
  public static Set<InjectionPoint> forInstanceMethodsAndFields(Class<?> type) {
    return forInstanceMethodsAndFields(TypeLiteral.get(type));
  }

  /**
   * Returns true if the binding annotation is in the wrong place.
   */
  private static boolean checkForMisplacedBindingAnnotations(Member member, Errors errors) {
    Annotation misplacedBindingAnnotation = Annotations.findBindingAnnotation(
        errors, member, ((AnnotatedElement) member).getAnnotations());
    if (misplacedBindingAnnotation == null) {
      return false;
    }

    // don't warn about misplaced binding annotations on methods when there's a field with the same
    // name. In Scala, fields always get accessor methods (that we need to ignore). See bug 242.
    if (member instanceof Method) {
      try {
        if (member.getDeclaringClass().getDeclaredField(member.getName()) != null) {
          return false;
        }
      } catch (NoSuchFieldException ignore) {
      }
    }

    errors.misplacedBindingAnnotation(member, misplacedBindingAnnotation);
    return true;
  }

  /**
   * Node in the doubly-linked list of injectable members (fields and methods).
   */
  static abstract class InjectableMember {
    final TypeLiteral<?> declaringType;
    final boolean optional;
    final boolean jsr330;
    InjectableMember previous;
    InjectableMember next;

    InjectableMember(TypeLiteral<?> declaringType, Annotation atInject) {
      this.declaringType = declaringType;

      if (atInject.annotationType() == javax.inject.Inject.class) {
        optional = false;
        jsr330 = true;
        return;
      }

      jsr330 = false;
      optional = ((Inject) atInject).optional();
    }

    abstract InjectionPoint toInjectionPoint();
  }

  static class InjectableField extends InjectableMember {
    final Field field;
    InjectableField(TypeLiteral<?> declaringType, Field field,
        Annotation atInject) {
      super(declaringType, atInject);
      this.field = field;
    }

    @Override
    InjectionPoint toInjectionPoint() {
      return new InjectionPoint(declaringType, field, optional);
    }
  }

  static class InjectableMethod extends InjectableMember {
    final Method method;
    /**
     * true if this method overrode a method that was annotated
     * with com.google.inject.Inject.  used to allow different
     * override behavior for guice inject vs javax.inject.Inject
     */
    boolean overrodeGuiceInject;
    InjectableMethod(TypeLiteral<?> declaringType, Method method,
        Annotation atInject) {
      super(declaringType, atInject);
      this.method = method;
    }

    @Override
    InjectionPoint toInjectionPoint() {
      return new InjectionPoint(declaringType, method, optional);
    }

    public boolean isFinal() {
      return Modifier.isFinal(method.getModifiers());
    }
  }

  static Annotation getAtInject(AnnotatedElement member) {
    Annotation a = member.getAnnotation(javax.inject.Inject.class);
    return a == null ? member.getAnnotation(Inject.class) : a;
  }

  /**
   * Linked list of injectable members.
   */
  static class InjectableMembers {
    InjectableMember head;
    InjectableMember tail;

    void add(InjectableMember member) {
      if (head == null) {
        head = tail = member;
      } else {
        member.previous = tail;
        tail.next = member;
        tail = member;
      }
    }

    void remove(InjectableMember member) {
      if (member.previous != null) {
        member.previous.next = member.next;
      }
      if (member.next != null) {
        member.next.previous = member.previous;
      }
      if (head == member) {
        head = member.next;
      }
      if (tail == member) {
        tail = member.previous;
      }
    }

    boolean isEmpty() {
      return head == null;
    }
  }

  /** Position in type hierarchy. */
  enum Position {
    TOP, // No need to check for overridden methods
    MIDDLE,
    BOTTOM // Methods won't be overridden
  }

  /**
   * Keeps track of injectable methods so we can remove methods that get overridden in O(1) time.
   * Uses our position in the type hierarchy to perform optimizations.
   */
  static class OverrideIndex {
    final InjectableMembers injectableMembers;
    Map<Signature, List<InjectableMethod>> bySignature;
    Position position = Position.TOP;

    OverrideIndex(InjectableMembers injectableMembers) {
      this.injectableMembers = injectableMembers;
    }

    /* Caches the signature for the last method. */
    Method lastMethod;
    Signature lastSignature;

    /**
     * Removes a method overridden by the given method, if present. In order to
     * remain backwards compatible with prior Guice versions, this will *not*
     * remove overridden methods if 'alwaysRemove' is false and the overridden
     * signature was annotated with a com.google.inject.Inject.
     * 
     * @param method
     *          The method used to determine what is overridden and should be
     *          removed.
     * @param alwaysRemove
     *          true if overridden methods should be removed even if they were
     *          guice @Inject
     * @param injectableMethod
     *          if this method overrode any guice @Inject methods,
     *          {@link InjectableMethod#overrodeGuiceInject} is set to true
     */
    boolean removeIfOverriddenBy(Method method, boolean alwaysRemove, 
        InjectableMethod injectableMethod) {
      if (position == Position.TOP) {
        // If we're at the top of the hierarchy, there's nothing to override.
        return false;
      }

      if (bySignature == null) {
        // We encountered a method in a subclass. Time to index the
        // methods in the parent class.
        bySignature = new HashMap<Signature, List<InjectableMethod>>();
        for (InjectableMember member = injectableMembers.head; member != null;
            member = member.next) {
          if (!(member instanceof InjectableMethod)) continue;
          InjectableMethod im = (InjectableMethod) member;
          if (im.isFinal()) continue;
          List<InjectableMethod> methods = new ArrayList<InjectableMethod>();
          methods.add(im);
          bySignature.put(new Signature(im.method), methods);
        }
      }

      lastMethod = method;
      Signature signature = lastSignature = new Signature(method);
      List<InjectableMethod> methods = bySignature.get(signature);
      boolean removed = false;
      if (methods != null) {
        for (Iterator<InjectableMethod> iterator = methods.iterator();
            iterator.hasNext();) {
          InjectableMethod possiblyOverridden = iterator.next();
          if (overrides(method, possiblyOverridden.method)) {
            boolean wasGuiceInject =
              !possiblyOverridden.jsr330 || possiblyOverridden.overrodeGuiceInject;
            if(injectableMethod != null) {
              injectableMethod.overrodeGuiceInject = wasGuiceInject;
            }
            // Only actually remove the methods if we want to force
            // remove or if the signature never specified @com.google.inject.Inject
            // somewhere.
            if(alwaysRemove || !wasGuiceInject) {
              removed = true;
              iterator.remove();
              injectableMembers.remove(possiblyOverridden);
            }
          }
        }
      }
      return removed;
    }

    /**
     * Adds the given method to the list of injection points. Keeps track of it in this index
     * in case it gets overridden.
     */
    void add(InjectableMethod injectableMethod) {
      injectableMembers.add(injectableMethod);
      if (position == Position.BOTTOM
          || injectableMethod.isFinal()) {
        // This method can't be overridden, so there's no need to index it.
        return;
      }
      if (bySignature != null) {
        // Try to reuse the signature we created during removal
        Signature signature = injectableMethod.method == lastMethod
            ? lastSignature : new Signature(injectableMethod.method);
        List<InjectableMethod> methods = bySignature.get(signature);
        if (methods == null) {
          methods = new ArrayList<InjectableMethod>();
          bySignature.put(signature, methods);
        }
        methods.add(injectableMethod);
      }
    }
  }

  /**
   * Returns an ordered, immutable set of injection points for the given type. Members in
   * superclasses come before members in subclasses. Within a class, fields come before methods.
   * Overridden methods are filtered out.
   *
   * @param statics true is this method should return static members, false for instance members
   * @param errors used to record errors
   */
  private static Set<InjectionPoint> getInjectionPoints(final TypeLiteral<?> type,
      boolean statics, Errors errors) {
    InjectableMembers injectableMembers = new InjectableMembers();
    OverrideIndex overrideIndex = null;

    List<TypeLiteral<?>> hierarchy = hierarchyFor(type);
    int topIndex = hierarchy.size() - 1;
    for (int i = topIndex; i >= 0; i--) {
      if (overrideIndex != null && i < topIndex) {
        // Knowing the position within the hierarchy helps us make optimizations.
        if (i == 0) {
          overrideIndex.position = Position.BOTTOM;
        } else {
          overrideIndex.position = Position.MIDDLE;
        }
      }

      TypeLiteral<?> current = hierarchy.get(i);

      for (Field field : current.getRawType().getDeclaredFields()) {
        if (Modifier.isStatic(field.getModifiers()) == statics) {
          Annotation atInject = getAtInject(field);
          if (atInject != null) {
            InjectableField injectableField = new InjectableField(current, field, atInject);
            if (injectableField.jsr330 && Modifier.isFinal(field.getModifiers())) {
              errors.cannotInjectFinalField(field);
            }
            injectableMembers.add(injectableField);
          }
        }
      }

      for (Method method : current.getRawType().getDeclaredMethods()) {
        if (Modifier.isStatic(method.getModifiers()) == statics) {
          Annotation atInject = getAtInject(method);
          if (atInject != null) {
            InjectableMethod injectableMethod = new InjectableMethod(
                current, method, atInject);
            if (checkForMisplacedBindingAnnotations(method, errors)
                | !isValidMethod(injectableMethod, errors)) {
              if (overrideIndex != null) {
                boolean removed = overrideIndex.removeIfOverriddenBy(method, false, injectableMethod);
                if(removed) {
                  logger.log(Level.WARNING, "Method: {0} is not a valid injectable method ("
                      + "because it either has misplaced binding annotations "
                      + "or specifies type parameters) but is overriding a method that is valid. "
                      + "Because it is not valid, the method will not be injected. "
                      + "To fix this, make the method a valid injectable method.", method);
                }
              }
              continue;
            }
            if (statics) {
              injectableMembers.add(injectableMethod);
            } else {
              if (overrideIndex == null) {
                /*
                 * Creating the override index lazily means that the first type in the hierarchy
                 * with injectable methods (not necessarily the top most type) will be treated as
                 * the TOP position and will enjoy the same optimizations (no checks for overridden
                 * methods, etc.).
                 */
                overrideIndex = new OverrideIndex(injectableMembers);
              } else {
                // Forcibly remove the overriden method, otherwise we'll inject
                // it twice.
                overrideIndex.removeIfOverriddenBy(method, true, injectableMethod);
              }
              overrideIndex.add(injectableMethod);
            }
          } else {
            if(overrideIndex != null) {
              boolean removed = overrideIndex.removeIfOverriddenBy(method, false, null);
              if(removed) {
                logger.log(Level.WARNING, "Method: {0} is not annotated with @Inject but "
                    + "is overriding a method that is annotated with @javax.inject.Inject.  Because "
                    + "it is not annotated with @Inject, the method will not be injected. "
                    + "To fix this, annotate the method with @Inject.", method);
              }
            }
          }
        }
      }
    }

    if (injectableMembers.isEmpty()) {
      return Collections.emptySet();
    }

    ImmutableSet.Builder<InjectionPoint> builder = ImmutableSet.builder();
    for (InjectableMember im = injectableMembers.head; im != null;
        im = im.next) {
      try {
        builder.add(im.toInjectionPoint());
      } catch (ConfigurationException ignorable) {
        if (!im.optional) {
          errors.merge(ignorable.getErrorMessages());
        }
      }
    }
    return builder.build();
  }

  private static boolean isValidMethod(InjectableMethod injectableMethod,
      Errors errors) {
    boolean result = true;
    if (injectableMethod.jsr330) {
      Method method = injectableMethod.method;
      if (Modifier.isAbstract(method.getModifiers())) {
        errors.cannotInjectAbstractMethod(method);
        result = false;
      }
      if (method.getTypeParameters().length > 0) {
        errors.cannotInjectMethodWithTypeParameters(method);
        result = false;
      }
    }
    return result;
  }

  private static List<TypeLiteral<?>> hierarchyFor(TypeLiteral<?> type) {
    List<TypeLiteral<?>> hierarchy = new ArrayList<TypeLiteral<?>>();
    TypeLiteral<?> current = type;
    while (current.getRawType() != Object.class) {
      hierarchy.add(current);
      current = current.getSupertype(current.getRawType().getSuperclass());
    }
    return hierarchy;
  }

  /**
   * Returns true if a overrides b. Assumes signatures of a and b are the same and a's declaring
   * class is a subclass of b's declaring class.
   */
  private static boolean overrides(Method a, Method b) {
    // See JLS section 8.4.8.1
    int modifiers = b.getModifiers();
    if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) {
      return true;
    }
    if (Modifier.isPrivate(modifiers)) {
      return false;
    }
    // b must be package-private
    return a.getDeclaringClass().getPackage().equals(b.getDeclaringClass().getPackage());
  }

  /**
   * A method signature. Used to handle method overridding.
   */
  static class Signature {

    final String name;
    final Class[] parameterTypes;
    final int hash;

    Signature(Method method) {
      this.name = method.getName();
      this.parameterTypes = method.getParameterTypes();

      int h = name.hashCode();
      h = h * 31 + parameterTypes.length;
      for (Class parameterType : parameterTypes) {
        h = h * 31 + parameterType.hashCode();
      }
      this.hash = h;
    }

    @Override public int hashCode() {
      return this.hash;
    }

    @Override public boolean equals(Object o) {
      if (!(o instanceof Signature)) {
        return false;
      }

      Signature other = (Signature) o;
      if (!name.equals(other.name)) {
        return false;
      }

      if (parameterTypes.length != other.parameterTypes.length) {
        return false;
      }

      for (int i = 0; i < parameterTypes.length; i++) {
        if (parameterTypes[i] != other.parameterTypes[i]) {
          return false;
        }
      }

      return true;
    }
  }
}
