Differentiate between TypeDescriptors with same annotations but different attributes
Issue: SPR-13714
This commit is contained in:
parent
06056e6aa6
commit
387c8a8181
|
|
@ -468,7 +468,7 @@ public class TypeDescriptor implements Serializable {
|
|||
return false;
|
||||
}
|
||||
for (Annotation ann : getAnnotations()) {
|
||||
if (!other.hasAnnotation(ann.annotationType())) {
|
||||
if (!ann.equals(other.getAnnotation(ann.annotationType()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,27 +52,11 @@ import static org.junit.Assert.*;
|
|||
* @author Andy Clement
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
* @author Nathan Piper
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class TypeDescriptorTests {
|
||||
|
||||
public List<String> listOfString;
|
||||
|
||||
public List<List<String>> listOfListOfString = new ArrayList<List<String>>();
|
||||
|
||||
public List<List> listOfListOfUnknown = new ArrayList<List>();
|
||||
|
||||
public int[] intArray;
|
||||
|
||||
public List<String>[] arrayOfListOfString;
|
||||
|
||||
public List<Integer> listField = new ArrayList<Integer>();
|
||||
|
||||
public Map<String, Integer> mapField = new HashMap<String, Integer>();
|
||||
|
||||
public Map<String, List<Integer>> nestedMapField = new HashMap<String, List<Integer>>();
|
||||
|
||||
|
||||
@Test
|
||||
public void parameterPrimitive() throws Exception {
|
||||
TypeDescriptor desc = new TypeDescriptor(new MethodParameter(getClass().getMethod("testParameterPrimitive", int.class), 0));
|
||||
|
|
@ -86,10 +70,6 @@ public class TypeDescriptorTests {
|
|||
assertFalse(desc.isMap());
|
||||
}
|
||||
|
||||
public void testParameterPrimitive(int primitive) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterScalar() throws Exception {
|
||||
TypeDescriptor desc = new TypeDescriptor(new MethodParameter(getClass().getMethod("testParameterScalar", String.class), 0));
|
||||
|
|
@ -104,10 +84,6 @@ public class TypeDescriptorTests {
|
|||
assertFalse(desc.isMap());
|
||||
}
|
||||
|
||||
public void testParameterScalar(String value) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterList() throws Exception {
|
||||
MethodParameter methodParameter = new MethodParameter(getClass().getMethod("testParameterList", List.class), 0);
|
||||
|
|
@ -129,10 +105,6 @@ public class TypeDescriptorTests {
|
|||
assertFalse(desc.isMap());
|
||||
}
|
||||
|
||||
public void testParameterList(List<List<Map<Integer, Enum<?>>>> list) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterListNoParamTypes() throws Exception {
|
||||
MethodParameter methodParameter = new MethodParameter(getClass().getMethod("testParameterListNoParamTypes", List.class), 0);
|
||||
|
|
@ -149,10 +121,6 @@ public class TypeDescriptorTests {
|
|||
assertFalse(desc.isMap());
|
||||
}
|
||||
|
||||
public void testParameterListNoParamTypes(List list) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterArray() throws Exception {
|
||||
MethodParameter methodParameter = new MethodParameter(getClass().getMethod("testParameterArray", Integer[].class), 0);
|
||||
|
|
@ -170,10 +138,6 @@ public class TypeDescriptorTests {
|
|||
assertFalse(desc.isMap());
|
||||
}
|
||||
|
||||
public void testParameterArray(Integer[] array) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterMap() throws Exception {
|
||||
MethodParameter methodParameter = new MethodParameter(getClass().getMethod("testParameterMap", Map.class), 0);
|
||||
|
|
@ -194,10 +158,6 @@ public class TypeDescriptorTests {
|
|||
assertEquals(String.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
public void testParameterMap(Map<Integer, List<String>> map) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterAnnotated() throws Exception {
|
||||
TypeDescriptor t1 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0));
|
||||
|
|
@ -208,36 +168,20 @@ public class TypeDescriptorTests {
|
|||
assertEquals(123, t1.getAnnotation(ParameterAnnotation.class).value());
|
||||
}
|
||||
|
||||
@Target({ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ParameterAnnotation {
|
||||
int value();
|
||||
}
|
||||
|
||||
public void testAnnotatedMethod(@ParameterAnnotation(123) String parameter) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyComplex() throws Exception {
|
||||
Property property = new Property(getClass(), getClass().getMethod("getComplexProperty"), getClass().getMethod("setComplexProperty", Map.class));
|
||||
Property property = new Property(getClass(), getClass().getMethod("getComplexProperty"),
|
||||
getClass().getMethod("setComplexProperty", Map.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(String.class, desc.getMapKeyTypeDescriptor().getType());
|
||||
assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
public Map<String, List<List<Integer>>> getComplexProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setComplexProperty(Map<String, List<List<Integer>>> complexProperty) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyGenericType() throws Exception {
|
||||
GenericType<Integer> genericBean = new IntegerType();
|
||||
Property property = new Property(getClass(), genericBean.getClass().getMethod("getProperty"), genericBean.getClass().getMethod("setProperty", Integer.class));
|
||||
Property property = new Property(getClass(), genericBean.getClass().getMethod("getProperty"),
|
||||
genericBean.getClass().getMethod("setProperty", Integer.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(Integer.class, desc.getType());
|
||||
}
|
||||
|
|
@ -245,7 +189,8 @@ public class TypeDescriptorTests {
|
|||
@Test
|
||||
public void propertyTypeCovariance() throws Exception {
|
||||
GenericType<Number> genericBean = new NumberType();
|
||||
Property property = new Property(getClass(), genericBean.getClass().getMethod("getProperty"), genericBean.getClass().getMethod("setProperty", Number.class));
|
||||
Property property = new Property(getClass(), genericBean.getClass().getMethod("getProperty"),
|
||||
genericBean.getClass().getMethod("setProperty", Number.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(Integer.class, desc.getType());
|
||||
}
|
||||
|
|
@ -253,69 +198,18 @@ public class TypeDescriptorTests {
|
|||
@Test
|
||||
public void propertyGenericTypeList() throws Exception {
|
||||
GenericType<Integer> genericBean = new IntegerType();
|
||||
Property property = new Property(getClass(), genericBean.getClass().getMethod("getListProperty"), genericBean.getClass().getMethod("setListProperty", List.class));
|
||||
Property property = new Property(getClass(), genericBean.getClass().getMethod("getListProperty"),
|
||||
genericBean.getClass().getMethod("setListProperty", List.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(List.class, desc.getType());
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
public interface GenericType<T> {
|
||||
T getProperty();
|
||||
|
||||
void setProperty(T t);
|
||||
|
||||
List<T> getListProperty();
|
||||
|
||||
void setListProperty(List<T> t);
|
||||
|
||||
}
|
||||
|
||||
public class IntegerType implements GenericType<Integer> {
|
||||
|
||||
@Override
|
||||
public Integer getProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(Integer t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getListProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListProperty(List<Integer> t) {
|
||||
}
|
||||
}
|
||||
|
||||
public class NumberType implements GenericType<Number> {
|
||||
|
||||
@Override
|
||||
public Integer getProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(Number t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Number> getListProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListProperty(List<Number> t) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyGenericClassList() throws Exception {
|
||||
IntegerClass genericBean = new IntegerClass();
|
||||
Property property = new Property(genericBean.getClass(), genericBean.getClass().getMethod("getListProperty"), genericBean.getClass().getMethod("setListProperty", List.class));
|
||||
Property property = new Property(genericBean.getClass(), genericBean.getClass().getMethod("getListProperty"),
|
||||
genericBean.getClass().getMethod("setListProperty", List.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(List.class, desc.getType());
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
|
||||
|
|
@ -323,32 +217,10 @@ public class TypeDescriptorTests {
|
|||
assertTrue(desc.hasAnnotation(MethodAnnotation1.class));
|
||||
}
|
||||
|
||||
public static class GenericClass<T> {
|
||||
|
||||
public T getProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setProperty(T t) {
|
||||
}
|
||||
|
||||
@MethodAnnotation1
|
||||
public List<T> getListProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setListProperty(List<T> t) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class IntegerClass extends GenericClass<Integer> {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void property() throws Exception {
|
||||
Property property = new Property(getClass(), getClass().getMethod("getProperty"), getClass().getMethod("setProperty", Map.class));
|
||||
Property property = new Property(
|
||||
getClass(), getClass().getMethod("getProperty"), getClass().getMethod("setProperty", Map.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(Map.class, desc.getType());
|
||||
assertEquals(Integer.class, desc.getMapKeyTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
|
|
@ -358,60 +230,6 @@ public class TypeDescriptorTests {
|
|||
assertNotNull(desc.getAnnotation(MethodAnnotation3.class));
|
||||
}
|
||||
|
||||
@MethodAnnotation1
|
||||
public Map<List<Integer>, List<Long>> getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
@MethodAnnotation2
|
||||
public void setProperty(Map<List<Integer>, List<Long>> property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
@MethodAnnotation3
|
||||
private Map<List<Integer>, List<Long>> property;
|
||||
|
||||
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MethodAnnotation1 {
|
||||
}
|
||||
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MethodAnnotation2 {
|
||||
}
|
||||
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MethodAnnotation3 {
|
||||
}
|
||||
|
||||
@MethodAnnotation1
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ComposedMethodAnnotation1 {}
|
||||
|
||||
@ComposedMethodAnnotation1
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ComposedComposedMethodAnnotation1 {}
|
||||
|
||||
@MethodAnnotation1
|
||||
public void methodWithLocalAnnotation() {}
|
||||
|
||||
@ComposedMethodAnnotation1
|
||||
public void methodWithComposedAnnotation() {}
|
||||
|
||||
@ComposedComposedMethodAnnotation1
|
||||
public void methodWithComposedComposedAnnotation() {}
|
||||
|
||||
private void assertAnnotationFoundOnMethod(Class<? extends Annotation> annotationType, String methodName) throws Exception {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(new MethodParameter(getClass().getMethod(methodName), -1));
|
||||
assertNotNull("Should have found @" + annotationType.getSimpleName() + " on " + methodName + ".",
|
||||
typeDescriptor.getAnnotation(annotationType));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnotationOnMethodThatIsLocallyAnnotated() throws Exception {
|
||||
assertAnnotationFoundOnMethod(MethodAnnotation1.class, "methodWithLocalAnnotation");
|
||||
|
|
@ -427,6 +245,12 @@ public class TypeDescriptorTests {
|
|||
assertAnnotationFoundOnMethod(MethodAnnotation1.class, "methodWithComposedComposedAnnotation");
|
||||
}
|
||||
|
||||
private void assertAnnotationFoundOnMethod(Class<? extends Annotation> annotationType, String methodName) throws Exception {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(new MethodParameter(getClass().getMethod(methodName), -1));
|
||||
assertNotNull("Should have found @" + annotationType.getSimpleName() + " on " + methodName + ".",
|
||||
typeDescriptor.getAnnotation(annotationType));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldScalar() throws Exception {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(getClass().getField("fieldScalar"));
|
||||
|
|
@ -438,8 +262,6 @@ public class TypeDescriptorTests {
|
|||
assertEquals(Integer.class, typeDescriptor.getObjectType());
|
||||
}
|
||||
|
||||
public Integer fieldScalar;
|
||||
|
||||
@Test
|
||||
public void fieldList() throws Exception {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("listOfString"));
|
||||
|
|
@ -504,8 +326,6 @@ public class TypeDescriptorTests {
|
|||
assertEquals(Long.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
public Map<List<Integer>, List<Long>> fieldMap;
|
||||
|
||||
@Test
|
||||
public void fieldAnnotated() throws Exception {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(getClass().getField("fieldAnnotated"));
|
||||
|
|
@ -513,15 +333,6 @@ public class TypeDescriptorTests {
|
|||
assertNotNull(typeDescriptor.getAnnotation(FieldAnnotation.class));
|
||||
}
|
||||
|
||||
@FieldAnnotation
|
||||
public List<String> fieldAnnotated;
|
||||
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface FieldAnnotation {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueOfScalar() {
|
||||
TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(Integer.class);
|
||||
|
|
@ -592,7 +403,7 @@ public class TypeDescriptorTests {
|
|||
assertEquals(String.class, t1.getType());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void nestedMethodParameterNot1NestedLevel() throws Exception {
|
||||
TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test4", List.class), 0, 2), 2);
|
||||
}
|
||||
|
|
@ -609,31 +420,11 @@ public class TypeDescriptorTests {
|
|||
assertNull(t1);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void nestedMethodParameterTypeInvalidNestingLevel() throws Exception {
|
||||
TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test5", String.class), 0, 2), 2);
|
||||
}
|
||||
|
||||
public void test1(List<String> param1) {
|
||||
|
||||
}
|
||||
|
||||
public void test2(List<List<String>> param1) {
|
||||
|
||||
}
|
||||
|
||||
public void test3(Map<Integer, String> param1) {
|
||||
|
||||
}
|
||||
|
||||
public void test4(List<Map<Integer, String>> param1) {
|
||||
|
||||
}
|
||||
|
||||
public void test5(String param1) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedNotParameterized() throws Exception {
|
||||
TypeDescriptor t1 = TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test6", List.class), 0), 1);
|
||||
|
|
@ -643,18 +434,12 @@ public class TypeDescriptorTests {
|
|||
assertNull(t2);
|
||||
}
|
||||
|
||||
public void test6(List<List> param1) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedFieldTypeMapTwoLevels() throws Exception {
|
||||
TypeDescriptor t1 = TypeDescriptor.nested(getClass().getField("test4"), 2);
|
||||
assertEquals(String.class, t1.getType());
|
||||
}
|
||||
|
||||
public List<Map<Integer, String>> test4;
|
||||
|
||||
@Test
|
||||
public void nestedPropertyTypeMapTwoLevels() throws Exception {
|
||||
Property property = new Property(getClass(), getClass().getMethod("getTest4"), getClass().getMethod("setTest4", List.class));
|
||||
|
|
@ -662,14 +447,6 @@ public class TypeDescriptorTests {
|
|||
assertEquals(String.class, t1.getType());
|
||||
}
|
||||
|
||||
public List<Map<Integer, String>> getTest4() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setTest4(List<Map<Integer, String>> test4) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collection() {
|
||||
TypeDescriptor desc = TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class));
|
||||
|
|
@ -762,9 +539,6 @@ public class TypeDescriptorTests {
|
|||
assertNotNull(desc.getAnnotation(FieldAnnotation.class));
|
||||
}
|
||||
|
||||
@FieldAnnotation
|
||||
public List<List<Integer>> listPreserveContext;
|
||||
|
||||
@Test
|
||||
public void mapKeyType() {
|
||||
TypeDescriptor desc = TypeDescriptor.valueOf(Map.class);
|
||||
|
|
@ -783,9 +557,6 @@ public class TypeDescriptorTests {
|
|||
assertNotNull(desc.getAnnotation(FieldAnnotation.class));
|
||||
}
|
||||
|
||||
@FieldAnnotation
|
||||
public Map<List<Integer>, List<Integer>> mapPreserveContext;
|
||||
|
||||
@Test
|
||||
public void mapValueType() {
|
||||
TypeDescriptor desc = TypeDescriptor.valueOf(Map.class);
|
||||
|
|
@ -805,7 +576,7 @@ public class TypeDescriptorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void equals() throws Exception {
|
||||
public void equality() throws Exception {
|
||||
TypeDescriptor t1 = TypeDescriptor.valueOf(String.class);
|
||||
TypeDescriptor t2 = TypeDescriptor.valueOf(String.class);
|
||||
TypeDescriptor t3 = TypeDescriptor.valueOf(Date.class);
|
||||
|
|
@ -826,6 +597,18 @@ public class TypeDescriptorTests {
|
|||
TypeDescriptor t11 = new TypeDescriptor(getClass().getField("mapField"));
|
||||
TypeDescriptor t12 = new TypeDescriptor(getClass().getField("mapField"));
|
||||
assertEquals(t11, t12);
|
||||
|
||||
TypeDescriptor t13 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0));
|
||||
TypeDescriptor t14 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0));
|
||||
assertEquals(t13, t14);
|
||||
|
||||
TypeDescriptor t15 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0));
|
||||
TypeDescriptor t16 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethodDifferentAnnotationValue", String.class), 0));
|
||||
assertNotEquals(t15, t16);
|
||||
|
||||
TypeDescriptor t17 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0));
|
||||
TypeDescriptor t18 = new TypeDescriptor(new MethodParameter(getClass().getMethod("test5", String.class), 0));
|
||||
assertNotEquals(t17, t18);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -844,10 +627,6 @@ public class TypeDescriptorTests {
|
|||
assertTrue(TypeDescriptor.valueOf(List.class).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
|
||||
}
|
||||
|
||||
public List notGenericList;
|
||||
|
||||
public List<Number> isAssignableElementTypes;
|
||||
|
||||
@Test
|
||||
public void isAssignableMapKeyValueTypes() throws Exception {
|
||||
assertTrue(new TypeDescriptor(getClass().getField("mapField")).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
|
||||
|
|
@ -857,10 +636,6 @@ public class TypeDescriptorTests {
|
|||
assertTrue(TypeDescriptor.valueOf(Map.class).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
|
||||
}
|
||||
|
||||
public Map notGenericMap;
|
||||
|
||||
public Map<CharSequence, Number> isAssignableMapKeyValueTypes;
|
||||
|
||||
@Test
|
||||
public void multiValueMap() throws Exception {
|
||||
TypeDescriptor td = new TypeDescriptor(getClass().getField("multiValueMap"));
|
||||
|
|
@ -871,8 +646,6 @@ public class TypeDescriptorTests {
|
|||
td.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
public MultiValueMap<String, Integer> multiValueMap = new LinkedMultiValueMap<String, Integer>();
|
||||
|
||||
@Test
|
||||
public void passDownGeneric() throws Exception {
|
||||
TypeDescriptor td = new TypeDescriptor(getClass().getField("passDownGeneric"));
|
||||
|
|
@ -881,12 +654,6 @@ public class TypeDescriptorTests {
|
|||
assertEquals(Integer.class, td.getElementTypeDescriptor().getElementTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
public PassDownGeneric<Integer> passDownGeneric = new PassDownGeneric<Integer>();
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class PassDownGeneric<T> extends ArrayList<List<Set<T>>> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpCast() throws Exception {
|
||||
Property property = new Property(getClass(), getClass().getMethod("getProperty"),
|
||||
|
|
@ -904,8 +671,9 @@ public class TypeDescriptorTests {
|
|||
try {
|
||||
typeDescriptor.upcast(Collection.class);
|
||||
fail("Did not throw");
|
||||
} catch(IllegalArgumentException e) {
|
||||
assertEquals("interface java.util.Map is not assignable to interface java.util.Collection", e.getMessage());
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertEquals("interface java.util.Map is not assignable to interface java.util.Collection", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -933,13 +701,13 @@ public class TypeDescriptorTests {
|
|||
|
||||
@Test
|
||||
public void createMapArray() throws Exception {
|
||||
TypeDescriptor mapType = TypeDescriptor.map(LinkedHashMap.class, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class));
|
||||
TypeDescriptor mapType = TypeDescriptor.map(
|
||||
LinkedHashMap.class, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class));
|
||||
TypeDescriptor arrayType = TypeDescriptor.array(mapType);
|
||||
assertEquals(arrayType.getType(), LinkedHashMap[].class);
|
||||
assertEquals(arrayType.getElementTypeDescriptor(), mapType);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void createStringArray() throws Exception {
|
||||
TypeDescriptor arrayType = TypeDescriptor.array(TypeDescriptor.valueOf(String.class));
|
||||
|
|
@ -985,4 +753,268 @@ public class TypeDescriptorTests {
|
|||
assertThat(TypeDescriptor.valueOf(Integer.class).getSource(), equalTo((Object) Integer.class));
|
||||
}
|
||||
|
||||
|
||||
// Methods designed for test introspection
|
||||
|
||||
public void testParameterPrimitive(int primitive) {
|
||||
}
|
||||
|
||||
public void testParameterScalar(String value) {
|
||||
}
|
||||
|
||||
public void testParameterList(List<List<Map<Integer, Enum<?>>>> list) {
|
||||
}
|
||||
|
||||
public void testParameterListNoParamTypes(List list) {
|
||||
}
|
||||
|
||||
public void testParameterArray(Integer[] array) {
|
||||
}
|
||||
|
||||
public void testParameterMap(Map<Integer, List<String>> map) {
|
||||
}
|
||||
|
||||
public void test1(List<String> param1) {
|
||||
}
|
||||
|
||||
public void test2(List<List<String>> param1) {
|
||||
}
|
||||
|
||||
public void test3(Map<Integer, String> param1) {
|
||||
}
|
||||
|
||||
public void test4(List<Map<Integer, String>> param1) {
|
||||
}
|
||||
|
||||
public void test5(String param1) {
|
||||
}
|
||||
|
||||
public void test6(List<List> param1) {
|
||||
}
|
||||
|
||||
public List<Map<Integer, String>> getTest4() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setTest4(List<Map<Integer, String>> test4) {
|
||||
}
|
||||
|
||||
public Map<String, List<List<Integer>>> getComplexProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@MethodAnnotation1
|
||||
public Map<List<Integer>, List<Long>> getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
@MethodAnnotation2
|
||||
public void setProperty(Map<List<Integer>, List<Long>> property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
@MethodAnnotation1
|
||||
public void methodWithLocalAnnotation() {
|
||||
}
|
||||
|
||||
@ComposedMethodAnnotation1
|
||||
public void methodWithComposedAnnotation() {
|
||||
}
|
||||
|
||||
@ComposedComposedMethodAnnotation1
|
||||
public void methodWithComposedComposedAnnotation() {
|
||||
}
|
||||
|
||||
public void setComplexProperty(Map<String, List<List<Integer>>> complexProperty) {
|
||||
}
|
||||
|
||||
public void testAnnotatedMethod(@ParameterAnnotation(123) String parameter) {
|
||||
}
|
||||
|
||||
public void testAnnotatedMethodDifferentAnnotationValue(@ParameterAnnotation(567) String parameter) {
|
||||
}
|
||||
|
||||
|
||||
// Fields designed for test introspection
|
||||
|
||||
public Integer fieldScalar;
|
||||
|
||||
public List<String> listOfString;
|
||||
|
||||
public List<List<String>> listOfListOfString = new ArrayList<List<String>>();
|
||||
|
||||
public List<List> listOfListOfUnknown = new ArrayList<List>();
|
||||
|
||||
public int[] intArray;
|
||||
|
||||
public List<String>[] arrayOfListOfString;
|
||||
|
||||
public List<Integer> listField = new ArrayList<Integer>();
|
||||
|
||||
public Map<String, Integer> mapField = new HashMap<String, Integer>();
|
||||
|
||||
public Map<String, List<Integer>> nestedMapField = new HashMap<String, List<Integer>>();
|
||||
|
||||
public Map<List<Integer>, List<Long>> fieldMap;
|
||||
|
||||
public List<Map<Integer, String>> test4;
|
||||
|
||||
@FieldAnnotation
|
||||
public List<String> fieldAnnotated;
|
||||
|
||||
@FieldAnnotation
|
||||
public List<List<Integer>> listPreserveContext;
|
||||
|
||||
@FieldAnnotation
|
||||
public Map<List<Integer>, List<Integer>> mapPreserveContext;
|
||||
|
||||
@MethodAnnotation3
|
||||
private Map<List<Integer>, List<Long>> property;
|
||||
|
||||
public List notGenericList;
|
||||
|
||||
public List<Number> isAssignableElementTypes;
|
||||
|
||||
public Map notGenericMap;
|
||||
|
||||
public Map<CharSequence, Number> isAssignableMapKeyValueTypes;
|
||||
|
||||
public MultiValueMap<String, Integer> multiValueMap = new LinkedMultiValueMap<String, Integer>();
|
||||
|
||||
public PassDownGeneric<Integer> passDownGeneric = new PassDownGeneric<Integer>();
|
||||
|
||||
|
||||
// Classes designed for test introspection
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class PassDownGeneric<T> extends ArrayList<List<Set<T>>> {
|
||||
}
|
||||
|
||||
|
||||
public static class GenericClass<T> {
|
||||
|
||||
public T getProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setProperty(T t) {
|
||||
}
|
||||
|
||||
@MethodAnnotation1
|
||||
public List<T> getListProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setListProperty(List<T> t) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class IntegerClass extends GenericClass<Integer> {
|
||||
}
|
||||
|
||||
|
||||
public interface GenericType<T> {
|
||||
|
||||
T getProperty();
|
||||
|
||||
void setProperty(T t);
|
||||
|
||||
List<T> getListProperty();
|
||||
|
||||
void setListProperty(List<T> t);
|
||||
}
|
||||
|
||||
|
||||
public class IntegerType implements GenericType<Integer> {
|
||||
|
||||
@Override
|
||||
public Integer getProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(Integer t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getListProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListProperty(List<Integer> t) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class NumberType implements GenericType<Number> {
|
||||
|
||||
@Override
|
||||
public Integer getProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(Number t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Number> getListProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListProperty(List<Number> t) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Annotations used on tested elements
|
||||
|
||||
@Target({ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ParameterAnnotation {
|
||||
|
||||
int value();
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface FieldAnnotation {
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MethodAnnotation1 {
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MethodAnnotation2 {
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MethodAnnotation3 {
|
||||
}
|
||||
|
||||
|
||||
@MethodAnnotation1
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ComposedMethodAnnotation1 {
|
||||
}
|
||||
|
||||
|
||||
@ComposedMethodAnnotation1
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ComposedComposedMethodAnnotation1 {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -478,6 +478,21 @@ public class GenericConversionServiceTests {
|
|||
assertTrue(converter.getNestedMatchAttempts() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void conditionalConverterCachingForDifferentAnnotationAttributes() throws Exception {
|
||||
conversionService.addConverter(new ColorConverter());
|
||||
conversionService.addConverter(new MyConditionalColorConverter());
|
||||
|
||||
assertEquals(Color.BLACK, conversionService.convert("000000xxxx",
|
||||
new TypeDescriptor(getClass().getField("activeColor"))));
|
||||
assertEquals(Color.BLACK, conversionService.convert(" #000000 ",
|
||||
new TypeDescriptor(getClass().getField("inactiveColor"))));
|
||||
assertEquals(Color.BLACK, conversionService.convert("000000yyyy",
|
||||
new TypeDescriptor(getClass().getField("activeColor"))));
|
||||
assertEquals(Color.BLACK, conversionService.convert(" #000000 ",
|
||||
new TypeDescriptor(getClass().getField("inactiveColor"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotSupportNullConvertibleTypesFromNonConditionalGenericConverter() {
|
||||
GenericConverter converter = new NonConditionalGenericConverter();
|
||||
|
|
@ -629,14 +644,49 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
|
||||
|
||||
@ExampleAnnotation(active = true)
|
||||
public String annotatedString;
|
||||
|
||||
@ExampleAnnotation(active = true)
|
||||
public Color activeColor;
|
||||
|
||||
@ExampleAnnotation(active = false)
|
||||
public Color inactiveColor;
|
||||
|
||||
public List<Integer> list;
|
||||
|
||||
public Map<String, Integer> map;
|
||||
|
||||
public Map<String, ?> wildcardMap;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Collection rawCollection;
|
||||
|
||||
public Collection<?> genericCollection;
|
||||
|
||||
public Collection<String> stringCollection;
|
||||
|
||||
public Collection<Integer> integerCollection;
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private static @interface ExampleAnnotation {}
|
||||
private @interface ExampleAnnotation {
|
||||
|
||||
private static interface MyBaseInterface {}
|
||||
boolean active();
|
||||
}
|
||||
|
||||
private static interface MyInterface extends MyBaseInterface {}
|
||||
|
||||
private static class MyInterfaceImplementer implements MyInterface {}
|
||||
private interface MyBaseInterface {
|
||||
}
|
||||
|
||||
|
||||
private interface MyInterface extends MyBaseInterface {
|
||||
}
|
||||
|
||||
|
||||
private static class MyInterfaceImplementer implements MyInterface {
|
||||
}
|
||||
|
||||
|
||||
private static class MyBaseInterfaceToStringConverter implements Converter<MyBaseInterface, String> {
|
||||
|
||||
|
|
@ -646,6 +696,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringArrayToResourceArrayConverter implements Converter<String[], Resource[]> {
|
||||
|
||||
@Override
|
||||
|
|
@ -654,6 +705,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringArrayToIntegerArrayConverter implements Converter<String[], Integer[]> {
|
||||
|
||||
@Override
|
||||
|
|
@ -662,6 +714,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringToIntegerArrayConverter implements Converter<String, Integer[]> {
|
||||
|
||||
@Override
|
||||
|
|
@ -671,6 +724,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class WithCopyConstructor {
|
||||
|
||||
WithCopyConstructor() {}
|
||||
|
|
@ -679,6 +733,7 @@ public class GenericConversionServiceTests {
|
|||
WithCopyConstructor(WithCopyConstructor value) {}
|
||||
}
|
||||
|
||||
|
||||
private static class MyConditionalConverter implements Converter<String, Color>, ConditionalConverter {
|
||||
|
||||
private int matchAttempts = 0;
|
||||
|
|
@ -699,6 +754,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class NonConditionalGenericConverter implements GenericConverter {
|
||||
|
||||
@Override
|
||||
|
|
@ -712,6 +768,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyConditionalGenericConverter implements GenericConverter, ConditionalConverter {
|
||||
|
||||
private final List<TypeDescriptor> sourceTypes = new ArrayList<TypeDescriptor>();
|
||||
|
|
@ -737,6 +794,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyConditionalConverterFactory implements ConverterFactory<String, Color>, ConditionalConverter {
|
||||
|
||||
private MyConditionalConverter converter = new MyConditionalConverter();
|
||||
|
|
@ -768,11 +826,13 @@ public class GenericConversionServiceTests {
|
|||
String getBaseCode();
|
||||
}
|
||||
|
||||
private static interface MyEnumInterface extends MyEnumBaseInterface {
|
||||
|
||||
private interface MyEnumInterface extends MyEnumBaseInterface {
|
||||
String getCode();
|
||||
}
|
||||
|
||||
private static enum MyEnum implements MyEnumInterface {
|
||||
|
||||
private enum MyEnum implements MyEnumInterface {
|
||||
|
||||
A("1"),
|
||||
B("2"),
|
||||
|
|
@ -795,7 +855,8 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
private static enum EnumWithSubclass {
|
||||
|
||||
private enum EnumWithSubclass {
|
||||
|
||||
FIRST {
|
||||
@Override
|
||||
|
|
@ -805,6 +866,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class MyStringToRawCollectionConverter implements Converter<String, Collection> {
|
||||
|
||||
|
|
@ -814,6 +876,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringToGenericCollectionConverter implements Converter<String, Collection<?>> {
|
||||
|
||||
@Override
|
||||
|
|
@ -822,6 +885,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyEnumInterfaceToStringConverter<T extends MyEnumInterface> implements Converter<T, String> {
|
||||
|
||||
@Override
|
||||
|
|
@ -830,14 +894,16 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class StringToMyEnumInterfaceConverterFactory implements ConverterFactory<String, MyEnumInterface> {
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <T extends MyEnumInterface> Converter<String, T> getConverter(Class<T> targetType) {
|
||||
return new StringToMyEnumInterfaceConverter(targetType);
|
||||
}
|
||||
|
||||
private static class StringToMyEnumInterfaceConverter<T extends Enum<?> & MyEnumInterface> implements Converter<String, T> {
|
||||
|
||||
private final Class<T> enumType;
|
||||
|
||||
public StringToMyEnumInterfaceConverter(Class<T> enumType) {
|
||||
|
|
@ -855,9 +921,10 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class StringToMyEnumBaseInterfaceConverterFactory implements ConverterFactory<String, MyEnumBaseInterface> {
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <T extends MyEnumBaseInterface> Converter<String, T> getConverter(Class<T> targetType) {
|
||||
return new StringToMyEnumBaseInterfaceConverter(targetType);
|
||||
}
|
||||
|
|
@ -881,6 +948,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringToStringCollectionConverter implements Converter<String, Collection<String>> {
|
||||
|
||||
@Override
|
||||
|
|
@ -889,6 +957,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringToIntegerCollectionConverter implements Converter<String, Collection<Integer>> {
|
||||
|
||||
@Override
|
||||
|
|
@ -897,6 +966,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class UntypedConverter implements Converter {
|
||||
|
||||
|
|
@ -906,28 +976,27 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class ColorConverter implements Converter<String, Color> {
|
||||
|
||||
@Override
|
||||
public Color convert(String source) { if (!source.startsWith("#")) source = "#" + source; return Color.decode(source); }
|
||||
public Color convert(String source) {
|
||||
return Color.decode(source.trim());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ExampleAnnotation
|
||||
public String annotatedString;
|
||||
private static class MyConditionalColorConverter implements Converter<String, Color>, ConditionalConverter {
|
||||
|
||||
public List<Integer> list;
|
||||
|
||||
public Map<String, Integer> map;
|
||||
|
||||
public Map<String, ?> wildcardMap;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Collection rawCollection;
|
||||
|
||||
public Collection<?> genericCollection;
|
||||
|
||||
public Collection<String> stringCollection;
|
||||
|
||||
public Collection<Integer> integerCollection;
|
||||
@Override
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
ExampleAnnotation ann = targetType.getAnnotation(ExampleAnnotation.class);
|
||||
return (ann != null && ann.active());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color convert(String source) {
|
||||
return Color.decode(source.substring(0, 6));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue