13beaaaff52598e849659281fed35dc29a221fac4limpbizkit/**
23beaaaff52598e849659281fed35dc29a221fac4limpbizkit * Copyright (C) 2008 Google Inc.
33beaaaff52598e849659281fed35dc29a221fac4limpbizkit *
43beaaaff52598e849659281fed35dc29a221fac4limpbizkit * Licensed under the Apache License, Version 2.0 (the "License");
53beaaaff52598e849659281fed35dc29a221fac4limpbizkit * you may not use this file except in compliance with the License.
63beaaaff52598e849659281fed35dc29a221fac4limpbizkit * You may obtain a copy of the License at
73beaaaff52598e849659281fed35dc29a221fac4limpbizkit *
83beaaaff52598e849659281fed35dc29a221fac4limpbizkit * http://www.apache.org/licenses/LICENSE-2.0
93beaaaff52598e849659281fed35dc29a221fac4limpbizkit *
103beaaaff52598e849659281fed35dc29a221fac4limpbizkit * Unless required by applicable law or agreed to in writing, software
113beaaaff52598e849659281fed35dc29a221fac4limpbizkit * distributed under the License is distributed on an "AS IS" BASIS,
123beaaaff52598e849659281fed35dc29a221fac4limpbizkit * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133beaaaff52598e849659281fed35dc29a221fac4limpbizkit * See the License for the specific language governing permissions and
143beaaaff52598e849659281fed35dc29a221fac4limpbizkit * limitations under the License.
153beaaaff52598e849659281fed35dc29a221fac4limpbizkit */
163beaaaff52598e849659281fed35dc29a221fac4limpbizkit
173beaaaff52598e849659281fed35dc29a221fac4limpbizkit
183beaaaff52598e849659281fed35dc29a221fac4limpbizkitpackage com.google.inject.internal;
193beaaaff52598e849659281fed35dc29a221fac4limpbizkit
20d9c913acca55023ef5d76a32c3d4a51ee6b420cbsberlinimport static com.google.common.base.Preconditions.checkArgument;
21d9c913acca55023ef5d76a32c3d4a51ee6b420cbsberlinimport static com.google.common.base.Preconditions.checkNotNull;
22b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
23b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.base.Objects;
24b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.ImmutableMap;
25b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.inject.ConfigurationException;
26825f8c1df885b9d7643a9e18e336984f0138edafsamebimport com.google.inject.Key;
27b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.inject.TypeLiteral;
28365f83483b550d95bae2f90bc16439d24713a124limpbizkitimport com.google.inject.util.Types;
29b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
303beaaaff52598e849659281fed35dc29a221fac4limpbizkitimport java.io.Serializable;
310bd3bd643f04f955bdb99e66375d4ee23131aa6dlimpbizkitimport java.lang.reflect.Array;
323beaaaff52598e849659281fed35dc29a221fac4limpbizkitimport java.lang.reflect.GenericArrayType;
334f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.lang.reflect.GenericDeclaration;
343beaaaff52598e849659281fed35dc29a221fac4limpbizkitimport java.lang.reflect.ParameterizedType;
353beaaaff52598e849659281fed35dc29a221fac4limpbizkitimport java.lang.reflect.Type;
364f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.lang.reflect.TypeVariable;
37cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkitimport java.lang.reflect.WildcardType;
383beaaaff52598e849659281fed35dc29a221fac4limpbizkitimport java.util.Arrays;
393beaaaff52598e849659281fed35dc29a221fac4limpbizkitimport java.util.Map;
404f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.util.NoSuchElementException;
413beaaaff52598e849659281fed35dc29a221fac4limpbizkit
423beaaaff52598e849659281fed35dc29a221fac4limpbizkit/**
433beaaaff52598e849659281fed35dc29a221fac4limpbizkit * Static methods for working with types that we aren't publishing in the
443beaaaff52598e849659281fed35dc29a221fac4limpbizkit * public {@code Types} API.
453beaaaff52598e849659281fed35dc29a221fac4limpbizkit *
463beaaaff52598e849659281fed35dc29a221fac4limpbizkit * @author jessewilson@google.com (Jesse Wilson)
473beaaaff52598e849659281fed35dc29a221fac4limpbizkit */
483beaaaff52598e849659281fed35dc29a221fac4limpbizkitpublic class MoreTypes {
49cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
50cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit  public static final Type[] EMPTY_TYPE_ARRAY = new Type[] {};
51cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
523beaaaff52598e849659281fed35dc29a221fac4limpbizkit  private MoreTypes() {}
533beaaaff52598e849659281fed35dc29a221fac4limpbizkit
543beaaaff52598e849659281fed35dc29a221fac4limpbizkit  private static final Map<TypeLiteral<?>, TypeLiteral<?>> PRIMITIVE_TO_WRAPPER
553beaaaff52598e849659281fed35dc29a221fac4limpbizkit      = new ImmutableMap.Builder<TypeLiteral<?>, TypeLiteral<?>>()
563beaaaff52598e849659281fed35dc29a221fac4limpbizkit          .put(TypeLiteral.get(boolean.class), TypeLiteral.get(Boolean.class))
573beaaaff52598e849659281fed35dc29a221fac4limpbizkit          .put(TypeLiteral.get(byte.class), TypeLiteral.get(Byte.class))
583beaaaff52598e849659281fed35dc29a221fac4limpbizkit          .put(TypeLiteral.get(short.class), TypeLiteral.get(Short.class))
593beaaaff52598e849659281fed35dc29a221fac4limpbizkit          .put(TypeLiteral.get(int.class), TypeLiteral.get(Integer.class))
603beaaaff52598e849659281fed35dc29a221fac4limpbizkit          .put(TypeLiteral.get(long.class), TypeLiteral.get(Long.class))
613beaaaff52598e849659281fed35dc29a221fac4limpbizkit          .put(TypeLiteral.get(float.class), TypeLiteral.get(Float.class))
623beaaaff52598e849659281fed35dc29a221fac4limpbizkit          .put(TypeLiteral.get(double.class), TypeLiteral.get(Double.class))
633beaaaff52598e849659281fed35dc29a221fac4limpbizkit          .put(TypeLiteral.get(char.class), TypeLiteral.get(Character.class))
643beaaaff52598e849659281fed35dc29a221fac4limpbizkit          .put(TypeLiteral.get(void.class), TypeLiteral.get(Void.class))
653beaaaff52598e849659281fed35dc29a221fac4limpbizkit          .build();
663beaaaff52598e849659281fed35dc29a221fac4limpbizkit
673beaaaff52598e849659281fed35dc29a221fac4limpbizkit  /**
68825f8c1df885b9d7643a9e18e336984f0138edafsameb   * Returns a key that doesn't hold any references to parent classes.
69825f8c1df885b9d7643a9e18e336984f0138edafsameb   * This is necessary for anonymous keys, so ensure we don't hold a ref
70825f8c1df885b9d7643a9e18e336984f0138edafsameb   * to the containing module (or class) forever.
71825f8c1df885b9d7643a9e18e336984f0138edafsameb   */
72825f8c1df885b9d7643a9e18e336984f0138edafsameb  public static <T> Key<T> canonicalizeKey(Key<T> key) {
73825f8c1df885b9d7643a9e18e336984f0138edafsameb    // If we know this isn't a subclass, return as-is.
74825f8c1df885b9d7643a9e18e336984f0138edafsameb    // Otherwise, recreate the key to avoid the subclass
75825f8c1df885b9d7643a9e18e336984f0138edafsameb    if (key.getClass() == Key.class) {
76825f8c1df885b9d7643a9e18e336984f0138edafsameb      return key;
77825f8c1df885b9d7643a9e18e336984f0138edafsameb    } else if (key.getAnnotation() != null) {
78825f8c1df885b9d7643a9e18e336984f0138edafsameb      return Key.get(key.getTypeLiteral(), key.getAnnotation());
79825f8c1df885b9d7643a9e18e336984f0138edafsameb    } else if (key.getAnnotationType() != null) {
80825f8c1df885b9d7643a9e18e336984f0138edafsameb      return Key.get(key.getTypeLiteral(), key.getAnnotationType());
81825f8c1df885b9d7643a9e18e336984f0138edafsameb    } else {
82825f8c1df885b9d7643a9e18e336984f0138edafsameb      return Key.get(key.getTypeLiteral());
83825f8c1df885b9d7643a9e18e336984f0138edafsameb    }
84825f8c1df885b9d7643a9e18e336984f0138edafsameb  }
85825f8c1df885b9d7643a9e18e336984f0138edafsameb
86825f8c1df885b9d7643a9e18e336984f0138edafsameb  /**
87365f83483b550d95bae2f90bc16439d24713a124limpbizkit   * Returns an type that's appropriate for use in a key.
88365f83483b550d95bae2f90bc16439d24713a124limpbizkit   *
89365f83483b550d95bae2f90bc16439d24713a124limpbizkit   * <p>If the raw type of {@code typeLiteral} is a {@code javax.inject.Provider}, this returns a
90365f83483b550d95bae2f90bc16439d24713a124limpbizkit   * {@code com.google.inject.Provider} with the same type parameters.
91365f83483b550d95bae2f90bc16439d24713a124limpbizkit   *
92365f83483b550d95bae2f90bc16439d24713a124limpbizkit   * <p>If the type is a primitive, the corresponding wrapper type will be returned.
934272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit   *
944272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit   * @throws ConfigurationException if {@code type} contains a type variable
953beaaaff52598e849659281fed35dc29a221fac4limpbizkit   */
96365f83483b550d95bae2f90bc16439d24713a124limpbizkit  public static <T> TypeLiteral<T> canonicalizeForKey(TypeLiteral<T> typeLiteral) {
97365f83483b550d95bae2f90bc16439d24713a124limpbizkit    Type type = typeLiteral.getType();
98365f83483b550d95bae2f90bc16439d24713a124limpbizkit    if (!isFullySpecified(type)) {
993748e4a0979e6332ab9f0a3601ab5b8e595b7a12sberlin      Errors errors = new Errors().keyNotFullySpecified(typeLiteral);
1003748e4a0979e6332ab9f0a3601ab5b8e595b7a12sberlin      throw new ConfigurationException(errors.getMessages());
1014272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    }
1024272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
103365f83483b550d95bae2f90bc16439d24713a124limpbizkit    if (typeLiteral.getRawType() == javax.inject.Provider.class) {
104365f83483b550d95bae2f90bc16439d24713a124limpbizkit      ParameterizedType parameterizedType = (ParameterizedType) type;
105365f83483b550d95bae2f90bc16439d24713a124limpbizkit
106365f83483b550d95bae2f90bc16439d24713a124limpbizkit      // the following casts are generally unsafe, but com.google.inject.Provider extends
107365f83483b550d95bae2f90bc16439d24713a124limpbizkit      // javax.inject.Provider and is covariant
108365f83483b550d95bae2f90bc16439d24713a124limpbizkit      @SuppressWarnings("unchecked")
109365f83483b550d95bae2f90bc16439d24713a124limpbizkit      TypeLiteral<T> guiceProviderType = (TypeLiteral<T>) TypeLiteral.get(
110365f83483b550d95bae2f90bc16439d24713a124limpbizkit          Types.providerOf(parameterizedType.getActualTypeArguments()[0]));
111365f83483b550d95bae2f90bc16439d24713a124limpbizkit      return guiceProviderType;
112365f83483b550d95bae2f90bc16439d24713a124limpbizkit    }
113365f83483b550d95bae2f90bc16439d24713a124limpbizkit
1143beaaaff52598e849659281fed35dc29a221fac4limpbizkit    @SuppressWarnings("unchecked")
115365f83483b550d95bae2f90bc16439d24713a124limpbizkit    TypeLiteral<T> wrappedPrimitives = (TypeLiteral<T>) PRIMITIVE_TO_WRAPPER.get(typeLiteral);
116825f8c1df885b9d7643a9e18e336984f0138edafsameb    if (wrappedPrimitives != null) {
117825f8c1df885b9d7643a9e18e336984f0138edafsameb      return wrappedPrimitives;
118825f8c1df885b9d7643a9e18e336984f0138edafsameb    }
119825f8c1df885b9d7643a9e18e336984f0138edafsameb
120825f8c1df885b9d7643a9e18e336984f0138edafsameb    // If we know this isn't a subclass, return as-is.
121825f8c1df885b9d7643a9e18e336984f0138edafsameb    if (typeLiteral.getClass() == TypeLiteral.class) {
122825f8c1df885b9d7643a9e18e336984f0138edafsameb      return typeLiteral;
123825f8c1df885b9d7643a9e18e336984f0138edafsameb    }
124825f8c1df885b9d7643a9e18e336984f0138edafsameb
125825f8c1df885b9d7643a9e18e336984f0138edafsameb    // recreate the TypeLiteral to avoid anonymous TypeLiterals from holding refs to their
126825f8c1df885b9d7643a9e18e336984f0138edafsameb    // surrounding classes.
127825f8c1df885b9d7643a9e18e336984f0138edafsameb    @SuppressWarnings("unchecked")
128825f8c1df885b9d7643a9e18e336984f0138edafsameb    TypeLiteral<T> recreated = (TypeLiteral<T>) TypeLiteral.get(typeLiteral.getType());
129825f8c1df885b9d7643a9e18e336984f0138edafsameb    return recreated;
1304272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit  }
1314272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
1324272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit  /**
1334272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit   * Returns true if {@code type} is free from type variables.
1344272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit   */
1354272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit  private static boolean isFullySpecified(Type type) {
1364272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    if (type instanceof Class) {
1374272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      return true;
1384272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
1394272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    } else if (type instanceof CompositeType) {
1404272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      return ((CompositeType) type).isFullySpecified();
1414272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
1424272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    } else if (type instanceof TypeVariable){
1434272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      return false;
1444272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
1454272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    } else {
1464272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      return ((CompositeType) canonicalize(type)).isFullySpecified();
1474272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    }
1483beaaaff52598e849659281fed35dc29a221fac4limpbizkit  }
1493beaaaff52598e849659281fed35dc29a221fac4limpbizkit
1503beaaaff52598e849659281fed35dc29a221fac4limpbizkit  /**
1513beaaaff52598e849659281fed35dc29a221fac4limpbizkit   * Returns a type that is functionally equal but not necessarily equal
1523beaaaff52598e849659281fed35dc29a221fac4limpbizkit   * according to {@link Object#equals(Object) Object.equals()}. The returned
1533beaaaff52598e849659281fed35dc29a221fac4limpbizkit   * type is {@link Serializable}.
1543beaaaff52598e849659281fed35dc29a221fac4limpbizkit   */
1553beaaaff52598e849659281fed35dc29a221fac4limpbizkit  public static Type canonicalize(Type type) {
1563ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit    if (type instanceof Class) {
1573ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      Class<?> c = (Class<?>) type;
1583ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;
1593ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit
1603ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit    } else if (type instanceof CompositeType) {
1613beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return type;
1623beaaaff52598e849659281fed35dc29a221fac4limpbizkit
1633beaaaff52598e849659281fed35dc29a221fac4limpbizkit    } else if (type instanceof ParameterizedType) {
1643beaaaff52598e849659281fed35dc29a221fac4limpbizkit      ParameterizedType p = (ParameterizedType) type;
165cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      return new ParameterizedTypeImpl(p.getOwnerType(),
1663beaaaff52598e849659281fed35dc29a221fac4limpbizkit          p.getRawType(), p.getActualTypeArguments());
1673beaaaff52598e849659281fed35dc29a221fac4limpbizkit
1683beaaaff52598e849659281fed35dc29a221fac4limpbizkit    } else if (type instanceof GenericArrayType) {
1693beaaaff52598e849659281fed35dc29a221fac4limpbizkit      GenericArrayType g = (GenericArrayType) type;
170cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      return new GenericArrayTypeImpl(g.getGenericComponentType());
1713beaaaff52598e849659281fed35dc29a221fac4limpbizkit
172cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    } else if (type instanceof WildcardType) {
173cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      WildcardType w = (WildcardType) type;
174cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds());
1753beaaaff52598e849659281fed35dc29a221fac4limpbizkit
1763beaaaff52598e849659281fed35dc29a221fac4limpbizkit    } else {
1773beaaaff52598e849659281fed35dc29a221fac4limpbizkit      // type is either serializable as-is or unsupported
1783beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return type;
1793beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
1803beaaaff52598e849659281fed35dc29a221fac4limpbizkit  }
1813beaaaff52598e849659281fed35dc29a221fac4limpbizkit
1823beaaaff52598e849659281fed35dc29a221fac4limpbizkit  public static Class<?> getRawType(Type type) {
1833beaaaff52598e849659281fed35dc29a221fac4limpbizkit    if (type instanceof Class<?>) {
1843beaaaff52598e849659281fed35dc29a221fac4limpbizkit      // type is a normal class.
1853beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return (Class<?>) type;
1863beaaaff52598e849659281fed35dc29a221fac4limpbizkit
1873beaaaff52598e849659281fed35dc29a221fac4limpbizkit    } else if (type instanceof ParameterizedType) {
1883beaaaff52598e849659281fed35dc29a221fac4limpbizkit      ParameterizedType parameterizedType = (ParameterizedType) type;
1893beaaaff52598e849659281fed35dc29a221fac4limpbizkit
1903beaaaff52598e849659281fed35dc29a221fac4limpbizkit      // I'm not exactly sure why getRawType() returns Type instead of Class.
1913beaaaff52598e849659281fed35dc29a221fac4limpbizkit      // Neal isn't either but suspects some pathological case related
1923beaaaff52598e849659281fed35dc29a221fac4limpbizkit      // to nested classes exists.
1933beaaaff52598e849659281fed35dc29a221fac4limpbizkit      Type rawType = parameterizedType.getRawType();
194cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      checkArgument(rawType instanceof Class,
195cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit          "Expected a Class, but <%s> is of type %s", type, type.getClass().getName());
1963beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return (Class<?>) rawType;
1973beaaaff52598e849659281fed35dc29a221fac4limpbizkit
1983beaaaff52598e849659281fed35dc29a221fac4limpbizkit    } else if (type instanceof GenericArrayType) {
1990bd3bd643f04f955bdb99e66375d4ee23131aa6dlimpbizkit      Type componentType = ((GenericArrayType)type).getGenericComponentType();
2000bd3bd643f04f955bdb99e66375d4ee23131aa6dlimpbizkit      return Array.newInstance(getRawType(componentType), 0).getClass();
2013beaaaff52598e849659281fed35dc29a221fac4limpbizkit
2024272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    } else if (type instanceof TypeVariable) {
2034272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      // we could use the variable's bounds, but that'll won't work if there are multiple.
2044272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      // having a raw type that's more general than necessary is okay
2054272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      return Object.class;
2064272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
2073beaaaff52598e849659281fed35dc29a221fac4limpbizkit    } else {
208cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
209cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit          + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
2103beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
2113beaaaff52598e849659281fed35dc29a221fac4limpbizkit  }
2123beaaaff52598e849659281fed35dc29a221fac4limpbizkit
2133beaaaff52598e849659281fed35dc29a221fac4limpbizkit  /**
2143beaaaff52598e849659281fed35dc29a221fac4limpbizkit   * Returns true if {@code a} and {@code b} are equal.
2153beaaaff52598e849659281fed35dc29a221fac4limpbizkit   */
2163beaaaff52598e849659281fed35dc29a221fac4limpbizkit  public static boolean equals(Type a, Type b) {
2173beaaaff52598e849659281fed35dc29a221fac4limpbizkit    if (a == b) {
2183beaaaff52598e849659281fed35dc29a221fac4limpbizkit      // also handles (a == null && b == null)
2193beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return true;
2203beaaaff52598e849659281fed35dc29a221fac4limpbizkit
2213beaaaff52598e849659281fed35dc29a221fac4limpbizkit    } else if (a instanceof Class) {
2223beaaaff52598e849659281fed35dc29a221fac4limpbizkit      // Class already specifies equals().
2233beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return a.equals(b);
2243beaaaff52598e849659281fed35dc29a221fac4limpbizkit
2253beaaaff52598e849659281fed35dc29a221fac4limpbizkit    } else if (a instanceof ParameterizedType) {
2263beaaaff52598e849659281fed35dc29a221fac4limpbizkit      if (!(b instanceof ParameterizedType)) {
2273beaaaff52598e849659281fed35dc29a221fac4limpbizkit        return false;
2283beaaaff52598e849659281fed35dc29a221fac4limpbizkit      }
2293beaaaff52598e849659281fed35dc29a221fac4limpbizkit
2304272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      // TODO: save a .clone() call
2313beaaaff52598e849659281fed35dc29a221fac4limpbizkit      ParameterizedType pa = (ParameterizedType) a;
2323beaaaff52598e849659281fed35dc29a221fac4limpbizkit      ParameterizedType pb = (ParameterizedType) b;
2333beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return Objects.equal(pa.getOwnerType(), pb.getOwnerType())
2343beaaaff52598e849659281fed35dc29a221fac4limpbizkit          && pa.getRawType().equals(pb.getRawType())
2353beaaaff52598e849659281fed35dc29a221fac4limpbizkit          && Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments());
2363beaaaff52598e849659281fed35dc29a221fac4limpbizkit
2373beaaaff52598e849659281fed35dc29a221fac4limpbizkit    } else if (a instanceof GenericArrayType) {
2383beaaaff52598e849659281fed35dc29a221fac4limpbizkit      if (!(b instanceof GenericArrayType)) {
2393beaaaff52598e849659281fed35dc29a221fac4limpbizkit        return false;
2403beaaaff52598e849659281fed35dc29a221fac4limpbizkit      }
2413beaaaff52598e849659281fed35dc29a221fac4limpbizkit
2423beaaaff52598e849659281fed35dc29a221fac4limpbizkit      GenericArrayType ga = (GenericArrayType) a;
2433beaaaff52598e849659281fed35dc29a221fac4limpbizkit      GenericArrayType gb = (GenericArrayType) b;
2443beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return equals(ga.getGenericComponentType(), gb.getGenericComponentType());
2453beaaaff52598e849659281fed35dc29a221fac4limpbizkit
246cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    } else if (a instanceof WildcardType) {
247cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      if (!(b instanceof WildcardType)) {
248cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        return false;
249cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      }
250cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
251cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      WildcardType wa = (WildcardType) a;
252cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      WildcardType wb = (WildcardType) b;
253cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds())
254cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit          && Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds());
255cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
2564272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    } else if (a instanceof TypeVariable) {
2574272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      if (!(b instanceof TypeVariable)) {
2584272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        return false;
2594272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      }
2604272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      TypeVariable<?> va = (TypeVariable) a;
2614272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      TypeVariable<?> vb = (TypeVariable) b;
262978ed86a76b3c47e8247f6691586b994bcf13dbcChristian Edward Gruber      return va.getGenericDeclaration().equals(vb.getGenericDeclaration())
2634272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit          && va.getName().equals(vb.getName());
2644272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
2653beaaaff52598e849659281fed35dc29a221fac4limpbizkit    } else {
2664272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      // This isn't a type we support. Could be a generic array type, wildcard type, etc.
2673beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return false;
2683beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
2693beaaaff52598e849659281fed35dc29a221fac4limpbizkit  }
2703beaaaff52598e849659281fed35dc29a221fac4limpbizkit
2713beaaaff52598e849659281fed35dc29a221fac4limpbizkit  private static int hashCodeOrZero(Object o) {
2723beaaaff52598e849659281fed35dc29a221fac4limpbizkit    return o != null ? o.hashCode() : 0;
2733beaaaff52598e849659281fed35dc29a221fac4limpbizkit  }
2743beaaaff52598e849659281fed35dc29a221fac4limpbizkit
2753ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit  public static String typeToString(Type type) {
2763ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit    return type instanceof Class ? ((Class) type).getName() : type.toString();
2773beaaaff52598e849659281fed35dc29a221fac4limpbizkit  }
2783beaaaff52598e849659281fed35dc29a221fac4limpbizkit
279564053fc876faf8325bb0d11e009c650bfaa588blimpbizkit  /**
28022de684ae3c7de50d59e1e3ec9a9ba4700483c1eSam Berlin   * Returns the generic supertype for {@code type}. For example, given a class {@code IntegerSet},
28122de684ae3c7de50d59e1e3ec9a9ba4700483c1eSam Berlin   * the result for when supertype is {@code Set.class} is {@code Set<Integer>} and the result
28222de684ae3c7de50d59e1e3ec9a9ba4700483c1eSam Berlin   * when the supertype is {@code Collection.class} is {@code Collection<Integer>}.
2834f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit   */
2844f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public static Type getGenericSupertype(Type type, Class<?> rawType, Class<?> toResolve) {
2854f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    if (toResolve == rawType) {
2864f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      return type;
2874f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
2884f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2894f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    // we skip searching through interfaces if unknown is an interface
2904f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    if (toResolve.isInterface()) {
2914f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      Class[] interfaces = rawType.getInterfaces();
2924f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      for (int i = 0, length = interfaces.length; i < length; i++) {
2934f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        if (interfaces[i] == toResolve) {
2944f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit          return rawType.getGenericInterfaces()[i];
2954f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        } else if (toResolve.isAssignableFrom(interfaces[i])) {
2964f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit          return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve);
2974f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        }
2984f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      }
2994f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
3004f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3014f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    // check our supertypes
3024f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    if (!rawType.isInterface()) {
3034f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      while (rawType != Object.class) {
3044f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        Class<?> rawSupertype = rawType.getSuperclass();
3054f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        if (rawSupertype == toResolve) {
3064f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit          return rawType.getGenericSuperclass();
3074f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        } else if (toResolve.isAssignableFrom(rawSupertype)) {
3084f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit          return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve);
3094f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        }
3104f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        rawType = rawSupertype;
3114f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      }
3124f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
3134f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3144f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    // we can't resolve this further
3154f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    return toResolve;
3164f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
3174f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3184f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public static Type resolveTypeVariable(Type type, Class<?> rawType, TypeVariable unknown) {
3194f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    Class<?> declaredByRaw = declaringClassOf(unknown);
3204f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3214f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    // we can't reduce this further
3224f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    if (declaredByRaw == null) {
3234f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      return unknown;
3244f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
3254f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3264f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    Type declaredBy = getGenericSupertype(type, rawType, declaredByRaw);
3274f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    if (declaredBy instanceof ParameterizedType) {
3284f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      int index = indexOf(declaredByRaw.getTypeParameters(), unknown);
3294f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      return ((ParameterizedType) declaredBy).getActualTypeArguments()[index];
3304f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
3314f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3324f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    return unknown;
3334f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
3344f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3354f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  private static int indexOf(Object[] array, Object toFind) {
3364f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    for (int i = 0; i < array.length; i++) {
3374f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      if (toFind.equals(array[i])) {
3384f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        return i;
3394f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      }
3404f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
3414f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    throw new NoSuchElementException();
3424f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
3434f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3444f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  /**
3454f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit   * Returns the declaring class of {@code typeVariable}, or {@code null} if it was not declared by
3464f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit   * a class.
3474f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit   */
3484f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  private static Class<?> declaringClassOf(TypeVariable typeVariable) {
3494f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
3504f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    return genericDeclaration instanceof Class
3514f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        ? (Class<?>) genericDeclaration
3524f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        : null;
3534f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
3544f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3554272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit  public static class ParameterizedTypeImpl
3564272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      implements ParameterizedType, Serializable, CompositeType {
3573beaaaff52598e849659281fed35dc29a221fac4limpbizkit    private final Type ownerType;
3583beaaaff52598e849659281fed35dc29a221fac4limpbizkit    private final Type rawType;
3593beaaaff52598e849659281fed35dc29a221fac4limpbizkit    private final Type[] typeArguments;
3603beaaaff52598e849659281fed35dc29a221fac4limpbizkit
3613beaaaff52598e849659281fed35dc29a221fac4limpbizkit    public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) {
36249f67c0f62bc1748dd32e1d86616085231e974e7limpbizkit      // require an owner type if the raw type needs it
36360826c015781b1173c9f98c8c22f63324ede6390bulach      ensureOwnerType(ownerType, rawType);
36449f67c0f62bc1748dd32e1d86616085231e974e7limpbizkit
3653beaaaff52598e849659281fed35dc29a221fac4limpbizkit      this.ownerType = ownerType == null ? null : canonicalize(ownerType);
3663beaaaff52598e849659281fed35dc29a221fac4limpbizkit      this.rawType = canonicalize(rawType);
3673beaaaff52598e849659281fed35dc29a221fac4limpbizkit      this.typeArguments = typeArguments.clone();
3683beaaaff52598e849659281fed35dc29a221fac4limpbizkit      for (int t = 0; t < this.typeArguments.length; t++) {
369cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        checkNotNull(this.typeArguments[t], "type parameter");
370cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        checkNotPrimitive(this.typeArguments[t], "type parameters");
3713beaaaff52598e849659281fed35dc29a221fac4limpbizkit        this.typeArguments[t] = canonicalize(this.typeArguments[t]);
3723beaaaff52598e849659281fed35dc29a221fac4limpbizkit      }
3733beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
3743beaaaff52598e849659281fed35dc29a221fac4limpbizkit
3753beaaaff52598e849659281fed35dc29a221fac4limpbizkit    public Type[] getActualTypeArguments() {
3763beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return typeArguments.clone();
3773beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
3783beaaaff52598e849659281fed35dc29a221fac4limpbizkit
3793beaaaff52598e849659281fed35dc29a221fac4limpbizkit    public Type getRawType() {
3803beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return rawType;
3813beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
3823beaaaff52598e849659281fed35dc29a221fac4limpbizkit
3833beaaaff52598e849659281fed35dc29a221fac4limpbizkit    public Type getOwnerType() {
3843beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return ownerType;
3853beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
3863beaaaff52598e849659281fed35dc29a221fac4limpbizkit
3874272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    public boolean isFullySpecified() {
3884272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      if (ownerType != null && !MoreTypes.isFullySpecified(ownerType)) {
3894272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        return false;
3904272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      }
3914272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
3924272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      if (!MoreTypes.isFullySpecified(rawType)) {
3934272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        return false;
3944272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      }
3954272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
3964272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      for (Type type : typeArguments) {
3974272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        if (!MoreTypes.isFullySpecified(type)) {
3984272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit          return false;
3994272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        }
4004272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      }
4014272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
4024272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      return true;
4034272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    }
4044272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
4053beaaaff52598e849659281fed35dc29a221fac4limpbizkit    @Override public boolean equals(Object other) {
4063beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return other instanceof ParameterizedType
4073beaaaff52598e849659281fed35dc29a221fac4limpbizkit          && MoreTypes.equals(this, (ParameterizedType) other);
4083beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
4093beaaaff52598e849659281fed35dc29a221fac4limpbizkit
4103beaaaff52598e849659281fed35dc29a221fac4limpbizkit    @Override public int hashCode() {
4113ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      return Arrays.hashCode(typeArguments)
4123ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit          ^ rawType.hashCode()
4133ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit          ^ hashCodeOrZero(ownerType);
4143beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
4153beaaaff52598e849659281fed35dc29a221fac4limpbizkit
4163beaaaff52598e849659281fed35dc29a221fac4limpbizkit    @Override public String toString() {
4173ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      StringBuilder stringBuilder = new StringBuilder(30 * (typeArguments.length + 1));
4183ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      stringBuilder.append(typeToString(rawType));
4192e8f7f9e9a7f3dbbebf76d3b64b0e668d1eb62casberlin
4202e8f7f9e9a7f3dbbebf76d3b64b0e668d1eb62casberlin      if (typeArguments.length == 0) {
4212e8f7f9e9a7f3dbbebf76d3b64b0e668d1eb62casberlin        return stringBuilder.toString();
4222e8f7f9e9a7f3dbbebf76d3b64b0e668d1eb62casberlin      }
4232e8f7f9e9a7f3dbbebf76d3b64b0e668d1eb62casberlin
4242e8f7f9e9a7f3dbbebf76d3b64b0e668d1eb62casberlin      stringBuilder.append("<").append(typeToString(typeArguments[0]));
4252e8f7f9e9a7f3dbbebf76d3b64b0e668d1eb62casberlin      for (int i = 1; i < typeArguments.length; i++) {
4262e8f7f9e9a7f3dbbebf76d3b64b0e668d1eb62casberlin        stringBuilder.append(", ").append(typeToString(typeArguments[i]));
4273ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      }
4283ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      return stringBuilder.append(">").toString();
4293beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
4303beaaaff52598e849659281fed35dc29a221fac4limpbizkit
43160826c015781b1173c9f98c8c22f63324ede6390bulach    private static void ensureOwnerType(Type ownerType, Type rawType) {
43260826c015781b1173c9f98c8c22f63324ede6390bulach      if (rawType instanceof Class<?>) {
43360826c015781b1173c9f98c8c22f63324ede6390bulach        Class rawTypeAsClass = (Class) rawType;
43460826c015781b1173c9f98c8c22f63324ede6390bulach        checkArgument(ownerType != null || rawTypeAsClass.getEnclosingClass() == null,
43560826c015781b1173c9f98c8c22f63324ede6390bulach            "No owner type for enclosed %s", rawType);
43660826c015781b1173c9f98c8c22f63324ede6390bulach        checkArgument(ownerType == null || rawTypeAsClass.getEnclosingClass() != null,
43760826c015781b1173c9f98c8c22f63324ede6390bulach            "Owner type for unenclosed %s", rawType);
43860826c015781b1173c9f98c8c22f63324ede6390bulach      }
43960826c015781b1173c9f98c8c22f63324ede6390bulach    }
44060826c015781b1173c9f98c8c22f63324ede6390bulach
4413beaaaff52598e849659281fed35dc29a221fac4limpbizkit    private static final long serialVersionUID = 0;
4423beaaaff52598e849659281fed35dc29a221fac4limpbizkit  }
4433beaaaff52598e849659281fed35dc29a221fac4limpbizkit
4444272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit  public static class GenericArrayTypeImpl
4454272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      implements GenericArrayType, Serializable, CompositeType {
4463beaaaff52598e849659281fed35dc29a221fac4limpbizkit    private final Type componentType;
4473beaaaff52598e849659281fed35dc29a221fac4limpbizkit
4483beaaaff52598e849659281fed35dc29a221fac4limpbizkit    public GenericArrayTypeImpl(Type componentType) {
4493beaaaff52598e849659281fed35dc29a221fac4limpbizkit      this.componentType = canonicalize(componentType);
4503beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
4513beaaaff52598e849659281fed35dc29a221fac4limpbizkit
4523beaaaff52598e849659281fed35dc29a221fac4limpbizkit    public Type getGenericComponentType() {
4533beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return componentType;
4543beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
4553beaaaff52598e849659281fed35dc29a221fac4limpbizkit
4564272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    public boolean isFullySpecified() {
4574272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      return MoreTypes.isFullySpecified(componentType);
4584272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    }
4594272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
4603beaaaff52598e849659281fed35dc29a221fac4limpbizkit    @Override public boolean equals(Object o) {
4613beaaaff52598e849659281fed35dc29a221fac4limpbizkit      return o instanceof GenericArrayType
4623beaaaff52598e849659281fed35dc29a221fac4limpbizkit          && MoreTypes.equals(this, (GenericArrayType) o);
4633beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
4643beaaaff52598e849659281fed35dc29a221fac4limpbizkit
4653beaaaff52598e849659281fed35dc29a221fac4limpbizkit    @Override public int hashCode() {
4663ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      return componentType.hashCode();
4673beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
4683beaaaff52598e849659281fed35dc29a221fac4limpbizkit
4693beaaaff52598e849659281fed35dc29a221fac4limpbizkit    @Override public String toString() {
4703ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      return typeToString(componentType) + "[]";
4713beaaaff52598e849659281fed35dc29a221fac4limpbizkit    }
4723beaaaff52598e849659281fed35dc29a221fac4limpbizkit
4733beaaaff52598e849659281fed35dc29a221fac4limpbizkit    private static final long serialVersionUID = 0;
4743beaaaff52598e849659281fed35dc29a221fac4limpbizkit  }
475564053fc876faf8325bb0d11e009c650bfaa588blimpbizkit
476564053fc876faf8325bb0d11e009c650bfaa588blimpbizkit  /**
477cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit   * The WildcardType interface supports multiple upper bounds and multiple
478cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit   * lower bounds. We only support what the Java 6 language needs - at most one
479cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit   * bound. If a lower bound is set, the upper bound must be Object.class.
480cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit   */
4814272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit  public static class WildcardTypeImpl implements WildcardType, Serializable, CompositeType {
482cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    private final Type upperBound;
483cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    private final Type lowerBound;
484cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
485cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    public WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) {
48659a6042697af2cceb2e3dc7b70246b841903eae6limpbizkit      checkArgument(lowerBounds.length <= 1, "Must have at most one lower bound.");
487cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      checkArgument(upperBounds.length == 1, "Must have exactly one upper bound.");
488cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
489cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      if (lowerBounds.length == 1) {
490cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        checkNotNull(lowerBounds[0], "lowerBound");
491cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        checkNotPrimitive(lowerBounds[0], "wildcard bounds");
492cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        checkArgument(upperBounds[0] == Object.class, "bounded both ways");
493cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        this.lowerBound = canonicalize(lowerBounds[0]);
494cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        this.upperBound = Object.class;
495cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
496cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      } else {
497cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        checkNotNull(upperBounds[0], "upperBound");
498cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        checkNotPrimitive(upperBounds[0], "wildcard bounds");
499cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        this.lowerBound = null;
500cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        this.upperBound = canonicalize(upperBounds[0]);
501cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      }
502cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    }
503cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
504cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    public Type[] getUpperBounds() {
505cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      return new Type[] { upperBound };
506cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    }
507cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
508cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    public Type[] getLowerBounds() {
509cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      return lowerBound != null ? new Type[] { lowerBound } : EMPTY_TYPE_ARRAY;
510cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    }
511cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
5124272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    public boolean isFullySpecified() {
5134272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit      return MoreTypes.isFullySpecified(upperBound)
5144272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit          && (lowerBound == null || MoreTypes.isFullySpecified(lowerBound));
5154272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    }
5164272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit
517cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    @Override public boolean equals(Object other) {
518cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit      return other instanceof WildcardType
519cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit          && MoreTypes.equals(this, (WildcardType) other);
520cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    }
521cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
522cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    @Override public int hashCode() {
5233ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      // this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds());
5243ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      return (lowerBound != null ? 31 + lowerBound.hashCode() : 1)
5253ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit          ^ (31 + upperBound.hashCode());
526cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    }
527cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
528cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    @Override public String toString() {
5293ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      if (lowerBound != null) {
5303ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit        return "? super " + typeToString(lowerBound);
5313ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      } else if (upperBound == Object.class) {
5323ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit        return "?";
5333ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      } else {
5343ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit        return "? extends " + typeToString(upperBound);
5353ea8095def50d99f8f8a49c0fa6cc25e82217109limpbizkit      }
536cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    }
537cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
538cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    private static final long serialVersionUID = 0;
539cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit  }
540cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
541cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit  private static void checkNotPrimitive(Type type, String use) {
542cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit    checkArgument(!(type instanceof Class<?>) || !((Class) type).isPrimitive(),
543cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit        "Primitive types are not allowed in %s: %s", use, type);
544cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit  }
545cb32cbcd87c8b511afd532fc626110ee9362fb03limpbizkit
5464272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit  /** A type formed from other types, such as arrays, parameterized types or wildcard types */
5474272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit  private interface CompositeType {
5484272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    /** Returns true if there are no type variables in this type. */
5494272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    boolean isFullySpecified();
5504272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit  }
5513beaaaff52598e849659281fed35dc29a221fac4limpbizkit}
552