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