added back element type checks in TypeDescriptor#isAssignable; clarified semantics in javadoc

This commit is contained in:
Keith Donald 2011-06-07 15:33:44 +00:00
parent 7dcd71c543
commit a60cb43c6a
2 changed files with 30 additions and 6 deletions

View File

@ -279,13 +279,30 @@ public class TypeDescriptor {
}
/**
* Returns true if an object of this type can be assigned to a reference of the given type.
* @param typeDescriptor the descriptor for the target type
* Returns true if an object of this type descriptor can be assigned to the location described by the given type descriptor.
* For example, valueOf(String.class).isAssignableTo(valueOf(CharSequence.class)) returns true because a String value can be assigned to a CharSequence variable.
* On the other hand, valueOf(Number.class).isAssignableTo(valueOf(Integer.class)) returns false because, while all Integers are Numbers, not all Numbers are Integers.
* <p>
* For arrays, collections, and maps, element and key/value types are checked if declared.
* For example, a List&lt;String&gt; field value is assignable to a Collection&lt;CharSequence&gt; field, but List&lt;Number&gt; is not assignable to List&lt;Integer&gt;.
* @return true if this type is assignable to the type represented by the provided type descriptor.
* @see #getObjectType()
*/
public boolean isAssignableTo(TypeDescriptor typeDescriptor) {
return typeDescriptor.getObjectType().isAssignableFrom(getObjectType());
boolean typesAssignable = typeDescriptor.getObjectType().isAssignableFrom(getObjectType());
if (!typesAssignable) {
return false;
}
if (isArray()) {
return getElementTypeDescriptor().isAssignableTo(typeDescriptor.getElementTypeDescriptor());
} else if (isCollection()) {
return isNestedAssignable(getElementTypeDescriptor(), typeDescriptor.getElementTypeDescriptor());
} else if (isMap()) {
return isNestedAssignable(getMapKeyTypeDescriptor(), typeDescriptor.getMapKeyTypeDescriptor()) &&
isNestedAssignable(getMapValueTypeDescriptor(), typeDescriptor.getMapValueTypeDescriptor());
} else {
return true;
}
}
// indexable type descriptor operations
@ -534,7 +551,14 @@ public class TypeDescriptor {
return value != null ? new TypeDescriptor(value.getClass(), null, null, null, annotations) : null;
}
}
private boolean isNestedAssignable(TypeDescriptor nestedTypeDescriptor, TypeDescriptor otherNestedTypeDescriptor) {
if (nestedTypeDescriptor == null || otherNestedTypeDescriptor == null) {
return true;
}
return nestedTypeDescriptor.isAssignableTo(otherNestedTypeDescriptor);
}
private String wildcard(TypeDescriptor typeDescriptor) {
return typeDescriptor != null ? typeDescriptor.toString() : "?";
}

View File

@ -759,7 +759,7 @@ public class TypeDescriptorTests {
@Test
public void isAssignableElementTypes() throws Exception {
assertTrue(new TypeDescriptor(getClass().getField("listField")).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
assertTrue(new TypeDescriptor(getClass().getField("isAssignableElementTypes")).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
assertFalse(new TypeDescriptor(getClass().getField("isAssignableElementTypes")).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
assertTrue(TypeDescriptor.valueOf(List.class).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
}
@ -768,7 +768,7 @@ public class TypeDescriptorTests {
@Test
public void isAssignableMapKeyValueTypes() throws Exception {
assertTrue(new TypeDescriptor(getClass().getField("mapField")).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
assertTrue(new TypeDescriptor(getClass().getField("isAssignableMapKeyValueTypes")).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
assertFalse(new TypeDescriptor(getClass().getField("isAssignableMapKeyValueTypes")).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
assertTrue(TypeDescriptor.valueOf(Map.class).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
}