/**
  * Method that tries to create specialized type given base type, and a sub-class thereof (which is
  * assumed to use same parametrization as supertype). Similar to calling {@link
  * JavaType#narrowBy(Class)}, but can change underlying {@link JavaType} (from simple to Map, for
  * example), unliked <code>narrowBy</code> which assumes same logical type.
  */
 public static JavaType specialize(JavaType baseType, Class<?> subclass) {
   // Currently only SimpleType instances can become something else
   if (baseType instanceof SimpleType) {
     // and only if subclass is an array, Collection or Map
     if (subclass.isArray()
         || Map.class.isAssignableFrom(subclass)
         || Collection.class.isAssignableFrom(subclass)) {
       // need to assert type compatibility...
       if (!baseType.getRawClass().isAssignableFrom(subclass)) {
         throw new IllegalArgumentException(
             "Class " + subclass.getClass().getName() + " not subtype of " + baseType);
       }
       // this _should_ work, right?
       JavaType subtype = instance._fromClass(subclass, new TypeBindings(baseType.getRawClass()));
       // one more thing: handlers to copy?
       Object h = baseType.getValueHandler();
       if (h != null) {
         subtype.setValueHandler(h);
       }
       h = baseType.getTypeHandler();
       if (h != null) {
         subtype = subtype.withTypeHandler(h);
       }
       return subtype;
     }
   }
   // otherwise regular narrowing should work just fine
   return baseType.narrowBy(subclass);
 }
 /**
  * Factory method for constructing {@link JavaType} that represents a parameterized type. For
  * example, to represent type <code>Iterator&lt;String></code>, you could call
  *
  * <pre>
  *  TypeFactory.parametricType(Iterator.class, String.class)
  * </pre>
  *
  * @since 1.5
  */
 public static JavaType parametricType(Class<?> parametrized, Class<?>... parameterClasses) {
   int len = parameterClasses.length;
   JavaType[] pt = new JavaType[len];
   for (int i = 0; i < len; ++i) {
     pt[i] = instance._fromClass(parameterClasses[i], null);
   }
   return parametricType(parametrized, pt);
 }
 protected static JavaType _resolveVariableViaSubTypes(
     HierarchicType leafType, String variableName, TypeBindings bindings) {
   // can't resolve raw types; possible to have as-of-yet-unbound types too:
   if (leafType != null && leafType.isGeneric()) {
     TypeVariable<?>[] typeVariables = leafType.getRawClass().getTypeParameters();
     for (int i = 0, len = typeVariables.length; i < len; ++i) {
       TypeVariable<?> tv = typeVariables[i];
       if (variableName.equals(tv.getName())) {
         // further resolution needed?
         Type type = leafType.asGeneric().getActualTypeArguments()[i];
         if (type instanceof TypeVariable<?>) {
           return _resolveVariableViaSubTypes(
               leafType.getSubType(), ((TypeVariable<?>) type).getName(), bindings);
         }
         // no we're good for the variable (but it may have parameterization of its own)
         return instance._fromType(type, bindings);
       }
     }
   }
   return instance._unknownType();
 }
  /**
   * Method that is to figure out actual type parameters that given class binds to generic types
   * defined by given (generic) interface or class. This could mean, for example, trying to figure
   * out key and value types for Map implementations.
   *
   * @since 1.6
   */
  public static JavaType[] findParameterTypes(Class<?> clz, Class<?> expType) {
    // First: find full inheritance chain
    HierarchicType subType = _findSuperTypeChain(clz, expType);
    // Caller is supposed to ensure this never happens, so:
    if (subType == null) {
      throw new IllegalArgumentException(
          "Class " + clz.getName() + " is not a subtype of " + expType.getName());
    }
    // Ok and then go to the ultimate super-type:
    HierarchicType superType = subType;
    while (superType.getSuperType() != null) {
      superType = superType.getSuperType();
    }
    // which ought to be generic (if not, it's raw type)
    if (!superType.isGeneric()) {
      return null;
    }
    // Otherwise this becomes a recursive thing

    // otherwise need to start unwinding
    ParameterizedType pt = superType.asGeneric();
    Type[] actualTypes = pt.getActualTypeArguments();
    JavaType[] resultTypes = new JavaType[actualTypes.length];
    // TODO: rewrite TypeBindings to also work properly with renaming, aliasing
    TypeBindings bindings = new TypeBindings(clz);
    for (int i = 0, len = actualTypes.length; i < len; ++i) {
      Type t = actualTypes[i];
      // Only type variables need immediate resolution
      if (t instanceof TypeVariable<?>) {
        resultTypes[i] =
            _resolveVariableViaSubTypes(
                superType.getSubType(), ((TypeVariable<?>) t).getName(), bindings);
      } else {
        resultTypes[i] = instance._fromType(t, bindings);
      }
    }
    return resultTypes;
  }
 public static JavaType type(Type type, TypeBindings bindings) {
   return instance._fromType(type, bindings);
 }
 /**
  * Factory method for constructing {@link JavaType} from given "raw" type; which may be anything
  * from simple {@link Class} to full generic type.
  *
  * @since 1.3
  */
 public static JavaType type(Type t) {
   return instance._fromType(t, null);
 }