private void registerTypeVariableIfNotPresent(TypeVariable<?> typeVariable) { if (!contextualActualTypeParameters.containsKey(typeVariable)) { contextualActualTypeParameters.put(typeVariable, boundsOf(typeVariable)); // logger.log("For '" + typeVariable.getGenericDeclaration() + "' found type variable : { '" + typeVariable + "(" + System.identityHashCode(typeVariable) + ")" + "' : '" + boundsOf(typeVariable) + "' }"); } }
/** * @param typeParameter The TypeVariable parameter * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable * then retrieve BoundedType of this TypeVariable */ private BoundedType boundsOf(TypeVariable<?> typeParameter) { if (typeParameter.getBounds()[0] instanceof TypeVariable) { return boundsOf((TypeVariable<?>) typeParameter.getBounds()[0]); } return new TypeVarBoundedType(typeParameter); }
protected void registerTypeVariablesOn(Type classType) { if (!(classType instanceof ParameterizedType)) { return; } ParameterizedType parameterizedType = (ParameterizedType) classType; TypeVariable<?>[] typeParameters = ((Class<?>) parameterizedType.getRawType()).getTypeParameters(); Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for (int i = 0; i < actualTypeArguments.length; i++) { TypeVariable<?> typeParameter = typeParameters[i]; Type actualTypeArgument = actualTypeArguments[i]; // Prevent registration of a cycle of TypeVariables. This can happen when we are processing // type parameters in a Method, while we already processed the type parameters of a class. if (actualTypeArgument instanceof TypeVariable && contextualActualTypeParameters.containsKey(typeParameter)) { continue; } if (actualTypeArgument instanceof WildcardType) { contextualActualTypeParameters.put(typeParameter, boundsOf((WildcardType) actualTypeArgument)); } else if (typeParameter != actualTypeArgument) { contextualActualTypeParameters.put(typeParameter, actualTypeArgument); } // logger.log("For '" + parameterizedType + "' found type variable : { '" + typeParameter + "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + actualTypeArgument + "(" + System.identityHashCode(typeParameter) + ")" + "' }"); } }
/** * @param wildCard The WildCard type * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable * then retrieve BoundedType of this TypeVariable */ private BoundedType boundsOf(WildcardType wildCard) { /* * According to JLS(http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1): * - Lower and upper can't coexist: (for instance, this is not allowed: <? extends List<String> & super MyInterface>) * - Multiple bounds are not supported (for instance, this is not allowed: <? extends List<String> & MyInterface>) */ WildCardBoundedType wildCardBoundedType = new WildCardBoundedType(wildCard); if (wildCardBoundedType.firstBound() instanceof TypeVariable) { return boundsOf((TypeVariable<?>) wildCardBoundedType.firstBound()); } return wildCardBoundedType; }