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    }