185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/** 2103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Copyright (C) 2008 Google Inc. 385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Licensed under the Apache License, Version 2.0 (the "License"); 5103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * you may not use this file except in compliance with the License. 685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * You may obtain a copy of the License at 785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * http://www.apache.org/licenses/LICENSE-2.0 985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 1085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Unless required by applicable law or agreed to in writing, software 1185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * distributed under the License is distributed on an "AS IS" BASIS, 1285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * See the License for the specific language governing permissions and 1485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * limitations under the License. 1585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 1685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 17103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 18103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliuspackage com.google.inject.internal; 19103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 2085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport static com.google.common.base.Preconditions.checkArgument; 2185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport static com.google.common.base.Preconditions.checkNotNull; 2285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 23103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusimport com.google.common.base.Objects; 24103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusimport com.google.common.collect.ImmutableMap; 25103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusimport com.google.inject.ConfigurationException; 2685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport com.google.inject.Key; 27103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusimport com.google.inject.TypeLiteral; 28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoimport com.google.inject.util.Types; 2985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 3085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.io.Serializable; 3185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.lang.reflect.Array; 3285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.lang.reflect.GenericArrayType; 3385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.lang.reflect.GenericDeclaration; 3485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.lang.reflect.ParameterizedType; 3585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.lang.reflect.Type; 3685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.lang.reflect.TypeVariable; 3785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.lang.reflect.WildcardType; 3885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.util.Arrays; 3985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.util.Map; 4085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoimport java.util.NoSuchElementException; 4185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 4285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/** 4385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Static methods for working with types that we aren't publishing in the 4485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * public {@code Types} API. 4585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 4685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * @author jessewilson@google.com (Jesse Wilson) 4785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 4885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hopublic class MoreTypes { 4985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 50103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius public static final Type[] EMPTY_TYPE_ARRAY = new Type[] {}; 5185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 5285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private MoreTypes() {} 5385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 5485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private static final Map<TypeLiteral<?>, TypeLiteral<?>> PRIMITIVE_TO_WRAPPER 5585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho = new ImmutableMap.Builder<TypeLiteral<?>, TypeLiteral<?>>() 5685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .put(TypeLiteral.get(boolean.class), TypeLiteral.get(Boolean.class)) 5785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .put(TypeLiteral.get(byte.class), TypeLiteral.get(Byte.class)) 5885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .put(TypeLiteral.get(short.class), TypeLiteral.get(Short.class)) 5985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .put(TypeLiteral.get(int.class), TypeLiteral.get(Integer.class)) 6085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .put(TypeLiteral.get(long.class), TypeLiteral.get(Long.class)) 6185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .put(TypeLiteral.get(float.class), TypeLiteral.get(Float.class)) 6285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .put(TypeLiteral.get(double.class), TypeLiteral.get(Double.class)) 6385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .put(TypeLiteral.get(char.class), TypeLiteral.get(Character.class)) 6485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .put(TypeLiteral.get(void.class), TypeLiteral.get(Void.class)) 6585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .build(); 6650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 67103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius /** 6885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Returns a key that doesn't hold any references to parent classes. 6927f654740f2a26ad62a5c155af9199af9e69b889claireho * This is necessary for anonymous keys, so ensure we don't hold a ref 7085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * to the containing module (or class) forever. 7185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 7285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public static <T> Key<T> canonicalizeKey(Key<T> key) { 7385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // If we know this isn't a subclass, return as-is. 7485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Otherwise, recreate the key to avoid the subclass 7585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (key.getClass() == Key.class) { 7685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return key; 7785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (key.getAnnotation() != null) { 78103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return Key.get(key.getTypeLiteral(), key.getAnnotation()); 7927f654740f2a26ad62a5c155af9199af9e69b889claireho } else if (key.getAnnotationType() != null) { 8085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return Key.get(key.getTypeLiteral(), key.getAnnotationType()); 8150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 8250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return Key.get(key.getTypeLiteral()); 8385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 84103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 85103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 86103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius /** 87103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Returns an type that's appropriate for use in a key. 88103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * 8985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * <p>If the raw type of {@code typeLiteral} is a {@code javax.inject.Provider}, this returns a 9085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * {@code com.google.inject.Provider} with the same type parameters. 9185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 9285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * <p>If the type is a primitive, the corresponding wrapper type will be returned. 9385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 9485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * @throws ConfigurationException if {@code type} contains a type variable 9585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 9685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public static <T> TypeLiteral<T> canonicalizeForKey(TypeLiteral<T> typeLiteral) { 9785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Type type = typeLiteral.getType(); 9885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (!isFullySpecified(type)) { 9985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Errors errors = new Errors().keyNotFullySpecified(typeLiteral); 10085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho throw new ConfigurationException(errors.getMessages()); 10185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 10285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 10385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (typeLiteral.getRawType() == javax.inject.Provider.class) { 10485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ParameterizedType parameterizedType = (ParameterizedType) type; 10585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 10685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // the following casts are generally unsafe, but com.google.inject.Provider extends 107103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // javax.inject.Provider and is covariant 108103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius @SuppressWarnings("unchecked") 109103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TypeLiteral<T> guiceProviderType = (TypeLiteral<T>) TypeLiteral.get( 11085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Types.providerOf(parameterizedType.getActualTypeArguments()[0])); 11185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return guiceProviderType; 11285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 11385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 11485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho @SuppressWarnings("unchecked") 11585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho TypeLiteral<T> wrappedPrimitives = (TypeLiteral<T>) PRIMITIVE_TO_WRAPPER.get(typeLiteral); 11685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (wrappedPrimitives != null) { 11785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return wrappedPrimitives; 118103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 11985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 12085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // If we know this isn't a subclass, return as-is. 12185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (typeLiteral.getClass() == TypeLiteral.class) { 12285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return typeLiteral; 12385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 12485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 12585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // recreate the TypeLiteral to avoid anonymous TypeLiterals from holding refs to their 12685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // surrounding classes. 12785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho @SuppressWarnings("unchecked") 12885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho TypeLiteral<T> recreated = (TypeLiteral<T>) TypeLiteral.get(typeLiteral.getType()); 12985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return recreated; 13085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 13185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 13285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /** 13385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Returns true if {@code type} is free from type variables. 13485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 13585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private static boolean isFullySpecified(Type type) { 13685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (type instanceof Class) { 13785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return true; 13885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 13985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (type instanceof CompositeType) { 14085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return ((CompositeType) type).isFullySpecified(); 14185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 14285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (type instanceof TypeVariable){ 14385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return false; 14485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 14585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else { 14685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return ((CompositeType) canonicalize(type)).isFullySpecified(); 14785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 14885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 149103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 150103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius /** 151103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Returns a type that is functionally equal but not necessarily equal 15285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * according to {@link Object#equals(Object) Object.equals()}. The returned 15385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * type is {@link Serializable}. 154103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius */ 15585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public static Type canonicalize(Type type) { 15685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (type instanceof Class) { 15785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Class<?> c = (Class<?>) type; 15885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c; 15985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 16085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (type instanceof CompositeType) { 16185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return type; 16285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 16385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (type instanceof ParameterizedType) { 16485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ParameterizedType p = (ParameterizedType) type; 16585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return new ParameterizedTypeImpl(p.getOwnerType(), 16685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho p.getRawType(), p.getActualTypeArguments()); 16785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 16885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (type instanceof GenericArrayType) { 16985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho GenericArrayType g = (GenericArrayType) type; 17085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return new GenericArrayTypeImpl(g.getGenericComponentType()); 17185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 17285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (type instanceof WildcardType) { 17385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho WildcardType w = (WildcardType) type; 17485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds()); 175103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 176103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 177103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // type is either serializable as-is or unsupported 178103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return type; 179103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 180103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 181103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 182103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius public static Class<?> getRawType(Type type) { 183103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (type instanceof Class<?>) { 184103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // type is a normal class. 185103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return (Class<?>) type; 186103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 187103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (type instanceof ParameterizedType) { 188103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius ParameterizedType parameterizedType = (ParameterizedType) type; 189103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 190103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // I'm not exactly sure why getRawType() returns Type instead of Class. 191103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Neal isn't either but suspects some pathological case related 192103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // to nested classes exists. 193103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius Type rawType = parameterizedType.getRawType(); 19485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho checkArgument(rawType instanceof Class, 19585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho "Expected a Class, but <%s> is of type %s", type, type.getClass().getName()); 19685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return (Class<?>) rawType; 19785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 19885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (type instanceof GenericArrayType) { 19985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Type componentType = ((GenericArrayType)type).getGenericComponentType(); 20085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return Array.newInstance(getRawType(componentType), 0).getClass(); 201103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 20285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (type instanceof TypeVariable) { 203103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // we could use the variable's bounds, but that'll won't work if there are multiple. 204103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // having a raw type that's more general than necessary is okay 205103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return Object.class; 20685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 20785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else { 20885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " 20985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName()); 21085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 21150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 21285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 21385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /** 21485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Returns true if {@code a} and {@code b} are equal. 21585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 21685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public static boolean equals(Type a, Type b) { 21785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (a == b) { 21885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // also handles (a == null && b == null) 21985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return true; 22085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 22185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (a instanceof Class) { 22285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Class already specifies equals(). 22385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return a.equals(b); 22485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 22585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (a instanceof ParameterizedType) { 22685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (!(b instanceof ParameterizedType)) { 22785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return false; 22885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 22985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 23085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // TODO: save a .clone() call 23185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ParameterizedType pa = (ParameterizedType) a; 23250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ParameterizedType pb = (ParameterizedType) b; 23385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return Objects.equal(pa.getOwnerType(), pb.getOwnerType()) 23485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho && pa.getRawType().equals(pb.getRawType()) 235103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius && Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments()); 236103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 23785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (a instanceof GenericArrayType) { 23885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (!(b instanceof GenericArrayType)) { 23985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return false; 24085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 24185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 24285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho GenericArrayType ga = (GenericArrayType) a; 24385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho GenericArrayType gb = (GenericArrayType) b; 24485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return equals(ga.getGenericComponentType(), gb.getGenericComponentType()); 24585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 24685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (a instanceof WildcardType) { 24785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (!(b instanceof WildcardType)) { 24885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return false; 24985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 25085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 25185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho WildcardType wa = (WildcardType) a; 25285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho WildcardType wb = (WildcardType) b; 25385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds()) 25485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho && Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds()); 25585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 25685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (a instanceof TypeVariable) { 25785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (!(b instanceof TypeVariable)) { 25885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return false; 25985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 26085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho TypeVariable<?> va = (TypeVariable) a; 26185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho TypeVariable<?> vb = (TypeVariable) b; 26285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return va.getGenericDeclaration().equals(vb.getGenericDeclaration()) 26385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho && va.getName().equals(vb.getName()); 26485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 26585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else { 26685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // This isn't a type we support. Could be a generic array type, wildcard type, etc. 26785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return false; 26885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 26985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 27085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 27185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private static int hashCodeOrZero(Object o) { 27285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return o != null ? o.hashCode() : 0; 27385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 27485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 27585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public static String typeToString(Type type) { 27685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return type instanceof Class ? ((Class) type).getName() : type.toString(); 27785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 27885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 27985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /** 28050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Returns the generic supertype for {@code type}. For example, given a class {@code IntegerSet}, 28150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * the result for when supertype is {@code Set.class} is {@code Set<Integer>} and the result 28250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * when the supertype is {@code Collection.class} is {@code Collection<Integer>}. 28350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 28485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public static Type getGenericSupertype(Type type, Class<?> rawType, Class<?> toResolve) { 28585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (toResolve == rawType) { 28685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return type; 28785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 28885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 28985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // we skip searching through interfaces if unknown is an interface 29085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (toResolve.isInterface()) { 29185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Class[] interfaces = rawType.getInterfaces(); 29285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho for (int i = 0, length = interfaces.length; i < length; i++) { 29385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (interfaces[i] == toResolve) { 29485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return rawType.getGenericInterfaces()[i]; 29585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (toResolve.isAssignableFrom(interfaces[i])) { 29685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve); 29785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 29885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 29985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 30085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 30185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // check our supertypes 30285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (!rawType.isInterface()) { 30385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho while (rawType != Object.class) { 30485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Class<?> rawSupertype = rawType.getSuperclass(); 30585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (rawSupertype == toResolve) { 30685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return rawType.getGenericSuperclass(); 30785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (toResolve.isAssignableFrom(rawSupertype)) { 30885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve); 30985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 31085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rawType = rawSupertype; 31185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 31285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 31385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 31485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // we can't resolve this further 31585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return toResolve; 31685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 31785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 31885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public static Type resolveTypeVariable(Type type, Class<?> rawType, TypeVariable unknown) { 31985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Class<?> declaredByRaw = declaringClassOf(unknown); 32085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 32185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // we can't reduce this further 32285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (declaredByRaw == null) { 32385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return unknown; 32485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 32585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 32685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Type declaredBy = getGenericSupertype(type, rawType, declaredByRaw); 32785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (declaredBy instanceof ParameterizedType) { 32885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int index = indexOf(declaredByRaw.getTypeParameters(), unknown); 32985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return ((ParameterizedType) declaredBy).getActualTypeArguments()[index]; 33085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 33185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 33285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return unknown; 33385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 33485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 33585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private static int indexOf(Object[] array, Object toFind) { 33685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho for (int i = 0; i < array.length; i++) { 33785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (toFind.equals(array[i])) { 33885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return i; 33985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 34085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 34185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho throw new NoSuchElementException(); 34285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 34385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 34485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /** 34585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Returns the declaring class of {@code typeVariable}, or {@code null} if it was not declared by 34685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * a class. 34785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 34885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private static Class<?> declaringClassOf(TypeVariable typeVariable) { 34985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration(); 35085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return genericDeclaration instanceof Class 35185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ? (Class<?>) genericDeclaration 35285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho : null; 35385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 35485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 35585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public static class ParameterizedTypeImpl 35685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho implements ParameterizedType, Serializable, CompositeType { 35785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private final Type ownerType; 35885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private final Type rawType; 35985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private final Type[] typeArguments; 36085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 36185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) { 36285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // require an owner type if the raw type needs it 36385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ensureOwnerType(ownerType, rawType); 36485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 36585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho this.ownerType = ownerType == null ? null : canonicalize(ownerType); 36685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho this.rawType = canonicalize(rawType); 36785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho this.typeArguments = typeArguments.clone(); 36885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho for (int t = 0; t < this.typeArguments.length; t++) { 36985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho checkNotNull(this.typeArguments[t], "type parameter"); 37085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho checkNotPrimitive(this.typeArguments[t], "type parameters"); 37185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho this.typeArguments[t] = canonicalize(this.typeArguments[t]); 37285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 37385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 37485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 37585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public Type[] getActualTypeArguments() { 376103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return typeArguments.clone(); 377103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 378103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 379103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius public Type getRawType() { 380103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return rawType; 381103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 38285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 38385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public Type getOwnerType() { 38450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return ownerType; 38550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 38650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 38750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho public boolean isFullySpecified() { 38850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ownerType != null && !MoreTypes.isFullySpecified(ownerType)) { 38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return false; 39050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 39185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 39285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (!MoreTypes.isFullySpecified(rawType)) { 39385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return false; 39485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 39585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 39685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho for (Type type : typeArguments) { 39785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (!MoreTypes.isFullySpecified(type)) { 39885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return false; 39985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 40085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 40185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 40285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return true; 40385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 40485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 40585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho @Override public boolean equals(Object other) { 40685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return other instanceof ParameterizedType 40785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho && MoreTypes.equals(this, (ParameterizedType) other); 40885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 40985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 41085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho @Override public int hashCode() { 41185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return Arrays.hashCode(typeArguments) 41285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ^ rawType.hashCode() 41385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ^ hashCodeOrZero(ownerType); 41485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 41585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 41685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho @Override public String toString() { 41785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho StringBuilder stringBuilder = new StringBuilder(30 * (typeArguments.length + 1)); 41885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho stringBuilder.append(typeToString(rawType)); 41985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 42085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (typeArguments.length == 0) { 42185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return stringBuilder.toString(); 42285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 42385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 42485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho stringBuilder.append("<").append(typeToString(typeArguments[0])); 42585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho for (int i = 1; i < typeArguments.length; i++) { 42685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho stringBuilder.append(", ").append(typeToString(typeArguments[i])); 42785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 42885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return stringBuilder.append(">").toString(); 42985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 430103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 431103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius private static void ensureOwnerType(Type ownerType, Type rawType) { 432103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (rawType instanceof Class<?>) { 433103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius Class rawTypeAsClass = (Class) rawType; 434103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius checkArgument(ownerType != null || rawTypeAsClass.getEnclosingClass() == null, 435103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius "No owner type for enclosed %s", rawType); 436103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius checkArgument(ownerType == null || rawTypeAsClass.getEnclosingClass() != null, 437103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius "Owner type for unenclosed %s", rawType); 438103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 439103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 44085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 44185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private static final long serialVersionUID = 0; 44285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 44385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 44485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public static class GenericArrayTypeImpl 44585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho implements GenericArrayType, Serializable, CompositeType { 44685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private final Type componentType; 44785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 44885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public GenericArrayTypeImpl(Type componentType) { 44985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho this.componentType = canonicalize(componentType); 45085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 45185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 45285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public Type getGenericComponentType() { 45385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return componentType; 45485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 45585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 45685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho public boolean isFullySpecified() { 45785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return MoreTypes.isFullySpecified(componentType); 45885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 45985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 46085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho @Override public boolean equals(Object o) { 46185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return o instanceof GenericArrayType 46285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho && MoreTypes.equals(this, (GenericArrayType) o); 46385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 46485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 46585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho @Override public int hashCode() { 46685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return componentType.hashCode(); 46785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 46885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 46985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho @Override public String toString() { 47085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return typeToString(componentType) + "[]"; 47185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 47285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 47385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private static final long serialVersionUID = 0; 47485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 47585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 47685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /** 47785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * The WildcardType interface supports multiple upper bounds and multiple 47885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * lower bounds. We only support what the Java 6 language needs - at most one 47985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * bound. If a lower bound is set, the upper bound must be Object.class. 48050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 48127f654740f2a26ad62a5c155af9199af9e69b889claireho public static class WildcardTypeImpl implements WildcardType, Serializable, CompositeType { 48227f654740f2a26ad62a5c155af9199af9e69b889claireho private final Type upperBound; 48327f654740f2a26ad62a5c155af9199af9e69b889claireho private final Type lowerBound; 48427f654740f2a26ad62a5c155af9199af9e69b889claireho 48527f654740f2a26ad62a5c155af9199af9e69b889claireho public WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) { 48627f654740f2a26ad62a5c155af9199af9e69b889claireho checkArgument(lowerBounds.length <= 1, "Must have at most one lower bound."); 48727f654740f2a26ad62a5c155af9199af9e69b889claireho checkArgument(upperBounds.length == 1, "Must have exactly one upper bound."); 48850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 48950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lowerBounds.length == 1) { 490103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius checkNotNull(lowerBounds[0], "lowerBound"); 491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho checkNotPrimitive(lowerBounds[0], "wildcard bounds"); 492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho checkArgument(upperBounds[0] == Object.class, "bounded both ways"); 49327f654740f2a26ad62a5c155af9199af9e69b889claireho this.lowerBound = canonicalize(lowerBounds[0]); 49427f654740f2a26ad62a5c155af9199af9e69b889claireho this.upperBound = Object.class; 49527f654740f2a26ad62a5c155af9199af9e69b889claireho 496103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 49750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho checkNotNull(upperBounds[0], "upperBound"); 49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho checkNotPrimitive(upperBounds[0], "wildcard bounds"); 499103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius this.lowerBound = null; 50050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho this.upperBound = canonicalize(upperBounds[0]); 50127f654740f2a26ad62a5c155af9199af9e69b889claireho } 50250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 50350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 50450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho public Type[] getUpperBounds() { 50550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return new Type[] { upperBound }; 506103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 50750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 508103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius public Type[] getLowerBounds() { 50927f654740f2a26ad62a5c155af9199af9e69b889claireho return lowerBound != null ? new Type[] { lowerBound } : EMPTY_TYPE_ARRAY; 51050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 51127f654740f2a26ad62a5c155af9199af9e69b889claireho 51250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho public boolean isFullySpecified() { 51350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return MoreTypes.isFullySpecified(upperBound) 51427f654740f2a26ad62a5c155af9199af9e69b889claireho && (lowerBound == null || MoreTypes.isFullySpecified(lowerBound)); 515103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 51650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 51727f654740f2a26ad62a5c155af9199af9e69b889claireho @Override public boolean equals(Object other) { 51827f654740f2a26ad62a5c155af9199af9e69b889claireho return other instanceof WildcardType 51927f654740f2a26ad62a5c155af9199af9e69b889claireho && MoreTypes.equals(this, (WildcardType) other); 52027f654740f2a26ad62a5c155af9199af9e69b889claireho } 52127f654740f2a26ad62a5c155af9199af9e69b889claireho 52227f654740f2a26ad62a5c155af9199af9e69b889claireho @Override public int hashCode() { 52327f654740f2a26ad62a5c155af9199af9e69b889claireho // this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds()); 52450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return (lowerBound != null ? 31 + lowerBound.hashCode() : 1) 52585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ^ (31 + upperBound.hashCode()); 52685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 52785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 52885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho @Override public String toString() { 52985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (lowerBound != null) { 53027f654740f2a26ad62a5c155af9199af9e69b889claireho return "? super " + typeToString(lowerBound); 53185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (upperBound == Object.class) { 53285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return "?"; 53385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else { 53485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return "? extends " + typeToString(upperBound); 53585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 53685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 53785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 53827f654740f2a26ad62a5c155af9199af9e69b889claireho private static final long serialVersionUID = 0; 53927f654740f2a26ad62a5c155af9199af9e69b889claireho } 540103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 54185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private static void checkNotPrimitive(Type type, String use) { 54285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho checkArgument(!(type instanceof Class<?>) || !((Class) type).isPrimitive(), 54385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho "Primitive types are not allowed in %s: %s", use, type); 54485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 54585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 54685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /** A type formed from other types, such as arrays, parameterized types or wildcard types */ 54785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho private interface CompositeType { 54850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /** Returns true if there are no type variables in this type. */ 54950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho boolean isFullySpecified(); 55050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 55150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 55285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho