示例#1
0
  /**
   * Tries to determine the type arguments of a class/interface based on a super parameterized
   * type's type arguments. This method is the inverse of {@link #getTypeArguments(Type, Class)}
   * which gets a class/interface's type arguments based on a subtype. It is far more limited in
   * determining the type arguments for the subject class's type variables in that it can only
   * determine those parameters that map from the subject {@link Class} object to the supertype.
   *
   * <p>Example: {@link java.util.TreeSet TreeSet} sets its parameter as the parameter for {@link
   * java.util.NavigableSet NavigableSet}, which in turn sets the parameter of {@link
   * java.util.SortedSet}, which in turn sets the parameter of {@link Set}, which in turn sets the
   * parameter of {@link java.util.Collection}, which in turn sets the parameter of {@link
   * java.lang.Iterable}. Since <code>TreeSet</code>'s parameter maps (indirectly) to <code>Iterable
   * </code>'s parameter, it will be able to determine that based on the super type <code>
   * Iterable<? extends
   * Map<Integer,? extends Collection<?>>></code>, the parameter of <code>TreeSet</code> is <code>
   * ? extends Map<Integer,? extends
   * Collection<?>></code>.
   *
   * @param cls the class whose type parameters are to be determined
   * @param superType the super type from which <code>cls</code>'s type arguments are to be
   *     determined
   * @return a map of the type assignments that could be determined for the type variables in each
   *     type in the inheritance hierarchy from <code>type</code> to <code>toClass</code> inclusive.
   */
  public static Map<TypeVariable<?>, Type> determineTypeArguments(
      Class<?> cls, ParameterizedType superType) {
    Class<?> superClass = getRawType(superType);

    // compatibility check
    if (!isAssignable(cls, superClass)) {
      return null;
    }

    if (cls.equals(superClass)) {
      return getTypeArguments(superType, superClass, null);
    }

    // get the next class in the inheritance hierarchy
    Type midType = getClosestParentType(cls, superClass);

    // can only be a class or a parameterized type
    if (midType instanceof Class<?>) {
      return determineTypeArguments((Class<?>) midType, superType);
    }

    ParameterizedType midParameterizedType = (ParameterizedType) midType;
    Class<?> midClass = getRawType(midParameterizedType);
    // get the type variables of the mid class that map to the type
    // arguments of the super class
    Map<TypeVariable<?>, Type> typeVarAssigns = determineTypeArguments(midClass, superType);
    // map the arguments of the mid type to the class type variables
    mapTypeVariablesToArguments(cls, midParameterizedType, typeVarAssigns);

    return typeVarAssigns;
  }
示例#2
0
 private static void mapTypeVariablesToArguments(
     Class paramClass, ParameterizedType paramParameterizedType, Map paramMap) {
   Type localType1 = paramParameterizedType.getOwnerType();
   if ((localType1 instanceof ParameterizedType))
     mapTypeVariablesToArguments(paramClass, (ParameterizedType) localType1, paramMap);
   Type[] arrayOfType = paramParameterizedType.getActualTypeArguments();
   TypeVariable[] arrayOfTypeVariable = getRawType(paramParameterizedType).getTypeParameters();
   List localList = Arrays.asList(paramClass.getTypeParameters());
   for (int i = 0; i < arrayOfType.length; i++) {
     TypeVariable localTypeVariable = arrayOfTypeVariable[i];
     Type localType2 = arrayOfType[i];
     if ((localList.contains(localType2)) && (paramMap.containsKey(localTypeVariable)))
       paramMap.put((TypeVariable) localType2, paramMap.get(localTypeVariable));
   }
 }
示例#3
0
 public static Map determineTypeArguments(
     Class paramClass, ParameterizedType paramParameterizedType) {
   Type localType;
   while (true) {
     Class localClass = getRawType(paramParameterizedType);
     if (!isAssignable(paramClass, localClass)) return null;
     if (paramClass.equals(localClass))
       return getTypeArguments(paramParameterizedType, localClass, null);
     localType = getClosestParentType(paramClass, localClass);
     if (!(localType instanceof Class)) break;
     paramClass = (Class) localType;
   }
   ParameterizedType localParameterizedType = (ParameterizedType) localType;
   Map localMap =
       determineTypeArguments(getRawType(localParameterizedType), paramParameterizedType);
   mapTypeVariablesToArguments(paramClass, localParameterizedType, localMap);
   return localMap;
 }
示例#4
0
  /**
   * @param cls
   * @param parameterizedType
   * @param typeVarAssigns
   */
  private static <T> void mapTypeVariablesToArguments(
      Class<T> cls,
      ParameterizedType parameterizedType,
      Map<TypeVariable<?>, Type> typeVarAssigns) {
    // capture the type variables from the owner type that have assignments
    Type ownerType = parameterizedType.getOwnerType();

    if (ownerType instanceof ParameterizedType) {
      // recursion to make sure the owner's owner type gets processed
      mapTypeVariablesToArguments(cls, (ParameterizedType) ownerType, typeVarAssigns);
    }

    // parameterizedType is a generic interface/class (or it's in the owner
    // hierarchy of said interface/class) implemented/extended by the class
    // cls. Find out which type variables of cls are type arguments of
    // parameterizedType:
    Type[] typeArgs = parameterizedType.getActualTypeArguments();

    // of the cls's type variables that are arguments of parameterizedType,
    // find out which ones can be determined from the super type's arguments
    TypeVariable<?>[] typeVars = getRawType(parameterizedType).getTypeParameters();

    // use List view of type parameters of cls so the contains() method can be used:
    List<TypeVariable<Class<T>>> typeVarList = Arrays.asList(cls.getTypeParameters());

    for (int i = 0; i < typeArgs.length; i++) {
      TypeVariable<?> typeVar = typeVars[i];
      Type typeArg = typeArgs[i];

      // argument of parameterizedType is a type variable of cls
      if (typeVarList.contains(typeArg)
          // type variable of parameterizedType has an assignment in
          // the super type.
          && typeVarAssigns.containsKey(typeVar)) {
        // map the assignment to the cls's type variable
        typeVarAssigns.put((TypeVariable<?>) typeArg, typeVarAssigns.get(typeVar));
      }
    }
  }