    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017    package org.apache.commons.lang3.reflect;
    018
    019    import java.lang.reflect.Array;
    020    import java.lang.reflect.GenericArrayType;
    021    import java.lang.reflect.ParameterizedType;
    022    import java.lang.reflect.Type;
    023    import java.lang.reflect.TypeVariable;
    024    import java.lang.reflect.WildcardType;
    025    import java.util.Arrays;
    026    import java.util.HashMap;
    027    import java.util.HashSet;
    028    import java.util.List;
    029    import java.util.Map;
    030    import java.util.Set;
    031
    032    import org.apache.commons.lang3.ClassUtils;
    033
    034    /**
    035     * <p> Utility methods focusing on type inspection, particularly with regard to
    036     * generics. </p>
    037     *
    038     * @author David M. Sledge
    039     * @author Matt Benson
    040     * @author James Carman
    041     * @since 3.0
    042     * @version $Id: TypeUtils.java 966171 2010-07-21 10:47:57Z sebb $
    043     */
    044    public class TypeUtils {
    045
    046        /**
    047         * <p> TypeUtils instances should NOT be constructed in standard
    048         * programming. Instead, the class should be used as
    049         * <code>TypeUtils.isAssignable(cls, toClass)</code>. </p> <p> This
    050         * constructor is public to permit tools that require a JavaBean instance to
    051         * operate. </p>
    052         */
    053        public TypeUtils() {
    054            super();
    055        }
    056
    057        /**
    058         * <p> Checks if the subject type may be implicitly cast to the target type
    059         * following the Java generics rules. If both types are {@link Class}
    060         * objects, the method returns the result of
    061         * {@link ClassUtils#isAssignable(Class, Class)}. </p>
    062         *
    063         * @param type the subject type to be assigned to the target type
    064         * @param toType the target type
    065         * @return <code>true</code> if <code>type</code> is assignable to <code>toType</code>.
    066         */
    067        public static boolean isAssignable(Type type, Type toType) {
    068            return isAssignable(type, toType, null);
    069        }
    070
    071        /**
    072         * <p> Checks if the subject type may be implicitly cast to the target type
    073         * following the Java generics rules. </p>
    074         *
    075         * @param type the subject type to be assigned to the target type
    076         * @param toType the target type
    077         * @param typeVarAssigns optional map of type variable assignments
    078         * @return <code>true</code> if <code>type</code> is assignable to <code>toType</code>.
    079         */
    080        private static boolean isAssignable(Type type, Type toType,
    081                Map<TypeVariable<?>, Type> typeVarAssigns) {
    082            if (toType == null || toType instanceof Class<?>) {
    083                return isAssignable(type, (Class<?>) toType);
    084            }
    085
    086            if (toType instanceof ParameterizedType) {
    087                return isAssignable(type, (ParameterizedType) toType, typeVarAssigns);
    088            }
    089
    090            if (toType instanceof GenericArrayType) {
    091                return isAssignable(type, (GenericArrayType) toType, typeVarAssigns);
    092            }
    093
    094            if (toType instanceof WildcardType) {
    095                return isAssignable(type, (WildcardType) toType, typeVarAssigns);
    096            }
    097
    098            // *
    099            if (toType instanceof TypeVariable<?>) {
    100                return isAssignable(type, (TypeVariable<?>) toType, typeVarAssigns);
    101            }
    102            // */
    103
    104            throw new IllegalStateException("found an unhandled type: " + toType);
    105        }
    106
    107        /**
    108         * <p> Checks if the subject type may be implicitly cast to the target class
    109         * following the Java generics rules. </p>
    110         *
    111         * @param type the subject type to be assigned to the target type
    112         * @param toClass the target class
    113         * @return true if <code>type</code> is assignable to <code>toClass</code>.
    114         */
    115        private static boolean isAssignable(Type type, Class<?> toClass) {
    116            if (type == null) {
    117                // consistency with ClassUtils.isAssignable() behavior
    118                return toClass == null || !toClass.isPrimitive();
    119            }
    120
    121            // only a null type can be assigned to null type which
    122            // would have cause the previous to return true
    123            if (toClass == null) {
    124                return false;
    125            }
    126
    127            // all types are assignable to themselves
    128            if (toClass.equals(type)) {
    129                return true;
    130            }
    131
    132            if (type instanceof Class<?>) {
    133                // just comparing two classes
    134                return ClassUtils.isAssignable((Class<?>) type, toClass);
    135            }
    136
    137            if (type instanceof ParameterizedType) {
    138                // only have to compare the raw type to the class
    139                return isAssignable(getRawType((ParameterizedType) type), toClass);
    140            }
    141
    142            // *
    143            if (type instanceof TypeVariable<?>) {
    144                // if any of the bounds are assignable to the class, then the
    145                // type is assignable to the class.
    146                for (Type bound : ((TypeVariable<?>) type).getBounds()) {
    147                    if (isAssignable(bound, toClass)) {
    148                        return true;
    149                    }
    150                }
    151
    152                return false;
    153            }
    154
    155            // the only classes to which a generic array type can be assigned
    156            // are class Object and array classes
    157            if (type instanceof GenericArrayType) {
    158                return toClass.equals(Object.class)
    159                        || toClass.isArray()
    160                        && isAssignable(((GenericArrayType) type).getGenericComponentType(), toClass
    161                                .getComponentType());
    162            }
    163
    164            // wildcard types are not assignable to a class (though one would think
    165            // "? super Object" would be assignable to Object)
    166            if (type instanceof WildcardType) {
    167                return false;
    168            }
    169
    170            throw new IllegalStateException("found an unhandled type: " + type);
    171        }
    172
    173        /**
    174         * <p> Checks if the subject type may be implicitly cast to the target
    175         * parameterized type following the Java generics rules. </p>
    176         *
    177         * @param type the subject type to be assigned to the target type
    178         * @param toParameterizedType the target parameterized type
    179         * @return true if <code>type</code> is assignable to <code>toType</code>.
    180         */
    181        private static boolean isAssignable(Type type, ParameterizedType toParameterizedType,
    182                Map<TypeVariable<?>, Type> typeVarAssigns) {
    183            if (type == null) {
    184                return true;
    185            }
    186
    187            // only a null type can be assigned to null type which
    188            // would have cause the previous to return true
    189            if (toParameterizedType == null) {
    190                return false;
    191            }
    192
    193            // all types are assignable to themselves
    194            if (toParameterizedType.equals(type)) {
    195                return true;
    196            }
    197
    198            // get the target type's raw type
    199            Class<?> toClass = getRawType(toParameterizedType);
    200            // get the subject type's type arguments including owner type arguments
    201            // and supertype arguments up to and including the target class.
    202            Map<TypeVariable<?>, Type> fromTypeVarAssigns = getTypeArguments(type, toClass, null);
    203
    204            // null means the two types are not compatible
    205            if (fromTypeVarAssigns == null) {
    206                return false;
    207            }
    208
    209            // compatible types, but there's no type arguments. this is equivalent
    210            // to comparing Map< ?, ? > to Map, and raw types are always assignable
    211            // to parameterized types.
    212            if (fromTypeVarAssigns.isEmpty()) {
    213                return true;
    214            }
    215
    216            // get the target type's type arguments including owner type arguments
    217            Map<TypeVariable<?>, Type> toTypeVarAssigns = getTypeArguments(toParameterizedType,
    218                    toClass, typeVarAssigns);
    219
    220            // now to check each type argument
    221            for (Map.Entry<TypeVariable<?>, Type> entry : toTypeVarAssigns.entrySet()) {
    222                Type toTypeArg = entry.getValue();
    223                Type fromTypeArg = fromTypeVarAssigns.get(entry.getKey());
    224
    225                // parameters must either be absent from the subject type, within
    226                // the bounds of the wildcard type, or be an exact match to the
    227                // parameters of the target type.
    228                if (fromTypeArg != null
    229                        && !toTypeArg.equals(fromTypeArg)
    230                        && !(toTypeArg instanceof WildcardType && isAssignable(fromTypeArg, toTypeArg,
    231                                typeVarAssigns))) {
    232                    return false;
    233                }
    234            }
    235
    236            return true;
    237        }
    238
    239        /**
    240         * <p> Checks if the subject type may be implicitly cast to the target
    241         * generic array type following the Java generics rules. </p>
    242         *
    243         * @param type the subject type to be assigned to the target type
    244         * @param toGenericArrayType the target generic array type
    245         * @return true if <code>type</code> is assignable to
    246         * <code>toGenericArrayType</code>.
    247         */
    248        private static boolean isAssignable(Type type, GenericArrayType toGenericArrayType,
    249                Map<TypeVariable<?>, Type> typeVarAssigns) {
    250            if (type == null) {
    251                return true;
    252            }
    253
    254            // only a null type can be assigned to null type which
    255            // would have cause the previous to return true
    256            if (toGenericArrayType == null) {
    257                return false;
    258            }
    259
    260            // all types are assignable to themselves
    261            if (toGenericArrayType.equals(type)) {
    262                return true;
    263            }
    264
    265            Type toComponentType = toGenericArrayType.getGenericComponentType();
    266
    267            if (type instanceof Class<?>) {
    268                Class<?> cls = (Class<?>) type;
    269
    270                // compare the component types
    271                return cls.isArray()
    272                        && isAssignable(cls.getComponentType(), toComponentType, typeVarAssigns);
    273            }
    274
    275            if (type instanceof GenericArrayType) {
    276                // compare the component types
    277                return isAssignable(((GenericArrayType) type).getGenericComponentType(),
    278                        toComponentType, typeVarAssigns);
    279            }
    280
    281            if (type instanceof WildcardType) {
    282                // so long as one of the upper bounds is assignable, it's good
    283                for (Type bound : getImplicitUpperBounds((WildcardType) type)) {
    284                    if (isAssignable(bound, toGenericArrayType)) {
    285                        return true;
    286                    }
    287                }
    288
    289                return false;
    290            }
    291
    292            if (type instanceof TypeVariable<?>) {
    293                // probably should remove the following logic and just return false.
    294                // type variables cannot specify arrays as bounds.
    295                for (Type bound : getImplicitBounds((TypeVariable<?>) type)) {
    296                    if (isAssignable(bound, toGenericArrayType)) {
    297                        return true;
    298                    }
    299                }
    300
    301                return false;
    302            }
    303
    304            if (type instanceof ParameterizedType) {
    305                // the raw type of a parameterized type is never an array or
    306                // generic array, otherwise the declaration would look like this:
    307                // Collection[]< ? extends String > collection;
    308                return false;
    309            }
    310
    311            throw new IllegalStateException("found an unhandled type: " + type);
    312        }
    313
    314        /**
    315         * <p> Checks if the subject type may be implicitly cast to the target
    316         * wildcard type following the Java generics rules. </p>
    317         *
    318         * @param type the subject type to be assigned to the target type
    319         * @param toWildcardType the target wildcard type
    320         * @return true if <code>type</code> is assignable to
    321         * <code>toWildcardType</code>.
    322         */
    323        private static boolean isAssignable(Type type, WildcardType toWildcardType,
    324                Map<TypeVariable<?>, Type> typeVarAssigns) {
    325            if (type == null) {
    326                return true;
    327            }
    328
    329            // only a null type can be assigned to null type which
    330            // would have cause the previous to return true
    331            if (toWildcardType == null) {
    332                return false;
    333            }
    334
    335            // all types are assignable to themselves
    336            if (toWildcardType.equals(type)) {
    337                return true;
    338            }
    339
    340            Type[] toUpperBounds = getImplicitUpperBounds(toWildcardType);
    341            Type[] toLowerBounds = getImplicitLowerBounds(toWildcardType);
    342
    343            if (type instanceof WildcardType) {
    344                WildcardType wildcardType = (WildcardType) type;
    345                Type[] upperBounds = getImplicitUpperBounds(wildcardType);
    346                Type[] lowerBounds = getImplicitLowerBounds(wildcardType);
    347
    348                for (Type toBound : toUpperBounds) {
    349                    // if there are assignments for unresolved type variables,
    350                    // now's the time to substitute them.
    351                    toBound = substituteTypeVariables(toBound, typeVarAssigns);
    352
    353                    // each upper bound of the subject type has to be assignable to
    354                    // each
    355                    // upper bound of the target type
    356                    for (Type bound : upperBounds) {
    357                        if (!isAssignable(bound, toBound, typeVarAssigns)) {
    358                            return false;
    359                        }
    360                    }
    361                }
    362
    363                for (Type toBound : toLowerBounds) {
    364                    // if there are assignments for unresolved type variables,
    365                    // now's the time to substitute them.
    366                    toBound = substituteTypeVariables(toBound, typeVarAssigns);
    367
    368                    // each lower bound of the target type has to be assignable to
    369                    // each
    370                    // lower bound of the subject type
    371                    for (Type bound : lowerBounds) {
    372                        if (!isAssignable(toBound, bound, typeVarAssigns)) {
    373                            return false;
    374                        }
    375                    }
    376                }
    377
    378                return true;
    379            }
    380
    381            for (Type toBound : toUpperBounds) {
    382                // if there are assignments for unresolved type variables,
    383                // now's the time to substitute them.
    384                if (!isAssignable(type, substituteTypeVariables(toBound, typeVarAssigns),
    385                        typeVarAssigns)) {
    386                    return false;
    387                }
    388            }
    389
    390            for (Type toBound : toLowerBounds) {
    391                // if there are assignments for unresolved type variables,
    392                // now's the time to substitute them.
    393                if (!isAssignable(substituteTypeVariables(toBound, typeVarAssigns), type,
    394                        typeVarAssigns)) {
    395                    return false;
    396                }
    397            }
    398
    399            return true;
    400        }
    401
    402        /**
    403         * <p> Checks if the subject type may be implicitly cast to the target type
    404         * variable following the Java generics rules. </p>
    405         *
    406         * @param type the subject type to be assigned to the target type
    407         * @param toTypeVariable the target type variable
    408         * @return true if <code>type</code> is assignable to
    409         * <code>toTypeVariable</code>.
    410         */
    411        private static boolean isAssignable(Type type, TypeVariable<?> toTypeVariable,
    412                Map<TypeVariable<?>, Type> typeVarAssigns) {
    413            if (type == null) {
    414                return true;
    415            }
    416
    417            // only a null type can be assigned to null type which
    418            // would have cause the previous to return true
    419            if (toTypeVariable == null) {
    420                return false;
    421            }
    422
    423            // all types are assignable to themselves
    424            if (toTypeVariable.equals(type)) {
    425                return true;
    426            }
    427
    428            if (type instanceof TypeVariable<?>) {
    429                // a type variable is assignable to another type variable, if
    430                // and only if the former is the latter, extends the latter, or
    431                // is otherwise a descendant of the latter.
    432                Type[] bounds = getImplicitBounds((TypeVariable<?>) type);
    433
    434                for (Type bound : bounds) {
    435                    if (isAssignable(bound, toTypeVariable, typeVarAssigns)) {
    436                        return true;
    437                    }
    438                }
    439            }
    440
    441            if (type instanceof Class<?> || type instanceof ParameterizedType
    442                    || type instanceof GenericArrayType || type instanceof WildcardType) {
    443                return false;
    444            }
    445
    446            throw new IllegalStateException("found an unhandled type: " + type);
    447        }
    448
    449        /**
    450         * <p> </p>
    451         *
    452         * @param type
    453         * @param typeVarAssigns
    454         * @return
    455         */
    456        private static Type substituteTypeVariables(Type type, Map<TypeVariable<?>, Type> typeVarAssigns) {
    457            if (type instanceof TypeVariable<?> && typeVarAssigns != null) {
    458                Type replacementType = typeVarAssigns.get(type);
    459
    460                if (replacementType == null) {
    461                    throw new IllegalArgumentException("missing assignment type for type variable "
    462                            + type);
    463                }
    464
    465                return replacementType;
    466            }
    467
    468            return type;
    469        }
    470
    471        /**
    472         * <p> Retrieves all the type arguments for this parameterized type
    473         * including owner hierarchy arguments such as <code>
    474         * Outer<K,V>.Inner<T>.DeepInner<E></code> . The arguments are returned in a
    475         * {@link Map} specifying the argument type for each {@link TypeVariable}.
    476         * </p>
    477         *
    478         * @param type specifies the subject parameterized type from which to
    479         * harvest the parameters.
    480         * @return a map of the type arguments to their respective type variables.
    481         */
    482        public static Map<TypeVariable<?>, Type> getTypeArguments(ParameterizedType type) {
    483            return getTypeArguments(type, getRawType(type), null);
    484        }
    485
    486        /**
    487         * <p> Gets the type arguments of a class/interface based on a subtype. For
    488         * instance, this method will determine that both of the parameters for the
    489         * interface {@link Map} are {@link Object} for the subtype
    490         * {@link java.util.Properties Properties} even though the subtype does not
    491         * directly implement the <code>Map</code> interface. <p> </p> This method
    492         * returns <code>null</code> if <code>type</code> is not assignable to
    493         * <code>toClass</code>. It returns an empty map if none of the classes or
    494         * interfaces in its inheritance hierarchy specify any type arguments. </p>
    495         * <p> A side-effect of this method is that it also retrieves the type
    496         * arguments for the classes and interfaces that are part of the hierarchy
    497         * between <code>type</code> and <code>toClass</code>. So with the above
    498         * example, this method will also determine that the type arguments for
    499         * {@link java.util.Hashtable Hashtable} are also both <code>Object</code>.
    500         * In cases where the interface specified by <code>toClass</code> is
    501         * (indirectly) implemented more than once (e.g. where <code>toClass</code>
    502         * specifies the interface {@link java.lang.Iterable Iterable} and
    503         * <code>type</code> specifies a parameterized type that implements both
    504         * {@link java.util.Set Set} and {@link java.util.Collection Collection}),
    505         * this method will look at the inheritance hierarchy of only one of the
    506         * implementations/subclasses; the first interface encountered that isn't a
    507         * subinterface to one of the others in the <code>type</code> to
    508         * <code>toClass</code> hierarchy. </p>
    509         *
    510         * @param type the type from which to determine the type parameters of
    511         * <code>toClass</code>
    512         * @param toClass the class whose type parameters are to be determined based
    513         * on the subtype <code>type</code>
    514         * @return a map of the type assignments for the type variables in each type
    515         * in the inheritance hierarchy from <code>type</code> to
    516         * <code>toClass</code> inclusive.
    517         */
    518        public static Map<TypeVariable<?>, Type> getTypeArguments(Type type, Class<?> toClass) {
    519            return getTypeArguments(type, toClass, null);
    520        }
    521
    522        /**
    523         * <p> Return a map of the type arguments of <code>type</code> in the context of <code>toClass</code>. </p>
    524         *
    525         * @param type
    526         * @param toClass
    527         * @param subtypeVarAssigns
    528         * @return
    529         */
    530        private static Map<TypeVariable<?>, Type> getTypeArguments(Type type, Class<?> toClass,
    531                Map<TypeVariable<?>, Type> subtypeVarAssigns) {
    532            if (type instanceof Class<?>) {
    533                return getTypeArguments((Class<?>) type, toClass, subtypeVarAssigns);
    534            }
    535
    536            if (type instanceof ParameterizedType) {
    537                return getTypeArguments((ParameterizedType) type, toClass, subtypeVarAssigns);
    538            }
    539
    540            if (type instanceof GenericArrayType) {
    541                return getTypeArguments(((GenericArrayType) type).getGenericComponentType(), toClass
    542                        .isArray() ? toClass.getComponentType() : toClass, subtypeVarAssigns);
    543            }
    544
    545            // since wildcard types are not assignable to classes, should this just
    546            // return null?
    547            if (type instanceof WildcardType) {
    548                for (Type bound : getImplicitUpperBounds((WildcardType) type)) {
    549                    // find the first bound that is assignable to the target class
    550                    if (isAssignable(bound, toClass)) {
    551                        return getTypeArguments(bound, toClass, subtypeVarAssigns);
    552                    }
    553                }
    554
    555                return null;
    556            }
    557
    558            // *
    559            if (type instanceof TypeVariable<?>) {
    560                for (Type bound : getImplicitBounds((TypeVariable<?>) type)) {
    561                    // find the first bound that is assignable to the target class
    562                    if (isAssignable(bound, toClass)) {
    563                        return getTypeArguments(bound, toClass, subtypeVarAssigns);
    564                    }
    565                }
    566
    567                return null;
    568            }
    569            // */
    570
    571            throw new IllegalStateException("found an unhandled type: " + type);
    572        }
    573
    574        /**
    575         * <p> </p>
    576         *
    577         * @param parameterizedType
    578         * @param toClass
    579         * @param subtypeVarAssigns
    580         * @return
    581         */
    582        private static Map<TypeVariable<?>, Type> getTypeArguments(
    583                ParameterizedType parameterizedType, Class<?> toClass,
    584                Map<TypeVariable<?>, Type> subtypeVarAssigns) {
    585            Class<?> cls = getRawType(parameterizedType);
    586
    587            // make sure they're assignable
    588            if (!isAssignable(cls, toClass)) {
    589                return null;
    590            }
    591
    592            Type ownerType = parameterizedType.getOwnerType();
    593            Map<TypeVariable<?>, Type> typeVarAssigns;
    594
    595            if (ownerType instanceof ParameterizedType) {
    596                // get the owner type arguments first
    597                ParameterizedType parameterizedOwnerType = (ParameterizedType) ownerType;
    598                typeVarAssigns = getTypeArguments(parameterizedOwnerType,
    599                        getRawType(parameterizedOwnerType), subtypeVarAssigns);
    600            } else {
    601                // no owner, prep the type variable assignments map
    602                typeVarAssigns = subtypeVarAssigns == null ? new HashMap<TypeVariable<?>, Type>()
    603                        : new HashMap<TypeVariable<?>, Type>(subtypeVarAssigns);
    604            }
    605
    606            // get the subject parameterized type's arguments
    607            Type[] typeArgs = parameterizedType.getActualTypeArguments();
    608            // and get the corresponding type variables from the raw class
    609            TypeVariable<?>[] typeParams = cls.getTypeParameters();
    610
    611            // map the arguments to their respective type variables
    612            for (int i = 0; i < typeParams.length; i++) {
    613                Type typeArg = typeArgs[i];
    614                typeVarAssigns.put(typeParams[i], typeVarAssigns.containsKey(typeArg) ? typeVarAssigns
    615                        .get(typeArg) : typeArg);
    616            }
    617
    618            if (toClass.equals(cls)) {
    619                // target class has been reached. Done.
    620                return typeVarAssigns;
    621            }
    622
    623            // walk the inheritance hierarchy until the target class is reached
    624            return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns);
    625        }
    626
    627        /**
    628         * <p> </p>
    629         *
    630         * @param cls
    631         * @param toClass
    632         * @param subtypeVarAssigns
    633         * @return
    634         */
    635        private static Map<TypeVariable<?>, Type> getTypeArguments(Class<?> cls, Class<?> toClass,
    636                Map<TypeVariable<?>, Type> subtypeVarAssigns) {
    637            // make sure they're assignable
    638            if (!isAssignable(cls, toClass)) {
    639                return null;
    640            }
    641
    642            // can't work with primitives
    643            if (cls.isPrimitive()) {
    644                // both classes are primitives?
    645                if (toClass.isPrimitive()) {
    646                    // dealing with widening here. No type arguments to be
    647                    // harvested with these two types.
    648                    return new HashMap<TypeVariable<?>, Type>();
    649                }
    650
    651                // work with wrapper the wrapper class instead of the primitive
    652                cls = ClassUtils.primitiveToWrapper(cls);
    653            }
    654
    655            // create a copy of the incoming map, or an empty one if it's null
    656            HashMap<TypeVariable<?>, Type> typeVarAssigns = subtypeVarAssigns == null ? new HashMap<TypeVariable<?>, Type>()
    657                    : new HashMap<TypeVariable<?>, Type>(subtypeVarAssigns);
    658
    659            // no arguments for the parameters, or target class has been reached
    660            if (cls.getTypeParameters().length > 0 || toClass.equals(cls)) {
    661                return typeVarAssigns;
    662            }
    663
    664            // walk the inheritance hierarchy until the target class is reached
    665            return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns);
    666        }
    667
    668        /**
    669         * <p> Tries to determine the type arguments of a class/interface based on a
    670         * super parameterized type's type arguments. This method is the inverse of
    671         * {@link #getTypeArguments(Type, Class)} which gets a class/interface's
    672         * type arguments based on a subtype. It is far more limited in determining
    673         * the type arguments for the subject class's type variables in that it can
    674         * only determine those parameters that map from the subject {@link Class}
    675         * object to the supertype. </p> <p> Example: {@link java.util.TreeSet
    676         * TreeSet} sets its parameter as the parameter for
    677         * {@link java.util.NavigableSet NavigableSet}, which in turn sets the
    678         * parameter of {@link java.util.SortedSet}, which in turn sets the
    679         * parameter of {@link Set}, which in turn sets the parameter of
    680         * {@link java.util.Collection}, which in turn sets the parameter of
    681         * {@link java.lang.Iterable}. Since <code>TreeSet</code>'s parameter maps
    682         * (indirectly) to <code>Iterable</code>'s parameter, it will be able to
    683         * determine that based on the super type <code>Iterable<? extends
    684         * Map<Integer,? extends Collection<?>>></code>, the parameter of
    685         * <code>TreeSet</code> is <code>? extends Map<Integer,? extends
    686         * Collection<?>></code>. </p>
    687         *
    688         * @param cls the class whose type parameters are to be determined
    689         * @param superType the super type from which <code>cls</code>'s type
    690         * arguments are to be determined
    691         * @return a map of the type assignments that could be determined for the
    692         * type variables in each type in the inheritance hierarchy from
    693         * <code>type</code> to <code>toClass</code> inclusive.
    694         */
    695        public static Map<TypeVariable<?>, Type> determineTypeArguments(Class<?> cls,
    696                ParameterizedType superType) {
    697            Class<?> superClass = getRawType(superType);
    698
    699            // compatibility check
    700            if (!isAssignable(cls, superClass)) {
    701                return null;
    702            }
    703
    704            if (cls.equals(superClass)) {
    705                return getTypeArguments(superType, superClass, null);
    706            }
    707
    708            // get the next class in the inheritance hierarchy
    709            Type midType = getClosestParentType(cls, superClass);
    710
    711            // can only be a class or a parameterized type
    712            if (midType instanceof Class<?>) {
    713                return determineTypeArguments((Class<?>) midType, superType);
    714            }
    715
    716            ParameterizedType midParameterizedType = (ParameterizedType) midType;
    717            Class<?> midClass = getRawType(midParameterizedType);
    718            // get the type variables of the mid class that map to the type
    719            // arguments of the super class
    720            Map<TypeVariable<?>, Type> typeVarAssigns = determineTypeArguments(midClass, superType);
    721            // map the arguments of the mid type to the class type variables
    722            mapTypeVariablesToArguments(cls, midParameterizedType, typeVarAssigns);
    723
    724            return typeVarAssigns;
    725        }
    726
    727        /**
    728         * <p> </p>
    729         *
    730         * @param cls
    731         * @param parameterizedType
    732         * @param typeVarAssigns
    733         */
    734        private static <T> void mapTypeVariablesToArguments(Class<T> cls,
    735                ParameterizedType parameterizedType, Map<TypeVariable<?>, Type> typeVarAssigns) {
    736            // capture the type variables from the owner type that have assignments
    737            Type ownerType = parameterizedType.getOwnerType();
    738
    739            if (ownerType instanceof ParameterizedType) {
    740                // recursion to make sure the owner's owner type gets processed
    741                mapTypeVariablesToArguments(cls, (ParameterizedType) ownerType, typeVarAssigns);
    742            }
    743
    744            // parameterizedType is a generic interface/class (or it's in the owner
    745            // hierarchy of said interface/class) implemented/extended by the class
    746            // cls. Find out which type variables of cls are type arguments of
    747            // parameterizedType:
    748            Type[] typeArgs = parameterizedType.getActualTypeArguments();
    749
    750            // of the cls's type variables that are arguments of parameterizedType,
    751            // find out which ones can be determined from the super type's arguments
    752            TypeVariable<?>[] typeVars = getRawType(parameterizedType).getTypeParameters();
    753
    754            // use List view of type parameters of cls so the contains() method can be used:
    755            List<TypeVariable<Class<T>>> typeVarList = Arrays.asList(cls
    756                    .getTypeParameters());
    757
    758            for (int i = 0; i < typeArgs.length; i++) {
    759                TypeVariable<?> typeVar = typeVars[i];
    760                Type typeArg = typeArgs[i];
    761
    762                // argument of parameterizedType is a type variable of cls
    763                if (typeVarList.contains(typeArg)
    764                // type variable of parameterizedType has an assignment in
    765                        // the super type.
    766                        && typeVarAssigns.containsKey(typeVar)) {
    767                    // map the assignment to the cls's type variable
    768                    typeVarAssigns.put((TypeVariable<?>) typeArg, typeVarAssigns.get(typeVar));
    769                }
    770            }
    771        }
    772
    773        /**
    774         * <p> Closest parent type? Closest to what? The closest parent type to the
    775         * super class specified by <code>superClass</code>. </p>
    776         *
    777         * @param cls
    778         * @param superClass
    779         * @return
    780         */
    781        private static Type getClosestParentType(Class<?> cls, Class<?> superClass) {
    782            // only look at the interfaces if the super class is also an interface
    783            if (superClass.isInterface()) {
    784                // get the generic interfaces of the subject class
    785                Type[] interfaceTypes = cls.getGenericInterfaces();
    786                // will hold the best generic interface match found
    787                Type genericInterface = null;
    788
    789                // find the interface closest to the super class
    790                for (int i = 0; i < interfaceTypes.length; i++) {
    791                    Type midType = interfaceTypes[i];
    792                    Class<?> midClass = null;
    793
    794                    if (midType instanceof ParameterizedType) {
    795                        midClass = getRawType((ParameterizedType) midType);
    796                    } else if (midType instanceof Class<?>) {
    797                        midClass = (Class<?>) midType;
    798                    } else {
    799                        throw new IllegalStateException("Unexpected generic"
    800                                + " interface type found: " + midType);
    801                    }
    802
    803                    // check if this interface is further up the inheritance chain
    804                    // than the previously found match
    805                    if (isAssignable(midClass, superClass)
    806                            && isAssignable(genericInterface, (Type) midClass)) {
    807                        genericInterface = midType;
    808                    }
    809                }
    810
    811                // found a match?
    812                if (genericInterface != null) {
    813                    return genericInterface;
    814                }
    815            }
    816
    817            // none of the interfaces were descendants of the target class, so the
    818            // super class has to be one, instead
    819            return cls.getGenericSuperclass();
    820        }
    821
    822        /**
    823         * <p> Checks if the given value can be assigned to the target type
    824         * following the Java generics rules. </p>
    825         *
    826         * @param value
    827         * @param type
    828         * @return true of <code>value</code> is an instance of <code>type</code>.
    829         */
    830        public static boolean isInstance(Object value, Type type) {
    831            if (type == null) {
    832                return false;
    833            }
    834
    835            return value == null ? !(type instanceof Class<?>) || !((Class<?>) type).isPrimitive()
    836                    : isAssignable(value.getClass(), type, null);
    837        }
    838
    839        /**
    840         * <p> This method strips out the redundant upper bound types in type
    841         * variable types and wildcard types (or it would with wildcard types if
    842         * multiple upper bounds were allowed). </p> <p> Example: with the variable
    843         * type declaration:
    844         *
    845         * <pre> &lt;K extends java.util.Collection&lt;String&gt; &amp;
    846         * java.util.List&lt;String&gt;&gt; </pre>
    847         *
    848         * since <code>List</code> is a subinterface of <code>Collection</code>,
    849         * this method will return the bounds as if the declaration had been:
    850         *
    851         * <pre> &lt;K extends java.util.List&lt;String&gt;&gt; </pre>
    852         *
    853         * </p>
    854         *
    855         * @param bounds an array of types representing the upper bounds of either
    856         * <code>WildcardType</code> or <code>TypeVariable</code>.
    857         * @return an array containing the values from <code>bounds</code> minus the
    858         * redundant types.
    859         */
    860        public static Type[] normalizeUpperBounds(Type[] bounds) {
    861            // don't bother if there's only one (or none) type
    862            if (bounds.length < 2) {
    863                return bounds;
    864            }
    865
    866            Set<Type> types = new HashSet<Type>(bounds.length);
    867
    868            for (Type type1 : bounds) {
    869                boolean subtypeFound = false;
    870
    871                for (Type type2 : bounds) {
    872                    if (type1 != type2 && isAssignable(type2, type1, null)) {
    873                        subtypeFound = true;
    874                        break;
    875                    }
    876                }
    877
    878                if (!subtypeFound) {
    879                    types.add(type1);
    880                }
    881            }
    882
    883            return types.toArray(new Type[0]);
    884        }
    885
    886        /**
    887         * <p> Returns an array containing the sole type of {@link Object} if
    888         * {@link TypeVariable#getBounds()} returns an empty array. Otherwise, it
    889         * returns the result of <code>TypeVariable.getBounds()</code> passed into
    890         * {@link #normalizeUpperBounds}. </p>
    891         *
    892         * @param typeVariable the subject type variable
    893         * @return a non-empty array containing the bounds of the type variable.
    894         */
    895        public static Type[] getImplicitBounds(TypeVariable<?> typeVariable) {
    896            Type[] bounds = typeVariable.getBounds();
    897
    898            return bounds.length == 0 ? new Type[] { Object.class } : normalizeUpperBounds(bounds);
    899        }
    900
    901        /**
    902         * <p> Returns an array containing the sole value of {@link Object} if
    903         * {@link WildcardType#getUpperBounds()} returns an empty array. Otherwise,
    904         * it returns the result of <code>WildcardType.getUpperBounds()</code>
    905         * passed into {@link #normalizeUpperBounds}. </p>
    906         *
    907         * @param wildcardType the subject wildcard type
    908         * @return a non-empty array containing the upper bounds of the wildcard
    909         * type.
    910         */
    911        public static Type[] getImplicitUpperBounds(WildcardType wildcardType) {
    912            Type[] bounds = wildcardType.getUpperBounds();
    913
    914            return bounds.length == 0 ? new Type[] { Object.class } : normalizeUpperBounds(bounds);
    915        }
    916
    917        /**
    918         * <p> Returns an array containing a single value of <code>null</code> if
    919         * {@link WildcardType#getLowerBounds()} returns an empty array. Otherwise,
    920         * it returns the result of <code>WildcardType.getLowerBounds()</code>. </p>
    921         *
    922         * @param wildcardType the subject wildcard type
    923         * @return a non-empty array containing the lower bounds of the wildcard
    924         * type.
    925         */
    926        public static Type[] getImplicitLowerBounds(WildcardType wildcardType) {
    927            Type[] bounds = wildcardType.getLowerBounds();
    928
    929            return bounds.length == 0 ? new Type[] { null } : bounds;
    930        }
    931
    932        /**
    933         * <p> Determines whether or not specified types satisfy the bounds of their
    934         * mapped type variables. When a type parameter extends another (such as
    935         * <code><T, S extends T></code>), uses another as a type parameter (such as
    936         * <code><T, S extends Comparable<T></code>), or otherwise depends on
    937         * another type variable to be specified, the dependencies must be included
    938         * in <code>typeVarAssigns</code>. </p>
    939         *
    940         * @param typeVarAssigns specifies the potential types to be assigned to the
    941         * type variables.
    942         * @return whether or not the types can be assigned to their respective type
    943         * variables.
    944         */
    945        public static boolean typesSatisfyVariables(Map<TypeVariable<?>, Type> typeVarAssigns) {
    946            // all types must be assignable to all the bounds of the their mapped
    947            // type variable.
    948            for (Map.Entry<TypeVariable<?>, Type> entry : typeVarAssigns.entrySet()) {
    949                TypeVariable<?> typeVar = entry.getKey();
    950                Type type = entry.getValue();
    951
    952                for (Type bound : getImplicitBounds(typeVar)) {
    953                    if (!isAssignable(type, substituteTypeVariables(bound, typeVarAssigns),
    954                            typeVarAssigns)) {
    955                        return false;
    956                    }
    957                }
    958            }
    959
    960            return true;
    961        }
    962
    963        /**
    964         * <p> Type-checking method of convenience. </p>
    965         *
    966         * @param parameterizedType
    967         * @return
    968         */
    969        private static Class<?> getRawType(ParameterizedType parameterizedType) {
    970            Type rawType = parameterizedType.getRawType();
    971
    972            // check if raw type is a Class object
    973            // not currently necessary, but since the return type is Type instead of
    974            // Class, there's enough reason to believe that future versions of Java
    975            // may return other Type implementations. And type-safety checking is
    976            // rarely a bad idea.
    977            if (!(rawType instanceof Class<?>)) {
    978                throw new IllegalStateException("Wait... What!? Type of rawType: " + rawType);
    979            }
    980
    981            return (Class<?>) rawType;
    982        }
    983
    984        /**
    985         * <p> Get the raw type of a Java type, given its context. Primarily for use
    986         * with {@link TypeVariable}s and {@link GenericArrayType}s, or when you do
    987         * not know the runtime type of <code>type</code>: if you know you have a
    988         * {@link Class} instance, it is already raw; if you know you have a
    989         * {@link ParameterizedType}, its raw type is only a method call away. </p>
    990         *
    991         * @param type to resolve
    992         * @param assigningType type to be resolved against
    993         * @return the resolved <code>Class</code> object or <code>null</code> if
    994         * the type could not be resolved
    995         */
    996        public static Class<?> getRawType(Type type, Type assigningType) {
    997            if (type instanceof Class<?>) {
    998                // it is raw, no problem
    999                return (Class<?>) type;
    1000            }
    1001
    1002            if (type instanceof ParameterizedType) {
    1003                // simple enough to get the raw type of a ParameterizedType
    1004                return getRawType((ParameterizedType) type);
    1005            }
    1006
    1007            if (type instanceof TypeVariable<?>) {
    1008                if (assigningType == null) {
    1009                    return null;
    1010                }
    1011
    1012                // get the entity declaring this type variable
    1013                Object genericDeclaration = ((TypeVariable<?>) type).getGenericDeclaration();
    1014
    1015                // can't get the raw type of a method- or constructor-declared type
    1016                // variable
    1017                if (!(genericDeclaration instanceof Class<?>)) {
    1018                    return null;
    1019                }
    1020
    1021                // get the type arguments for the declaring class/interface based
    1022                // on the enclosing type
    1023                Map<TypeVariable<?>, Type> typeVarAssigns = getTypeArguments(assigningType,
    1024                        (Class<?>) genericDeclaration);
    1025
    1026                // enclosingType has to be a subclass (or subinterface) of the
    1027                // declaring type
    1028                if (typeVarAssigns == null) {
    1029                    return null;
    1030                }
    1031
    1032                // get the argument assigned to this type variable
    1033                Type typeArgument = typeVarAssigns.get(type);
    1034
    1035                if (typeArgument == null) {
    1036                    return null;
    1037                }
    1038
    1039                // get the argument for this type variable
    1040                return getRawType(typeArgument, assigningType);
    1041            }
    1042
    1043            if (type instanceof GenericArrayType) {
    1044                // get raw component type
    1045                Class<?> rawComponentType = getRawType(((GenericArrayType) type)
    1046                        .getGenericComponentType(), assigningType);
    1047
    1048                // create array type from raw component type and return its class
    1049                return Array.newInstance(rawComponentType, 0).getClass();
    1050            }
    1051
    1052            // (hand-waving) this is not the method you're looking for
    1053            if (type instanceof WildcardType) {
    1054                return null;
    1055            }
    1056
    1057            throw new IllegalArgumentException("unknown type: " + type);
    1058        }
    1059
    1060    }