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