提交 387c8a81 编写于 作者: J Juergen Hoeller

Differentiate between TypeDescriptors with same annotations but different attributes

Issue: SPR-13714
上级 06056e6a
......@@ -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 {
boolean active();
}
private interface MyBaseInterface {
}
private static interface MyBaseInterface {}
private static interface MyInterface extends MyBaseInterface {}
private interface MyInterface extends MyBaseInterface {
}
private static class MyInterfaceImplementer implements MyInterface {
}
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;
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;
private static class MyConditionalColorConverter implements Converter<String, Color>, ConditionalConverter {
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));
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册