Coverage Report - org.apache.commons.lang3.reflect.TypeUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
TypeUtils
67%
309/455
57%
234/406
5,013
TypeUtils$1
100%
2/2
N/A
5,013
TypeUtils$GenericArrayTypeImpl
60%
6/10
0%
0/6
5,013
TypeUtils$ParameterizedTypeImpl
61%
11/18
50%
3/6
5,013
TypeUtils$WildcardTypeBuilder
100%
8/8
N/A
5,013
TypeUtils$WildcardTypeImpl
66%
10/15
50%
3/6
5,013
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.lang3.reflect;
 18  
 
 19  
 import java.lang.reflect.Array;
 20  
 import java.lang.reflect.GenericArrayType;
 21  
 import java.lang.reflect.GenericDeclaration;
 22  
 import java.lang.reflect.ParameterizedType;
 23  
 import java.lang.reflect.Type;
 24  
 import java.lang.reflect.TypeVariable;
 25  
 import java.lang.reflect.WildcardType;
 26  
 import java.util.Arrays;
 27  
 import java.util.Collections;
 28  
 import java.util.HashMap;
 29  
 import java.util.HashSet;
 30  
 import java.util.List;
 31  
 import java.util.Map;
 32  
 import java.util.Set;
 33  
 
 34  
 import org.apache.commons.lang3.ArrayUtils;
 35  
 import org.apache.commons.lang3.ClassUtils;
 36  
 import org.apache.commons.lang3.ObjectUtils;
 37  
 import org.apache.commons.lang3.Validate;
 38  
 import org.apache.commons.lang3.builder.Builder;
 39  
 
 40  
 /**
 41  
  * <p> Utility methods focusing on type inspection, particularly with regard to
 42  
  * generics. </p>
 43  
  *
 44  
  * @since 3.0
 45  
  */
 46  3
 public class TypeUtils {
 47  
 
 48  
     /**
 49  
      * {@link WildcardType} builder.
 50  
      * @since 3.2
 51  
      */
 52  6
     public static class WildcardTypeBuilder implements Builder<WildcardType> {
 53  
         /**
 54  
          * Constructor
 55  
          */
 56  6
         private WildcardTypeBuilder() {
 57  6
         }
 58  
         
 59  
         private Type[] upperBounds;
 60  
         private Type[] lowerBounds;
 61  
 
 62  
         /**
 63  
          * Specify upper bounds of the wildcard type to build.
 64  
          * @param bounds to set
 65  
          * @return {@code this}
 66  
          */
 67  
         public WildcardTypeBuilder withUpperBounds(final Type... bounds) {
 68  4
             this.upperBounds = bounds;
 69  4
             return this;
 70  
         }
 71  
 
 72  
         /**
 73  
          * Specify lower bounds of the wildcard type to build.
 74  
          * @param bounds to set
 75  
          * @return {@code this}
 76  
          */
 77  
         public WildcardTypeBuilder withLowerBounds(final Type... bounds) {
 78  3
             this.lowerBounds = bounds;
 79  3
             return this;
 80  
         }
 81  
 
 82  
         /**
 83  
          * {@inheritDoc}
 84  
          */
 85  
         @Override
 86  
         public WildcardType build() {
 87  6
             return new WildcardTypeImpl(upperBounds, lowerBounds);
 88  
         }
 89  
     }
 90  
 
 91  
     /**
 92  
      * GenericArrayType implementation class.
 93  
      * @since 3.2 
 94  
      */
 95  1
     private static final class GenericArrayTypeImpl implements GenericArrayType {
 96  
         private final Type componentType;
 97  
 
 98  
         /**
 99  
          * Constructor
 100  
          * @param componentType of this array type
 101  
          */
 102  1
         private GenericArrayTypeImpl(final Type componentType) {
 103  1
             this.componentType = componentType;
 104  1
         }
 105  
 
 106  
         /**
 107  
          * {@inheritDoc}
 108  
          */
 109  
         @Override
 110  
         public Type getGenericComponentType() {
 111  2
             return componentType;
 112  
         }
 113  
 
 114  
         /**
 115  
          * {@inheritDoc}
 116  
          */
 117  
         @Override
 118  
         public String toString() {
 119  1
             return TypeUtils.toString(this);
 120  
         }
 121  
 
 122  
         /**
 123  
          * {@inheritDoc}
 124  
          */
 125  
         @Override
 126  
         public boolean equals(final Object obj) {
 127  0
             return obj == this || obj instanceof GenericArrayType && TypeUtils.equals(this, (GenericArrayType) obj);
 128  
         }
 129  
 
 130  
         /**
 131  
          * {@inheritDoc}
 132  
          */
 133  
         @Override
 134  
         public int hashCode() {
 135  0
             int result = 67 << 4;
 136  0
             result |= componentType.hashCode();
 137  0
             return result;
 138  
         }
 139  
     }
 140  
 
 141  
     /**
 142  
      * ParameterizedType implementation class.
 143  
      * @since 3.2 
 144  
      */
 145  6
     private static final class ParameterizedTypeImpl implements ParameterizedType {
 146  
         private final Class<?> raw;
 147  
         private final Type useOwner;
 148  
         private final Type[] typeArguments;
 149  
 
 150  
         /**
 151  
          * Constructor
 152  
          * @param raw type
 153  
          * @param useOwner owner type to use, if any
 154  
          * @param typeArguments formal type arguments
 155  
          */
 156  6
         private ParameterizedTypeImpl(final Class<?> raw, final Type useOwner, final Type[] typeArguments) {
 157  6
             this.raw = raw;
 158  6
             this.useOwner = useOwner;
 159  6
             this.typeArguments = typeArguments.clone();
 160  6
         }
 161  
 
 162  
         /**
 163  
          * {@inheritDoc}
 164  
          */
 165  
         @Override
 166  
         public Type getRawType() {
 167  9
             return raw;
 168  
         }
 169  
 
 170  
         /**
 171  
          * {@inheritDoc}
 172  
          */
 173  
         @Override
 174  
         public Type getOwnerType() {
 175  8
             return useOwner;
 176  
         }
 177  
 
 178  
         /**
 179  
          * {@inheritDoc}
 180  
          */
 181  
         @Override
 182  
         public Type[] getActualTypeArguments() {
 183  8
             return typeArguments.clone();
 184  
         }
 185  
 
 186  
         /**
 187  
          * {@inheritDoc}
 188  
          */
 189  
         @Override
 190  
         public String toString() {
 191  1
             return TypeUtils.toString(this);
 192  
         }
 193  
 
 194  
         /**
 195  
          * {@inheritDoc}
 196  
          */
 197  
         @Override
 198  
         public boolean equals(final Object obj) {
 199  2
             return obj == this || obj instanceof ParameterizedType && TypeUtils.equals(this, ((ParameterizedType) obj));
 200  
         }
 201  
 
 202  
         /**
 203  
          * {@inheritDoc}
 204  
          */
 205  
         @SuppressWarnings( "deprecation" )  // ObjectUtils.hashCode(Object) has been deprecated in 3.2
 206  
         @Override
 207  
         public int hashCode() {
 208  0
             int result = 71 << 4;
 209  0
             result |= raw.hashCode();
 210  0
             result <<= 4;
 211  0
             result |= ObjectUtils.hashCode(useOwner);
 212  0
             result <<= 8;
 213  0
             result |= Arrays.hashCode(typeArguments);
 214  0
             return result;
 215  
         }
 216  
     }
 217  
 
 218  
     /**
 219  
      * WildcardType implementation class.
 220  
      * @since 3.2 
 221  
      */
 222  6
     private static final class WildcardTypeImpl implements WildcardType {
 223  1
         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  6
         private WildcardTypeImpl(final Type[] upperBounds, final Type[] lowerBounds) {
 234  6
             this.upperBounds = ObjectUtils.defaultIfNull(upperBounds, EMPTY_BOUNDS);
 235  6
             this.lowerBounds = ObjectUtils.defaultIfNull(lowerBounds, EMPTY_BOUNDS);
 236  6
         }
 237  
 
 238  
         /**
 239  
          * {@inheritDoc}
 240  
          */
 241  
         @Override
 242  
         public Type[] getUpperBounds() {
 243  14
             return upperBounds.clone();
 244  
         }
 245  
 
 246  
         /**
 247  
          * {@inheritDoc}
 248  
          */
 249  
         @Override
 250  
         public Type[] getLowerBounds() {
 251  14
             return lowerBounds.clone();
 252  
         }
 253  
 
 254  
         /**
 255  
          * {@inheritDoc}
 256  
          */
 257  
         @Override
 258  
         public String toString() {
 259  4
             return TypeUtils.toString(this);
 260  
         }
 261  
 
 262  
         /**
 263  
          * {@inheritDoc}
 264  
          */
 265  
         @Override
 266  
         public boolean equals(final Object obj) {
 267  1
             return obj == this || obj instanceof WildcardType && TypeUtils.equals(this, (WildcardType) obj);
 268  
         }
 269  
 
 270  
         /**
 271  
          * {@inheritDoc}
 272  
          */
 273  
         @Override
 274  
         public int hashCode() {
 275  0
             int result = 73 << 8;
 276  0
             result |= Arrays.hashCode(upperBounds);
 277  0
             result <<= 8;
 278  0
             result |= Arrays.hashCode(lowerBounds);
 279  0
             return result;
 280  
         }
 281  
     }
 282  
 
 283  
     /**
 284  
      * A wildcard instance matching {@code ?}.
 285  
      * @since 3.2
 286  
      */
 287  1
     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  0
         super();
 298  0
     }
 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  170
         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  336
         if (toType == null || toType instanceof Class<?>) {
 326  143
             return isAssignable(type, (Class<?>) toType);
 327  
         }
 328  
 
 329  193
         if (toType instanceof ParameterizedType) {
 330  106
             return isAssignable(type, (ParameterizedType) toType, typeVarAssigns);
 331  
         }
 332  
 
 333  87
         if (toType instanceof GenericArrayType) {
 334  43
             return isAssignable(type, (GenericArrayType) toType, typeVarAssigns);
 335  
         }
 336  
 
 337  44
         if (toType instanceof WildcardType) {
 338  44
             return isAssignable(type, (WildcardType) toType, typeVarAssigns);
 339  
         }
 340  
 
 341  0
         if (toType instanceof TypeVariable<?>) {
 342  0
             return isAssignable(type, (TypeVariable<?>) toType, typeVarAssigns);
 343  
         }
 344  
 
 345  0
         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  551
         if (type == null) {
 358  
             // consistency with ClassUtils.isAssignable() behavior
 359  44
             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  507
         if (toClass == null) {
 365  8
             return false;
 366  
         }
 367  
 
 368  
         // all types are assignable to themselves
 369  499
         if (toClass.equals(type)) {
 370  326
             return true;
 371  
         }
 372  
 
 373  173
         if (type instanceof Class<?>) {
 374  
             // just comparing two classes
 375  154
             return ClassUtils.isAssignable((Class<?>) type, toClass);
 376  
         }
 377  
 
 378  19
         if (type instanceof ParameterizedType) {
 379  
             // only have to compare the raw type to the class
 380  13
             return isAssignable(getRawType((ParameterizedType) type), toClass);
 381  
         }
 382  
 
 383  
         // *
 384  6
         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  0
             for (final Type bound : ((TypeVariable<?>) type).getBounds()) {
 388  0
                 if (isAssignable(bound, toClass)) {
 389  0
                     return true;
 390  
                 }
 391  
             }
 392  
 
 393  0
             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  6
         if (type instanceof GenericArrayType) {
 399  6
             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  0
         if (type instanceof WildcardType) {
 408  0
             return false;
 409  
         }
 410  
 
 411  0
         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  106
         if (type == null) {
 426  0
             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  106
         if (toParameterizedType == null) {
 432  0
             return false;
 433  
         }
 434  
 
 435  
         // all types are assignable to themselves
 436  106
         if (toParameterizedType.equals(type)) {
 437  6
             return true;
 438  
         }
 439  
 
 440  
         // get the target type's raw type
 441  100
         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  100
         final Map<TypeVariable<?>, Type> fromTypeVarAssigns = getTypeArguments(type, toClass, null);
 445  
 
 446  
         // null means the two types are not compatible
 447  100
         if (fromTypeVarAssigns == null) {
 448  0
             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  100
         if (fromTypeVarAssigns.isEmpty()) {
 455  12
             return true;
 456  
         }
 457  
 
 458  
         // get the target type's type arguments including owner type arguments
 459  88
         final Map<TypeVariable<?>, Type> toTypeVarAssigns = getTypeArguments(toParameterizedType,
 460  
                 toClass, typeVarAssigns);
 461  
 
 462  
         // now to check each type argument
 463  88
         for (final TypeVariable<?> var : toTypeVarAssigns.keySet()) {
 464  97
             final Type toTypeArg = unrollVariableAssignments(var, toTypeVarAssigns);
 465  97
             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  97
             if (fromTypeArg != null
 471  
                     && !toTypeArg.equals(fromTypeArg)
 472  
                     && !(toTypeArg instanceof WildcardType && isAssignable(fromTypeArg, toTypeArg,
 473  
                             typeVarAssigns))) {
 474  49
                 return false;
 475  
             }
 476  48
         }
 477  39
         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  198
             result = typeVarAssigns.get(var);
 492  198
             if (result instanceof TypeVariable<?> && !result.equals(var)) {
 493  4
                 var = (TypeVariable<?>) result;
 494  4
                 continue;
 495  
             }
 496  
             break;
 497  
         } while (true);
 498  194
         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  43
         if (type == null) {
 514  0
             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  43
         if (toGenericArrayType == null) {
 520  0
             return false;
 521  
         }
 522  
 
 523  
         // all types are assignable to themselves
 524  43
         if (toGenericArrayType.equals(type)) {
 525  6
             return true;
 526  
         }
 527  
 
 528  37
         final Type toComponentType = toGenericArrayType.getGenericComponentType();
 529  
 
 530  37
         if (type instanceof Class<?>) {
 531  7
             final Class<?> cls = (Class<?>) type;
 532  
 
 533  
             // compare the component types
 534  7
             return cls.isArray()
 535  
                     && isAssignable(cls.getComponentType(), toComponentType, typeVarAssigns);
 536  
         }
 537  
 
 538  30
         if (type instanceof GenericArrayType) {
 539  
             // compare the component types
 540  30
             return isAssignable(((GenericArrayType) type).getGenericComponentType(),
 541  
                     toComponentType, typeVarAssigns);
 542  
         }
 543  
 
 544  0
         if (type instanceof WildcardType) {
 545  
             // so long as one of the upper bounds is assignable, it's good
 546  0
             for (final Type bound : getImplicitUpperBounds((WildcardType) type)) {
 547  0
                 if (isAssignable(bound, toGenericArrayType)) {
 548  0
                     return true;
 549  
                 }
 550  
             }
 551  
 
 552  0
             return false;
 553  
         }
 554  
 
 555  0
         if (type instanceof TypeVariable<?>) {
 556  
             // probably should remove the following logic and just return false.
 557  
             // type variables cannot specify arrays as bounds.
 558  0
             for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) {
 559  0
                 if (isAssignable(bound, toGenericArrayType)) {
 560  0
                     return true;
 561  
                 }
 562  
             }
 563  
 
 564  0
             return false;
 565  
         }
 566  
 
 567  0
         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  0
             return false;
 572  
         }
 573  
 
 574  0
         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  44
         if (type == null) {
 590  0
             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  44
         if (toWildcardType == null) {
 596  0
             return false;
 597  
         }
 598  
 
 599  
         // all types are assignable to themselves
 600  44
         if (toWildcardType.equals(type)) {
 601  0
             return true;
 602  
         }
 603  
 
 604  44
         final Type[] toUpperBounds = getImplicitUpperBounds(toWildcardType);
 605  44
         final Type[] toLowerBounds = getImplicitLowerBounds(toWildcardType);
 606  
 
 607  44
         if (type instanceof WildcardType) {
 608  24
             final WildcardType wildcardType = (WildcardType) type;
 609  24
             final Type[] upperBounds = getImplicitUpperBounds(wildcardType);
 610  24
             final Type[] lowerBounds = getImplicitLowerBounds(wildcardType);
 611  
 
 612  42
             for (Type toBound : toUpperBounds) {
 613  
                 // if there are assignments for unresolved type variables,
 614  
                 // now's the time to substitute them.
 615  24
                 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  42
                 for (final Type bound : upperBounds) {
 621  24
                     if (!isAssignable(bound, toBound, typeVarAssigns)) {
 622  6
                         return false;
 623  
                     }
 624  
                 }
 625  
             }
 626  
 
 627  26
             for (Type toBound : toLowerBounds) {
 628  
                 // if there are assignments for unresolved type variables,
 629  
                 // now's the time to substitute them.
 630  18
                 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  26
                 for (final Type bound : lowerBounds) {
 636  18
                     if (!isAssignable(toBound, bound, typeVarAssigns)) {
 637  10
                         return false;
 638  
                     }
 639  
                 }
 640  
             }
 641  8
             return true;
 642  
         }
 643  
 
 644  38
         for (final Type toBound : toUpperBounds) {
 645  
             // if there are assignments for unresolved type variables,
 646  
             // now's the time to substitute them.
 647  20
             if (!isAssignable(type, substituteTypeVariables(toBound, typeVarAssigns),
 648  
                     typeVarAssigns)) {
 649  2
                 return false;
 650  
             }
 651  
         }
 652  
 
 653  34
         for (final Type toBound : toLowerBounds) {
 654  
             // if there are assignments for unresolved type variables,
 655  
             // now's the time to substitute them.
 656  18
             if (!isAssignable(substituteTypeVariables(toBound, typeVarAssigns), type,
 657  
                     typeVarAssigns)) {
 658  2
                 return false;
 659  
             }
 660  
         }
 661  16
         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  0
         if (type == null) {
 677  0
             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  0
         if (toTypeVariable == null) {
 683  0
             return false;
 684  
         }
 685  
 
 686  
         // all types are assignable to themselves
 687  0
         if (toTypeVariable.equals(type)) {
 688  0
             return true;
 689  
         }
 690  
 
 691  0
         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  0
             final Type[] bounds = getImplicitBounds((TypeVariable<?>) type);
 696  
 
 697  0
             for (final Type bound : bounds) {
 698  0
                 if (isAssignable(bound, toTypeVariable, typeVarAssigns)) {
 699  0
                     return true;
 700  
                 }
 701  
             }
 702  
         }
 703  
 
 704  0
         if (type instanceof Class<?> || type instanceof ParameterizedType
 705  
                 || type instanceof GenericArrayType || type instanceof WildcardType) {
 706  0
             return false;
 707  
         }
 708  
 
 709  0
         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  83
         if (type instanceof TypeVariable<?> && typeVarAssigns != null) {
 722  2
             final Type replacementType = typeVarAssigns.get(type);
 723  
 
 724  2
             if (replacementType == null) {
 725  0
                 throw new IllegalArgumentException("missing assignment type for type variable "
 726  
                         + type);
 727  
             }
 728  2
             return replacementType;
 729  
         }
 730  81
         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  0
         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>
 756  
      * <p>This method 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  56
         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  248
         if (type instanceof Class<?>) {
 797  90
             return getTypeArguments((Class<?>) type, toClass, subtypeVarAssigns);
 798  
         }
 799  
 
 800  158
         if (type instanceof ParameterizedType) {
 801  158
             return getTypeArguments((ParameterizedType) type, toClass, subtypeVarAssigns);
 802  
         }
 803  
 
 804  0
         if (type instanceof GenericArrayType) {
 805  0
             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  0
         if (type instanceof WildcardType) {
 812  0
             for (final Type bound : getImplicitUpperBounds((WildcardType) type)) {
 813  
                 // find the first bound that is assignable to the target class
 814  0
                 if (isAssignable(bound, toClass)) {
 815  0
                     return getTypeArguments(bound, toClass, subtypeVarAssigns);
 816  
                 }
 817  
             }
 818  
 
 819  0
             return null;
 820  
         }
 821  
 
 822  0
         if (type instanceof TypeVariable<?>) {
 823  0
             for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) {
 824  
                 // find the first bound that is assignable to the target class
 825  0
                 if (isAssignable(bound, toClass)) {
 826  0
                     return getTypeArguments(bound, toClass, subtypeVarAssigns);
 827  
                 }
 828  
             }
 829  
 
 830  0
             return null;
 831  
         }
 832  0
         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  261
         final Class<?> cls = getRawType(parameterizedType);
 847  
 
 848  
         // make sure they're assignable
 849  261
         if (!isAssignable(cls, toClass)) {
 850  0
             return null;
 851  
         }
 852  
 
 853  261
         final Type ownerType = parameterizedType.getOwnerType();
 854  
         Map<TypeVariable<?>, Type> typeVarAssigns;
 855  
 
 856  261
         if (ownerType instanceof ParameterizedType) {
 857  
             // get the owner type arguments first
 858  14
             final ParameterizedType parameterizedOwnerType = (ParameterizedType) ownerType;
 859  14
             typeVarAssigns = getTypeArguments(parameterizedOwnerType,
 860  
                     getRawType(parameterizedOwnerType), subtypeVarAssigns);
 861  14
         } else {
 862  
             // no owner, prep the type variable assignments map
 863  247
             typeVarAssigns = subtypeVarAssigns == null ? new HashMap<TypeVariable<?>, Type>()
 864  
                     : new HashMap<TypeVariable<?>, Type>(subtypeVarAssigns);
 865  
         }
 866  
 
 867  
         // get the subject parameterized type's arguments
 868  261
         final Type[] typeArgs = parameterizedType.getActualTypeArguments();
 869  
         // and get the corresponding type variables from the raw class
 870  261
         final TypeVariable<?>[] typeParams = cls.getTypeParameters();
 871  
 
 872  
         // map the arguments to their respective type variables
 873  543
         for (int i = 0; i < typeParams.length; i++) {
 874  282
             final Type typeArg = typeArgs[i];
 875  282
             typeVarAssigns.put(typeParams[i], typeVarAssigns.containsKey(typeArg) ? typeVarAssigns
 876  
                     .get(typeArg) : typeArg);
 877  
         }
 878  
 
 879  261
         if (toClass.equals(cls)) {
 880  
             // target class has been reached. Done.
 881  239
             return typeVarAssigns;
 882  
         }
 883  
 
 884  
         // walk the inheritance hierarchy until the target class is reached
 885  22
         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  90
         if (!isAssignable(cls, toClass)) {
 900  0
             return null;
 901  
         }
 902  
 
 903  
         // can't work with primitives
 904  90
         if (cls.isPrimitive()) {
 905  
             // both classes are primitives?
 906  3
             if (toClass.isPrimitive()) {
 907  
                 // dealing with widening here. No type arguments to be
 908  
                 // harvested with these two types.
 909  0
                 return new HashMap<TypeVariable<?>, Type>();
 910  
             }
 911  
 
 912  
             // work with wrapper the wrapper class instead of the primitive
 913  3
             cls = ClassUtils.primitiveToWrapper(cls);
 914  
         }
 915  
 
 916  
         // create a copy of the incoming map, or an empty one if it's null
 917  90
         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  90
         if (toClass.equals(cls)) {
 922  20
             return typeVarAssigns;
 923  
         }
 924  
 
 925  
         // walk the inheritance hierarchy until the target class is reached
 926  70
         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  6
         Validate.notNull(cls, "cls is null");
 959  6
         Validate.notNull(superType, "superType is null");
 960  
 
 961  6
         final Class<?> superClass = getRawType(superType);
 962  
 
 963  
         // compatibility check
 964  6
         if (!isAssignable(cls, superClass)) {
 965  0
             return null;
 966  
         }
 967  
 
 968  6
         if (cls.equals(superClass)) {
 969  1
             return getTypeArguments(superType, superClass, null);
 970  
         }
 971  
 
 972  
         // get the next class in the inheritance hierarchy
 973  5
         final Type midType = getClosestParentType(cls, superClass);
 974  
 
 975  
         // can only be a class or a parameterized type
 976  5
         if (midType instanceof Class<?>) {
 977  0
             return determineTypeArguments((Class<?>) midType, superType);
 978  
         }
 979  
 
 980  5
         final ParameterizedType midParameterizedType = (ParameterizedType) midType;
 981  5
         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  5
         final Map<TypeVariable<?>, Type> typeVarAssigns = determineTypeArguments(midClass, superType);
 985  
         // map the arguments of the mid type to the class type variables
 986  5
         mapTypeVariablesToArguments(cls, midParameterizedType, typeVarAssigns);
 987  
 
 988  5
         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  5
         final Type ownerType = parameterizedType.getOwnerType();
 1003  
 
 1004  5
         if (ownerType instanceof ParameterizedType) {
 1005  
             // recursion to make sure the owner's owner type gets processed
 1006  0
             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  5
         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  5
         final TypeVariable<?>[] typeVars = getRawType(parameterizedType).getTypeParameters();
 1018  
 
 1019  
         // use List view of type parameters of cls so the contains() method can be used:
 1020  5
         final List<TypeVariable<Class<T>>> typeVarList = Arrays.asList(cls
 1021  
                 .getTypeParameters());
 1022  
 
 1023  10
         for (int i = 0; i < typeArgs.length; i++) {
 1024  5
             final TypeVariable<?> typeVar = typeVars[i];
 1025  5
             final Type typeArg = typeArgs[i];
 1026  
 
 1027  
             // argument of parameterizedType is a type variable of cls
 1028  5
             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  5
                 typeVarAssigns.put((TypeVariable<?>) typeArg, typeVarAssigns.get(typeVar));
 1034  
             }
 1035  
         }
 1036  5
     }
 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  97
         if (superClass.isInterface()) {
 1049  
             // get the generic interfaces of the subject class
 1050  31
             final Type[] interfaceTypes = cls.getGenericInterfaces();
 1051  
             // will hold the best generic interface match found
 1052  31
             Type genericInterface = null;
 1053  
 
 1054  
             // find the interface closest to the super class
 1055  62
             for (final Type midType : interfaceTypes) {
 1056  31
                 Class<?> midClass = null;
 1057  
 
 1058  31
                 if (midType instanceof ParameterizedType) {
 1059  29
                     midClass = getRawType((ParameterizedType) midType);
 1060  2
                 } else if (midType instanceof Class<?>) {
 1061  2
                     midClass = (Class<?>) midType;
 1062  
                 } else {
 1063  0
                     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  31
                 if (isAssignable(midClass, superClass)
 1070  
                         && isAssignable(genericInterface, (Type) midClass)) {
 1071  29
                     genericInterface = midType;
 1072  
                 }
 1073  
             }
 1074  
 
 1075  
             // found a match?
 1076  31
             if (genericInterface != null) {
 1077  29
                 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  68
         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  2
         if (type == null) {
 1096  0
             return false;
 1097  
         }
 1098  
 
 1099  2
         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>&lt;K extends java.util.Collection&lt;String&gt; &amp;
 1110  
      * java.util.List&lt;String&gt;&gt;</pre>
 1111  
      *
 1112  
      * <p>
 1113  
      * since {@code List} is a subinterface of {@code Collection},
 1114  
      * this method will return the bounds as if the declaration had been:
 1115  
      * </p>
 1116  
      *
 1117  
      * <pre>&lt;K extends java.util.List&lt;String&gt;&gt;</pre>
 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  73
         Validate.notNull(bounds, "null value specified for bounds array");
 1126  
         // don't bother if there's only one (or none) type
 1127  73
         if (bounds.length < 2) {
 1128  72
             return bounds;
 1129  
         }
 1130  
 
 1131  1
         final Set<Type> types = new HashSet<Type>(bounds.length);
 1132  
 
 1133  3
         for (final Type type1 : bounds) {
 1134  2
             boolean subtypeFound = false;
 1135  
 
 1136  6
             for (final Type type2 : bounds) {
 1137  4
                 if (type1 != type2 && isAssignable(type2, type1, null)) {
 1138  0
                     subtypeFound = true;
 1139  0
                     break;
 1140  
                 }
 1141  
             }
 1142  
 
 1143  2
             if (!subtypeFound) {
 1144  2
                 types.add(type1);
 1145  
             }
 1146  
         }
 1147  
 
 1148  1
         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  3
         Validate.notNull(typeVariable, "typeVariable is null");
 1162  3
         final Type[] bounds = typeVariable.getBounds();
 1163  
 
 1164  3
         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  71
         Validate.notNull(wildcardType, "wildcardType is null");
 1179  71
         final Type[] bounds = wildcardType.getUpperBounds();
 1180  
 
 1181  71
         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  71
         Validate.notNull(wildcardType, "wildcardType is null");
 1195  71
         final Type[] bounds = wildcardType.getLowerBounds();
 1196  
 
 1197  71
         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  3
         Validate.notNull(typeVarAssigns, "typeVarAssigns is null");
 1215  
         // all types must be assignable to all the bounds of the their mapped
 1216  
         // type variable.
 1217  3
         for (final Map.Entry<TypeVariable<?>, Type> entry : typeVarAssigns.entrySet()) {
 1218  3
             final TypeVariable<?> typeVar = entry.getKey();
 1219  3
             final Type type = entry.getValue();
 1220  
 
 1221  6
             for (final Type bound : getImplicitBounds(typeVar)) {
 1222  3
                 if (!isAssignable(type, substituteTypeVariables(bound, typeVarAssigns),
 1223  
                         typeVarAssigns)) {
 1224  0
                     return false;
 1225  
                 }
 1226  
             }
 1227  3
         }
 1228  3
         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  437
         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  437
         if (!(rawType instanceof Class<?>)) {
 1247  0
             throw new IllegalStateException("Wait... What!? Type of rawType: " + rawType);
 1248  
         }
 1249  
 
 1250  437
         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  14
         if (type instanceof Class<?>) {
 1267  
             // it is raw, no problem
 1268  4
             return (Class<?>) type;
 1269  
         }
 1270  
 
 1271  10
         if (type instanceof ParameterizedType) {
 1272  
             // simple enough to get the raw type of a ParameterizedType
 1273  4
             return getRawType((ParameterizedType) type);
 1274  
         }
 1275  
 
 1276  6
         if (type instanceof TypeVariable<?>) {
 1277  5
             if (assigningType == null) {
 1278  0
                 return null;
 1279  
             }
 1280  
 
 1281  
             // get the entity declaring this type variable
 1282  5
             final Object genericDeclaration = ((TypeVariable<?>) type).getGenericDeclaration();
 1283  
 
 1284  
             // can't get the raw type of a method- or constructor-declared type
 1285  
             // variable
 1286  5
             if (!(genericDeclaration instanceof Class<?>)) {
 1287  0
                 return null;
 1288  
             }
 1289  
 
 1290  
             // get the type arguments for the declaring class/interface based
 1291  
             // on the enclosing type
 1292  5
             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  5
             if (typeVarAssigns == null) {
 1298  0
                 return null;
 1299  
             }
 1300  
 
 1301  
             // get the argument assigned to this type variable
 1302  5
             final Type typeArgument = typeVarAssigns.get(type);
 1303  
 
 1304  5
             if (typeArgument == null) {
 1305  1
                 return null;
 1306  
             }
 1307  
 
 1308  
             // get the argument for this type variable
 1309  4
             return getRawType(typeArgument, assigningType);
 1310  
         }
 1311  
 
 1312  1
         if (type instanceof GenericArrayType) {
 1313  
             // get raw component type
 1314  1
             final Class<?> rawComponentType = getRawType(((GenericArrayType) type)
 1315  
                     .getGenericComponentType(), assigningType);
 1316  
 
 1317  
             // create array type from raw component type and return its class
 1318  1
             return Array.newInstance(rawComponentType, 0).getClass();
 1319  
         }
 1320  
 
 1321  
         // (hand-waving) this is not the method you're looking for
 1322  0
         if (type instanceof WildcardType) {
 1323  0
             return null;
 1324  
         }
 1325  
 
 1326  0
         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  34
         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  30
         if (type instanceof Class<?>) {
 1345  18
             final Class<?> clazz = (Class<?>) type;
 1346  18
             return clazz.isArray() ? clazz.getComponentType() : null;
 1347  
         }
 1348  12
         if (type instanceof GenericArrayType) {
 1349  6
             return ((GenericArrayType) type).getGenericComponentType();
 1350  
         }
 1351  6
         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  9
         if (typeArguments == null) {
 1364  0
             typeArguments = Collections.<TypeVariable<?>, Type> emptyMap();
 1365  
         }
 1366  9
         if (containsTypeVariables(type)) {
 1367  3
             if (type instanceof TypeVariable<?>) {
 1368  3
                 return unrollVariables(typeArguments, typeArguments.get(type));
 1369  
             }
 1370  0
             if (type instanceof ParameterizedType) {
 1371  0
                 final ParameterizedType p = (ParameterizedType) type;
 1372  
                 final Map<TypeVariable<?>, Type> parameterizedTypeArguments;
 1373  0
                 if (p.getOwnerType() == null) {
 1374  0
                     parameterizedTypeArguments = typeArguments;
 1375  
                 } else {
 1376  0
                     parameterizedTypeArguments = new HashMap<TypeVariable<?>, Type>(typeArguments);
 1377  0
                     parameterizedTypeArguments.putAll(TypeUtils.getTypeArguments(p));
 1378  
                 }
 1379  0
                 final Type[] args = p.getActualTypeArguments();
 1380  0
                 for (int i = 0; i < args.length; i++) {
 1381  0
                     final Type unrolled = unrollVariables(parameterizedTypeArguments, args[i]);
 1382  0
                     if (unrolled != null) {
 1383  0
                         args[i] = unrolled;
 1384  
                     }
 1385  
                 }
 1386  0
                 return parameterizeWithOwner(p.getOwnerType(), (Class<?>) p.getRawType(), args);
 1387  
             }
 1388  0
             if (type instanceof WildcardType) {
 1389  0
                 final WildcardType wild = (WildcardType) type;
 1390  0
                 return wildcardType().withUpperBounds(unrollBounds(typeArguments, wild.getUpperBounds()))
 1391  
                     .withLowerBounds(unrollBounds(typeArguments, wild.getLowerBounds())).build();
 1392  
             }
 1393  
         }
 1394  6
         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  0
         Type[] result = bounds;
 1407  0
         int i = 0;
 1408  0
         for (; i < result.length; i++) {
 1409  0
             final Type unrolled = unrollVariables(typeArguments, result[i]);
 1410  0
             if (unrolled == null) {
 1411  0
                 result = ArrayUtils.remove(result, i--);
 1412  
             } else {
 1413  0
                 result[i] = unrolled;
 1414  
             }
 1415  
         }
 1416  0
         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(final Type type) {
 1427  9
         if (type instanceof TypeVariable<?>) {
 1428  3
             return true;
 1429  
         }
 1430  6
         if (type instanceof Class<?>) {
 1431  6
             return ((Class<?>) type).getTypeParameters().length > 0;
 1432  
         }
 1433  0
         if (type instanceof ParameterizedType) {
 1434  0
             for (final Type arg : ((ParameterizedType) type).getActualTypeArguments()) {
 1435  0
                 if (containsTypeVariables(arg)) {
 1436  0
                     return true;
 1437  
                 }
 1438  
             }
 1439  0
             return false;
 1440  
         }
 1441  0
         if (type instanceof WildcardType) {
 1442  0
             final WildcardType wild = (WildcardType) type;
 1443  0
             return containsTypeVariables(TypeUtils.getImplicitLowerBounds(wild)[0])
 1444  
                 || containsTypeVariables(TypeUtils.getImplicitUpperBounds(wild)[0]);
 1445  
         }
 1446  0
         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  5
         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  0
         Validate.notNull(raw, "raw class is null");
 1472  0
         Validate.notNull(typeArgMappings, "typeArgMappings is null");
 1473  0
         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  6
         Validate.notNull(raw, "raw class is null");
 1489  
         final Type useOwner;
 1490  6
         if (raw.getEnclosingClass() == null) {
 1491  5
             Validate.isTrue(owner == null, "no owner allowed for top-level %s", raw);
 1492  5
             useOwner = null;
 1493  1
         } else if (owner == null) {
 1494  0
             useOwner = raw.getEnclosingClass();
 1495  
         } else {
 1496  1
             Validate.isTrue(TypeUtils.isAssignable(owner, raw.getEnclosingClass()),
 1497  
                 "%s is invalid owner type for parameterized %s", owner, raw);
 1498  1
             useOwner = owner;
 1499  
         }
 1500  6
         Validate.noNullElements(typeArguments, "null type argument at index %s");
 1501  6
         Validate.isTrue(raw.getTypeParameters().length == typeArguments.length,
 1502  
             "invalid number of type parameters specified: expected %d, got %d", raw.getTypeParameters().length,
 1503  
             typeArguments.length);
 1504  
 
 1505  6
         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  0
         Validate.notNull(raw, "raw class is null");
 1520  0
         Validate.notNull(typeArgMappings, "typeArgMappings is null");
 1521  0
         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(final Map<TypeVariable<?>, Type> mappings, final TypeVariable<?>[] variables) {
 1531  0
         final Type[] result = new Type[variables.length];
 1532  0
         int index = 0;
 1533  0
         for (final TypeVariable<?> var : variables) {
 1534  0
             Validate.isTrue(mappings.containsKey(var), "missing argument mapping for %s", toString(var));
 1535  0
             result[index++] = mappings.get(var);
 1536  
         }
 1537  0
         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  6
         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  1
         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  
     @SuppressWarnings( "deprecation" )  // ObjectUtils.equals(Object, Object) has been deprecated in 3.2
 1570  
     public static boolean equals(final Type t1, final Type t2) {
 1571  31
         if (ObjectUtils.equals(t1, t2)) {
 1572  28
             return true;
 1573  
         }
 1574  3
         if (t1 instanceof ParameterizedType) {
 1575  1
             return equals((ParameterizedType) t1, t2);
 1576  
         }
 1577  2
         if (t1 instanceof GenericArrayType) {
 1578  0
             return equals((GenericArrayType) t1, t2);
 1579  
         }
 1580  2
         if (t1 instanceof WildcardType) {
 1581  1
             return equals((WildcardType) t1, t2);
 1582  
         }
 1583  1
         return false;
 1584  
     }
 1585  
 
 1586  
     /**
 1587  
      * Learn whether {@code t} equals {@code p}.
 1588  
      * @param p LHS
 1589  
      * @param t RHS
 1590  
      * @return boolean
 1591  
      * @since 3.2
 1592  
      */
 1593  
     private static boolean equals(final ParameterizedType p, final Type t) {
 1594  3
         if (t instanceof ParameterizedType) {
 1595  2
             final ParameterizedType other = (ParameterizedType) t;
 1596  2
             if (equals(p.getRawType(), other.getRawType()) && equals(p.getOwnerType(), other.getOwnerType())) {
 1597  2
                 return equals(p.getActualTypeArguments(), other.getActualTypeArguments());
 1598  
             }
 1599  
         }
 1600  1
         return false;
 1601  
     }
 1602  
 
 1603  
     /**
 1604  
      * Learn whether {@code t} equals {@code a}.
 1605  
      * @param a LHS
 1606  
      * @param t RHS
 1607  
      * @return boolean
 1608  
      * @since 3.2
 1609  
      */
 1610  
     private static boolean equals(final GenericArrayType a, final Type t) {
 1611  0
         return t instanceof GenericArrayType
 1612  
             && equals(a.getGenericComponentType(), ((GenericArrayType) t).getGenericComponentType());
 1613  
     }
 1614  
 
 1615  
     /**
 1616  
      * Learn whether {@code t} equals {@code w}.
 1617  
      * @param w LHS
 1618  
      * @param t RHS
 1619  
      * @return boolean
 1620  
      * @since 3.2
 1621  
      */
 1622  
     private static boolean equals(final WildcardType w, final Type t) {
 1623  2
         if (t instanceof WildcardType) {
 1624  1
             final WildcardType other = (WildcardType) t;
 1625  1
             return equals(getImplicitLowerBounds(w), getImplicitLowerBounds(other))
 1626  
                 && equals(getImplicitUpperBounds(w), getImplicitUpperBounds(other));
 1627  
         }
 1628  1
         return false;
 1629  
     }
 1630  
 
 1631  
     /**
 1632  
      * Learn whether {@code t1} equals {@code t2}.
 1633  
      * @param t1 LHS
 1634  
      * @param t2 RHS
 1635  
      * @return boolean
 1636  
      * @since 3.2
 1637  
      */
 1638  
     private static boolean equals(final Type[] t1, final Type[] t2) {
 1639  4
         if (t1.length == t2.length) {
 1640  8
             for (int i = 0; i < t1.length; i++) {
 1641  4
                 if (!equals(t1[i], t2[i])) {
 1642  0
                     return false;
 1643  
                 }
 1644  
             }
 1645  4
             return true;
 1646  
         }
 1647  0
         return false;
 1648  
     }
 1649  
 
 1650  
     /**
 1651  
      * Present a given type as a Java-esque String.
 1652  
      *
 1653  
      * @param type the type to create a String representation for, not {@code null}
 1654  
      * @return String
 1655  
      * @since 3.2
 1656  
      */
 1657  
     public static String toString(final Type type) {
 1658  35
         Validate.notNull(type);
 1659  35
         if (type instanceof Class<?>) {
 1660  16
             return classToString((Class<?>) type);
 1661  
         }
 1662  19
         if (type instanceof ParameterizedType) {
 1663  7
             return parameterizedTypeToString((ParameterizedType) type);
 1664  
         }
 1665  12
         if (type instanceof WildcardType) {
 1666  9
             return wildcardTypeToString((WildcardType) type);
 1667  
         }
 1668  3
         if (type instanceof TypeVariable<?>) {
 1669  2
             return typeVariableToString((TypeVariable<?>) type);
 1670  
         }
 1671  1
         if (type instanceof GenericArrayType) {
 1672  1
             return genericArrayTypeToString((GenericArrayType) type);
 1673  
         }
 1674  0
         throw new IllegalArgumentException(ObjectUtils.identityToString(type));
 1675  
     }
 1676  
 
 1677  
     /**
 1678  
      * Format a {@link TypeVariable} including its {@link GenericDeclaration}.
 1679  
      *
 1680  
      * @param var the type variable to create a String representation for, not {@code null}
 1681  
      * @return String
 1682  
      * @since 3.2
 1683  
      */
 1684  
     public static String toLongString(final TypeVariable<?> var) {
 1685  12
         Validate.notNull(var, "var is null");
 1686  12
         final StringBuilder buf = new StringBuilder();
 1687  12
         final GenericDeclaration d = ((TypeVariable<?>) var).getGenericDeclaration();
 1688  12
         if (d instanceof Class<?>) {
 1689  12
             Class<?> c = (Class<?>) d;
 1690  
             while (true) {
 1691  12
                 if (c.getEnclosingClass() == null) {
 1692  12
                     buf.insert(0, c.getName());
 1693  12
                     break;
 1694  
                 }
 1695  0
                 buf.insert(0, c.getSimpleName()).insert(0, '.');
 1696  0
                 c = c.getEnclosingClass();
 1697  
             }
 1698  12
         } else if (d instanceof Type) {// not possible as of now
 1699  0
             buf.append(toString((Type) d));
 1700  
         } else {
 1701  0
             buf.append(d);
 1702  
         }
 1703  12
         return buf.append(':').append(typeVariableToString(var)).toString();
 1704  
     }
 1705  
 
 1706  
     /**
 1707  
      * Wrap the specified {@link Type} in a {@link Typed} wrapper.
 1708  
      *
 1709  
      * @param <T> inferred generic type
 1710  
      * @param type to wrap
 1711  
      * @return Typed&lt;T&gt;
 1712  
      * @since 3.2
 1713  
      */
 1714  
     public static <T> Typed<T> wrap(final Type type) {
 1715  2
         return new Typed<T>() {
 1716  
             @Override
 1717  
             public Type getType() {
 1718  2
                 return type;
 1719  
             }
 1720  
         };
 1721  
     }
 1722  
 
 1723  
     /**
 1724  
      * Wrap the specified {@link Class} in a {@link Typed} wrapper.
 1725  
      *
 1726  
      * @param <T> generic type
 1727  
      * @param type to wrap
 1728  
      * @return Typed&lt;T&gt;
 1729  
      * @since 3.2
 1730  
      */
 1731  
     public static <T> Typed<T> wrap(final Class<T> type) {
 1732  1
         return TypeUtils.<T> wrap((Type) type);
 1733  
     }
 1734  
 
 1735  
     /**
 1736  
      * Format a {@link Class} as a {@link String}.
 1737  
      * @param c {@code Class} to format
 1738  
      * @return String
 1739  
      * @since 3.2
 1740  
      */
 1741  
     private static String classToString(final Class<?> c) {
 1742  16
         final StringBuilder buf = new StringBuilder();
 1743  
 
 1744  16
         if (c.getEnclosingClass() != null) {
 1745  0
             buf.append(classToString(c.getEnclosingClass())).append('.').append(c.getSimpleName());
 1746  
         } else {
 1747  16
             buf.append(c.getName());
 1748  
         }
 1749  16
         if (c.getTypeParameters().length > 0) {
 1750  0
             buf.append('<');
 1751  0
             appendAllTo(buf, ", ", c.getTypeParameters());
 1752  0
             buf.append('>');
 1753  
         }
 1754  16
         return buf.toString();
 1755  
     }
 1756  
 
 1757  
     /**
 1758  
      * Format a {@link TypeVariable} as a {@link String}.
 1759  
      * @param v {@code TypeVariable} to format
 1760  
      * @return String
 1761  
      * @since 3.2
 1762  
      */
 1763  
     private static String typeVariableToString(final TypeVariable<?> v) {
 1764  14
         final StringBuilder buf = new StringBuilder(v.getName());
 1765  14
         final Type[] bounds = v.getBounds();
 1766  14
         if (bounds.length > 0 && !(bounds.length == 1 && Object.class.equals(bounds[0]))) {
 1767  0
             buf.append(" extends ");
 1768  0
             appendAllTo(buf, " & ", v.getBounds());
 1769  
         }
 1770  14
         return buf.toString();
 1771  
     }
 1772  
 
 1773  
     /**
 1774  
      * Format a {@link ParameterizedType} as a {@link String}.
 1775  
      * @param p {@code ParameterizedType} to format
 1776  
      * @return String
 1777  
      * @since 3.2
 1778  
      */
 1779  
     private static String parameterizedTypeToString(final ParameterizedType p) {
 1780  7
         final StringBuilder buf = new StringBuilder();
 1781  
 
 1782  7
         final Type useOwner = p.getOwnerType();
 1783  7
         final Class<?> raw = (Class<?>) p.getRawType();
 1784  7
         final Type[] typeArguments = p.getActualTypeArguments();
 1785  7
         if (useOwner == null) {
 1786  7
             buf.append(raw.getName());
 1787  
         } else {
 1788  0
             if (useOwner instanceof Class<?>) {
 1789  0
                 buf.append(((Class<?>) useOwner).getName());
 1790  
             } else {
 1791  0
                 buf.append(useOwner.toString());
 1792  
             }
 1793  0
             buf.append('.').append(raw.getSimpleName());
 1794  
         }
 1795  
 
 1796  7
         appendAllTo(buf.append('<'), ", ", typeArguments).append('>');
 1797  7
         return buf.toString();
 1798  
     }
 1799  
 
 1800  
     /**
 1801  
      * Format a {@link WildcardType} as a {@link String}.
 1802  
      * @param w {@code WildcardType} to format
 1803  
      * @return String
 1804  
      * @since 3.2
 1805  
      */
 1806  
     private static String wildcardTypeToString(final WildcardType w) {
 1807  9
         final StringBuilder buf = new StringBuilder().append('?');
 1808  9
         final Type[] lowerBounds = w.getLowerBounds();
 1809  9
         final Type[] upperBounds = w.getUpperBounds();
 1810  9
         if (lowerBounds.length > 1 || lowerBounds.length == 1 && lowerBounds[0] != null) {
 1811  4
             appendAllTo(buf.append(" super "), " & ", lowerBounds);
 1812  5
         } else if (upperBounds.length > 1 || upperBounds.length == 1 && !Object.class.equals(upperBounds[0])) {
 1813  3
             appendAllTo(buf.append(" extends "), " & ", upperBounds);
 1814  
         }
 1815  9
         return buf.toString();
 1816  
     }
 1817  
 
 1818  
     /**
 1819  
      * Format a {@link GenericArrayType} as a {@link String}.
 1820  
      * @param g {@code GenericArrayType} to format
 1821  
      * @return String
 1822  
      * @since 3.2
 1823  
      */
 1824  
     private static String genericArrayTypeToString(final GenericArrayType g) {
 1825  1
         return String.format("%s[]", toString(g.getGenericComponentType()));
 1826  
     }
 1827  
 
 1828  
     /**
 1829  
      * Append {@code types} to @{code buf} with separator {@code sep}.
 1830  
      * @param buf destination
 1831  
      * @param sep separator
 1832  
      * @param types to append
 1833  
      * @return {@code buf}
 1834  
      * @since 3.2
 1835  
      */
 1836  
     private static StringBuilder appendAllTo(final StringBuilder buf, final String sep, final Type... types) {
 1837  14
         Validate.notEmpty(Validate.noNullElements(types));
 1838  14
         if (types.length > 0) {
 1839  14
             buf.append(toString(types[0]));
 1840  14
             for (int i = 1; i < types.length; i++) {
 1841  0
                 buf.append(sep).append(toString(types[i]));
 1842  
             }
 1843  
         }
 1844  14
         return buf;
 1845  
     }
 1846  
 
 1847  
 }