protected static HierarchicType _findSuperInterfaceChain(Type currentType, Class<?> target) {
   HierarchicType current = new HierarchicType(currentType);
   Class<?> raw = current.getRawClass();
   if (raw == target) {
     return current;
   }
   // Otherwise, keep on going down the rat hole; first implemented interaces
   Type[] parents = raw.getGenericInterfaces();
   // as long as there are superclasses
   // and unless we have already seen the type (<T extends X<T>>)
   if (parents != null) {
     for (Type parent : parents) {
       HierarchicType sup = _findSuperInterfaceChain(parent, target);
       if (sup != null) {
         sup.setSubType(current);
         current.setSuperType(sup);
         return current;
       }
     }
   }
   // and then super-class if any
   Type parent = raw.getGenericSuperclass();
   if (parent != null) {
     HierarchicType sup = _findSuperInterfaceChain(parent, target);
     if (sup != null) {
       sup.setSubType(current);
       current.setSuperType(sup);
       return current;
     }
   }
   return null;
 }
 protected static HierarchicType _findSuperClassChain(Type currentType, Class<?> target) {
   HierarchicType current = new HierarchicType(currentType);
   Class<?> raw = current.getRawClass();
   if (raw == target) {
     return current;
   }
   // Otherwise, keep on going down the rat hole...
   Type parent = raw.getGenericSuperclass();
   if (parent != null) {
     HierarchicType sup = _findSuperClassChain(parent, target);
     if (sup != null) {
       sup.setSubType(current);
       current.setSuperType(sup);
       return current;
     }
   }
   return null;
 }
 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;
  }