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 */ 017package org.apache.commons.lang3.reflect; 018 019import java.lang.reflect.Array; 020import java.lang.reflect.GenericArrayType; 021import java.lang.reflect.GenericDeclaration; 022import java.lang.reflect.ParameterizedType; 023import java.lang.reflect.Type; 024import java.lang.reflect.TypeVariable; 025import java.lang.reflect.WildcardType; 026import java.util.Arrays; 027import java.util.Collections; 028import java.util.HashMap; 029import java.util.HashSet; 030import java.util.List; 031import java.util.Map; 032import java.util.Set; 033 034import org.apache.commons.lang3.ArrayUtils; 035import org.apache.commons.lang3.ClassUtils; 036import org.apache.commons.lang3.ObjectUtils; 037import org.apache.commons.lang3.Validate; 038import org.apache.commons.lang3.builder.Builder; 039 040/** 041 * <p> Utility methods focusing on type inspection, particularly with regard to 042 * generics. </p> 043 * 044 * @since 3.0 045 * @version $Id: TypeUtils.java 1583482 2014-03-31 22:54:57Z niallp $ 046 */ 047public class TypeUtils { 048 049 /** 050 * {@link WildcardType} builder. 051 * @since 3.2 052 */ 053 public static class WildcardTypeBuilder implements Builder<WildcardType> { 054 /** 055 * Constructor 056 */ 057 private WildcardTypeBuilder() { 058 } 059 060 private Type[] upperBounds; 061 private Type[] lowerBounds; 062 063 /** 064 * Specify upper bounds of the wildcard type to build. 065 * @param bounds to set 066 * @return {@code this} 067 */ 068 public WildcardTypeBuilder withUpperBounds(Type... bounds) { 069 this.upperBounds = bounds; 070 return this; 071 } 072 073 /** 074 * Specify lower bounds of the wildcard type to build. 075 * @param bounds to set 076 * @return {@code this} 077 */ 078 public WildcardTypeBuilder withLowerBounds(Type... bounds) { 079 this.lowerBounds = bounds; 080 return this; 081 } 082 083 /** 084 * {@inheritDoc} 085 */ 086 @Override 087 public WildcardType build() { 088 return new WildcardTypeImpl(upperBounds, lowerBounds); 089 } 090 } 091 092 /** 093 * GenericArrayType implementation class. 094 * @since 3.2 095 */ 096 private static final class GenericArrayTypeImpl implements GenericArrayType { 097 private final Type componentType; 098 099 /** 100 * Constructor 101 * @param componentType of this array type 102 */ 103 private GenericArrayTypeImpl(Type componentType) { 104 this.componentType = componentType; 105 } 106 107 /** 108 * {@inheritDoc} 109 */ 110 @Override 111 public Type getGenericComponentType() { 112 return componentType; 113 } 114 115 /** 116 * {@inheritDoc} 117 */ 118 @Override 119 public String toString() { 120 return TypeUtils.toString(this); 121 } 122 123 /** 124 * {@inheritDoc} 125 */ 126 @Override 127 public boolean equals(Object obj) { 128 return obj == this || obj instanceof GenericArrayType && TypeUtils.equals(this, (GenericArrayType) obj); 129 } 130 131 /** 132 * {@inheritDoc} 133 */ 134 @Override 135 public int hashCode() { 136 int result = 67 << 4; 137 result |= componentType.hashCode(); 138 return result; 139 } 140 } 141 142 /** 143 * ParameterizedType implementation class. 144 * @since 3.2 145 */ 146 private static final class ParameterizedTypeImpl implements ParameterizedType { 147 private final Class<?> raw; 148 private final Type useOwner; 149 private final Type[] typeArguments; 150 151 /** 152 * Constructor 153 * @param raw type 154 * @param useOwner owner type to use, if any 155 * @param typeArguments formal type arguments 156 */ 157 private ParameterizedTypeImpl(Class<?> raw, Type useOwner, Type[] typeArguments) { 158 this.raw = raw; 159 this.useOwner = useOwner; 160 this.typeArguments = typeArguments; 161 } 162 163 /** 164 * {@inheritDoc} 165 */ 166 @Override 167 public Type getRawType() { 168 return raw; 169 } 170 171 /** 172 * {@inheritDoc} 173 */ 174 @Override 175 public Type getOwnerType() { 176 return useOwner; 177 } 178 179 /** 180 * {@inheritDoc} 181 */ 182 @Override 183 public Type[] getActualTypeArguments() { 184 return typeArguments.clone(); 185 } 186 187 /** 188 * {@inheritDoc} 189 */ 190 @Override 191 public String toString() { 192 return TypeUtils.toString(this); 193 } 194 195 /** 196 * {@inheritDoc} 197 */ 198 @Override 199 public boolean equals(Object obj) { 200 return obj == this || obj instanceof ParameterizedType && TypeUtils.equals(this, ((ParameterizedType) obj)); 201 } 202 203 /** 204 * {@inheritDoc} 205 */ 206 @SuppressWarnings( "deprecation" ) // ObjectUtils.hashCode(Object) has been deprecated in 3.2 207 @Override 208 public int hashCode() { 209 int result = 71 << 4; 210 result |= raw.hashCode(); 211 result <<= 4; 212 result |= ObjectUtils.hashCode(useOwner); 213 result <<= 8; 214 result |= Arrays.hashCode(typeArguments); 215 return result; 216 } 217 } 218 219 /** 220 * WildcardType implementation class. 221 * @since 3.2 222 */ 223 private static final class WildcardTypeImpl implements WildcardType { 224 private static final Type[] EMPTY_BOUNDS = new Type[0]; 225 226 private final Type[] upperBounds; 227 private final Type[] lowerBounds; 228 229 /** 230 * Constructor 231 * @param upperBounds of this type 232 * @param lowerBounds of this type 233 */ 234 private WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) { 235 this.upperBounds = ObjectUtils.defaultIfNull(upperBounds, EMPTY_BOUNDS); 236 this.lowerBounds = ObjectUtils.defaultIfNull(lowerBounds, EMPTY_BOUNDS); 237 } 238 239 /** 240 * {@inheritDoc} 241 */ 242 @Override 243 public Type[] getUpperBounds() { 244 return upperBounds.clone(); 245 } 246 247 /** 248 * {@inheritDoc} 249 */ 250 @Override 251 public Type[] getLowerBounds() { 252 return lowerBounds.clone(); 253 } 254 255 /** 256 * {@inheritDoc} 257 */ 258 @Override 259 public String toString() { 260 return TypeUtils.toString(this); 261 } 262 263 /** 264 * {@inheritDoc} 265 */ 266 @Override 267 public boolean equals(Object obj) { 268 return obj == this || obj instanceof WildcardType && TypeUtils.equals(this, (WildcardType) obj); 269 } 270 271 /** 272 * {@inheritDoc} 273 */ 274 @Override 275 public int hashCode() { 276 int result = 73 << 8; 277 result |= Arrays.hashCode(upperBounds); 278 result <<= 8; 279 result |= Arrays.hashCode(lowerBounds); 280 return result; 281 } 282 } 283 284 /** 285 * A wildcard instance matching {@code ?}. 286 * @since 3.2 287 */ 288 public static final WildcardType WILDCARD_ALL = wildcardType().withUpperBounds(Object.class).build(); 289 290 /** 291 * <p>{@code TypeUtils} instances should NOT be constructed in standard 292 * programming. Instead, the class should be used as 293 * {@code TypeUtils.isAssignable(cls, toClass)}.</p> <p>This 294 * constructor is public to permit tools that require a JavaBean instance to 295 * operate.</p> 296 */ 297 public TypeUtils() { 298 super(); 299 } 300 301 /** 302 * <p>Checks if the subject type may be implicitly cast to the target type 303 * following the Java generics rules. If both types are {@link Class} 304 * objects, the method returns the result of 305 * {@link ClassUtils#isAssignable(Class, Class)}.</p> 306 * 307 * @param type the subject type to be assigned to the target type 308 * @param toType the target type 309 * @return {@code true} if {@code type} is assignable to {@code toType}. 310 */ 311 public static boolean isAssignable(final Type type, final Type toType) { 312 return isAssignable(type, toType, null); 313 } 314 315 /** 316 * <p>Checks if the subject type may be implicitly cast to the target type 317 * following the Java generics rules.</p> 318 * 319 * @param type the subject type to be assigned to the target type 320 * @param toType the target type 321 * @param typeVarAssigns optional map of type variable assignments 322 * @return {@code true} if {@code type} is assignable to {@code toType}. 323 */ 324 private static boolean isAssignable(final Type type, final Type toType, 325 final Map<TypeVariable<?>, Type> typeVarAssigns) { 326 if (toType == null || toType instanceof Class<?>) { 327 return isAssignable(type, (Class<?>) toType); 328 } 329 330 if (toType instanceof ParameterizedType) { 331 return isAssignable(type, (ParameterizedType) toType, typeVarAssigns); 332 } 333 334 if (toType instanceof GenericArrayType) { 335 return isAssignable(type, (GenericArrayType) toType, typeVarAssigns); 336 } 337 338 if (toType instanceof WildcardType) { 339 return isAssignable(type, (WildcardType) toType, typeVarAssigns); 340 } 341 342 if (toType instanceof TypeVariable<?>) { 343 return isAssignable(type, (TypeVariable<?>) toType, typeVarAssigns); 344 } 345 346 throw new IllegalStateException("found an unhandled type: " + toType); 347 } 348 349 /** 350 * <p>Checks if the subject type may be implicitly cast to the target class 351 * following the Java generics rules.</p> 352 * 353 * @param type the subject type to be assigned to the target type 354 * @param toClass the target class 355 * @return {@code true} if {@code type} is assignable to {@code toClass}. 356 */ 357 private static boolean isAssignable(final Type type, final Class<?> toClass) { 358 if (type == null) { 359 // consistency with ClassUtils.isAssignable() behavior 360 return toClass == null || !toClass.isPrimitive(); 361 } 362 363 // only a null type can be assigned to null type which 364 // would have cause the previous to return true 365 if (toClass == null) { 366 return false; 367 } 368 369 // all types are assignable to themselves 370 if (toClass.equals(type)) { 371 return true; 372 } 373 374 if (type instanceof Class<?>) { 375 // just comparing two classes 376 return ClassUtils.isAssignable((Class<?>) type, toClass); 377 } 378 379 if (type instanceof ParameterizedType) { 380 // only have to compare the raw type to the class 381 return isAssignable(getRawType((ParameterizedType) type), toClass); 382 } 383 384 // * 385 if (type instanceof TypeVariable<?>) { 386 // if any of the bounds are assignable to the class, then the 387 // type is assignable to the class. 388 for (final Type bound : ((TypeVariable<?>) type).getBounds()) { 389 if (isAssignable(bound, toClass)) { 390 return true; 391 } 392 } 393 394 return false; 395 } 396 397 // the only classes to which a generic array type can be assigned 398 // are class Object and array classes 399 if (type instanceof GenericArrayType) { 400 return toClass.equals(Object.class) 401 || toClass.isArray() 402 && isAssignable(((GenericArrayType) type).getGenericComponentType(), toClass 403 .getComponentType()); 404 } 405 406 // wildcard types are not assignable to a class (though one would think 407 // "? super Object" would be assignable to Object) 408 if (type instanceof WildcardType) { 409 return false; 410 } 411 412 throw new IllegalStateException("found an unhandled type: " + type); 413 } 414 415 /** 416 * <p>Checks if the subject type may be implicitly cast to the target 417 * parameterized type following the Java generics rules.</p> 418 * 419 * @param type the subject type to be assigned to the target type 420 * @param toParameterizedType the target parameterized type 421 * @param typeVarAssigns a map with type variables 422 * @return {@code true} if {@code type} is assignable to {@code toType}. 423 */ 424 private static boolean isAssignable(final Type type, final ParameterizedType toParameterizedType, 425 final Map<TypeVariable<?>, Type> typeVarAssigns) { 426 if (type == null) { 427 return true; 428 } 429 430 // only a null type can be assigned to null type which 431 // would have cause the previous to return true 432 if (toParameterizedType == null) { 433 return false; 434 } 435 436 // all types are assignable to themselves 437 if (toParameterizedType.equals(type)) { 438 return true; 439 } 440 441 // get the target type's raw type 442 final Class<?> toClass = getRawType(toParameterizedType); 443 // get the subject type's type arguments including owner type arguments 444 // and supertype arguments up to and including the target class. 445 final Map<TypeVariable<?>, Type> fromTypeVarAssigns = getTypeArguments(type, toClass, null); 446 447 // null means the two types are not compatible 448 if (fromTypeVarAssigns == null) { 449 return false; 450 } 451 452 // compatible types, but there's no type arguments. this is equivalent 453 // to comparing Map< ?, ? > to Map, and raw types are always assignable 454 // to parameterized types. 455 if (fromTypeVarAssigns.isEmpty()) { 456 return true; 457 } 458 459 // get the target type's type arguments including owner type arguments 460 final Map<TypeVariable<?>, Type> toTypeVarAssigns = getTypeArguments(toParameterizedType, 461 toClass, typeVarAssigns); 462 463 // now to check each type argument 464 for (final TypeVariable<?> var : toTypeVarAssigns.keySet()) { 465 final Type toTypeArg = unrollVariableAssignments(var, toTypeVarAssigns); 466 final Type fromTypeArg = unrollVariableAssignments(var, fromTypeVarAssigns); 467 468 // parameters must either be absent from the subject type, within 469 // the bounds of the wildcard type, or be an exact match to the 470 // parameters of the target type. 471 if (fromTypeArg != null 472 && !toTypeArg.equals(fromTypeArg) 473 && !(toTypeArg instanceof WildcardType && isAssignable(fromTypeArg, toTypeArg, 474 typeVarAssigns))) { 475 return false; 476 } 477 } 478 return true; 479 } 480 481 /** 482 * Look up {@code var} in {@code typeVarAssigns} <em>transitively</em>, 483 * i.e. keep looking until the value found is <em>not</em> a type variable. 484 * @param var the type variable to look up 485 * @param typeVarAssigns the map used for the look up 486 * @return Type or {@code null} if some variable was not in the map 487 * @since 3.2 488 */ 489 private static Type unrollVariableAssignments(TypeVariable<?> var, final Map<TypeVariable<?>, Type> typeVarAssigns) { 490 Type result; 491 do { 492 result = typeVarAssigns.get(var); 493 if (result instanceof TypeVariable<?> && !result.equals(var)) { 494 var = (TypeVariable<?>) result; 495 continue; 496 } 497 break; 498 } while (true); 499 return result; 500 } 501 502 /** 503 * <p>Checks if the subject type may be implicitly cast to the target 504 * generic array type following the Java generics rules.</p> 505 * 506 * @param type the subject type to be assigned to the target type 507 * @param toGenericArrayType the target generic array type 508 * @param typeVarAssigns a map with type variables 509 * @return {@code true} if {@code type} is assignable to 510 * {@code toGenericArrayType}. 511 */ 512 private static boolean isAssignable(final Type type, final GenericArrayType toGenericArrayType, 513 final Map<TypeVariable<?>, Type> typeVarAssigns) { 514 if (type == null) { 515 return true; 516 } 517 518 // only a null type can be assigned to null type which 519 // would have cause the previous to return true 520 if (toGenericArrayType == null) { 521 return false; 522 } 523 524 // all types are assignable to themselves 525 if (toGenericArrayType.equals(type)) { 526 return true; 527 } 528 529 final Type toComponentType = toGenericArrayType.getGenericComponentType(); 530 531 if (type instanceof Class<?>) { 532 final Class<?> cls = (Class<?>) type; 533 534 // compare the component types 535 return cls.isArray() 536 && isAssignable(cls.getComponentType(), toComponentType, typeVarAssigns); 537 } 538 539 if (type instanceof GenericArrayType) { 540 // compare the component types 541 return isAssignable(((GenericArrayType) type).getGenericComponentType(), 542 toComponentType, typeVarAssigns); 543 } 544 545 if (type instanceof WildcardType) { 546 // so long as one of the upper bounds is assignable, it's good 547 for (final Type bound : getImplicitUpperBounds((WildcardType) type)) { 548 if (isAssignable(bound, toGenericArrayType)) { 549 return true; 550 } 551 } 552 553 return false; 554 } 555 556 if (type instanceof TypeVariable<?>) { 557 // probably should remove the following logic and just return false. 558 // type variables cannot specify arrays as bounds. 559 for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) { 560 if (isAssignable(bound, toGenericArrayType)) { 561 return true; 562 } 563 } 564 565 return false; 566 } 567 568 if (type instanceof ParameterizedType) { 569 // the raw type of a parameterized type is never an array or 570 // generic array, otherwise the declaration would look like this: 571 // Collection[]< ? extends String > collection; 572 return false; 573 } 574 575 throw new IllegalStateException("found an unhandled type: " + type); 576 } 577 578 /** 579 * <p>Checks if the subject type may be implicitly cast to the target 580 * wildcard type following the Java generics rules.</p> 581 * 582 * @param type the subject type to be assigned to the target type 583 * @param toWildcardType the target wildcard type 584 * @param typeVarAssigns a map with type variables 585 * @return {@code true} if {@code type} is assignable to 586 * {@code toWildcardType}. 587 */ 588 private static boolean isAssignable(final Type type, final WildcardType toWildcardType, 589 final Map<TypeVariable<?>, Type> typeVarAssigns) { 590 if (type == null) { 591 return true; 592 } 593 594 // only a null type can be assigned to null type which 595 // would have cause the previous to return true 596 if (toWildcardType == null) { 597 return false; 598 } 599 600 // all types are assignable to themselves 601 if (toWildcardType.equals(type)) { 602 return true; 603 } 604 605 final Type[] toUpperBounds = getImplicitUpperBounds(toWildcardType); 606 final Type[] toLowerBounds = getImplicitLowerBounds(toWildcardType); 607 608 if (type instanceof WildcardType) { 609 final WildcardType wildcardType = (WildcardType) type; 610 final Type[] upperBounds = getImplicitUpperBounds(wildcardType); 611 final Type[] lowerBounds = getImplicitLowerBounds(wildcardType); 612 613 for (Type toBound : toUpperBounds) { 614 // if there are assignments for unresolved type variables, 615 // now's the time to substitute them. 616 toBound = substituteTypeVariables(toBound, typeVarAssigns); 617 618 // each upper bound of the subject type has to be assignable to 619 // each 620 // upper bound of the target type 621 for (final Type bound : upperBounds) { 622 if (!isAssignable(bound, toBound, typeVarAssigns)) { 623 return false; 624 } 625 } 626 } 627 628 for (Type toBound : toLowerBounds) { 629 // if there are assignments for unresolved type variables, 630 // now's the time to substitute them. 631 toBound = substituteTypeVariables(toBound, typeVarAssigns); 632 633 // each lower bound of the target type has to be assignable to 634 // each 635 // lower bound of the subject type 636 for (final Type bound : lowerBounds) { 637 if (!isAssignable(toBound, bound, typeVarAssigns)) { 638 return false; 639 } 640 } 641 } 642 return true; 643 } 644 645 for (final Type toBound : toUpperBounds) { 646 // if there are assignments for unresolved type variables, 647 // now's the time to substitute them. 648 if (!isAssignable(type, substituteTypeVariables(toBound, typeVarAssigns), 649 typeVarAssigns)) { 650 return false; 651 } 652 } 653 654 for (final Type toBound : toLowerBounds) { 655 // if there are assignments for unresolved type variables, 656 // now's the time to substitute them. 657 if (!isAssignable(substituteTypeVariables(toBound, typeVarAssigns), type, 658 typeVarAssigns)) { 659 return false; 660 } 661 } 662 return true; 663 } 664 665 /** 666 * <p>Checks if the subject type may be implicitly cast to the target type 667 * variable following the Java generics rules.</p> 668 * 669 * @param type the subject type to be assigned to the target type 670 * @param toTypeVariable the target type variable 671 * @param typeVarAssigns a map with type variables 672 * @return {@code true} if {@code type} is assignable to 673 * {@code toTypeVariable}. 674 */ 675 private static boolean isAssignable(final Type type, final TypeVariable<?> toTypeVariable, 676 final Map<TypeVariable<?>, Type> typeVarAssigns) { 677 if (type == null) { 678 return true; 679 } 680 681 // only a null type can be assigned to null type which 682 // would have cause the previous to return true 683 if (toTypeVariable == null) { 684 return false; 685 } 686 687 // all types are assignable to themselves 688 if (toTypeVariable.equals(type)) { 689 return true; 690 } 691 692 if (type instanceof TypeVariable<?>) { 693 // a type variable is assignable to another type variable, if 694 // and only if the former is the latter, extends the latter, or 695 // is otherwise a descendant of the latter. 696 final Type[] bounds = getImplicitBounds((TypeVariable<?>) type); 697 698 for (final Type bound : bounds) { 699 if (isAssignable(bound, toTypeVariable, typeVarAssigns)) { 700 return true; 701 } 702 } 703 } 704 705 if (type instanceof Class<?> || type instanceof ParameterizedType 706 || type instanceof GenericArrayType || type instanceof WildcardType) { 707 return false; 708 } 709 710 throw new IllegalStateException("found an unhandled type: " + type); 711 } 712 713 /** 714 * <p>Find the mapping for {@code type} in {@code typeVarAssigns}.</p> 715 * 716 * @param type the type to be replaced 717 * @param typeVarAssigns the map with type variables 718 * @return the replaced type 719 * @throws IllegalArgumentException if the type cannot be substituted 720 */ 721 private static Type substituteTypeVariables(final Type type, final Map<TypeVariable<?>, Type> typeVarAssigns) { 722 if (type instanceof TypeVariable<?> && typeVarAssigns != null) { 723 final Type replacementType = typeVarAssigns.get(type); 724 725 if (replacementType == null) { 726 throw new IllegalArgumentException("missing assignment type for type variable " 727 + type); 728 } 729 return replacementType; 730 } 731 return type; 732 } 733 734 /** 735 * <p>Retrieves all the type arguments for this parameterized type 736 * including owner hierarchy arguments such as 737 * {@code Outer<K,V>.Inner<T>.DeepInner<E>} . 738 * The arguments are returned in a 739 * {@link Map} specifying the argument type for each {@link TypeVariable}. 740 * </p> 741 * 742 * @param type specifies the subject parameterized type from which to 743 * harvest the parameters. 744 * @return a {@code Map} of the type arguments to their respective type 745 * variables. 746 */ 747 public static Map<TypeVariable<?>, Type> getTypeArguments(final ParameterizedType type) { 748 return getTypeArguments(type, getRawType(type), null); 749 } 750 751 /** 752 * <p>Gets the type arguments of a class/interface based on a subtype. For 753 * instance, this method will determine that both of the parameters for the 754 * interface {@link Map} are {@link Object} for the subtype 755 * {@link java.util.Properties Properties} even though the subtype does not 756 * directly implement the {@code Map} interface.</p> 757 * <p>This method returns {@code null} if {@code type} is not assignable to 758 * {@code toClass}. It returns an empty map if none of the classes or 759 * interfaces in its inheritance hierarchy specify any type arguments.</p> 760 * <p>A side effect of this method is that it also retrieves the type 761 * arguments for the classes and interfaces that are part of the hierarchy 762 * between {@code type} and {@code toClass}. So with the above 763 * example, this method will also determine that the type arguments for 764 * {@link java.util.Hashtable Hashtable} are also both {@code Object}. 765 * In cases where the interface specified by {@code toClass} is 766 * (indirectly) implemented more than once (e.g. where {@code toClass} 767 * specifies the interface {@link java.lang.Iterable Iterable} and 768 * {@code type} specifies a parameterized type that implements both 769 * {@link java.util.Set Set} and {@link java.util.Collection Collection}), 770 * this method will look at the inheritance hierarchy of only one of the 771 * implementations/subclasses; the first interface encountered that isn't a 772 * subinterface to one of the others in the {@code type} to 773 * {@code toClass} hierarchy.</p> 774 * 775 * @param type the type from which to determine the type parameters of 776 * {@code toClass} 777 * @param toClass the class whose type parameters are to be determined based 778 * on the subtype {@code type} 779 * @return a {@code Map} of the type assignments for the type variables in 780 * each type in the inheritance hierarchy from {@code type} to 781 * {@code toClass} inclusive. 782 */ 783 public static Map<TypeVariable<?>, Type> getTypeArguments(final Type type, final Class<?> toClass) { 784 return getTypeArguments(type, toClass, null); 785 } 786 787 /** 788 * <p>Return a map of the type arguments of @{code type} in the context of {@code toClass}.</p> 789 * 790 * @param type the type in question 791 * @param toClass the class 792 * @param subtypeVarAssigns a map with type variables 793 * @return the {@code Map} with type arguments 794 */ 795 private static Map<TypeVariable<?>, Type> getTypeArguments(final Type type, final Class<?> toClass, 796 final Map<TypeVariable<?>, Type> subtypeVarAssigns) { 797 if (type instanceof Class<?>) { 798 return getTypeArguments((Class<?>) type, toClass, subtypeVarAssigns); 799 } 800 801 if (type instanceof ParameterizedType) { 802 return getTypeArguments((ParameterizedType) type, toClass, subtypeVarAssigns); 803 } 804 805 if (type instanceof GenericArrayType) { 806 return getTypeArguments(((GenericArrayType) type).getGenericComponentType(), toClass 807 .isArray() ? toClass.getComponentType() : toClass, subtypeVarAssigns); 808 } 809 810 // since wildcard types are not assignable to classes, should this just 811 // return null? 812 if (type instanceof WildcardType) { 813 for (final Type bound : getImplicitUpperBounds((WildcardType) type)) { 814 // find the first bound that is assignable to the target class 815 if (isAssignable(bound, toClass)) { 816 return getTypeArguments(bound, toClass, subtypeVarAssigns); 817 } 818 } 819 820 return null; 821 } 822 823 if (type instanceof TypeVariable<?>) { 824 for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) { 825 // find the first bound that is assignable to the target class 826 if (isAssignable(bound, toClass)) { 827 return getTypeArguments(bound, toClass, subtypeVarAssigns); 828 } 829 } 830 831 return null; 832 } 833 throw new IllegalStateException("found an unhandled type: " + type); 834 } 835 836 /** 837 * <p>Return a map of the type arguments of a parameterized type in the context of {@code toClass}.</p> 838 * 839 * @param parameterizedType the parameterized type 840 * @param toClass the class 841 * @param subtypeVarAssigns a map with type variables 842 * @return the {@code Map} with type arguments 843 */ 844 private static Map<TypeVariable<?>, Type> getTypeArguments( 845 final ParameterizedType parameterizedType, final Class<?> toClass, 846 final Map<TypeVariable<?>, Type> subtypeVarAssigns) { 847 final Class<?> cls = getRawType(parameterizedType); 848 849 // make sure they're assignable 850 if (!isAssignable(cls, toClass)) { 851 return null; 852 } 853 854 final Type ownerType = parameterizedType.getOwnerType(); 855 Map<TypeVariable<?>, Type> typeVarAssigns; 856 857 if (ownerType instanceof ParameterizedType) { 858 // get the owner type arguments first 859 final ParameterizedType parameterizedOwnerType = (ParameterizedType) ownerType; 860 typeVarAssigns = getTypeArguments(parameterizedOwnerType, 861 getRawType(parameterizedOwnerType), subtypeVarAssigns); 862 } else { 863 // no owner, prep the type variable assignments map 864 typeVarAssigns = subtypeVarAssigns == null ? new HashMap<TypeVariable<?>, Type>() 865 : new HashMap<TypeVariable<?>, Type>(subtypeVarAssigns); 866 } 867 868 // get the subject parameterized type's arguments 869 final Type[] typeArgs = parameterizedType.getActualTypeArguments(); 870 // and get the corresponding type variables from the raw class 871 final TypeVariable<?>[] typeParams = cls.getTypeParameters(); 872 873 // map the arguments to their respective type variables 874 for (int i = 0; i < typeParams.length; i++) { 875 final Type typeArg = typeArgs[i]; 876 typeVarAssigns.put(typeParams[i], typeVarAssigns.containsKey(typeArg) ? typeVarAssigns 877 .get(typeArg) : typeArg); 878 } 879 880 if (toClass.equals(cls)) { 881 // target class has been reached. Done. 882 return typeVarAssigns; 883 } 884 885 // walk the inheritance hierarchy until the target class is reached 886 return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns); 887 } 888 889 /** 890 * <p>Return a map of the type arguments of a class in the context of @{code toClass}.</p> 891 * 892 * @param cls the class in question 893 * @param toClass the context class 894 * @param subtypeVarAssigns a map with type variables 895 * @return the {@code Map} with type arguments 896 */ 897 private static Map<TypeVariable<?>, Type> getTypeArguments(Class<?> cls, final Class<?> toClass, 898 final Map<TypeVariable<?>, Type> subtypeVarAssigns) { 899 // make sure they're assignable 900 if (!isAssignable(cls, toClass)) { 901 return null; 902 } 903 904 // can't work with primitives 905 if (cls.isPrimitive()) { 906 // both classes are primitives? 907 if (toClass.isPrimitive()) { 908 // dealing with widening here. No type arguments to be 909 // harvested with these two types. 910 return new HashMap<TypeVariable<?>, Type>(); 911 } 912 913 // work with wrapper the wrapper class instead of the primitive 914 cls = ClassUtils.primitiveToWrapper(cls); 915 } 916 917 // create a copy of the incoming map, or an empty one if it's null 918 final HashMap<TypeVariable<?>, Type> typeVarAssigns = subtypeVarAssigns == null ? new HashMap<TypeVariable<?>, Type>() 919 : new HashMap<TypeVariable<?>, Type>(subtypeVarAssigns); 920 921 // has target class been reached? 922 if (toClass.equals(cls)) { 923 return typeVarAssigns; 924 } 925 926 // walk the inheritance hierarchy until the target class is reached 927 return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns); 928 } 929 930 /** 931 * <p>Tries to determine the type arguments of a class/interface based on a 932 * super parameterized type's type arguments. This method is the inverse of 933 * {@link #getTypeArguments(Type, Class)} which gets a class/interface's 934 * type arguments based on a subtype. It is far more limited in determining 935 * the type arguments for the subject class's type variables in that it can 936 * only determine those parameters that map from the subject {@link Class} 937 * object to the supertype.</p> <p>Example: {@link java.util.TreeSet 938 * TreeSet} sets its parameter as the parameter for 939 * {@link java.util.NavigableSet NavigableSet}, which in turn sets the 940 * parameter of {@link java.util.SortedSet}, which in turn sets the 941 * parameter of {@link Set}, which in turn sets the parameter of 942 * {@link java.util.Collection}, which in turn sets the parameter of 943 * {@link java.lang.Iterable}. Since {@code TreeSet}'s parameter maps 944 * (indirectly) to {@code Iterable}'s parameter, it will be able to 945 * determine that based on the super type {@code Iterable<? extends 946 * Map<Integer, ? extends Collection<?>>>}, the parameter of 947 * {@code TreeSet} is {@code ? extends Map<Integer, ? extends 948 * Collection<?>>}.</p> 949 * 950 * @param cls the class whose type parameters are to be determined, not {@code null} 951 * @param superType the super type from which {@code cls}'s type 952 * arguments are to be determined, not {@code null} 953 * @return a {@code Map} of the type assignments that could be determined 954 * for the type variables in each type in the inheritance hierarchy from 955 * {@code type} to {@code toClass} inclusive. 956 */ 957 public static Map<TypeVariable<?>, Type> determineTypeArguments(final Class<?> cls, 958 final ParameterizedType superType) { 959 Validate.notNull(cls, "cls is null"); 960 Validate.notNull(superType, "superType is null"); 961 962 final Class<?> superClass = getRawType(superType); 963 964 // compatibility check 965 if (!isAssignable(cls, superClass)) { 966 return null; 967 } 968 969 if (cls.equals(superClass)) { 970 return getTypeArguments(superType, superClass, null); 971 } 972 973 // get the next class in the inheritance hierarchy 974 final Type midType = getClosestParentType(cls, superClass); 975 976 // can only be a class or a parameterized type 977 if (midType instanceof Class<?>) { 978 return determineTypeArguments((Class<?>) midType, superType); 979 } 980 981 final ParameterizedType midParameterizedType = (ParameterizedType) midType; 982 final Class<?> midClass = getRawType(midParameterizedType); 983 // get the type variables of the mid class that map to the type 984 // arguments of the super class 985 final Map<TypeVariable<?>, Type> typeVarAssigns = determineTypeArguments(midClass, superType); 986 // map the arguments of the mid type to the class type variables 987 mapTypeVariablesToArguments(cls, midParameterizedType, typeVarAssigns); 988 989 return typeVarAssigns; 990 } 991 992 /** 993 * <p>Performs a mapping of type variables.</p> 994 * 995 * @param <T> the generic type of the class in question 996 * @param cls the class in question 997 * @param parameterizedType the parameterized type 998 * @param typeVarAssigns the map to be filled 999 */ 1000 private static <T> void mapTypeVariablesToArguments(final Class<T> cls, 1001 final ParameterizedType parameterizedType, final Map<TypeVariable<?>, Type> typeVarAssigns) { 1002 // capture the type variables from the owner type that have assignments 1003 final Type ownerType = parameterizedType.getOwnerType(); 1004 1005 if (ownerType instanceof ParameterizedType) { 1006 // recursion to make sure the owner's owner type gets processed 1007 mapTypeVariablesToArguments(cls, (ParameterizedType) ownerType, typeVarAssigns); 1008 } 1009 1010 // parameterizedType is a generic interface/class (or it's in the owner 1011 // hierarchy of said interface/class) implemented/extended by the class 1012 // cls. Find out which type variables of cls are type arguments of 1013 // parameterizedType: 1014 final Type[] typeArgs = parameterizedType.getActualTypeArguments(); 1015 1016 // of the cls's type variables that are arguments of parameterizedType, 1017 // find out which ones can be determined from the super type's arguments 1018 final TypeVariable<?>[] typeVars = getRawType(parameterizedType).getTypeParameters(); 1019 1020 // use List view of type parameters of cls so the contains() method can be used: 1021 final List<TypeVariable<Class<T>>> typeVarList = Arrays.asList(cls 1022 .getTypeParameters()); 1023 1024 for (int i = 0; i < typeArgs.length; i++) { 1025 final TypeVariable<?> typeVar = typeVars[i]; 1026 final Type typeArg = typeArgs[i]; 1027 1028 // argument of parameterizedType is a type variable of cls 1029 if (typeVarList.contains(typeArg) 1030 // type variable of parameterizedType has an assignment in 1031 // the super type. 1032 && typeVarAssigns.containsKey(typeVar)) { 1033 // map the assignment to the cls's type variable 1034 typeVarAssigns.put((TypeVariable<?>) typeArg, typeVarAssigns.get(typeVar)); 1035 } 1036 } 1037 } 1038 1039 /** 1040 * <p>Get the closest parent type to the 1041 * super class specified by {@code superClass}.</p> 1042 * 1043 * @param cls the class in question 1044 * @param superClass the super class 1045 * @return the closes parent type 1046 */ 1047 private static Type getClosestParentType(final Class<?> cls, final Class<?> superClass) { 1048 // only look at the interfaces if the super class is also an interface 1049 if (superClass.isInterface()) { 1050 // get the generic interfaces of the subject class 1051 final Type[] interfaceTypes = cls.getGenericInterfaces(); 1052 // will hold the best generic interface match found 1053 Type genericInterface = null; 1054 1055 // find the interface closest to the super class 1056 for (final Type midType : interfaceTypes) { 1057 Class<?> midClass = null; 1058 1059 if (midType instanceof ParameterizedType) { 1060 midClass = getRawType((ParameterizedType) midType); 1061 } else if (midType instanceof Class<?>) { 1062 midClass = (Class<?>) midType; 1063 } else { 1064 throw new IllegalStateException("Unexpected generic" 1065 + " interface type found: " + midType); 1066 } 1067 1068 // check if this interface is further up the inheritance chain 1069 // than the previously found match 1070 if (isAssignable(midClass, superClass) 1071 && isAssignable(genericInterface, (Type) midClass)) { 1072 genericInterface = midType; 1073 } 1074 } 1075 1076 // found a match? 1077 if (genericInterface != null) { 1078 return genericInterface; 1079 } 1080 } 1081 1082 // none of the interfaces were descendants of the target class, so the 1083 // super class has to be one, instead 1084 return cls.getGenericSuperclass(); 1085 } 1086 1087 /** 1088 * <p>Checks if the given value can be assigned to the target type 1089 * following the Java generics rules.</p> 1090 * 1091 * @param value the value to be checked 1092 * @param type the target type 1093 * @return {@code true} if {@code value} is an instance of {@code type}. 1094 */ 1095 public static boolean isInstance(final Object value, final Type type) { 1096 if (type == null) { 1097 return false; 1098 } 1099 1100 return value == null ? !(type instanceof Class<?>) || !((Class<?>) type).isPrimitive() 1101 : isAssignable(value.getClass(), type, null); 1102 } 1103 1104 /** 1105 * <p>This method strips out the redundant upper bound types in type 1106 * variable types and wildcard types (or it would with wildcard types if 1107 * multiple upper bounds were allowed).</p> <p>Example, with the variable 1108 * type declaration: 1109 * 1110 * <pre><K extends java.util.Collection<String> & 1111 * java.util.List<String>></pre> 1112 * 1113 * <p> 1114 * since {@code List} is a subinterface of {@code Collection}, 1115 * this method will return the bounds as if the declaration had been: 1116 * </p> 1117 * 1118 * <pre><K extends java.util.List<String>></pre> 1119 * 1120 * @param bounds an array of types representing the upper bounds of either 1121 * {@link WildcardType} or {@link TypeVariable}, not {@code null}. 1122 * @return an array containing the values from {@code bounds} minus the 1123 * redundant types. 1124 */ 1125 public static Type[] normalizeUpperBounds(final Type[] bounds) { 1126 Validate.notNull(bounds, "null value specified for bounds array"); 1127 // don't bother if there's only one (or none) type 1128 if (bounds.length < 2) { 1129 return bounds; 1130 } 1131 1132 final Set<Type> types = new HashSet<Type>(bounds.length); 1133 1134 for (final Type type1 : bounds) { 1135 boolean subtypeFound = false; 1136 1137 for (final Type type2 : bounds) { 1138 if (type1 != type2 && isAssignable(type2, type1, null)) { 1139 subtypeFound = true; 1140 break; 1141 } 1142 } 1143 1144 if (!subtypeFound) { 1145 types.add(type1); 1146 } 1147 } 1148 1149 return types.toArray(new Type[types.size()]); 1150 } 1151 1152 /** 1153 * <p>Returns an array containing the sole type of {@link Object} if 1154 * {@link TypeVariable#getBounds()} returns an empty array. Otherwise, it 1155 * returns the result of {@link TypeVariable#getBounds()} passed into 1156 * {@link #normalizeUpperBounds}.</p> 1157 * 1158 * @param typeVariable the subject type variable, not {@code null} 1159 * @return a non-empty array containing the bounds of the type variable. 1160 */ 1161 public static Type[] getImplicitBounds(final TypeVariable<?> typeVariable) { 1162 Validate.notNull(typeVariable, "typeVariable is null"); 1163 final Type[] bounds = typeVariable.getBounds(); 1164 1165 return bounds.length == 0 ? new Type[] { Object.class } : normalizeUpperBounds(bounds); 1166 } 1167 1168 /** 1169 * <p>Returns an array containing the sole value of {@link Object} if 1170 * {@link WildcardType#getUpperBounds()} returns an empty array. Otherwise, 1171 * it returns the result of {@link WildcardType#getUpperBounds()} 1172 * passed into {@link #normalizeUpperBounds}.</p> 1173 * 1174 * @param wildcardType the subject wildcard type, not {@code null} 1175 * @return a non-empty array containing the upper bounds of the wildcard 1176 * type. 1177 */ 1178 public static Type[] getImplicitUpperBounds(final WildcardType wildcardType) { 1179 Validate.notNull(wildcardType, "wildcardType is null"); 1180 final Type[] bounds = wildcardType.getUpperBounds(); 1181 1182 return bounds.length == 0 ? new Type[] { Object.class } : normalizeUpperBounds(bounds); 1183 } 1184 1185 /** 1186 * <p>Returns an array containing a single value of {@code null} if 1187 * {@link WildcardType#getLowerBounds()} returns an empty array. Otherwise, 1188 * it returns the result of {@link WildcardType#getLowerBounds()}.</p> 1189 * 1190 * @param wildcardType the subject wildcard type, not {@code null} 1191 * @return a non-empty array containing the lower bounds of the wildcard 1192 * type. 1193 */ 1194 public static Type[] getImplicitLowerBounds(final WildcardType wildcardType) { 1195 Validate.notNull(wildcardType, "wildcardType is null"); 1196 final Type[] bounds = wildcardType.getLowerBounds(); 1197 1198 return bounds.length == 0 ? new Type[] { null } : bounds; 1199 } 1200 1201 /** 1202 * <p>Determines whether or not specified types satisfy the bounds of their 1203 * mapped type variables. When a type parameter extends another (such as 1204 * {@code <T, S extends T>}), uses another as a type parameter (such as 1205 * {@code <T, S extends Comparable>>}), or otherwise depends on 1206 * another type variable to be specified, the dependencies must be included 1207 * in {@code typeVarAssigns}.</p> 1208 * 1209 * @param typeVarAssigns specifies the potential types to be assigned to the 1210 * type variables, not {@code null}. 1211 * @return whether or not the types can be assigned to their respective type 1212 * variables. 1213 */ 1214 public static boolean typesSatisfyVariables(final Map<TypeVariable<?>, Type> typeVarAssigns) { 1215 Validate.notNull(typeVarAssigns, "typeVarAssigns is null"); 1216 // all types must be assignable to all the bounds of the their mapped 1217 // type variable. 1218 for (final Map.Entry<TypeVariable<?>, Type> entry : typeVarAssigns.entrySet()) { 1219 final TypeVariable<?> typeVar = entry.getKey(); 1220 final Type type = entry.getValue(); 1221 1222 for (final Type bound : getImplicitBounds(typeVar)) { 1223 if (!isAssignable(type, substituteTypeVariables(bound, typeVarAssigns), 1224 typeVarAssigns)) { 1225 return false; 1226 } 1227 } 1228 } 1229 return true; 1230 } 1231 1232 /** 1233 * <p>Transforms the passed in type to a {@link Class} object. Type-checking method of convenience.</p> 1234 * 1235 * @param parameterizedType the type to be converted 1236 * @return the corresponding {@code Class} object 1237 * @throws IllegalStateException if the conversion fails 1238 */ 1239 private static Class<?> getRawType(final ParameterizedType parameterizedType) { 1240 final Type rawType = parameterizedType.getRawType(); 1241 1242 // check if raw type is a Class object 1243 // not currently necessary, but since the return type is Type instead of 1244 // Class, there's enough reason to believe that future versions of Java 1245 // may return other Type implementations. And type-safety checking is 1246 // rarely a bad idea. 1247 if (!(rawType instanceof Class<?>)) { 1248 throw new IllegalStateException("Wait... What!? Type of rawType: " + rawType); 1249 } 1250 1251 return (Class<?>) rawType; 1252 } 1253 1254 /** 1255 * <p>Get the raw type of a Java type, given its context. Primarily for use 1256 * with {@link TypeVariable}s and {@link GenericArrayType}s, or when you do 1257 * not know the runtime type of {@code type}: if you know you have a 1258 * {@link Class} instance, it is already raw; if you know you have a 1259 * {@link ParameterizedType}, its raw type is only a method call away.</p> 1260 * 1261 * @param type to resolve 1262 * @param assigningType type to be resolved against 1263 * @return the resolved {@link Class} object or {@code null} if 1264 * the type could not be resolved 1265 */ 1266 public static Class<?> getRawType(final Type type, final Type assigningType) { 1267 if (type instanceof Class<?>) { 1268 // it is raw, no problem 1269 return (Class<?>) type; 1270 } 1271 1272 if (type instanceof ParameterizedType) { 1273 // simple enough to get the raw type of a ParameterizedType 1274 return getRawType((ParameterizedType) type); 1275 } 1276 1277 if (type instanceof TypeVariable<?>) { 1278 if (assigningType == null) { 1279 return null; 1280 } 1281 1282 // get the entity declaring this type variable 1283 final Object genericDeclaration = ((TypeVariable<?>) type).getGenericDeclaration(); 1284 1285 // can't get the raw type of a method- or constructor-declared type 1286 // variable 1287 if (!(genericDeclaration instanceof Class<?>)) { 1288 return null; 1289 } 1290 1291 // get the type arguments for the declaring class/interface based 1292 // on the enclosing type 1293 final Map<TypeVariable<?>, Type> typeVarAssigns = getTypeArguments(assigningType, 1294 (Class<?>) genericDeclaration); 1295 1296 // enclosingType has to be a subclass (or subinterface) of the 1297 // declaring type 1298 if (typeVarAssigns == null) { 1299 return null; 1300 } 1301 1302 // get the argument assigned to this type variable 1303 final Type typeArgument = typeVarAssigns.get(type); 1304 1305 if (typeArgument == null) { 1306 return null; 1307 } 1308 1309 // get the argument for this type variable 1310 return getRawType(typeArgument, assigningType); 1311 } 1312 1313 if (type instanceof GenericArrayType) { 1314 // get raw component type 1315 final Class<?> rawComponentType = getRawType(((GenericArrayType) type) 1316 .getGenericComponentType(), assigningType); 1317 1318 // create array type from raw component type and return its class 1319 return Array.newInstance(rawComponentType, 0).getClass(); 1320 } 1321 1322 // (hand-waving) this is not the method you're looking for 1323 if (type instanceof WildcardType) { 1324 return null; 1325 } 1326 1327 throw new IllegalArgumentException("unknown type: " + type); 1328 } 1329 1330 /** 1331 * Learn whether the specified type denotes an array type. 1332 * @param type the type to be checked 1333 * @return {@code true} if {@code type} is an array class or a {@link GenericArrayType}. 1334 */ 1335 public static boolean isArrayType(final Type type) { 1336 return type instanceof GenericArrayType || type instanceof Class<?> && ((Class<?>) type).isArray(); 1337 } 1338 1339 /** 1340 * Get the array component type of {@code type}. 1341 * @param type the type to be checked 1342 * @return component type or null if type is not an array type 1343 */ 1344 public static Type getArrayComponentType(final Type type) { 1345 if (type instanceof Class<?>) { 1346 final Class<?> clazz = (Class<?>) type; 1347 return clazz.isArray() ? clazz.getComponentType() : null; 1348 } 1349 if (type instanceof GenericArrayType) { 1350 return ((GenericArrayType) type).getGenericComponentType(); 1351 } 1352 return null; 1353 } 1354 1355 /** 1356 * Get a type representing {@code type} with variable assignments "unrolled." 1357 * 1358 * @param typeArguments as from {@link TypeUtils#getTypeArguments(Type, Class)} 1359 * @param type the type to unroll variable assignments for 1360 * @return Type 1361 * @since 3.2 1362 */ 1363 public static Type unrollVariables(Map<TypeVariable<?>, Type> typeArguments, final Type type) { 1364 if (typeArguments == null) { 1365 typeArguments = Collections.<TypeVariable<?>, Type> emptyMap(); 1366 } 1367 if (containsTypeVariables(type)) { 1368 if (type instanceof TypeVariable<?>) { 1369 return unrollVariables(typeArguments, typeArguments.get(type)); 1370 } 1371 if (type instanceof ParameterizedType) { 1372 final ParameterizedType p = (ParameterizedType) type; 1373 final Map<TypeVariable<?>, Type> parameterizedTypeArguments; 1374 if (p.getOwnerType() == null) { 1375 parameterizedTypeArguments = typeArguments; 1376 } else { 1377 parameterizedTypeArguments = new HashMap<TypeVariable<?>, Type>(typeArguments); 1378 parameterizedTypeArguments.putAll(TypeUtils.getTypeArguments(p)); 1379 } 1380 final Type[] args = p.getActualTypeArguments(); 1381 for (int i = 0; i < args.length; i++) { 1382 final Type unrolled = unrollVariables(parameterizedTypeArguments, args[i]); 1383 if (unrolled != null) { 1384 args[i] = unrolled; 1385 } 1386 } 1387 return parameterizeWithOwner(p.getOwnerType(), (Class<?>) p.getRawType(), args); 1388 } 1389 if (type instanceof WildcardType) { 1390 final WildcardType wild = (WildcardType) type; 1391 return wildcardType().withUpperBounds(unrollBounds(typeArguments, wild.getUpperBounds())) 1392 .withLowerBounds(unrollBounds(typeArguments, wild.getLowerBounds())).build(); 1393 } 1394 } 1395 return type; 1396 } 1397 1398 /** 1399 * Local helper method to unroll variables in a type bounds array. 1400 * 1401 * @param typeArguments assignments {@link Map} 1402 * @param bounds in which to expand variables 1403 * @return {@code bounds} with any variables reassigned 1404 * @since 3.2 1405 */ 1406 private static Type[] unrollBounds(final Map<TypeVariable<?>, Type> typeArguments, final Type[] bounds) { 1407 Type[] result = bounds; 1408 int i = 0; 1409 for (; i < result.length; i++) { 1410 final Type unrolled = unrollVariables(typeArguments, result[i]); 1411 if (unrolled == null) { 1412 result = ArrayUtils.remove(result, i--); 1413 } else { 1414 result[i] = unrolled; 1415 } 1416 } 1417 return result; 1418 } 1419 1420 /** 1421 * Learn, recursively, whether any of the type parameters associated with {@code type} are bound to variables. 1422 * 1423 * @param type the type to check for type variables 1424 * @return boolean 1425 * @since 3.2 1426 */ 1427 public static boolean containsTypeVariables(Type type) { 1428 if (type instanceof TypeVariable<?>) { 1429 return true; 1430 } 1431 if (type instanceof Class<?>) { 1432 return ((Class<?>) type).getTypeParameters().length > 0; 1433 } 1434 if (type instanceof ParameterizedType) { 1435 for (Type arg : ((ParameterizedType) type).getActualTypeArguments()) { 1436 if (containsTypeVariables(arg)) { 1437 return true; 1438 } 1439 } 1440 return false; 1441 } 1442 if (type instanceof WildcardType) { 1443 WildcardType wild = (WildcardType) type; 1444 return containsTypeVariables(TypeUtils.getImplicitLowerBounds(wild)[0]) 1445 || containsTypeVariables(TypeUtils.getImplicitUpperBounds(wild)[0]); 1446 } 1447 return false; 1448 } 1449 1450 /** 1451 * Create a parameterized type instance. 1452 * 1453 * @param raw the raw class to create a parameterized type instance for 1454 * @param typeArguments the types used for parameterization 1455 * @return {@link ParameterizedType} 1456 * @since 3.2 1457 */ 1458 public static final ParameterizedType parameterize(final Class<?> raw, final Type... typeArguments) { 1459 return parameterizeWithOwner(null, raw, typeArguments); 1460 } 1461 1462 /** 1463 * Create a parameterized type instance. 1464 * 1465 * @param raw the raw class to create a parameterized type instance for 1466 * @param typeArgMappings the mapping used for parameterization 1467 * @return {@link ParameterizedType} 1468 * @since 3.2 1469 */ 1470 public static final ParameterizedType parameterize(final Class<?> raw, 1471 final Map<TypeVariable<?>, Type> typeArgMappings) { 1472 Validate.notNull(raw, "raw class is null"); 1473 Validate.notNull(typeArgMappings, "typeArgMappings is null"); 1474 return parameterizeWithOwner(null, raw, extractTypeArgumentsFrom(typeArgMappings, raw.getTypeParameters())); 1475 } 1476 1477 /** 1478 * Create a parameterized type instance. 1479 * 1480 * @param owner the owning type 1481 * @param raw the raw class to create a parameterized type instance for 1482 * @param typeArguments the types used for parameterization 1483 * 1484 * @return {@link ParameterizedType} 1485 * @since 3.2 1486 */ 1487 public static final ParameterizedType parameterizeWithOwner(final Type owner, final Class<?> raw, 1488 final Type... typeArguments) { 1489 Validate.notNull(raw, "raw class is null"); 1490 final Type useOwner; 1491 if (raw.getEnclosingClass() == null) { 1492 Validate.isTrue(owner == null, "no owner allowed for top-level %s", raw); 1493 useOwner = null; 1494 } else if (owner == null) { 1495 useOwner = raw.getEnclosingClass(); 1496 } else { 1497 Validate.isTrue(TypeUtils.isAssignable(owner, raw.getEnclosingClass()), 1498 "%s is invalid owner type for parameterized %s", owner, raw); 1499 useOwner = owner; 1500 } 1501 Validate.noNullElements(typeArguments, "null type argument at index %s"); 1502 Validate.isTrue(raw.getTypeParameters().length == typeArguments.length, 1503 "invalid number of type parameters specified: expected %s, got %s", raw.getTypeParameters().length, 1504 typeArguments.length); 1505 1506 return new ParameterizedTypeImpl(raw, useOwner, typeArguments); 1507 } 1508 1509 /** 1510 * Create a parameterized type instance. 1511 * 1512 * @param owner the owning type 1513 * @param raw the raw class to create a parameterized type instance for 1514 * @param typeArgMappings the mapping used for parameterization 1515 * @return {@link ParameterizedType} 1516 * @since 3.2 1517 */ 1518 public static final ParameterizedType parameterizeWithOwner(final Type owner, final Class<?> raw, 1519 final Map<TypeVariable<?>, Type> typeArgMappings) { 1520 Validate.notNull(raw, "raw class is null"); 1521 Validate.notNull(typeArgMappings, "typeArgMappings is null"); 1522 return parameterizeWithOwner(owner, raw, extractTypeArgumentsFrom(typeArgMappings, raw.getTypeParameters())); 1523 } 1524 1525 /** 1526 * Helper method to establish the formal parameters for a parameterized type. 1527 * @param mappings map containing the assignements 1528 * @param variables expected map keys 1529 * @return array of map values corresponding to specified keys 1530 */ 1531 private static Type[] extractTypeArgumentsFrom(Map<TypeVariable<?>, Type> mappings, TypeVariable<?>[] variables) { 1532 final Type[] result = new Type[variables.length]; 1533 int index = 0; 1534 for (TypeVariable<?> var : variables) { 1535 Validate.isTrue(mappings.containsKey(var), "missing argument mapping for %s", toString(var)); 1536 result[index++] = mappings.get(var); 1537 } 1538 return result; 1539 } 1540 1541 /** 1542 * Get a {@link WildcardTypeBuilder}. 1543 * @return {@link WildcardTypeBuilder} 1544 * @since 3.2 1545 */ 1546 public static WildcardTypeBuilder wildcardType() { 1547 return new WildcardTypeBuilder(); 1548 } 1549 1550 /** 1551 * Create a generic array type instance. 1552 * 1553 * @param componentType the type of the elements of the array. For example the component type of {@code boolean[]} 1554 * is {@code boolean} 1555 * @return {@link GenericArrayType} 1556 * @since 3.2 1557 */ 1558 public static GenericArrayType genericArrayType(final Type componentType) { 1559 return new GenericArrayTypeImpl(Validate.notNull(componentType, "componentType is null")); 1560 } 1561 1562 /** 1563 * Check equality of types. 1564 * 1565 * @param t1 the first type 1566 * @param t2 the second type 1567 * @return boolean 1568 * @since 3.2 1569 */ 1570 @SuppressWarnings( "deprecation" ) // ObjectUtils.equals(Object, Object) has been deprecated in 3.2 1571 public static boolean equals(Type t1, Type t2) { 1572 if (ObjectUtils.equals(t1, t2)) { 1573 return true; 1574 } 1575 if (t1 instanceof ParameterizedType) { 1576 return equals((ParameterizedType) t1, t2); 1577 } 1578 if (t1 instanceof GenericArrayType) { 1579 return equals((GenericArrayType) t1, t2); 1580 } 1581 if (t1 instanceof WildcardType) { 1582 return equals((WildcardType) t1, t2); 1583 } 1584 return false; 1585 } 1586 1587 /** 1588 * Learn whether {@code t} equals {@code p}. 1589 * @param p LHS 1590 * @param t RHS 1591 * @return boolean 1592 * @since 3.2 1593 */ 1594 private static boolean equals(ParameterizedType p, Type t) { 1595 if (t instanceof ParameterizedType) { 1596 final ParameterizedType other = (ParameterizedType) t; 1597 if (equals(p.getRawType(), other.getRawType()) && equals(p.getOwnerType(), other.getOwnerType())) { 1598 return equals(p.getActualTypeArguments(), other.getActualTypeArguments()); 1599 } 1600 } 1601 return false; 1602 } 1603 1604 /** 1605 * Learn whether {@code t} equals {@code a}. 1606 * @param a LHS 1607 * @param t RHS 1608 * @return boolean 1609 * @since 3.2 1610 */ 1611 private static boolean equals(GenericArrayType a, Type t) { 1612 return t instanceof GenericArrayType 1613 && equals(a.getGenericComponentType(), ((GenericArrayType) t).getGenericComponentType()); 1614 } 1615 1616 /** 1617 * Learn whether {@code t} equals {@code w}. 1618 * @param w LHS 1619 * @param t RHS 1620 * @return boolean 1621 * @since 3.2 1622 */ 1623 private static boolean equals(WildcardType w, Type t) { 1624 if (t instanceof WildcardType) { 1625 final WildcardType other = (WildcardType) t; 1626 return equals(w.getLowerBounds(), other.getLowerBounds()) 1627 && equals(TypeUtils.getImplicitUpperBounds(w), TypeUtils.getImplicitUpperBounds(other)); 1628 } 1629 return true; 1630 } 1631 1632 /** 1633 * Learn whether {@code t1} equals {@code t2}. 1634 * @param t1 LHS 1635 * @param t2 RHS 1636 * @return boolean 1637 * @since 3.2 1638 */ 1639 private static boolean equals(Type[] t1, Type[] t2) { 1640 if (t1.length == t2.length) { 1641 for (int i = 0; i < t1.length; i++) { 1642 if (!equals(t1[i], t2[i])) { 1643 return false; 1644 } 1645 } 1646 return true; 1647 } 1648 return false; 1649 } 1650 1651 /** 1652 * Present a given type as a Java-esque String. 1653 * 1654 * @param type the type to create a String representation for, not {@code null} 1655 * @return String 1656 * @since 3.2 1657 */ 1658 public static String toString(Type type) { 1659 Validate.notNull(type); 1660 if (type instanceof Class<?>) { 1661 return classToString((Class<?>) type); 1662 } 1663 if (type instanceof ParameterizedType) { 1664 return parameterizedTypeToString((ParameterizedType) type); 1665 } 1666 if (type instanceof WildcardType) { 1667 return wildcardTypeToString((WildcardType) type); 1668 } 1669 if (type instanceof TypeVariable<?>) { 1670 return typeVariableToString((TypeVariable<?>) type); 1671 } 1672 if (type instanceof GenericArrayType) { 1673 return genericArrayTypeToString((GenericArrayType) type); 1674 } 1675 throw new IllegalArgumentException(ObjectUtils.identityToString(type)); 1676 } 1677 1678 /** 1679 * Format a {@link TypeVariable} including its {@link GenericDeclaration}. 1680 * 1681 * @param var the type variable to create a String representation for, not {@code null} 1682 * @return String 1683 * @since 3.2 1684 */ 1685 public static String toLongString(TypeVariable<?> var) { 1686 Validate.notNull(var, "var is null"); 1687 final StringBuilder buf = new StringBuilder(); 1688 final GenericDeclaration d = ((TypeVariable<?>) var).getGenericDeclaration(); 1689 if (d instanceof Class<?>) { 1690 Class<?> c = (Class<?>) d; 1691 while (true) { 1692 if (c.getEnclosingClass() == null) { 1693 buf.insert(0, c.getName()); 1694 break; 1695 } 1696 buf.insert(0, c.getSimpleName()).insert(0, '.'); 1697 c = c.getEnclosingClass(); 1698 } 1699 } else if (d instanceof Type) {// not possible as of now 1700 buf.append(toString((Type) d)); 1701 } else { 1702 buf.append(d); 1703 } 1704 return buf.append(':').append(typeVariableToString(var)).toString(); 1705 } 1706 1707 /** 1708 * Wrap the specified {@link Type} in a {@link Typed} wrapper. 1709 * 1710 * @param <T> inferred generic type 1711 * @param type to wrap 1712 * @return Typed<T> 1713 * @since 3.2 1714 */ 1715 public static <T> Typed<T> wrap(final Type type) { 1716 return new Typed<T>() { 1717 @Override 1718 public Type getType() { 1719 return type; 1720 } 1721 }; 1722 } 1723 1724 /** 1725 * Wrap the specified {@link Class} in a {@link Typed} wrapper. 1726 * 1727 * @param <T> generic type 1728 * @param type to wrap 1729 * @return Typed<T> 1730 * @since 3.2 1731 */ 1732 public static <T> Typed<T> wrap(final Class<T> type) { 1733 return TypeUtils.<T> wrap((Type) type); 1734 } 1735 1736 /** 1737 * Format a {@link Class} as a {@link String}. 1738 * @param c {@code Class} to format 1739 * @return String 1740 * @since 3.2 1741 */ 1742 private static String classToString(Class<?> c) { 1743 final StringBuilder buf = new StringBuilder(); 1744 1745 if (c.getEnclosingClass() != null) { 1746 buf.append(classToString(c.getEnclosingClass())).append('.').append(c.getSimpleName()); 1747 } else { 1748 buf.append(c.getName()); 1749 } 1750 if (c.getTypeParameters().length > 0) { 1751 buf.append('<'); 1752 appendAllTo(buf, ", ", c.getTypeParameters()); 1753 buf.append('>'); 1754 } 1755 return buf.toString(); 1756 } 1757 1758 /** 1759 * Format a {@link TypeVariable} as a {@link String}. 1760 * @param v {@code TypeVariable} to format 1761 * @return String 1762 * @since 3.2 1763 */ 1764 private static String typeVariableToString(TypeVariable<?> v) { 1765 final StringBuilder buf = new StringBuilder(v.getName()); 1766 final Type[] bounds = v.getBounds(); 1767 if (bounds.length > 0 && !(bounds.length == 1 && Object.class.equals(bounds[0]))) { 1768 buf.append(" extends "); 1769 appendAllTo(buf, " & ", v.getBounds()); 1770 } 1771 return buf.toString(); 1772 } 1773 1774 /** 1775 * Format a {@link ParameterizedType} as a {@link String}. 1776 * @param p {@code ParameterizedType} to format 1777 * @return String 1778 * @since 3.2 1779 */ 1780 private static String parameterizedTypeToString(ParameterizedType p) { 1781 final StringBuilder buf = new StringBuilder(); 1782 1783 final Type useOwner = p.getOwnerType(); 1784 final Class<?> raw = (Class<?>) p.getRawType(); 1785 final Type[] typeArguments = p.getActualTypeArguments(); 1786 if (useOwner == null) { 1787 buf.append(raw.getName()); 1788 } else { 1789 if (useOwner instanceof Class<?>) { 1790 buf.append(((Class<?>) useOwner).getName()); 1791 } else { 1792 buf.append(useOwner.toString()); 1793 } 1794 buf.append('.').append(raw.getSimpleName()); 1795 } 1796 1797 appendAllTo(buf.append('<'), ", ", typeArguments).append('>'); 1798 return buf.toString(); 1799 } 1800 1801 /** 1802 * Format a {@link WildcardType} as a {@link String}. 1803 * @param w {@code WildcardType} to format 1804 * @return String 1805 * @since 3.2 1806 */ 1807 private static String wildcardTypeToString(WildcardType w) { 1808 final StringBuilder buf = new StringBuilder().append('?'); 1809 final Type[] lowerBounds = w.getLowerBounds(); 1810 final Type[] upperBounds = w.getUpperBounds(); 1811 if (lowerBounds.length > 0) { 1812 appendAllTo(buf.append(" super "), " & ", lowerBounds); 1813 } else if (!(upperBounds.length == 1 && Object.class.equals(upperBounds[0]))) { 1814 appendAllTo(buf.append(" extends "), " & ", upperBounds); 1815 } 1816 return buf.toString(); 1817 } 1818 1819 /** 1820 * Format a {@link GenericArrayType} as a {@link String}. 1821 * @param g {@code GenericArrayType} to format 1822 * @return String 1823 * @since 3.2 1824 */ 1825 private static String genericArrayTypeToString(GenericArrayType g) { 1826 return String.format("%s[]", toString(g.getGenericComponentType())); 1827 } 1828 1829 /** 1830 * Append {@code types} to @{code buf} with separator {@code sep}. 1831 * @param buf destination 1832 * @param sep separator 1833 * @param types to append 1834 * @return {@code buf} 1835 * @since 3.2 1836 */ 1837 private static StringBuilder appendAllTo(StringBuilder buf, String sep, Type... types) { 1838 Validate.notEmpty(Validate.noNullElements(types)); 1839 if (types.length > 0) { 1840 buf.append(toString(types[0])); 1841 for (int i = 1; i < types.length; i++) { 1842 buf.append(sep).append(toString(types[i])); 1843 } 1844 } 1845 return buf; 1846 } 1847 1848}