17dd252788645e940eada959bdde927426e2531c9Paul Duffin/*
27dd252788645e940eada959bdde927426e2531c9Paul Duffin * Copyright (C) 2011 The Guava Authors
37dd252788645e940eada959bdde927426e2531c9Paul Duffin *
47dd252788645e940eada959bdde927426e2531c9Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
57dd252788645e940eada959bdde927426e2531c9Paul Duffin * you may not use this file except in compliance with the License.
67dd252788645e940eada959bdde927426e2531c9Paul Duffin * You may obtain a copy of the License at
77dd252788645e940eada959bdde927426e2531c9Paul Duffin *
87dd252788645e940eada959bdde927426e2531c9Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
97dd252788645e940eada959bdde927426e2531c9Paul Duffin *
107dd252788645e940eada959bdde927426e2531c9Paul Duffin * Unless required by applicable law or agreed to in writing, software
117dd252788645e940eada959bdde927426e2531c9Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
127dd252788645e940eada959bdde927426e2531c9Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137dd252788645e940eada959bdde927426e2531c9Paul Duffin * See the License for the specific language governing permissions and
147dd252788645e940eada959bdde927426e2531c9Paul Duffin * limitations under the License.
157dd252788645e940eada959bdde927426e2531c9Paul Duffin */
167dd252788645e940eada959bdde927426e2531c9Paul Duffin
177dd252788645e940eada959bdde927426e2531c9Paul Duffinpackage com.google.common.reflect;
187dd252788645e940eada959bdde927426e2531c9Paul Duffin
197dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static com.google.common.base.Preconditions.checkArgument;
207dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull;
217dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static com.google.common.collect.Iterables.transform;
227dd252788645e940eada959bdde927426e2531c9Paul Duffin
237dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.annotations.VisibleForTesting;
247dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.base.Function;
257dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.base.Joiner;
267dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.base.Objects;
277dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.base.Predicates;
287dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.ImmutableList;
297dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.Iterables;
307dd252788645e940eada959bdde927426e2531c9Paul Duffin
317dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.io.Serializable;
327dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Array;
337dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.GenericArrayType;
347dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.GenericDeclaration;
357dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.ParameterizedType;
367dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Type;
377dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.TypeVariable;
387dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.WildcardType;
397dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Arrays;
407dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Collection;
410888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.concurrent.atomic.AtomicReference;
427dd252788645e940eada959bdde927426e2531c9Paul Duffin
437dd252788645e940eada959bdde927426e2531c9Paul Duffinimport javax.annotation.Nullable;
447dd252788645e940eada959bdde927426e2531c9Paul Duffin
457dd252788645e940eada959bdde927426e2531c9Paul Duffin/**
467dd252788645e940eada959bdde927426e2531c9Paul Duffin * Utilities for working with {@link Type}.
477dd252788645e940eada959bdde927426e2531c9Paul Duffin *
487dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Ben Yu
497dd252788645e940eada959bdde927426e2531c9Paul Duffin */
507dd252788645e940eada959bdde927426e2531c9Paul Duffinfinal class Types {
517dd252788645e940eada959bdde927426e2531c9Paul Duffin
527dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Class#toString without the "class " and "interface " prefixes */
530888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static final Function<Type, String> TYPE_TO_STRING =
540888a09821a98ac0680fad765217302858e70fa4Paul Duffin      new Function<Type, String>() {
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin        @Override public String apply(Type from) {
560888a09821a98ac0680fad765217302858e70fa4Paul Duffin          return Types.toString(from);
570888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
580888a09821a98ac0680fad765217302858e70fa4Paul Duffin      };
597dd252788645e940eada959bdde927426e2531c9Paul Duffin
607dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static final Joiner COMMA_JOINER = Joiner.on(", ").useForNull("null");
617dd252788645e940eada959bdde927426e2531c9Paul Duffin
627dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Returns the array type of {@code componentType}. */
637dd252788645e940eada959bdde927426e2531c9Paul Duffin  static Type newArrayType(Type componentType) {
647dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (componentType instanceof WildcardType) {
657dd252788645e940eada959bdde927426e2531c9Paul Duffin      WildcardType wildcard = (WildcardType) componentType;
667dd252788645e940eada959bdde927426e2531c9Paul Duffin      Type[] lowerBounds = wildcard.getLowerBounds();
677dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkArgument(lowerBounds.length <= 1, "Wildcard cannot have more than one lower bounds.");
687dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (lowerBounds.length == 1) {
697dd252788645e940eada959bdde927426e2531c9Paul Duffin        return supertypeOf(newArrayType(lowerBounds[0]));
707dd252788645e940eada959bdde927426e2531c9Paul Duffin      } else {
717dd252788645e940eada959bdde927426e2531c9Paul Duffin        Type[] upperBounds = wildcard.getUpperBounds();
727dd252788645e940eada959bdde927426e2531c9Paul Duffin        checkArgument(upperBounds.length == 1, "Wildcard should have only one upper bound.");
737dd252788645e940eada959bdde927426e2531c9Paul Duffin        return subtypeOf(newArrayType(upperBounds[0]));
747dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
757dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
767dd252788645e940eada959bdde927426e2531c9Paul Duffin    return JavaVersion.CURRENT.newArrayType(componentType);
777dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
787dd252788645e940eada959bdde927426e2531c9Paul Duffin
797dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
807dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Returns a type where {@code rawType} is parameterized by
817dd252788645e940eada959bdde927426e2531c9Paul Duffin   * {@code arguments} and is owned by {@code ownerType}.
827dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
830888a09821a98ac0680fad765217302858e70fa4Paul Duffin  static ParameterizedType newParameterizedTypeWithOwner(
840888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Nullable Type ownerType, Class<?> rawType, Type... arguments) {
857dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (ownerType == null) {
867dd252788645e940eada959bdde927426e2531c9Paul Duffin      return newParameterizedType(rawType, arguments);
877dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
887dd252788645e940eada959bdde927426e2531c9Paul Duffin    // ParameterizedTypeImpl constructor already checks, but we want to throw NPE before IAE
897dd252788645e940eada959bdde927426e2531c9Paul Duffin    checkNotNull(arguments);
907dd252788645e940eada959bdde927426e2531c9Paul Duffin    checkArgument(rawType.getEnclosingClass() != null, "Owner type for unenclosed %s", rawType);
917dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new ParameterizedTypeImpl(ownerType, rawType, arguments);
927dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
937dd252788645e940eada959bdde927426e2531c9Paul Duffin
947dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
957dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Returns a type where {@code rawType} is parameterized by
967dd252788645e940eada959bdde927426e2531c9Paul Duffin   * {@code arguments}.
977dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
987dd252788645e940eada959bdde927426e2531c9Paul Duffin  static ParameterizedType newParameterizedType(Class<?> rawType, Type... arguments) {
990888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return new ParameterizedTypeImpl(
1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin          ClassOwnership.JVM_BEHAVIOR.getOwnerType(rawType), rawType, arguments);
1017dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1027dd252788645e940eada959bdde927426e2531c9Paul Duffin
1037dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Decides what owner type to use for constructing {@link ParameterizedType} from a raw class. */
1047dd252788645e940eada959bdde927426e2531c9Paul Duffin  private enum ClassOwnership {
1057dd252788645e940eada959bdde927426e2531c9Paul Duffin
1067dd252788645e940eada959bdde927426e2531c9Paul Duffin    OWNED_BY_ENCLOSING_CLASS {
1077dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Nullable
1080888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override
1097dd252788645e940eada959bdde927426e2531c9Paul Duffin      Class<?> getOwnerType(Class<?> rawType) {
1107dd252788645e940eada959bdde927426e2531c9Paul Duffin        return rawType.getEnclosingClass();
1117dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
1127dd252788645e940eada959bdde927426e2531c9Paul Duffin    },
1137dd252788645e940eada959bdde927426e2531c9Paul Duffin    LOCAL_CLASS_HAS_NO_OWNER {
1147dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Nullable
1150888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override
1167dd252788645e940eada959bdde927426e2531c9Paul Duffin      Class<?> getOwnerType(Class<?> rawType) {
1177dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (rawType.isLocalClass()) {
1187dd252788645e940eada959bdde927426e2531c9Paul Duffin          return null;
1197dd252788645e940eada959bdde927426e2531c9Paul Duffin        } else {
1207dd252788645e940eada959bdde927426e2531c9Paul Duffin          return rawType.getEnclosingClass();
1217dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
1227dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
1237dd252788645e940eada959bdde927426e2531c9Paul Duffin    };
1247dd252788645e940eada959bdde927426e2531c9Paul Duffin
1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Nullable abstract Class<?> getOwnerType(Class<?> rawType);
1267dd252788645e940eada959bdde927426e2531c9Paul Duffin
1277dd252788645e940eada959bdde927426e2531c9Paul Duffin    static final ClassOwnership JVM_BEHAVIOR = detectJvmBehavior();
1287dd252788645e940eada959bdde927426e2531c9Paul Duffin
1297dd252788645e940eada959bdde927426e2531c9Paul Duffin    private static ClassOwnership detectJvmBehavior() {
1307dd252788645e940eada959bdde927426e2531c9Paul Duffin      class LocalClass<T> {}
1317dd252788645e940eada959bdde927426e2531c9Paul Duffin      Class<?> subclass = new LocalClass<String>() {}.getClass();
1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin      ParameterizedType parameterizedType = (ParameterizedType)
1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin          subclass.getGenericSuperclass();
1347dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (ClassOwnership behavior : ClassOwnership.values()) {
1357dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (behavior.getOwnerType(LocalClass.class) == parameterizedType.getOwnerType()) {
1367dd252788645e940eada959bdde927426e2531c9Paul Duffin          return behavior;
1377dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
1387dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
1397dd252788645e940eada959bdde927426e2531c9Paul Duffin      throw new AssertionError();
1407dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1417dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1427dd252788645e940eada959bdde927426e2531c9Paul Duffin
1437dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
1447dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Returns a new {@link TypeVariable} that belongs to {@code declaration} with
1457dd252788645e940eada959bdde927426e2531c9Paul Duffin   * {@code name} and {@code bounds}.
1467dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin  static <D extends GenericDeclaration> TypeVariable<D> newArtificialTypeVariable(
1480888a09821a98ac0680fad765217302858e70fa4Paul Duffin      D declaration, String name, Type... bounds) {
1490888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new TypeVariableImpl<D>(
1500888a09821a98ac0680fad765217302858e70fa4Paul Duffin        declaration,
1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin        name,
1520888a09821a98ac0680fad765217302858e70fa4Paul Duffin        (bounds.length == 0)
1530888a09821a98ac0680fad765217302858e70fa4Paul Duffin            ? new Type[] { Object.class }
1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin            : bounds);
1557dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1567dd252788645e940eada959bdde927426e2531c9Paul Duffin
1577dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Returns a new {@link WildcardType} with {@code upperBound}. */
1580888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @VisibleForTesting static WildcardType subtypeOf(Type upperBound) {
1597dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new WildcardTypeImpl(new Type[0], new Type[] { upperBound });
1607dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1617dd252788645e940eada959bdde927426e2531c9Paul Duffin
1627dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Returns a new {@link WildcardType} with {@code lowerBound}. */
1630888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @VisibleForTesting static WildcardType supertypeOf(Type lowerBound) {
1647dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new WildcardTypeImpl(new Type[] { lowerBound }, new Type[] { Object.class });
1657dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1667dd252788645e940eada959bdde927426e2531c9Paul Duffin
1677dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
1687dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Returns human readable string representation of {@code type}.
1697dd252788645e940eada959bdde927426e2531c9Paul Duffin   * <ul>
1707dd252788645e940eada959bdde927426e2531c9Paul Duffin   * <li> For array type {@code Foo[]}, {@code "com.mypackage.Foo[]"} are
1717dd252788645e940eada959bdde927426e2531c9Paul Duffin   * returned.
1727dd252788645e940eada959bdde927426e2531c9Paul Duffin   * <li> For any class, {@code theClass.getName()} are returned.
1737dd252788645e940eada959bdde927426e2531c9Paul Duffin   * <li> For all other types, {@code type.toString()} are returned.
1747dd252788645e940eada959bdde927426e2531c9Paul Duffin   * </ul>
1757dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
1767dd252788645e940eada959bdde927426e2531c9Paul Duffin  static String toString(Type type) {
1770888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return (type instanceof Class)
1780888a09821a98ac0680fad765217302858e70fa4Paul Duffin        ? ((Class<?>) type).getName()
1790888a09821a98ac0680fad765217302858e70fa4Paul Duffin        : type.toString();
1807dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1817dd252788645e940eada959bdde927426e2531c9Paul Duffin
1820888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Nullable static Type getComponentType(Type type) {
1837dd252788645e940eada959bdde927426e2531c9Paul Duffin    checkNotNull(type);
1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin    final AtomicReference<Type> result = new AtomicReference<Type>();
1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin    new TypeVisitor() {
1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override void visitTypeVariable(TypeVariable<?> t) {
1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin        result.set(subtypeOfComponentType(t.getBounds()));
1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1890888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override void visitWildcardType(WildcardType t) {
1900888a09821a98ac0680fad765217302858e70fa4Paul Duffin        result.set(subtypeOfComponentType(t.getUpperBounds()));
1910888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1920888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override void visitGenericArrayType(GenericArrayType t) {
1930888a09821a98ac0680fad765217302858e70fa4Paul Duffin        result.set(t.getGenericComponentType());
1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override void visitClass(Class<?> t) {
1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin        result.set(t.getComponentType());
1970888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }.visit(type);
1990888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return result.get();
2007dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2017dd252788645e940eada959bdde927426e2531c9Paul Duffin
2027dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
2037dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Returns {@code ? extends X} if any of {@code bounds} is a subtype of {@code X[]}; or null
2047dd252788645e940eada959bdde927426e2531c9Paul Duffin   * otherwise.
2057dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
2060888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Nullable private static Type subtypeOfComponentType(Type[] bounds) {
2077dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (Type bound : bounds) {
2087dd252788645e940eada959bdde927426e2531c9Paul Duffin      Type componentType = getComponentType(bound);
2097dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (componentType != null) {
2107dd252788645e940eada959bdde927426e2531c9Paul Duffin        // Only the first bound can be a class or array.
2117dd252788645e940eada959bdde927426e2531c9Paul Duffin        // Bounds after the first can only be interfaces.
2127dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (componentType instanceof Class) {
2137dd252788645e940eada959bdde927426e2531c9Paul Duffin          Class<?> componentClass = (Class<?>) componentType;
2147dd252788645e940eada959bdde927426e2531c9Paul Duffin          if (componentClass.isPrimitive()) {
2157dd252788645e940eada959bdde927426e2531c9Paul Duffin            return componentClass;
2167dd252788645e940eada959bdde927426e2531c9Paul Duffin          }
2177dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
2187dd252788645e940eada959bdde927426e2531c9Paul Duffin        return subtypeOf(componentType);
2197dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
2207dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2217dd252788645e940eada959bdde927426e2531c9Paul Duffin    return null;
2227dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2237dd252788645e940eada959bdde927426e2531c9Paul Duffin
2240888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static final class GenericArrayTypeImpl
2250888a09821a98ac0680fad765217302858e70fa4Paul Duffin      implements GenericArrayType, Serializable {
2267dd252788645e940eada959bdde927426e2531c9Paul Duffin
2277dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final Type componentType;
2287dd252788645e940eada959bdde927426e2531c9Paul Duffin
2297dd252788645e940eada959bdde927426e2531c9Paul Duffin    GenericArrayTypeImpl(Type componentType) {
2307dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.componentType = JavaVersion.CURRENT.usedInGenericType(componentType);
2317dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2327dd252788645e940eada959bdde927426e2531c9Paul Duffin
2330888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Type getGenericComponentType() {
2347dd252788645e940eada959bdde927426e2531c9Paul Duffin      return componentType;
2357dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2367dd252788645e940eada959bdde927426e2531c9Paul Duffin
2370888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public String toString() {
2387dd252788645e940eada959bdde927426e2531c9Paul Duffin      return Types.toString(componentType) + "[]";
2397dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2407dd252788645e940eada959bdde927426e2531c9Paul Duffin
2410888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public int hashCode() {
2427dd252788645e940eada959bdde927426e2531c9Paul Duffin      return componentType.hashCode();
2437dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2447dd252788645e940eada959bdde927426e2531c9Paul Duffin
2450888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public boolean equals(Object obj) {
2467dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (obj instanceof GenericArrayType) {
2477dd252788645e940eada959bdde927426e2531c9Paul Duffin        GenericArrayType that = (GenericArrayType) obj;
2480888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return Objects.equal(
2490888a09821a98ac0680fad765217302858e70fa4Paul Duffin            getGenericComponentType(), that.getGenericComponentType());
2507dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
2517dd252788645e940eada959bdde927426e2531c9Paul Duffin      return false;
2527dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2537dd252788645e940eada959bdde927426e2531c9Paul Duffin
2547dd252788645e940eada959bdde927426e2531c9Paul Duffin    private static final long serialVersionUID = 0;
2557dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2567dd252788645e940eada959bdde927426e2531c9Paul Duffin
2570888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static final class ParameterizedTypeImpl
2580888a09821a98ac0680fad765217302858e70fa4Paul Duffin      implements ParameterizedType, Serializable {
2597dd252788645e940eada959bdde927426e2531c9Paul Duffin
2607dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final Type ownerType;
2617dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final ImmutableList<Type> argumentsList;
2627dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final Class<?> rawType;
2637dd252788645e940eada959bdde927426e2531c9Paul Duffin
2640888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ParameterizedTypeImpl(
2650888a09821a98ac0680fad765217302858e70fa4Paul Duffin        @Nullable Type ownerType, Class<?> rawType, Type[] typeArguments) {
2667dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkNotNull(rawType);
2677dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkArgument(typeArguments.length == rawType.getTypeParameters().length);
2687dd252788645e940eada959bdde927426e2531c9Paul Duffin      disallowPrimitiveType(typeArguments, "type parameter");
2697dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.ownerType = ownerType;
2707dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.rawType = rawType;
2717dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.argumentsList = JavaVersion.CURRENT.usedInGenericType(typeArguments);
2727dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2737dd252788645e940eada959bdde927426e2531c9Paul Duffin
2740888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Type[] getActualTypeArguments() {
2757dd252788645e940eada959bdde927426e2531c9Paul Duffin      return toArray(argumentsList);
2767dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2777dd252788645e940eada959bdde927426e2531c9Paul Duffin
2780888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Type getRawType() {
2797dd252788645e940eada959bdde927426e2531c9Paul Duffin      return rawType;
2807dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2817dd252788645e940eada959bdde927426e2531c9Paul Duffin
2820888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Type getOwnerType() {
2837dd252788645e940eada959bdde927426e2531c9Paul Duffin      return ownerType;
2847dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2857dd252788645e940eada959bdde927426e2531c9Paul Duffin
2860888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public String toString() {
2877dd252788645e940eada959bdde927426e2531c9Paul Duffin      StringBuilder builder = new StringBuilder();
2887dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (ownerType != null) {
2897dd252788645e940eada959bdde927426e2531c9Paul Duffin        builder.append(Types.toString(ownerType)).append('.');
2907dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
2910888a09821a98ac0680fad765217302858e70fa4Paul Duffin      builder.append(rawType.getName())
2920888a09821a98ac0680fad765217302858e70fa4Paul Duffin          .append('<')
2930888a09821a98ac0680fad765217302858e70fa4Paul Duffin          .append(COMMA_JOINER.join(transform(argumentsList, TYPE_TO_STRING)))
2940888a09821a98ac0680fad765217302858e70fa4Paul Duffin          .append('>');
2957dd252788645e940eada959bdde927426e2531c9Paul Duffin      return builder.toString();
2967dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2977dd252788645e940eada959bdde927426e2531c9Paul Duffin
2980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public int hashCode() {
2990888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return (ownerType == null ? 0 : ownerType.hashCode())
3000888a09821a98ac0680fad765217302858e70fa4Paul Duffin          ^ argumentsList.hashCode() ^ rawType.hashCode();
3017dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3027dd252788645e940eada959bdde927426e2531c9Paul Duffin
3030888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public boolean equals(Object other) {
3047dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (!(other instanceof ParameterizedType)) {
3057dd252788645e940eada959bdde927426e2531c9Paul Duffin        return false;
3067dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
3077dd252788645e940eada959bdde927426e2531c9Paul Duffin      ParameterizedType that = (ParameterizedType) other;
3087dd252788645e940eada959bdde927426e2531c9Paul Duffin      return getRawType().equals(that.getRawType())
3097dd252788645e940eada959bdde927426e2531c9Paul Duffin          && Objects.equal(getOwnerType(), that.getOwnerType())
3100888a09821a98ac0680fad765217302858e70fa4Paul Duffin          && Arrays.equals(
3110888a09821a98ac0680fad765217302858e70fa4Paul Duffin              getActualTypeArguments(), that.getActualTypeArguments());
3127dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3137dd252788645e940eada959bdde927426e2531c9Paul Duffin
3147dd252788645e940eada959bdde927426e2531c9Paul Duffin    private static final long serialVersionUID = 0;
3157dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3167dd252788645e940eada959bdde927426e2531c9Paul Duffin
3170888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static final class TypeVariableImpl<D extends GenericDeclaration>
3180888a09821a98ac0680fad765217302858e70fa4Paul Duffin      implements TypeVariable<D> {
3197dd252788645e940eada959bdde927426e2531c9Paul Duffin
3207dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final D genericDeclaration;
3217dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final String name;
3227dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final ImmutableList<Type> bounds;
3237dd252788645e940eada959bdde927426e2531c9Paul Duffin
3247dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeVariableImpl(D genericDeclaration, String name, Type[] bounds) {
3257dd252788645e940eada959bdde927426e2531c9Paul Duffin      disallowPrimitiveType(bounds, "bound for type variable");
3267dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.genericDeclaration = checkNotNull(genericDeclaration);
3277dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.name = checkNotNull(name);
3287dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.bounds = ImmutableList.copyOf(bounds);
3297dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3307dd252788645e940eada959bdde927426e2531c9Paul Duffin
3310888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Type[] getBounds() {
3327dd252788645e940eada959bdde927426e2531c9Paul Duffin      return toArray(bounds);
3337dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3347dd252788645e940eada959bdde927426e2531c9Paul Duffin
3350888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public D getGenericDeclaration() {
3367dd252788645e940eada959bdde927426e2531c9Paul Duffin      return genericDeclaration;
3377dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3387dd252788645e940eada959bdde927426e2531c9Paul Duffin
3390888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public String getName() {
3407dd252788645e940eada959bdde927426e2531c9Paul Duffin      return name;
3417dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3427dd252788645e940eada959bdde927426e2531c9Paul Duffin
3430888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public String toString() {
3447dd252788645e940eada959bdde927426e2531c9Paul Duffin      return name;
3457dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3467dd252788645e940eada959bdde927426e2531c9Paul Duffin
3470888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public int hashCode() {
3487dd252788645e940eada959bdde927426e2531c9Paul Duffin      return genericDeclaration.hashCode() ^ name.hashCode();
3497dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3507dd252788645e940eada959bdde927426e2531c9Paul Duffin
3510888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public boolean equals(Object obj) {
3520888a09821a98ac0680fad765217302858e70fa4Paul Duffin      if (NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) {
3530888a09821a98ac0680fad765217302858e70fa4Paul Duffin        // equal only to our TypeVariable implementation with identical bounds
3540888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (obj instanceof TypeVariableImpl) {
3550888a09821a98ac0680fad765217302858e70fa4Paul Duffin          TypeVariableImpl<?> that = (TypeVariableImpl<?>) obj;
3560888a09821a98ac0680fad765217302858e70fa4Paul Duffin          return name.equals(that.getName())
3570888a09821a98ac0680fad765217302858e70fa4Paul Duffin              && genericDeclaration.equals(that.getGenericDeclaration())
3580888a09821a98ac0680fad765217302858e70fa4Paul Duffin              && bounds.equals(that.bounds);
3590888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
3600888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return false;
3610888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } else {
3620888a09821a98ac0680fad765217302858e70fa4Paul Duffin        // equal to any TypeVariable implementation regardless of bounds
3630888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (obj instanceof TypeVariable) {
3640888a09821a98ac0680fad765217302858e70fa4Paul Duffin          TypeVariable<?> that = (TypeVariable<?>) obj;
3650888a09821a98ac0680fad765217302858e70fa4Paul Duffin          return name.equals(that.getName())
3660888a09821a98ac0680fad765217302858e70fa4Paul Duffin              && genericDeclaration.equals(that.getGenericDeclaration());
3670888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
3680888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return false;
3697dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
3707dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3717dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3727dd252788645e940eada959bdde927426e2531c9Paul Duffin
3737dd252788645e940eada959bdde927426e2531c9Paul Duffin  static final class WildcardTypeImpl implements WildcardType, Serializable {
3747dd252788645e940eada959bdde927426e2531c9Paul Duffin
3757dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final ImmutableList<Type> lowerBounds;
3767dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final ImmutableList<Type> upperBounds;
3777dd252788645e940eada959bdde927426e2531c9Paul Duffin
3787dd252788645e940eada959bdde927426e2531c9Paul Duffin    WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) {
3797dd252788645e940eada959bdde927426e2531c9Paul Duffin      disallowPrimitiveType(lowerBounds, "lower bound for wildcard");
3807dd252788645e940eada959bdde927426e2531c9Paul Duffin      disallowPrimitiveType(upperBounds, "upper bound for wildcard");
3817dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.lowerBounds = JavaVersion.CURRENT.usedInGenericType(lowerBounds);
3827dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.upperBounds = JavaVersion.CURRENT.usedInGenericType(upperBounds);
3837dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3847dd252788645e940eada959bdde927426e2531c9Paul Duffin
3850888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Type[] getLowerBounds() {
3867dd252788645e940eada959bdde927426e2531c9Paul Duffin      return toArray(lowerBounds);
3877dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3887dd252788645e940eada959bdde927426e2531c9Paul Duffin
3890888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public Type[] getUpperBounds() {
3907dd252788645e940eada959bdde927426e2531c9Paul Duffin      return toArray(upperBounds);
3917dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3927dd252788645e940eada959bdde927426e2531c9Paul Duffin
3930888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public boolean equals(Object obj) {
3947dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (obj instanceof WildcardType) {
3957dd252788645e940eada959bdde927426e2531c9Paul Duffin        WildcardType that = (WildcardType) obj;
3967dd252788645e940eada959bdde927426e2531c9Paul Duffin        return lowerBounds.equals(Arrays.asList(that.getLowerBounds()))
3977dd252788645e940eada959bdde927426e2531c9Paul Duffin            && upperBounds.equals(Arrays.asList(that.getUpperBounds()));
3987dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
3997dd252788645e940eada959bdde927426e2531c9Paul Duffin      return false;
4007dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
4017dd252788645e940eada959bdde927426e2531c9Paul Duffin
4020888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public int hashCode() {
4037dd252788645e940eada959bdde927426e2531c9Paul Duffin      return lowerBounds.hashCode() ^ upperBounds.hashCode();
4047dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
4057dd252788645e940eada959bdde927426e2531c9Paul Duffin
4060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override public String toString() {
4077dd252788645e940eada959bdde927426e2531c9Paul Duffin      StringBuilder builder = new StringBuilder("?");
4087dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (Type lowerBound : lowerBounds) {
4097dd252788645e940eada959bdde927426e2531c9Paul Duffin        builder.append(" super ").append(Types.toString(lowerBound));
4107dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4117dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (Type upperBound : filterUpperBounds(upperBounds)) {
4127dd252788645e940eada959bdde927426e2531c9Paul Duffin        builder.append(" extends ").append(Types.toString(upperBound));
4137dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4147dd252788645e940eada959bdde927426e2531c9Paul Duffin      return builder.toString();
4157dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
4167dd252788645e940eada959bdde927426e2531c9Paul Duffin
4177dd252788645e940eada959bdde927426e2531c9Paul Duffin    private static final long serialVersionUID = 0;
4187dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4197dd252788645e940eada959bdde927426e2531c9Paul Duffin
4207dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static Type[] toArray(Collection<Type> types) {
4217dd252788645e940eada959bdde927426e2531c9Paul Duffin    return types.toArray(new Type[types.size()]);
4227dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4237dd252788645e940eada959bdde927426e2531c9Paul Duffin
4247dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static Iterable<Type> filterUpperBounds(Iterable<Type> bounds) {
4250888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return Iterables.filter(
4260888a09821a98ac0680fad765217302858e70fa4Paul Duffin        bounds, Predicates.not(Predicates.<Type>equalTo(Object.class)));
4277dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4287dd252788645e940eada959bdde927426e2531c9Paul Duffin
4297dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void disallowPrimitiveType(Type[] types, String usedAs) {
4307dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (Type type : types) {
4317dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (type instanceof Class) {
4327dd252788645e940eada959bdde927426e2531c9Paul Duffin        Class<?> cls = (Class<?>) type;
4330888a09821a98ac0680fad765217302858e70fa4Paul Duffin        checkArgument(!cls.isPrimitive(),
4340888a09821a98ac0680fad765217302858e70fa4Paul Duffin            "Primitive type '%s' used as %s", cls, usedAs);
4357dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4367dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
4377dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4387dd252788645e940eada959bdde927426e2531c9Paul Duffin
4397dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Returns the {@code Class} object of arrays with {@code componentType}. */
4407dd252788645e940eada959bdde927426e2531c9Paul Duffin  static Class<?> getArrayClass(Class<?> componentType) {
4417dd252788645e940eada959bdde927426e2531c9Paul Duffin    // TODO(user): This is not the most efficient way to handle generic
4427dd252788645e940eada959bdde927426e2531c9Paul Duffin    // arrays, but is there another way to extract the array class in a
4437dd252788645e940eada959bdde927426e2531c9Paul Duffin    // non-hacky way (i.e. using String value class names- "[L...")?
4447dd252788645e940eada959bdde927426e2531c9Paul Duffin    return Array.newInstance(componentType, 0).getClass();
4457dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4467dd252788645e940eada959bdde927426e2531c9Paul Duffin
4477dd252788645e940eada959bdde927426e2531c9Paul Duffin  // TODO(benyu): Once we are on Java 7, delete this abstraction
4487dd252788645e940eada959bdde927426e2531c9Paul Duffin  enum JavaVersion {
4497dd252788645e940eada959bdde927426e2531c9Paul Duffin
4507dd252788645e940eada959bdde927426e2531c9Paul Duffin    JAVA6 {
4510888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override GenericArrayType newArrayType(Type componentType) {
4527dd252788645e940eada959bdde927426e2531c9Paul Duffin        return new GenericArrayTypeImpl(componentType);
4537dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4540888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override Type usedInGenericType(Type type) {
4557dd252788645e940eada959bdde927426e2531c9Paul Duffin        checkNotNull(type);
4567dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (type instanceof Class) {
4577dd252788645e940eada959bdde927426e2531c9Paul Duffin          Class<?> cls = (Class<?>) type;
4587dd252788645e940eada959bdde927426e2531c9Paul Duffin          if (cls.isArray()) {
4597dd252788645e940eada959bdde927426e2531c9Paul Duffin            return new GenericArrayTypeImpl(cls.getComponentType());
4607dd252788645e940eada959bdde927426e2531c9Paul Duffin          }
4617dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
4627dd252788645e940eada959bdde927426e2531c9Paul Duffin        return type;
4637dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4647dd252788645e940eada959bdde927426e2531c9Paul Duffin    },
4657dd252788645e940eada959bdde927426e2531c9Paul Duffin    JAVA7 {
4660888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override Type newArrayType(Type componentType) {
4677dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (componentType instanceof Class) {
4687dd252788645e940eada959bdde927426e2531c9Paul Duffin          return getArrayClass((Class<?>) componentType);
4697dd252788645e940eada959bdde927426e2531c9Paul Duffin        } else {
4707dd252788645e940eada959bdde927426e2531c9Paul Duffin          return new GenericArrayTypeImpl(componentType);
4717dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
4727dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4730888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override Type usedInGenericType(Type type) {
4747dd252788645e940eada959bdde927426e2531c9Paul Duffin        return checkNotNull(type);
4757dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4760888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
4770888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ;
4787dd252788645e940eada959bdde927426e2531c9Paul Duffin
4790888a09821a98ac0680fad765217302858e70fa4Paul Duffin    static final JavaVersion CURRENT =
4800888a09821a98ac0680fad765217302858e70fa4Paul Duffin        (new TypeCapture<int[]>() {}.capture() instanceof Class)
4810888a09821a98ac0680fad765217302858e70fa4Paul Duffin        ? JAVA7 : JAVA6;
4827dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract Type newArrayType(Type componentType);
4837dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract Type usedInGenericType(Type type);
4847dd252788645e940eada959bdde927426e2531c9Paul Duffin
4857dd252788645e940eada959bdde927426e2531c9Paul Duffin    final ImmutableList<Type> usedInGenericType(Type[] types) {
4867dd252788645e940eada959bdde927426e2531c9Paul Duffin      ImmutableList.Builder<Type> builder = ImmutableList.builder();
4877dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (Type type : types) {
4887dd252788645e940eada959bdde927426e2531c9Paul Duffin        builder.add(usedInGenericType(type));
4897dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4907dd252788645e940eada959bdde927426e2531c9Paul Duffin      return builder.build();
4917dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
4927dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4937dd252788645e940eada959bdde927426e2531c9Paul Duffin
4940888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
4950888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Per https://code.google.com/p/guava-libraries/issues/detail?id=1635,
4960888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * In JDK 1.7.0_51-b13, TypeVariableImpl.equals() is changed to no longer be equal to custom
4970888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * TypeVariable implementations. As a result, we need to make sure our TypeVariable implementation
4980888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * respects symmetry.
4990888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Moreover, we don't want to reconstruct a native type variable <A> using our implementation
5000888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * unless some of its bounds have changed in resolution. This avoids creating unequal TypeVariable
5010888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * implementation unnecessarily. When the bounds do change, however, it's fine for the synthetic
5020888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * TypeVariable to be unequal to any native TypeVariable anyway.
5030888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
5040888a09821a98ac0680fad765217302858e70fa4Paul Duffin  static final class NativeTypeVariableEquals<X> {
5050888a09821a98ac0680fad765217302858e70fa4Paul Duffin    static final boolean NATIVE_TYPE_VARIABLE_ONLY =
5060888a09821a98ac0680fad765217302858e70fa4Paul Duffin        !NativeTypeVariableEquals.class.getTypeParameters()[0].equals(
5070888a09821a98ac0680fad765217302858e70fa4Paul Duffin            newArtificialTypeVariable(NativeTypeVariableEquals.class, "X"));
5080888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
5090888a09821a98ac0680fad765217302858e70fa4Paul Duffin
5107dd252788645e940eada959bdde927426e2531c9Paul Duffin  private Types() {}
5117dd252788645e940eada959bdde927426e2531c9Paul Duffin}
512