From 3db5a299bb2f490fa23e2409150c5df07ad4f696 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 11 Feb 2010 12:23:57 +0000 Subject: [PATCH] canConvert checks Collection/Map element types as well (SPR-6564) --- .../beans/ResourceTestBean.java | 49 +++++++++++++++++++ .../ConversionServiceFactoryBeanTests.java | 48 +++++++++++++++--- .../context/support/conversionService.xml | 31 ++++++++++++ .../core/convert/TypeDescriptor.java | 35 ++++++++++++- 4 files changed, 155 insertions(+), 8 deletions(-) create mode 100644 org.springframework.context/src/test/java/org/springframework/context/support/conversionService.xml diff --git a/org.springframework.context/src/test/java/org/springframework/beans/ResourceTestBean.java b/org.springframework.context/src/test/java/org/springframework/beans/ResourceTestBean.java index d9d8cd166a..bfe6daffe2 100644 --- a/org.springframework.context/src/test/java/org/springframework/beans/ResourceTestBean.java +++ b/org.springframework.context/src/test/java/org/springframework/beans/ResourceTestBean.java @@ -1,6 +1,23 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.beans; import java.io.InputStream; +import java.util.Map; import org.springframework.core.io.Resource; @@ -14,6 +31,13 @@ public class ResourceTestBean { private InputStream inputStream; + private Resource[] resourceArray; + + private Map resourceMap; + + private Map resourceArrayMap; + + public ResourceTestBean() { } @@ -22,6 +46,7 @@ public class ResourceTestBean { this.inputStream = inputStream; } + public void setResource(Resource resource) { this.resource = resource; } @@ -38,4 +63,28 @@ public class ResourceTestBean { return inputStream; } + public Resource[] getResourceArray() { + return resourceArray; + } + + public void setResourceArray(Resource[] resourceArray) { + this.resourceArray = resourceArray; + } + + public Map getResourceMap() { + return resourceMap; + } + + public void setResourceMap(Map resourceMap) { + this.resourceMap = resourceMap; + } + + public Map getResourceArrayMap() { + return resourceArrayMap; + } + + public void setResourceArrayMap(Map resourceArrayMap) { + this.resourceArrayMap = resourceArrayMap; + } + } diff --git a/org.springframework.context/src/test/java/org/springframework/context/support/ConversionServiceFactoryBeanTests.java b/org.springframework.context/src/test/java/org/springframework/context/support/ConversionServiceFactoryBeanTests.java index ec2519336d..feae0fc786 100644 --- a/org.springframework.context/src/test/java/org/springframework/context/support/ConversionServiceFactoryBeanTests.java +++ b/org.springframework.context/src/test/java/org/springframework/context/support/ConversionServiceFactoryBeanTests.java @@ -1,18 +1,42 @@ -package org.springframework.context.support; +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import static org.junit.Assert.assertTrue; +package org.springframework.context.support; +import java.util.Collections; import java.util.HashSet; import java.util.Set; -import java.util.Collections; +import static org.junit.Assert.*; import org.junit.Test; + +import org.springframework.beans.ResourceTestBean; +import org.springframework.context.ApplicationContext; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.ConverterFactory; import org.springframework.core.convert.converter.GenericConverter; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.FileSystemResource; +/** + * @author Keith Donald + * @author Juergen Hoeller + */ public class ConversionServiceFactoryBeanTests { @Test @@ -67,15 +91,27 @@ public class ConversionServiceFactoryBeanTests { factory.afterPropertiesSet(); } + @Test + public void conversionServiceInApplicationContext() { + ApplicationContext ctx = new ClassPathXmlApplicationContext("conversionService.xml", getClass()); + ResourceTestBean tb = ctx.getBean("resourceTestBean", ResourceTestBean.class); + assertTrue(tb.getResource() instanceof ClassPathResource); + assertTrue(tb.getResourceArray().length > 1); + assertTrue(tb.getResourceArray()[0] instanceof FileSystemResource); + assertTrue(tb.getResourceMap().size() == 1); + assertTrue(tb.getResourceMap().get("key1") instanceof ClassPathResource); + assertTrue(tb.getResourceArrayMap().size() == 1); + assertTrue(tb.getResourceArrayMap().get("key1").length > 1); + assertTrue(tb.getResourceArrayMap().get("key1")[0] instanceof FileSystemResource); + } + + public static class Foo { - } public static class Bar { - } public static class Baz { - } } diff --git a/org.springframework.context/src/test/java/org/springframework/context/support/conversionService.xml b/org.springframework.context/src/test/java/org/springframework/context/support/conversionService.xml new file mode 100644 index 0000000000..115b36904b --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/context/support/conversionService.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java b/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java index 25e6daeece..5258c95909 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java @@ -269,7 +269,7 @@ public class TypeDescriptor { @SuppressWarnings("unchecked") public Class getMapKeyType() { if (this.field != null) { - return GenericCollectionTypeResolver.getMapKeyFieldType(field); + return GenericCollectionTypeResolver.getMapKeyFieldType(this.field); } else if (this.methodParameter != null) { return GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter); @@ -370,7 +370,38 @@ public class TypeDescriptor { * @return true if this type is assignable to the target */ public boolean isAssignableTo(TypeDescriptor targetType) { - return isTypeAssignableTo(targetType.getType()); + Class targetClass = targetType.getType(); + if (!isTypeAssignableTo(targetClass)) { + return false; + } + if (targetClass != null) { + if (Collection.class.isAssignableFrom(targetClass)) { + Class elementType = targetType.getCollectionElementType(); + if (elementType != null) { + Class sourceElementType = getCollectionElementType(); + if (sourceElementType == null || !elementType.isAssignableFrom(sourceElementType)) { + return false; + } + } + } + else if (Map.class.isAssignableFrom(targetClass)) { + Class keyType = targetType.getMapKeyType(); + if (keyType != null) { + Class sourceKeyType = getMapKeyType(); + if (sourceKeyType == null || !keyType.isAssignableFrom(sourceKeyType)) { + return false; + } + } + Class valueType = targetType.getMapValueType(); + if (valueType != null) { + Class sourceValueType = getMapValueType(); + if (sourceValueType == null || !valueType.isAssignableFrom(sourceValueType)) { + return false; + } + } + } + } + return true; } /**