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> <K extends java.util.Collection<String> &
846 * java.util.List<String>> </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> <K extends java.util.List<String>> </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 }