@Nullable
  public static Type resolveVariable(
      TypeVariable variable, final Class classType, boolean resolveInInterfacesOnly) {
    final Class aClass = getRawType(classType);
    int index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(aClass), variable);
    if (index >= 0) {
      return variable;
    }

    final Class[] classes = ReflectionCache.getInterfaces(aClass);
    final Type[] genericInterfaces = ReflectionCache.getGenericInterfaces(aClass);
    for (int i = 0; i <= classes.length; i++) {
      Class anInterface;
      if (i < classes.length) {
        anInterface = classes[i];
      } else {
        anInterface = ReflectionCache.getSuperClass(aClass);
        if (resolveInInterfacesOnly || anInterface == null) {
          continue;
        }
      }
      final Type resolved = resolveVariable(variable, anInterface);
      if (resolved instanceof Class || resolved instanceof ParameterizedType) {
        return resolved;
      }
      if (resolved instanceof TypeVariable) {
        final TypeVariable typeVariable = (TypeVariable) resolved;
        index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(anInterface), typeVariable);
        if (index < 0) {
          LOG.error(
              "Cannot resolve type variable:\n"
                  + "typeVariable = "
                  + typeVariable
                  + "\n"
                  + "genericDeclaration = "
                  + declarationToString(typeVariable.getGenericDeclaration())
                  + "\n"
                  + "searching in "
                  + declarationToString(anInterface));
        }
        final Type type =
            i < genericInterfaces.length ? genericInterfaces[i] : aClass.getGenericSuperclass();
        if (type instanceof Class) {
          return Object.class;
        }
        if (type instanceof ParameterizedType) {
          return getActualTypeArguments((ParameterizedType) type)[index];
        }
        throw new AssertionError("Invalid type: " + type);
      }
    }
    return null;
  }
 public static Type resolveVariableInHierarchy(final TypeVariable variable, final Class aClass) {
   Type type;
   Class current = aClass;
   while ((type = resolveVariable(variable, current, false)) == null) {
     current = ReflectionCache.getSuperClass(current);
     if (current == null) {
       return null;
     }
   }
   if (type instanceof TypeVariable) {
     return resolveVariableInHierarchy((TypeVariable) type, aClass);
   }
   return type;
 }