Types.java revision 7dd252788645e940eada959bdde927426e2531c9
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;
417dd252788645e940eada959bdde927426e2531c9Paul Duffin
427dd252788645e940eada959bdde927426e2531c9Paul Duffinimport javax.annotation.Nullable;
437dd252788645e940eada959bdde927426e2531c9Paul Duffin
447dd252788645e940eada959bdde927426e2531c9Paul Duffin/**
457dd252788645e940eada959bdde927426e2531c9Paul Duffin * Utilities for working with {@link Type}.
467dd252788645e940eada959bdde927426e2531c9Paul Duffin *
477dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Ben Yu
487dd252788645e940eada959bdde927426e2531c9Paul Duffin */
497dd252788645e940eada959bdde927426e2531c9Paul Duffinfinal class Types {
507dd252788645e940eada959bdde927426e2531c9Paul Duffin
517dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Class#toString without the "class " and "interface " prefixes */
527dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static final Function<Type, String> TYPE_TO_STRING = new Function<Type, String>() {
537dd252788645e940eada959bdde927426e2531c9Paul Duffin    public String apply(Type from) {
547dd252788645e940eada959bdde927426e2531c9Paul Duffin      return Types.toString(from);
557dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
567dd252788645e940eada959bdde927426e2531c9Paul Duffin  };
577dd252788645e940eada959bdde927426e2531c9Paul Duffin
587dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static final Joiner COMMA_JOINER = Joiner.on(", ").useForNull("null");
597dd252788645e940eada959bdde927426e2531c9Paul Duffin
607dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Returns the array type of {@code componentType}. */
617dd252788645e940eada959bdde927426e2531c9Paul Duffin  static Type newArrayType(Type componentType) {
627dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (componentType instanceof WildcardType) {
637dd252788645e940eada959bdde927426e2531c9Paul Duffin      WildcardType wildcard = (WildcardType) componentType;
647dd252788645e940eada959bdde927426e2531c9Paul Duffin      Type[] lowerBounds = wildcard.getLowerBounds();
657dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkArgument(lowerBounds.length <= 1, "Wildcard cannot have more than one lower bounds.");
667dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (lowerBounds.length == 1) {
677dd252788645e940eada959bdde927426e2531c9Paul Duffin        return supertypeOf(newArrayType(lowerBounds[0]));
687dd252788645e940eada959bdde927426e2531c9Paul Duffin      } else {
697dd252788645e940eada959bdde927426e2531c9Paul Duffin        Type[] upperBounds = wildcard.getUpperBounds();
707dd252788645e940eada959bdde927426e2531c9Paul Duffin        checkArgument(upperBounds.length == 1, "Wildcard should have only one upper bound.");
717dd252788645e940eada959bdde927426e2531c9Paul Duffin        return subtypeOf(newArrayType(upperBounds[0]));
727dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
737dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
747dd252788645e940eada959bdde927426e2531c9Paul Duffin    return JavaVersion.CURRENT.newArrayType(componentType);
757dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
767dd252788645e940eada959bdde927426e2531c9Paul Duffin
777dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
787dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Returns a type where {@code rawType} is parameterized by
797dd252788645e940eada959bdde927426e2531c9Paul Duffin   * {@code arguments} and is owned by {@code ownerType}.
807dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
817dd252788645e940eada959bdde927426e2531c9Paul Duffin  static ParameterizedType newParameterizedTypeWithOwner(@Nullable Type ownerType,
827dd252788645e940eada959bdde927426e2531c9Paul Duffin      Class<?> rawType, Type... arguments) {
837dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (ownerType == null) {
847dd252788645e940eada959bdde927426e2531c9Paul Duffin      return newParameterizedType(rawType, arguments);
857dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
867dd252788645e940eada959bdde927426e2531c9Paul Duffin    // ParameterizedTypeImpl constructor already checks, but we want to throw NPE before IAE
877dd252788645e940eada959bdde927426e2531c9Paul Duffin    checkNotNull(arguments);
887dd252788645e940eada959bdde927426e2531c9Paul Duffin    checkArgument(rawType.getEnclosingClass() != null, "Owner type for unenclosed %s", rawType);
897dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new ParameterizedTypeImpl(ownerType, rawType, arguments);
907dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
917dd252788645e940eada959bdde927426e2531c9Paul Duffin
927dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
937dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Returns a type where {@code rawType} is parameterized by
947dd252788645e940eada959bdde927426e2531c9Paul Duffin   * {@code arguments}.
957dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
967dd252788645e940eada959bdde927426e2531c9Paul Duffin  static ParameterizedType newParameterizedType(Class<?> rawType, Type... arguments) {
977dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new ParameterizedTypeImpl(ClassOwnership.JVM_BEHAVIOR.getOwnerType(rawType), rawType,
987dd252788645e940eada959bdde927426e2531c9Paul Duffin        arguments);
997dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1007dd252788645e940eada959bdde927426e2531c9Paul Duffin
1017dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Decides what owner type to use for constructing {@link ParameterizedType} from a raw class. */
1027dd252788645e940eada959bdde927426e2531c9Paul Duffin  private enum ClassOwnership {
1037dd252788645e940eada959bdde927426e2531c9Paul Duffin
1047dd252788645e940eada959bdde927426e2531c9Paul Duffin    OWNED_BY_ENCLOSING_CLASS {
1057dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Override
1067dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Nullable
1077dd252788645e940eada959bdde927426e2531c9Paul Duffin      Class<?> getOwnerType(Class<?> rawType) {
1087dd252788645e940eada959bdde927426e2531c9Paul Duffin        return rawType.getEnclosingClass();
1097dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
1107dd252788645e940eada959bdde927426e2531c9Paul Duffin    },
1117dd252788645e940eada959bdde927426e2531c9Paul Duffin    LOCAL_CLASS_HAS_NO_OWNER {
1127dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Override
1137dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Nullable
1147dd252788645e940eada959bdde927426e2531c9Paul Duffin      Class<?> getOwnerType(Class<?> rawType) {
1157dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (rawType.isLocalClass()) {
1167dd252788645e940eada959bdde927426e2531c9Paul Duffin          return null;
1177dd252788645e940eada959bdde927426e2531c9Paul Duffin        } else {
1187dd252788645e940eada959bdde927426e2531c9Paul Duffin          return rawType.getEnclosingClass();
1197dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
1207dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
1217dd252788645e940eada959bdde927426e2531c9Paul Duffin    };
1227dd252788645e940eada959bdde927426e2531c9Paul Duffin
1237dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Nullable
1247dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract Class<?> getOwnerType(Class<?> rawType);
1257dd252788645e940eada959bdde927426e2531c9Paul Duffin
1267dd252788645e940eada959bdde927426e2531c9Paul Duffin    static final ClassOwnership JVM_BEHAVIOR = detectJvmBehavior();
1277dd252788645e940eada959bdde927426e2531c9Paul Duffin
1287dd252788645e940eada959bdde927426e2531c9Paul Duffin    private static ClassOwnership detectJvmBehavior() {
1297dd252788645e940eada959bdde927426e2531c9Paul Duffin      class LocalClass<T> {}
1307dd252788645e940eada959bdde927426e2531c9Paul Duffin      Class<?> subclass = new LocalClass<String>() {}.getClass();
1317dd252788645e940eada959bdde927426e2531c9Paul Duffin      ParameterizedType parameterizedType = (ParameterizedType) subclass.getGenericSuperclass();
1327dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (ClassOwnership behavior : ClassOwnership.values()) {
1337dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (behavior.getOwnerType(LocalClass.class) == parameterizedType.getOwnerType()) {
1347dd252788645e940eada959bdde927426e2531c9Paul Duffin          return behavior;
1357dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
1367dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
1377dd252788645e940eada959bdde927426e2531c9Paul Duffin      throw new AssertionError();
1387dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1397dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1407dd252788645e940eada959bdde927426e2531c9Paul Duffin
1417dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
1427dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Returns a new {@link TypeVariable} that belongs to {@code declaration} with
1437dd252788645e940eada959bdde927426e2531c9Paul Duffin   * {@code name} and {@code bounds}.
1447dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
1457dd252788645e940eada959bdde927426e2531c9Paul Duffin  static <D extends GenericDeclaration> TypeVariable<D> newTypeVariable(D declaration, String name,
1467dd252788645e940eada959bdde927426e2531c9Paul Duffin      Type... bounds) {
1477dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new TypeVariableImpl<D>(declaration, name,
1487dd252788645e940eada959bdde927426e2531c9Paul Duffin        (bounds.length == 0) ? new Type[] { Object.class } : bounds);
1497dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1507dd252788645e940eada959bdde927426e2531c9Paul Duffin
1517dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Returns a new {@link WildcardType} with {@code upperBound}. */
1527dd252788645e940eada959bdde927426e2531c9Paul Duffin  @VisibleForTesting
1537dd252788645e940eada959bdde927426e2531c9Paul Duffin  static WildcardType subtypeOf(Type upperBound) {
1547dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new WildcardTypeImpl(new Type[0], new Type[] { upperBound });
1557dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1567dd252788645e940eada959bdde927426e2531c9Paul Duffin
1577dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Returns a new {@link WildcardType} with {@code lowerBound}. */
1587dd252788645e940eada959bdde927426e2531c9Paul Duffin  @VisibleForTesting
1597dd252788645e940eada959bdde927426e2531c9Paul Duffin  static WildcardType supertypeOf(Type lowerBound) {
1607dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new WildcardTypeImpl(new Type[] { lowerBound }, new Type[] { Object.class });
1617dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1627dd252788645e940eada959bdde927426e2531c9Paul Duffin
1637dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
1647dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Returns human readable string representation of {@code type}.
1657dd252788645e940eada959bdde927426e2531c9Paul Duffin   * <ul>
1667dd252788645e940eada959bdde927426e2531c9Paul Duffin   * <li> For array type {@code Foo[]}, {@code "com.mypackage.Foo[]"} are
1677dd252788645e940eada959bdde927426e2531c9Paul Duffin   * returned.
1687dd252788645e940eada959bdde927426e2531c9Paul Duffin   * <li> For any class, {@code theClass.getName()} are returned.
1697dd252788645e940eada959bdde927426e2531c9Paul Duffin   * <li> For all other types, {@code type.toString()} are returned.
1707dd252788645e940eada959bdde927426e2531c9Paul Duffin   * </ul>
1717dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
1727dd252788645e940eada959bdde927426e2531c9Paul Duffin  static String toString(Type type) {
1737dd252788645e940eada959bdde927426e2531c9Paul Duffin    return (type instanceof Class) ? ((Class<?>) type).getName() : type.toString();
1747dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1757dd252788645e940eada959bdde927426e2531c9Paul Duffin
1767dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Nullable
1777dd252788645e940eada959bdde927426e2531c9Paul Duffin  static Type getComponentType(Type type) {
1787dd252788645e940eada959bdde927426e2531c9Paul Duffin    checkNotNull(type);
1797dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (type instanceof Class) {
1807dd252788645e940eada959bdde927426e2531c9Paul Duffin      return ((Class<?>) type).getComponentType();
1817dd252788645e940eada959bdde927426e2531c9Paul Duffin    } else if (type instanceof GenericArrayType) {
1827dd252788645e940eada959bdde927426e2531c9Paul Duffin      return ((GenericArrayType) type).getGenericComponentType();
1837dd252788645e940eada959bdde927426e2531c9Paul Duffin    } else if (type instanceof WildcardType) {
1847dd252788645e940eada959bdde927426e2531c9Paul Duffin      return subtypeOfComponentType(((WildcardType) type).getUpperBounds());
1857dd252788645e940eada959bdde927426e2531c9Paul Duffin    } else if (type instanceof TypeVariable) {
1867dd252788645e940eada959bdde927426e2531c9Paul Duffin      return subtypeOfComponentType(((TypeVariable<?>) type).getBounds());
1877dd252788645e940eada959bdde927426e2531c9Paul Duffin    } else {
1887dd252788645e940eada959bdde927426e2531c9Paul Duffin      return null;
1897dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1907dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1917dd252788645e940eada959bdde927426e2531c9Paul Duffin
1927dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
1937dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Returns {@code ? extends X} if any of {@code bounds} is a subtype of {@code X[]}; or null
1947dd252788645e940eada959bdde927426e2531c9Paul Duffin   * otherwise.
1957dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
1967dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Nullable
1977dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static Type subtypeOfComponentType(Type[] bounds) {
1987dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (Type bound : bounds) {
1997dd252788645e940eada959bdde927426e2531c9Paul Duffin      Type componentType = getComponentType(bound);
2007dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (componentType != null) {
2017dd252788645e940eada959bdde927426e2531c9Paul Duffin        // Only the first bound can be a class or array.
2027dd252788645e940eada959bdde927426e2531c9Paul Duffin        // Bounds after the first can only be interfaces.
2037dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (componentType instanceof Class) {
2047dd252788645e940eada959bdde927426e2531c9Paul Duffin          Class<?> componentClass = (Class<?>) componentType;
2057dd252788645e940eada959bdde927426e2531c9Paul Duffin          if (componentClass.isPrimitive()) {
2067dd252788645e940eada959bdde927426e2531c9Paul Duffin            return componentClass;
2077dd252788645e940eada959bdde927426e2531c9Paul Duffin          }
2087dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
2097dd252788645e940eada959bdde927426e2531c9Paul Duffin        return subtypeOf(componentType);
2107dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
2117dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2127dd252788645e940eada959bdde927426e2531c9Paul Duffin    return null;
2137dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2147dd252788645e940eada959bdde927426e2531c9Paul Duffin
2157dd252788645e940eada959bdde927426e2531c9Paul Duffin  static boolean containsTypeVariable(@Nullable Type type) {
2167dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (type instanceof TypeVariable) {
2177dd252788645e940eada959bdde927426e2531c9Paul Duffin      return true;
2187dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2197dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (type instanceof GenericArrayType) {
2207dd252788645e940eada959bdde927426e2531c9Paul Duffin      return containsTypeVariable(((GenericArrayType) type).getGenericComponentType());
2217dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2227dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (type instanceof ParameterizedType) {
2237dd252788645e940eada959bdde927426e2531c9Paul Duffin      return containsTypeVariable(((ParameterizedType) type).getActualTypeArguments());
2247dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2257dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (type instanceof WildcardType) {
2267dd252788645e940eada959bdde927426e2531c9Paul Duffin      WildcardType wildcard = (WildcardType) type;
2277dd252788645e940eada959bdde927426e2531c9Paul Duffin      return containsTypeVariable(wildcard.getUpperBounds())
2287dd252788645e940eada959bdde927426e2531c9Paul Duffin          || containsTypeVariable(wildcard.getLowerBounds());
2297dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2307dd252788645e940eada959bdde927426e2531c9Paul Duffin    return false;
2317dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2327dd252788645e940eada959bdde927426e2531c9Paul Duffin
2337dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static boolean containsTypeVariable(Type[] types) {
2347dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (Type paramType : types) {
2357dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (containsTypeVariable(paramType)) {
2367dd252788645e940eada959bdde927426e2531c9Paul Duffin        return true;
2377dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
2387dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2397dd252788645e940eada959bdde927426e2531c9Paul Duffin    return false;
2407dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2417dd252788645e940eada959bdde927426e2531c9Paul Duffin
2427dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static final class GenericArrayTypeImpl implements GenericArrayType, Serializable {
2437dd252788645e940eada959bdde927426e2531c9Paul Duffin
2447dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final Type componentType;
2457dd252788645e940eada959bdde927426e2531c9Paul Duffin
2467dd252788645e940eada959bdde927426e2531c9Paul Duffin    GenericArrayTypeImpl(Type componentType) {
2477dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.componentType = JavaVersion.CURRENT.usedInGenericType(componentType);
2487dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2497dd252788645e940eada959bdde927426e2531c9Paul Duffin
2507dd252788645e940eada959bdde927426e2531c9Paul Duffin    public Type getGenericComponentType() {
2517dd252788645e940eada959bdde927426e2531c9Paul Duffin      return componentType;
2527dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2537dd252788645e940eada959bdde927426e2531c9Paul Duffin
2547dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
2557dd252788645e940eada959bdde927426e2531c9Paul Duffin    public String toString() {
2567dd252788645e940eada959bdde927426e2531c9Paul Duffin      return Types.toString(componentType) + "[]";
2577dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2587dd252788645e940eada959bdde927426e2531c9Paul Duffin
2597dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
2607dd252788645e940eada959bdde927426e2531c9Paul Duffin    public int hashCode() {
2617dd252788645e940eada959bdde927426e2531c9Paul Duffin      return componentType.hashCode();
2627dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2637dd252788645e940eada959bdde927426e2531c9Paul Duffin
2647dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
2657dd252788645e940eada959bdde927426e2531c9Paul Duffin    public boolean equals(Object obj) {
2667dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (obj instanceof GenericArrayType) {
2677dd252788645e940eada959bdde927426e2531c9Paul Duffin        GenericArrayType that = (GenericArrayType) obj;
2687dd252788645e940eada959bdde927426e2531c9Paul Duffin        return Objects.equal(getGenericComponentType(), that.getGenericComponentType());
2697dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
2707dd252788645e940eada959bdde927426e2531c9Paul Duffin      return false;
2717dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2727dd252788645e940eada959bdde927426e2531c9Paul Duffin
2737dd252788645e940eada959bdde927426e2531c9Paul Duffin    private static final long serialVersionUID = 0;
2747dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2757dd252788645e940eada959bdde927426e2531c9Paul Duffin
2767dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static final class ParameterizedTypeImpl implements ParameterizedType, Serializable {
2777dd252788645e940eada959bdde927426e2531c9Paul Duffin
2787dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final Type ownerType;
2797dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final ImmutableList<Type> argumentsList;
2807dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final Class<?> rawType;
2817dd252788645e940eada959bdde927426e2531c9Paul Duffin
2827dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedTypeImpl(@Nullable Type ownerType, Class<?> rawType, Type[] typeArguments) {
2837dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkNotNull(rawType);
2847dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkArgument(typeArguments.length == rawType.getTypeParameters().length);
2857dd252788645e940eada959bdde927426e2531c9Paul Duffin      disallowPrimitiveType(typeArguments, "type parameter");
2867dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.ownerType = ownerType;
2877dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.rawType = rawType;
2887dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.argumentsList = JavaVersion.CURRENT.usedInGenericType(typeArguments);
2897dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2907dd252788645e940eada959bdde927426e2531c9Paul Duffin
2917dd252788645e940eada959bdde927426e2531c9Paul Duffin    public Type[] getActualTypeArguments() {
2927dd252788645e940eada959bdde927426e2531c9Paul Duffin      return toArray(argumentsList);
2937dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2947dd252788645e940eada959bdde927426e2531c9Paul Duffin
2957dd252788645e940eada959bdde927426e2531c9Paul Duffin    public Type getRawType() {
2967dd252788645e940eada959bdde927426e2531c9Paul Duffin      return rawType;
2977dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2987dd252788645e940eada959bdde927426e2531c9Paul Duffin
2997dd252788645e940eada959bdde927426e2531c9Paul Duffin    public Type getOwnerType() {
3007dd252788645e940eada959bdde927426e2531c9Paul Duffin      return ownerType;
3017dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3027dd252788645e940eada959bdde927426e2531c9Paul Duffin
3037dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
3047dd252788645e940eada959bdde927426e2531c9Paul Duffin    public String toString() {
3057dd252788645e940eada959bdde927426e2531c9Paul Duffin      StringBuilder builder = new StringBuilder();
3067dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (ownerType != null) {
3077dd252788645e940eada959bdde927426e2531c9Paul Duffin        builder.append(Types.toString(ownerType)).append('.');
3087dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
3097dd252788645e940eada959bdde927426e2531c9Paul Duffin      builder.append(rawType.getName()).append('<')
3107dd252788645e940eada959bdde927426e2531c9Paul Duffin          .append(COMMA_JOINER.join(transform(argumentsList, TYPE_TO_STRING))).append('>');
3117dd252788645e940eada959bdde927426e2531c9Paul Duffin      return builder.toString();
3127dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3137dd252788645e940eada959bdde927426e2531c9Paul Duffin
3147dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
3157dd252788645e940eada959bdde927426e2531c9Paul Duffin    public int hashCode() {
3167dd252788645e940eada959bdde927426e2531c9Paul Duffin      return (ownerType == null ? 0 : ownerType.hashCode()) ^ argumentsList.hashCode()
3177dd252788645e940eada959bdde927426e2531c9Paul Duffin          ^ rawType.hashCode();
3187dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3197dd252788645e940eada959bdde927426e2531c9Paul Duffin
3207dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
3217dd252788645e940eada959bdde927426e2531c9Paul Duffin    public boolean equals(Object other) {
3227dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (!(other instanceof ParameterizedType)) {
3237dd252788645e940eada959bdde927426e2531c9Paul Duffin        return false;
3247dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
3257dd252788645e940eada959bdde927426e2531c9Paul Duffin      ParameterizedType that = (ParameterizedType) other;
3267dd252788645e940eada959bdde927426e2531c9Paul Duffin      return getRawType().equals(that.getRawType())
3277dd252788645e940eada959bdde927426e2531c9Paul Duffin          && Objects.equal(getOwnerType(), that.getOwnerType())
3287dd252788645e940eada959bdde927426e2531c9Paul Duffin          && Arrays.equals(getActualTypeArguments(), that.getActualTypeArguments());
3297dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3307dd252788645e940eada959bdde927426e2531c9Paul Duffin
3317dd252788645e940eada959bdde927426e2531c9Paul Duffin    private static final long serialVersionUID = 0;
3327dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3337dd252788645e940eada959bdde927426e2531c9Paul Duffin
3347dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static final class TypeVariableImpl<D extends GenericDeclaration> implements
3357dd252788645e940eada959bdde927426e2531c9Paul Duffin      TypeVariable<D> {
3367dd252788645e940eada959bdde927426e2531c9Paul Duffin
3377dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final D genericDeclaration;
3387dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final String name;
3397dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final ImmutableList<Type> bounds;
3407dd252788645e940eada959bdde927426e2531c9Paul Duffin
3417dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeVariableImpl(D genericDeclaration, String name, Type[] bounds) {
3427dd252788645e940eada959bdde927426e2531c9Paul Duffin      disallowPrimitiveType(bounds, "bound for type variable");
3437dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.genericDeclaration = checkNotNull(genericDeclaration);
3447dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.name = checkNotNull(name);
3457dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.bounds = ImmutableList.copyOf(bounds);
3467dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3477dd252788645e940eada959bdde927426e2531c9Paul Duffin
3487dd252788645e940eada959bdde927426e2531c9Paul Duffin    public Type[] getBounds() {
3497dd252788645e940eada959bdde927426e2531c9Paul Duffin      return toArray(bounds);
3507dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3517dd252788645e940eada959bdde927426e2531c9Paul Duffin
3527dd252788645e940eada959bdde927426e2531c9Paul Duffin    public D getGenericDeclaration() {
3537dd252788645e940eada959bdde927426e2531c9Paul Duffin      return genericDeclaration;
3547dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3557dd252788645e940eada959bdde927426e2531c9Paul Duffin
3567dd252788645e940eada959bdde927426e2531c9Paul Duffin    public String getName() {
3577dd252788645e940eada959bdde927426e2531c9Paul Duffin      return name;
3587dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3597dd252788645e940eada959bdde927426e2531c9Paul Duffin
3607dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
3617dd252788645e940eada959bdde927426e2531c9Paul Duffin    public String toString() {
3627dd252788645e940eada959bdde927426e2531c9Paul Duffin      return name;
3637dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3647dd252788645e940eada959bdde927426e2531c9Paul Duffin
3657dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
3667dd252788645e940eada959bdde927426e2531c9Paul Duffin    public int hashCode() {
3677dd252788645e940eada959bdde927426e2531c9Paul Duffin      return genericDeclaration.hashCode() ^ name.hashCode();
3687dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3697dd252788645e940eada959bdde927426e2531c9Paul Duffin
3707dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
3717dd252788645e940eada959bdde927426e2531c9Paul Duffin    public boolean equals(Object obj) {
3727dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (obj instanceof TypeVariable) {
3737dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeVariable<?> that = (TypeVariable<?>) obj;
3747dd252788645e940eada959bdde927426e2531c9Paul Duffin        return name.equals(that.getName())
3757dd252788645e940eada959bdde927426e2531c9Paul Duffin            && genericDeclaration.equals(that.getGenericDeclaration());
3767dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
3777dd252788645e940eada959bdde927426e2531c9Paul Duffin      return false;
3787dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3797dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3807dd252788645e940eada959bdde927426e2531c9Paul Duffin
3817dd252788645e940eada959bdde927426e2531c9Paul Duffin  static final class WildcardTypeImpl implements WildcardType, Serializable {
3827dd252788645e940eada959bdde927426e2531c9Paul Duffin
3837dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final ImmutableList<Type> lowerBounds;
3847dd252788645e940eada959bdde927426e2531c9Paul Duffin    private final ImmutableList<Type> upperBounds;
3857dd252788645e940eada959bdde927426e2531c9Paul Duffin
3867dd252788645e940eada959bdde927426e2531c9Paul Duffin    WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) {
3877dd252788645e940eada959bdde927426e2531c9Paul Duffin      disallowPrimitiveType(lowerBounds, "lower bound for wildcard");
3887dd252788645e940eada959bdde927426e2531c9Paul Duffin      disallowPrimitiveType(upperBounds, "upper bound for wildcard");
3897dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.lowerBounds = JavaVersion.CURRENT.usedInGenericType(lowerBounds);
3907dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.upperBounds = JavaVersion.CURRENT.usedInGenericType(upperBounds);
3917dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3927dd252788645e940eada959bdde927426e2531c9Paul Duffin
3937dd252788645e940eada959bdde927426e2531c9Paul Duffin    public Type[] getLowerBounds() {
3947dd252788645e940eada959bdde927426e2531c9Paul Duffin      return toArray(lowerBounds);
3957dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3967dd252788645e940eada959bdde927426e2531c9Paul Duffin
3977dd252788645e940eada959bdde927426e2531c9Paul Duffin    public Type[] getUpperBounds() {
3987dd252788645e940eada959bdde927426e2531c9Paul Duffin      return toArray(upperBounds);
3997dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
4007dd252788645e940eada959bdde927426e2531c9Paul Duffin
4017dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
4027dd252788645e940eada959bdde927426e2531c9Paul Duffin    public boolean equals(Object obj) {
4037dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (obj instanceof WildcardType) {
4047dd252788645e940eada959bdde927426e2531c9Paul Duffin        WildcardType that = (WildcardType) obj;
4057dd252788645e940eada959bdde927426e2531c9Paul Duffin        return lowerBounds.equals(Arrays.asList(that.getLowerBounds()))
4067dd252788645e940eada959bdde927426e2531c9Paul Duffin            && upperBounds.equals(Arrays.asList(that.getUpperBounds()));
4077dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4087dd252788645e940eada959bdde927426e2531c9Paul Duffin      return false;
4097dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
4107dd252788645e940eada959bdde927426e2531c9Paul Duffin
4117dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
4127dd252788645e940eada959bdde927426e2531c9Paul Duffin    public int hashCode() {
4137dd252788645e940eada959bdde927426e2531c9Paul Duffin      return lowerBounds.hashCode() ^ upperBounds.hashCode();
4147dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
4157dd252788645e940eada959bdde927426e2531c9Paul Duffin
4167dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
4177dd252788645e940eada959bdde927426e2531c9Paul Duffin    public String toString() {
4187dd252788645e940eada959bdde927426e2531c9Paul Duffin      StringBuilder builder = new StringBuilder("?");
4197dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (Type lowerBound : lowerBounds) {
4207dd252788645e940eada959bdde927426e2531c9Paul Duffin        builder.append(" super ").append(Types.toString(lowerBound));
4217dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4227dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (Type upperBound : filterUpperBounds(upperBounds)) {
4237dd252788645e940eada959bdde927426e2531c9Paul Duffin        builder.append(" extends ").append(Types.toString(upperBound));
4247dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4257dd252788645e940eada959bdde927426e2531c9Paul Duffin      return builder.toString();
4267dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
4277dd252788645e940eada959bdde927426e2531c9Paul Duffin
4287dd252788645e940eada959bdde927426e2531c9Paul Duffin    private static final long serialVersionUID = 0;
4297dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4307dd252788645e940eada959bdde927426e2531c9Paul Duffin
4317dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static Type[] toArray(Collection<Type> types) {
4327dd252788645e940eada959bdde927426e2531c9Paul Duffin    return types.toArray(new Type[types.size()]);
4337dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4347dd252788645e940eada959bdde927426e2531c9Paul Duffin
4357dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static Iterable<Type> filterUpperBounds(Iterable<Type> bounds) {
4367dd252788645e940eada959bdde927426e2531c9Paul Duffin    return Iterables.filter(bounds, Predicates.not(Predicates.<Type> equalTo(Object.class)));
4377dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4387dd252788645e940eada959bdde927426e2531c9Paul Duffin
4397dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void disallowPrimitiveType(Type[] types, String usedAs) {
4407dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (Type type : types) {
4417dd252788645e940eada959bdde927426e2531c9Paul Duffin      if (type instanceof Class) {
4427dd252788645e940eada959bdde927426e2531c9Paul Duffin        Class<?> cls = (Class<?>) type;
4437dd252788645e940eada959bdde927426e2531c9Paul Duffin        checkArgument(!cls.isPrimitive(), "Primitive type '%s' used as %s", cls, usedAs);
4447dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4457dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
4467dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4477dd252788645e940eada959bdde927426e2531c9Paul Duffin
4487dd252788645e940eada959bdde927426e2531c9Paul Duffin  /** Returns the {@code Class} object of arrays with {@code componentType}. */
4497dd252788645e940eada959bdde927426e2531c9Paul Duffin  static Class<?> getArrayClass(Class<?> componentType) {
4507dd252788645e940eada959bdde927426e2531c9Paul Duffin    // TODO(user): This is not the most efficient way to handle generic
4517dd252788645e940eada959bdde927426e2531c9Paul Duffin    // arrays, but is there another way to extract the array class in a
4527dd252788645e940eada959bdde927426e2531c9Paul Duffin    // non-hacky way (i.e. using String value class names- "[L...")?
4537dd252788645e940eada959bdde927426e2531c9Paul Duffin    return Array.newInstance(componentType, 0).getClass();
4547dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4557dd252788645e940eada959bdde927426e2531c9Paul Duffin
4567dd252788645e940eada959bdde927426e2531c9Paul Duffin  // TODO(benyu): Once we are on Java 7, delete this abstraction
4577dd252788645e940eada959bdde927426e2531c9Paul Duffin  enum JavaVersion {
4587dd252788645e940eada959bdde927426e2531c9Paul Duffin
4597dd252788645e940eada959bdde927426e2531c9Paul Duffin    JAVA6 {
4607dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Override
4617dd252788645e940eada959bdde927426e2531c9Paul Duffin      GenericArrayType newArrayType(Type componentType) {
4627dd252788645e940eada959bdde927426e2531c9Paul Duffin        return new GenericArrayTypeImpl(componentType);
4637dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4647dd252788645e940eada959bdde927426e2531c9Paul Duffin
4657dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Override
4667dd252788645e940eada959bdde927426e2531c9Paul Duffin      Type usedInGenericType(Type type) {
4677dd252788645e940eada959bdde927426e2531c9Paul Duffin        checkNotNull(type);
4687dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (type instanceof Class) {
4697dd252788645e940eada959bdde927426e2531c9Paul Duffin          Class<?> cls = (Class<?>) type;
4707dd252788645e940eada959bdde927426e2531c9Paul Duffin          if (cls.isArray()) {
4717dd252788645e940eada959bdde927426e2531c9Paul Duffin            return new GenericArrayTypeImpl(cls.getComponentType());
4727dd252788645e940eada959bdde927426e2531c9Paul Duffin          }
4737dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
4747dd252788645e940eada959bdde927426e2531c9Paul Duffin        return type;
4757dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4767dd252788645e940eada959bdde927426e2531c9Paul Duffin    },
4777dd252788645e940eada959bdde927426e2531c9Paul Duffin    JAVA7 {
4787dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Override
4797dd252788645e940eada959bdde927426e2531c9Paul Duffin      Type newArrayType(Type componentType) {
4807dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (componentType instanceof Class) {
4817dd252788645e940eada959bdde927426e2531c9Paul Duffin          return getArrayClass((Class<?>) componentType);
4827dd252788645e940eada959bdde927426e2531c9Paul Duffin        } else {
4837dd252788645e940eada959bdde927426e2531c9Paul Duffin          return new GenericArrayTypeImpl(componentType);
4847dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
4857dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4867dd252788645e940eada959bdde927426e2531c9Paul Duffin
4877dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Override
4887dd252788645e940eada959bdde927426e2531c9Paul Duffin      Type usedInGenericType(Type type) {
4897dd252788645e940eada959bdde927426e2531c9Paul Duffin        return checkNotNull(type);
4907dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
4917dd252788645e940eada959bdde927426e2531c9Paul Duffin    };
4927dd252788645e940eada959bdde927426e2531c9Paul Duffin
4937dd252788645e940eada959bdde927426e2531c9Paul Duffin    static final JavaVersion CURRENT = (new TypeCapture<int[]>() {}.capture() instanceof Class) ? JAVA7
4947dd252788645e940eada959bdde927426e2531c9Paul Duffin        : JAVA6;
4957dd252788645e940eada959bdde927426e2531c9Paul Duffin
4967dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract Type newArrayType(Type componentType);
4977dd252788645e940eada959bdde927426e2531c9Paul Duffin
4987dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract Type usedInGenericType(Type type);
4997dd252788645e940eada959bdde927426e2531c9Paul Duffin
5007dd252788645e940eada959bdde927426e2531c9Paul Duffin    final ImmutableList<Type> usedInGenericType(Type[] types) {
5017dd252788645e940eada959bdde927426e2531c9Paul Duffin      ImmutableList.Builder<Type> builder = ImmutableList.builder();
5027dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (Type type : types) {
5037dd252788645e940eada959bdde927426e2531c9Paul Duffin        builder.add(usedInGenericType(type));
5047dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
5057dd252788645e940eada959bdde927426e2531c9Paul Duffin      return builder.build();
5067dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
5077dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5087dd252788645e940eada959bdde927426e2531c9Paul Duffin
5097dd252788645e940eada959bdde927426e2531c9Paul Duffin  private Types() {}
5107dd252788645e940eada959bdde927426e2531c9Paul Duffin}
511