in bval-jsr/src/main/java/org/apache/bval/util/reflection/TypeUtils.java [419:478]
private static boolean isAssignable(final Type type, final ParameterizedType toParameterizedType,
final Map<TypeVariable<?>, Type> typeVarAssigns) {
if (type == null) {
return true;
}
// only a null type can be assigned to null type which
// would have cause the previous to return true
if (toParameterizedType == null) {
return false;
}
// all types are assignable to themselves
if (toParameterizedType.equals(type)) {
return true;
}
// get the target type's raw type
final Class<?> toClass = getRawType(toParameterizedType);
// get the subject type's type arguments including owner type arguments
// and supertype arguments up to and including the target class.
final Map<TypeVariable<?>, Type> fromTypeVarAssigns = getTypeArguments(type, toClass, null);
// null means the two types are not compatible
if (fromTypeVarAssigns == null) {
return false;
}
// compatible types, but there's no type arguments. this is equivalent
// to comparing Map< ?, ? > to Map, and raw types are always assignable
// to parameterized types.
if (fromTypeVarAssigns.isEmpty()) {
return true;
}
// get the target type's type arguments including owner type arguments
final Map<TypeVariable<?>, Type> toTypeVarAssigns = getTypeArguments(toParameterizedType,
toClass, typeVarAssigns);
// now to check each type argument
for (final TypeVariable<?> var : toTypeVarAssigns.keySet()) {
final Type toTypeArg = unrollVariableAssignments(var, toTypeVarAssigns);
final Type fromTypeArg = unrollVariableAssignments(var, fromTypeVarAssigns);
if (toTypeArg == null && fromTypeArg instanceof Class) {
continue;
}
// parameters must either be absent from the subject type, within
// the bounds of the wildcard type, or be an exact match to the
// parameters of the target type.
if (fromTypeArg != null
&& !toTypeArg.equals(fromTypeArg)
&& !(toTypeArg instanceof WildcardType && isAssignable(fromTypeArg, toTypeArg,
typeVarAssigns))) {
return false;
}
}
return true;
}