From 45a0cadf8e7fc5cc082c11ef03f77dc017af64c4 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sun, 9 Aug 2009 00:46:49 +0000 Subject: [PATCH] revised core conversion package for BeanWrapper/BeanFactory integration --- .../beans/AbstractPropertyAccessor.java | 2 + .../beans/BeanWrapperImpl.java | 21 +- .../beans/ConfigurablePropertyAccessor.java | 15 +- .../beans/PropertyEditorRegistrySupport.java | 19 ++ .../beans/TypeConverterDelegate.java | 20 +- .../beans/TypeMismatchException.java | 10 +- .../config/ConfigurableBeanFactory.java | 12 + .../factory/support/AbstractBeanFactory.java | 14 + .../propertyeditors/PropertiesEditor.java | 9 +- .../DefaultListableBeanFactoryTests.java | 45 ++-- .../context/expression/MapAccessor.java | 4 +- .../core/CollectionFactory.java | 95 ++++++- ...xception.java => ConversionException.java} | 23 +- .../convert/ConversionFailedException.java | 41 +-- ...eConverter.java => ConversionService.java} | 31 ++- .../convert/ConverterNotFoundException.java | 23 +- .../core/convert/TypeDescriptor.java | 225 ++++++++-------- .../core/convert/converter/Converter.java | 26 +- .../convert/converter/ConverterFactory.java | 12 +- .../core/convert/converter/ConverterInfo.java | 20 +- .../convert/converter/ConverterRegistry.java | 12 +- .../support/AbstractCollectionConverter.java | 62 +++-- .../core/convert/support/ArrayToArray.java | 13 +- .../convert/support/ArrayToCollection.java | 20 +- .../support/CharacterToNumberFactory.java | 21 +- .../convert/support/CollectionToArray.java | 12 +- .../support/CollectionToCollection.java | 30 +-- .../convert/support/ConversionExecutor.java | 18 +- .../core/convert/support/ConversionUtils.java | 81 ------ ...ter.java => DefaultConversionService.java} | 29 +- ...ter.java => GenericConversionService.java} | 247 ++++++++++-------- .../convert/support/MapEntryConverter.java | 40 +-- .../core/convert/support/MapToMap.java | 67 ++--- .../convert/support/MapToStringArray.java | 34 +-- .../support/MapToStringCollection.java | 27 +- .../support/NoOpConversionExecutor.java | 19 +- .../convert/support/NumberToCharacter.java | 18 +- .../support/NumberToNumberFactory.java | 23 +- .../core/convert/support/ObjectToArray.java | 23 +- .../convert/support/ObjectToCollection.java | 59 ++--- .../core/convert/support/ObjectToString.java | 15 +- .../support/StaticConversionExecutor.java | 43 +-- .../convert/support/StringArrayToMap.java | 50 ++-- .../support/StringCollectionToMap.java | 12 +- .../core/convert/support/StringToArray.java | 12 +- .../convert/support/StringToBigDecimal.java | 16 +- .../convert/support/StringToBigInteger.java | 16 +- .../core/convert/support/StringToBoolean.java | 23 +- .../core/convert/support/StringToByte.java | 17 +- .../convert/support/StringToCharacter.java | 16 +- .../convert/support/StringToCollection.java | 11 +- .../core/convert/support/StringToDouble.java | 13 +- .../convert/support/StringToEnumFactory.java | 23 +- .../core/convert/support/StringToFloat.java | 11 +- .../core/convert/support/StringToInteger.java | 17 +- .../core/convert/support/StringToLocale.java | 16 +- .../core/convert/support/StringToLong.java | 19 +- .../core/convert/support/StringToMap.java | 12 +- .../core/convert/support/StringToShort.java | 19 +- .../org/springframework/util/SharedMap.java | 44 ---- .../util/SharedMapDecorator.java | 106 -------- .../util/StringKeyedMapAdapter.java | 17 +- .../convert/support/ArrayToArrayTests.java | 30 ++- .../support/ArrayToCollectionTests.java | 46 +++- .../support/CollectionToArrayTests.java | 33 ++- .../support/CollectionToCollectionTests.java | 90 ++++--- ...ava => DefaultConversionServiceTests.java} | 22 +- ...ava => GenericConversionServiceTests.java} | 14 +- .../core/convert/support/MapToMapTests.java | 31 ++- .../util/SharedMapDecoratorTests.java | 62 ----- 70 files changed, 1265 insertions(+), 1113 deletions(-) rename org.springframework.core/src/main/java/org/springframework/core/convert/{ConvertException.java => ConversionException.java} (69%) rename org.springframework.core/src/main/java/org/springframework/core/convert/{TypeConverter.java => ConversionService.java} (77%) delete mode 100644 org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionUtils.java rename org.springframework.core/src/main/java/org/springframework/core/convert/support/{DefaultTypeConverter.java => DefaultConversionService.java} (70%) rename org.springframework.core/src/main/java/org/springframework/core/convert/support/{GenericTypeConverter.java => GenericConversionService.java} (69%) delete mode 100644 org.springframework.core/src/main/java/org/springframework/util/SharedMap.java delete mode 100644 org.springframework.core/src/main/java/org/springframework/util/SharedMapDecorator.java rename org.springframework.core/src/test/java/org/springframework/core/convert/support/{DefaultTypeConverterTests.java => DefaultConversionServiceTests.java} (86%) rename org.springframework.core/src/test/java/org/springframework/core/convert/support/{GenericTypeConverterTests.java => GenericConversionServiceTests.java} (92%) delete mode 100644 org.springframework.core/src/test/java/org/springframework/util/SharedMapDecoratorTests.java diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/AbstractPropertyAccessor.java b/org.springframework.beans/src/main/java/org/springframework/beans/AbstractPropertyAccessor.java index 4a2f380d81d..d20a8ededac 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/AbstractPropertyAccessor.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/AbstractPropertyAccessor.java @@ -21,6 +21,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import org.springframework.core.convert.ConversionService; + /** * Abstract implementation of the {@link PropertyAccessor} interface. * Provides base implementations of all convenience methods, with the diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java b/org.springframework.beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java index 3e2b1c7cb86..970c068ff13 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java @@ -38,6 +38,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.GenericCollectionTypeResolver; import org.springframework.core.MethodParameter; +import org.springframework.core.convert.ConversionException; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -145,7 +146,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra * Create new BeanWrapperImpl, wrapping a new instance of the specified class. * @param clazz class to instantiate and wrap */ - public BeanWrapperImpl(Class clazz) { + public BeanWrapperImpl(Class clazz) { registerDefaultEditors(); setWrappedInstance(BeanUtils.instantiateClass(clazz)); } @@ -365,8 +366,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra return false; } - public Object convertIfNecessary( - Object value, Class requiredType, MethodParameter methodParam) throws TypeMismatchException { + public T convertIfNecessary( + Object value, Class requiredType, MethodParameter methodParam) throws TypeMismatchException { try { return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam); } @@ -572,7 +573,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra } } - Object value = null; + Object value; if (System.getSecurityManager() != null) { try { @@ -580,8 +581,9 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra public Object run() throws Exception { return readMethod.invoke(object, (Object[]) null); } - },acc); - } catch (PrivilegedActionException pae) { + }, acc); + } + catch (PrivilegedActionException pae) { throw pae.getException(); } } @@ -625,7 +627,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra } else if (value instanceof Map) { Map map = (Map) value; - Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), i + 1); + Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), i + 1); // IMPORTANT: Do not pass full property name in here - property editors // must not kick in for map keys but rather only for map values. Object convertedMapKey = this.typeConverterDelegate.convertIfNecessary(key, mapKeyType); @@ -945,6 +947,11 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException()); } } + catch (ConversionException ex) { + PropertyChangeEvent pce = + new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue()); + throw new TypeMismatchException(pce, pd.getPropertyType(), ex); + } catch (IllegalArgumentException ex) { PropertyChangeEvent pce = new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue()); diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/ConfigurablePropertyAccessor.java b/org.springframework.beans/src/main/java/org/springframework/beans/ConfigurablePropertyAccessor.java index aeb563c271a..54dd62cf53a 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/ConfigurablePropertyAccessor.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/ConfigurablePropertyAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2009 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. @@ -16,6 +16,8 @@ package org.springframework.beans; +import org.springframework.core.convert.ConversionService; + /** * Interface that encapsulates configuration methods for a PropertyAccessor. * Also extends the PropertyEditorRegistry interface, which defines methods @@ -29,6 +31,17 @@ package org.springframework.beans; */ public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter { + /** + * Specify a Spring 3.0 ConversionService to use for converting + * property values, as an alternative to JavaBeans PropertyEditors. + */ + void setConversionService(ConversionService conversionService); + + /** + * Return the associated ConversionService, if any. + */ + ConversionService getConversionService(); + /** * Set whether to extract the old property value when applying a * property editor to a new value for a property. diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java b/org.springframework.beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java index 6dd3162d157..364d89d1e83 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java @@ -57,6 +57,7 @@ import org.springframework.beans.propertyeditors.PropertiesEditor; import org.springframework.beans.propertyeditors.StringArrayPropertyEditor; import org.springframework.beans.propertyeditors.URIEditor; import org.springframework.beans.propertyeditors.URLEditor; +import org.springframework.core.convert.ConversionService; import org.springframework.core.io.Resource; import org.springframework.core.io.support.ResourceArrayPropertyEditor; import org.springframework.util.ClassUtils; @@ -75,6 +76,8 @@ import org.springframework.util.ClassUtils; */ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry { + private ConversionService conversionService; + private boolean defaultEditorsActive = false; private boolean configValueEditorsActive = false; @@ -90,6 +93,22 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry { private Map customEditorCache; + /** + * Specify a Spring 3.0 ConversionService to use for converting + * property values, as an alternative to JavaBeans PropertyEditors. + */ + public void setConversionService(ConversionService conversionService) { + this.conversionService = conversionService; + } + + /** + * Return the associated ConversionService, if any. + */ + public ConversionService getConversionService() { + return this.conversionService; + } + + //--------------------------------------------------------------------- // Management of default editors //--------------------------------------------------------------------- diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java b/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java index 948e2511546..d530566e1a4 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java @@ -30,6 +30,8 @@ import org.apache.commons.logging.LogFactory; import org.springframework.core.CollectionFactory; import org.springframework.core.GenericCollectionTypeResolver; import org.springframework.core.MethodParameter; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.TypeDescriptor; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -160,6 +162,18 @@ class TypeConverterDelegate { // Custom editor for this type? PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName); + // No custom editor but custom ConversionService specified? + ConversionService conversionService = this.propertyEditorRegistry.getConversionService(); + if (editor == null && conversionService != null && convertedValue != null && + conversionService.canConvert(convertedValue.getClass(), requiredType)) { + if (methodParam != null) { + return (T) conversionService.convert(convertedValue, new TypeDescriptor(methodParam)); + } + else { + return conversionService.convert(convertedValue, requiredType); + } + } + // Value not of required type? if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) { if (editor == null) { @@ -265,7 +279,7 @@ class TypeConverterDelegate { * @return the new value, possibly the result of type conversion * @throws IllegalArgumentException if type conversion failed */ - protected Object doConvertValue(Object oldValue, Object newValue, Class requiredType, PropertyEditor editor) { + protected Object doConvertValue(Object oldValue, Object newValue, Class requiredType, PropertyEditor editor) { Object convertedValue = newValue; boolean sharedEditor = false; @@ -307,6 +321,8 @@ class TypeConverterDelegate { } } + Object returnValue = convertedValue; + if (requiredType != null && !requiredType.isArray() && convertedValue instanceof String[]) { // Convert String array to a comma-separated String. // Only applies if no PropertyEditor converted the String array before. @@ -335,7 +351,7 @@ class TypeConverterDelegate { } } - return convertedValue; + return returnValue; } /** diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/TypeMismatchException.java b/org.springframework.beans/src/main/java/org/springframework/beans/TypeMismatchException.java index 2ecfaa7bf3d..b50580bf309 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/TypeMismatchException.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/TypeMismatchException.java @@ -56,10 +56,10 @@ public class TypeMismatchException extends PropertyAccessException { */ public TypeMismatchException(PropertyChangeEvent propertyChangeEvent, Class requiredType, Throwable cause) { super(propertyChangeEvent, - "Failed to convert property value of type [" + - ClassUtils.getDescriptiveType(propertyChangeEvent.getNewValue()) + "]" + + "Failed to convert property value of type '" + + ClassUtils.getDescriptiveType(propertyChangeEvent.getNewValue()) + "'" + (requiredType != null ? - " to required type [" + ClassUtils.getQualifiedName(requiredType) + "]" : "") + + " to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : "") + (propertyChangeEvent.getPropertyName() != null ? " for property '" + propertyChangeEvent.getPropertyName() + "'" : ""), cause); @@ -83,8 +83,8 @@ public class TypeMismatchException extends PropertyAccessException { * @param cause the root cause (may be null) */ public TypeMismatchException(Object value, Class requiredType, Throwable cause) { - super("Failed to convert value of type [" + ClassUtils.getDescriptiveType(value) + "]" + - (requiredType != null ? " to required type [" + ClassUtils.getQualifiedName(requiredType) + "]" : ""), + super("Failed to convert value of type '" + ClassUtils.getDescriptiveType(value) + "'" + + (requiredType != null ? " to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : ""), cause); this.value = value; this.requiredType = requiredType; diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java index 0aa5c35d45b..8df463db5cb 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java @@ -25,6 +25,7 @@ import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.HierarchicalBeanFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.core.convert.ConversionService; import org.springframework.util.StringValueResolver; /** @@ -134,6 +135,17 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single */ BeanExpressionResolver getBeanExpressionResolver(); + /** + * Specify a Spring 3.0 ConversionService to use for converting + * property values, as an alternative to JavaBeans PropertyEditors. + */ + void setConversionService(ConversionService conversionService); + + /** + * Return the associated ConversionService, if any. + */ + ConversionService getConversionService(); + /** * Add a PropertyEditorRegistrar to be applied to all bean creation processes. *

Such a registrar creates new PropertyEditor instances and registers them diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java index 99fecc32894..bb5580de84a 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java @@ -66,6 +66,7 @@ import org.springframework.beans.factory.config.InstantiationAwareBeanPostProces import org.springframework.beans.factory.config.Scope; import org.springframework.core.DecoratingClassLoader; import org.springframework.core.NamedThreadLocal; +import org.springframework.core.convert.ConversionService; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -120,6 +121,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp /** Resolution strategy for expressions in bean definition values */ private BeanExpressionResolver beanExpressionResolver; + /** Spring 3.0 ConversionService to use instead of PropertyEditors */ + private ConversionService conversionService; + /** Custom PropertyEditorRegistrars to apply to the beans of this factory */ private final Set propertyEditorRegistrars = new LinkedHashSet(4); @@ -620,6 +624,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return this.beanExpressionResolver; } + public void setConversionService(ConversionService conversionService) { + this.conversionService = conversionService; + } + + public ConversionService getConversionService() { + return this.conversionService; + } + public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) { Assert.notNull(registrar, "PropertyEditorRegistrar must not be null"); this.propertyEditorRegistrars.add(registrar); @@ -669,6 +681,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp else { // Build default TypeConverter, registering custom editors. SimpleTypeConverter typeConverter = new SimpleTypeConverter(); + typeConverter.setConversionService(getConversionService()); registerCustomEditors(typeConverter); return typeConverter; } @@ -937,6 +950,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp * @param bw the BeanWrapper to initialize */ protected void initBeanWrapper(BeanWrapper bw) { + bw.setConversionService(getConversionService()); registerCustomEditors(bw); } diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/propertyeditors/PropertiesEditor.java b/org.springframework.beans/src/main/java/org/springframework/beans/propertyeditors/PropertiesEditor.java index 6acc6819ee0..1a6d4962481 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/propertyeditors/PropertiesEditor.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/propertyeditors/PropertiesEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2009 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. @@ -37,13 +37,6 @@ import java.util.Properties; * @see java.util.Properties#load */ public class PropertiesEditor extends PropertyEditorSupport { - - /** - * Any of these characters, if they're first after whitespace or first - * on a line, mean that the line is a comment and should be ignored. - */ - private final static String COMMENT_MARKERS = "#!"; - /** * Convert {@link String} into {@link Properties}, considering it as diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java index 12bc63ba8de..a9a2885613e 100644 --- a/org.springframework.beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java +++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java @@ -16,15 +16,6 @@ package org.springframework.beans.factory; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - import java.lang.reflect.Field; import java.net.MalformedURLException; import java.security.AccessControlContext; @@ -40,12 +31,19 @@ import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; - import javax.security.auth.Subject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import static org.junit.Assert.*; import org.junit.Test; +import test.beans.DerivedTestBean; +import test.beans.DummyFactory; +import test.beans.ITestBean; +import test.beans.LifecycleBean; +import test.beans.NestedTestBean; +import test.beans.TestBean; + import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.NotWritablePropertyException; @@ -73,17 +71,12 @@ import org.springframework.beans.factory.xml.ConstructorDependenciesBean; import org.springframework.beans.factory.xml.DependenciesBean; import org.springframework.beans.propertyeditors.CustomNumberEditor; import org.springframework.core.MethodParameter; +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.util.StopWatch; -import test.beans.DerivedTestBean; -import test.beans.DummyFactory; -import test.beans.ITestBean; -import test.beans.LifecycleBean; -import test.beans.NestedTestBean; -import test.beans.TestBean; - /** * Tests properties population and autowire behavior. * @@ -835,6 +828,24 @@ public final class DefaultListableBeanFactoryTests { assertTrue(testBean.getMyFloat().floatValue() == 1.1f); } + @Test + public void testCustomConverter() { + DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + DefaultConversionService conversionService = new DefaultConversionService(); + conversionService.add(new Converter() { + public Float convert(String source) throws Exception { + NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN); + return nf.parse(source).floatValue(); + } + }); + lbf.setConversionService(conversionService); + MutablePropertyValues pvs = new MutablePropertyValues(); + pvs.addPropertyValue("myFloat", "1,1"); + lbf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class, pvs)); + TestBean testBean = (TestBean) lbf.getBean("testBean"); + assertTrue(testBean.getMyFloat().floatValue() == 1.1f); + } + @Test public void testCustomEditorWithBeanReference() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); diff --git a/org.springframework.context/src/main/java/org/springframework/context/expression/MapAccessor.java b/org.springframework.context/src/main/java/org/springframework/context/expression/MapAccessor.java index 1fbe259b693..ab59d802903 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/expression/MapAccessor.java +++ b/org.springframework.context/src/main/java/org/springframework/context/expression/MapAccessor.java @@ -18,11 +18,11 @@ package org.springframework.context.expression; import java.util.Map; +import org.springframework.core.convert.TypeDescriptor; import org.springframework.expression.AccessException; import org.springframework.expression.EvaluationContext; import org.springframework.expression.PropertyAccessor; import org.springframework.expression.TypedValue; -import org.springframework.expression.spel.ast.CommonTypeDescriptors; /** * EL property accessor that knows how to traverse the keys @@ -39,7 +39,7 @@ public class MapAccessor implements PropertyAccessor { } public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException { - return new TypedValue(((Map) target).get(name),CommonTypeDescriptors.OBJECT_TYPE_DESCRIPTOR); + return new TypedValue(((Map) target).get(name), TypeDescriptor.valueOf(Object.class)); } public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException { diff --git a/org.springframework.core/src/main/java/org/springframework/core/CollectionFactory.java b/org.springframework.core/src/main/java/org/springframework/core/CollectionFactory.java index 2cdff0ca5fa..98105e81b35 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/CollectionFactory.java +++ b/org.springframework.core/src/main/java/org/springframework/core/CollectionFactory.java @@ -56,6 +56,10 @@ public abstract class CollectionFactory { private static final String NAVIGABLE_MAP_CLASS_NAME = "java.util.NavigableMap"; + private static Class navigableSet = null; + + private static Class navigableMap = null; + private static final Set approximableCollectionTypes = new HashSet(10); private static final Set approximableMapTypes = new HashSet(6); @@ -72,8 +76,10 @@ public abstract class CollectionFactory { // New Java 6 collection interfaces try { - approximableCollectionTypes.add(ClassUtils.forName(NAVIGABLE_SET_CLASS_NAME, CollectionFactory.class.getClassLoader())); - approximableMapTypes.add(ClassUtils.forName(NAVIGABLE_MAP_CLASS_NAME, CollectionFactory.class.getClassLoader())); + navigableSet = ClassUtils.forName(NAVIGABLE_SET_CLASS_NAME, CollectionFactory.class.getClassLoader()); + navigableMap = ClassUtils.forName(NAVIGABLE_MAP_CLASS_NAME, CollectionFactory.class.getClassLoader()); + approximableCollectionTypes.add(navigableSet); + approximableMapTypes.add(navigableMap); } catch (ClassNotFoundException ex) { // not running on Java 6 or above... @@ -187,7 +193,7 @@ public abstract class CollectionFactory { * @return true if the type is approximable, * false if it is not */ - public static boolean isApproximableCollectionType(Class collectionType) { + public static boolean isApproximableCollectionType(Class collectionType) { return (collectionType != null && approximableCollectionTypes.contains(collectionType)); } @@ -195,9 +201,9 @@ public abstract class CollectionFactory { * Create the most approximate collection for the given collection. *

Creates an ArrayList, TreeSet or linked Set for a List, SortedSet * or Set, respectively. - * @param collection the original collection object + * @param collection the original Collection object * @param initialCapacity the initial capacity - * @return the new collection instance + * @return the new Collection instance * @see java.util.ArrayList * @see java.util.TreeSet * @see java.util.LinkedHashSet @@ -218,6 +224,45 @@ public abstract class CollectionFactory { } } + /** + * Create the most appropriate collection for the given collection type. + *

Creates an ArrayList, TreeSet or linked Set for a List, SortedSet + * or Set, respectively. + * @param collectionType the desired type of the target Collection + * @param initialCapacity the initial capacity + * @return the new Collection instance + * @see java.util.ArrayList + * @see java.util.TreeSet + * @see java.util.LinkedHashSet + */ + public static Collection createCollection(Class collectionType, int initialCapacity) { + if (collectionType.isInterface()) { + if (List.class.equals(collectionType)) { + return new ArrayList(initialCapacity); + } + else if (SortedSet.class.equals(collectionType) || collectionType.equals(navigableSet)) { + return new TreeSet(); + } + else if (Set.class.equals(collectionType) || Collection.class.equals(collectionType)) { + return new LinkedHashSet(initialCapacity); + } + else { + throw new IllegalArgumentException("Unsupported Collection interface: " + collectionType.getName()); + } + } + else { + if (!Collection.class.isAssignableFrom(collectionType)) { + throw new IllegalArgumentException("Unsupported Collection type: " + collectionType.getName()); + } + try { + return (Collection) collectionType.newInstance(); + } + catch (Exception ex) { + throw new IllegalArgumentException("Could not instantiate Collection type: " + collectionType.getName()); + } + } + } + /** * Determine whether the given map type is an approximable type, * i.e. a type that {@link #createApproximateMap} can approximate. @@ -225,16 +270,16 @@ public abstract class CollectionFactory { * @return true if the type is approximable, * false if it is not */ - public static boolean isApproximableMapType(Class mapType) { + public static boolean isApproximableMapType(Class mapType) { return (mapType != null && approximableMapTypes.contains(mapType)); } /** * Create the most approximate map for the given map. *

Creates a TreeMap or linked Map for a SortedMap or Map, respectively. - * @param map the original map object + * @param map the original Map object * @param initialCapacity the initial capacity - * @return the new collection instance + * @return the new Map instance * @see java.util.TreeMap * @see java.util.LinkedHashMap */ @@ -248,6 +293,40 @@ public abstract class CollectionFactory { } } + /** + * Create the most approximate map for the given map. + *

Creates a TreeMap or linked Map for a SortedMap or Map, respectively. + * @param collectionType the desired type of the target Map + * @param initialCapacity the initial capacity + * @return the new Map instance + * @see java.util.TreeMap + * @see java.util.LinkedHashMap + */ + public static Map createMap(Class mapType, int initialCapacity) { + if (mapType.isInterface()) { + if (Map.class.equals(mapType)) { + return new LinkedHashMap(initialCapacity); + } + else if (SortedMap.class.equals(mapType) || mapType.equals(navigableMap)) { + return new TreeMap(); + } + else { + throw new IllegalArgumentException("Unsupported Map interface: " + mapType.getName()); + } + } + else { + if (!Map.class.isAssignableFrom(mapType)) { + throw new IllegalArgumentException("Unsupported Map type: " + mapType.getName()); + } + try { + return (Map) mapType.newInstance(); + } + catch (Exception ex) { + throw new IllegalArgumentException("Could not instantiate Map type: " + mapType.getName()); + } + } + } + /** * ConcurrentMap adapter for the JDK ConcurrentHashMap class. diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/ConvertException.java b/org.springframework.core/src/main/java/org/springframework/core/convert/ConversionException.java similarity index 69% rename from org.springframework.core/src/main/java/org/springframework/core/convert/ConvertException.java rename to org.springframework.core/src/main/java/org/springframework/core/convert/ConversionException.java index a05ee34e5c8..4ddf15d8390 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/ConvertException.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/ConversionException.java @@ -1,41 +1,46 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert; +import org.springframework.core.NestedRuntimeException; + /** * Base class for exceptions thrown by the convert system. + * * @author Keith Donald * @since 3.0 */ -public abstract class ConvertException extends RuntimeException { +public abstract class ConversionException extends NestedRuntimeException { /** - * Creates a new conversion exception. + * Construct a new conversion exception. * @param message the exception message * @param cause the cause */ - public ConvertException(String message, Throwable cause) { + public ConversionException(String message, Throwable cause) { super(message, cause); } /** - * Creates a new conversion exception. + * Construct a new conversion exception. * @param message the exception message */ - public ConvertException(String message) { + public ConversionException(String message) { super(message); } + } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/ConversionFailedException.java b/org.springframework.core/src/main/java/org/springframework/core/convert/ConversionFailedException.java index e0e3ae61e97..ab3e33b2856 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/ConversionFailedException.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/ConversionFailedException.java @@ -1,28 +1,31 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert; import org.springframework.core.style.StylerUtils; +import org.springframework.util.ClassUtils; /** * Thrown when an attempt to execute a type conversion fails. + * * @author Keith Donald * @since 3.0 */ -public class ConversionFailedException extends ConvertException { +public class ConversionFailedException extends ConversionException { private transient Object value; @@ -30,22 +33,23 @@ public class ConversionFailedException extends ConvertException { private Class targetType; + /** - * Creates a new conversion exception. + * Create a new conversion exception. * @param value the value we tried to convert * @param sourceType the value's original type * @param targetType the value's target type * @param cause the cause of the conversion failure */ public ConversionFailedException(Object value, Class sourceType, Class targetType, Throwable cause) { - super(defaultMessage(value, sourceType, targetType, cause), cause); + super(buildDefaultMessage(value, sourceType, targetType, cause), cause); this.value = value; this.sourceType = sourceType; this.targetType = targetType; } /** - * Creates a new conversion exception. + * Create a new conversion exception. * @param value the value we tried to convert * @param sourceType the value's original type * @param targetType the value's target type @@ -58,30 +62,33 @@ public class ConversionFailedException extends ConvertException { this.targetType = targetType; } + /** - * Returns the actual value we tried to convert, an instance of {@link #getSourceType()}. + * Return the actual value we tried to convert, an instance of {@link #getSourceType()}. */ public Object getValue() { - return value; + return this.value; } /** - * Returns the source type we tried to convert the value from. + * Return the source type we tried to convert the value from. */ public Class getSourceType() { - return sourceType; + return this.sourceType; } /** * Returns the target type we tried to convert the value to. */ public Class getTargetType() { - return targetType; + return this.targetType; } - private static String defaultMessage(Object value, Class sourceType, Class targetType, Throwable cause) { - return "Unable to convert value " + StylerUtils.style(value) + " from type [" + sourceType.getName() - + "] to type [" + targetType.getName() + "]; reason = '" + cause.getMessage() + "'"; + + private static String buildDefaultMessage(Object value, Class sourceType, Class targetType, Throwable cause) { + return "Unable to convert value " + StylerUtils.style(value) + " from type '" + + ClassUtils.getQualifiedName(sourceType) + "' to type '" + + ClassUtils.getQualifiedName(targetType) + "'; reason = '" + cause.getMessage() + "'"; } -} \ No newline at end of file +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/TypeConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/ConversionService.java similarity index 77% rename from org.springframework.core/src/main/java/org/springframework/core/convert/TypeConverter.java rename to org.springframework.core/src/main/java/org/springframework/core/convert/ConversionService.java index 8a7150fbd54..29a46dde85b 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/TypeConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/ConversionService.java @@ -1,29 +1,32 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert; /** * A service interface for type conversion. This is the entry point into the convert system. - *

- * Call {@link #convert(Object, Class)} to perform a thread-safe type conversion using this system.
- * Call {@link #convert(Object, TypeDescriptor)} to perform a conversion with additional context about the targetType to convert to. + * + *

Call {@link #convert(Object, Class)} to perform a thread-safe type conversion using this system. + * Call {@link #convert(Object, TypeDescriptor)} to perform a conversion with additional context + * about the targetType to convert to. + * * @author Keith Donald * @since 3.0 */ -public interface TypeConverter { +public interface ConversionService { /** * Returns true if objects of sourceType can be converted to targetType. @@ -39,24 +42,24 @@ public interface TypeConverter { * @param targetType context about the target type to convert to * @return true if a conversion can be performed, false if not */ - boolean canConvert(Class sourceType, TypeDescriptor targetType); + boolean canConvert(Class sourceType, TypeDescriptor targetType); /** * Convert the source to targetType. * @param source the source to convert from (may be null) * @param targetType the target type to convert to * @return the converted object, an instance of targetType, or null if a null source was provided - * @throws ConvertException if an exception occurred + * @throws ConversionException if an exception occurred */ - T convert(S source, Class targetType); + T convert(Object source, Class targetType); /** * Convert the source to type T needed by the conversion point. * @param source the source to convert from (may be null) * @param targetType context about the target type to convert to * @return the converted object, an instance of {@link TypeDescriptor#getType()}, or null if a null source was provided - * @throws ConvertException if an exception occurred + * @throws ConversionException if an exception occurred */ - T convert(S source, TypeDescriptor targetType); + Object convert(Object source, TypeDescriptor targetType); -} \ No newline at end of file +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/ConverterNotFoundException.java b/org.springframework.core/src/main/java/org/springframework/core/convert/ConverterNotFoundException.java index 5e86f273761..2d25b57a3d2 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/ConverterNotFoundException.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/ConverterNotFoundException.java @@ -1,30 +1,33 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert; /** * Thrown when a suitable converter could not be found in a conversion service. + * * @author Keith Donald * @since 3.0 */ -public class ConverterNotFoundException extends ConvertException { +public class ConverterNotFoundException extends ConversionException { - private Class sourceType; + private final Class sourceType; + + private final Class targetType; - private Class targetType; /** * Creates a new conversion executor not found exception. @@ -38,17 +41,19 @@ public class ConverterNotFoundException extends ConvertException { this.targetType = targetType; } + /** * Returns the source type that was requested to convert from. */ public Class getSourceType() { - return sourceType; + return this.sourceType; } /** * Returns the target type that was requested to convert to. */ public Class getTargetType() { - return targetType; + return this.targetType; } + } 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 123adc1712a..f1f10a63c40 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 @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert; import java.lang.annotation.Annotation; @@ -24,19 +25,17 @@ import java.util.Map; import org.springframework.core.GenericCollectionTypeResolver; import org.springframework.core.MethodParameter; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; /** * Context about a type to convert to. + * * @author Keith Donald * @author Andy Clement * @since 3.0 */ -public class TypeDescriptor { +public class TypeDescriptor { - /** - * Constant value for the null object - */ - @SuppressWarnings("unchecked") public final static TypeDescriptor NULL = new TypeDescriptor((Class) null); private MethodParameter methodParameter; @@ -47,6 +46,7 @@ public class TypeDescriptor { private Class type; + /** * Creates a new descriptor for the given type. * Use this constructor when a conversion point comes from a source such as a Map or collection, where no additional context is available. @@ -76,18 +76,40 @@ public class TypeDescriptor { this.field = field; } + + /** + * Return the wrapped MethodParameter, if any. + *

Note: Either MethodParameter or Field is available. + * @return the MethodParameter, or null if none + */ + public MethodParameter getMethodParameter() { + return this.methodParameter; + } + + /** + * Return the wrapped Field, if any. + *

Note: Either MethodParameter or Field is available. + * @return the Field, or null if none + */ + public Field getField() { + return this.field; + } + /** * Determine the declared (non-generic) type of the wrapped parameter/field. * @return the declared type (never null) */ public Class getType() { - if (type != null) { - return wrapperType(type); - } else if (field != null) { - return wrapperType(field.getType()); - } else if (methodParameter != null) { - return wrapperType(methodParameter.getParameterType()); - } else { + if (this.type != null) { + return wrapperType(this.type); + } + else if (this.field != null) { + return wrapperType(this.field.getType()); + } + else if (this.methodParameter != null) { + return wrapperType(this.methodParameter.getParameterType()); + } + else { return null; } } @@ -99,7 +121,8 @@ public class TypeDescriptor { Class type = getType(); if (type != null) { return getType().getName(); - } else { + } + else { return null; } } @@ -109,11 +132,7 @@ public class TypeDescriptor { */ public boolean isArray() { Class type = getType(); - if (type != null) { - return type.isArray(); - } else { - return false; - } + return (type != null && type.isArray()); } /** @@ -124,15 +143,17 @@ public class TypeDescriptor { } /** - * If this type is an array type or {@link Collection} type, returns the underlying element type. Returns null if - * the type is neither an array or collection. + * If this type is an array type or {@link Collection} type, returns the underlying element type. + * Returns null if the type is neither an array or collection. */ public Class getElementType() { if (isArray()) { return getArrayComponentType(); - } else if (isCollection()) { + } + else if (isCollection()) { return getCollectionElementType(); - } else { + } + else { return null; } } @@ -148,7 +169,7 @@ public class TypeDescriptor { * Is this descriptor for a map where the key type and value type are known? */ public boolean isMapEntryTypeKnown() { - return isMap() && getMapKeyType() != null && getMapValueType() != null; + return (isMap() && getMapKeyType() != null && getMapValueType() != null); } /** @@ -156,11 +177,13 @@ public class TypeDescriptor { * @return the generic type, or null if none */ public Class getMapKeyType() { - if (field != null) { + if (this.field != null) { return GenericCollectionTypeResolver.getMapKeyFieldType(field); - } else if (methodParameter != null) { - return GenericCollectionTypeResolver.getMapKeyParameterType(methodParameter); - } else { + } + else if (this.methodParameter != null) { + return GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter); + } + else { return null; } } @@ -170,11 +193,13 @@ public class TypeDescriptor { * @return the generic type, or null if none */ public Class getMapValueType() { - if (field != null) { - return GenericCollectionTypeResolver.getMapValueFieldType(field); - } else if (methodParameter != null) { - return GenericCollectionTypeResolver.getMapValueParameterType(methodParameter); - } else { + if (this.field != null) { + return GenericCollectionTypeResolver.getMapValueFieldType(this.field); + } + else if (this.methodParameter != null) { + return GenericCollectionTypeResolver.getMapValueParameterType(this.methodParameter); + } + else { return null; } } @@ -183,48 +208,26 @@ public class TypeDescriptor { * Obtain the annotations associated with the wrapped parameter/field, if any. */ public Annotation[] getAnnotations() { - if (field != null) { - if (cachedFieldAnnotations == null) { - cachedFieldAnnotations = field.getAnnotations(); + if (this.field != null) { + if (this.cachedFieldAnnotations == null) { + this.cachedFieldAnnotations = field.getAnnotations(); } - return cachedFieldAnnotations; - } else if (methodParameter != null) { - return methodParameter.getMethod().getAnnotations(); - } else { + return this.cachedFieldAnnotations; + } + else if (this.methodParameter != null) { + return this.methodParameter.getMethod().getAnnotations(); + } + else { return new Annotation[0]; } } - /** - * Return the wrapped MethodParameter, if any. - *

- * Note: Either MethodParameter or Field is available. - * @return the MethodParameter, or null if none - */ - public MethodParameter getMethodParameter() { - return methodParameter; - } - - /** - * Return the wrapped Field, if any. - *

- * Note: Either MethodParameter or Field is available. - * @return the Field, or null if none - */ - public Field getField() { - return field; - } - /** * Returns true if this type is an abstract class. */ public boolean isAbstractClass() { Class type = getType(); - if (type != null) { - return !getType().isInterface() && Modifier.isAbstract(getType().getModifiers()); - } else { - return false; - } + return (type != null && !getType().isInterface() && Modifier.isAbstract(getType().getModifiers())); } /** @@ -232,11 +235,7 @@ public class TypeDescriptor { */ public boolean isInstance(Object obj) { Class type = getType(); - if (type != null) { - return getType().isInstance(obj); - } else { - return false; - } + return (type != null && getType().isInstance(obj)); } /** @@ -244,33 +243,8 @@ public class TypeDescriptor { * @param targetType the target type * @return true if this type is assignable to the target */ - @SuppressWarnings("unchecked") public boolean isAssignableTo(TypeDescriptor targetType) { - return targetType.getType().isAssignableFrom(getType()); - } - - /** - * Creates a new type descriptor for the given class. - * @param type the class - * @return the type descriptor - */ - public static TypeDescriptor valueOf(Class type) { - // TODO needs a cache for common type descriptors - return new TypeDescriptor(type); - } - - /** - * Creates a new type descriptor for the class of the given object. - * @param object the object - * @return the type descriptor - */ - @SuppressWarnings("unchecked") - public static TypeDescriptor forObject(Object object) { - if (object == null) { - return NULL; - } else { - return valueOf(object.getClass()); - } + return ClassUtils.isAssignable(targetType.getType(), getType()); } /** @@ -281,7 +255,8 @@ public class TypeDescriptor { if (isArray()) { // TODO should properly handle multi dimensional arrays stringValue.append(getArrayComponentType().getName()).append("[]"); - } else { + } + else { Class clazz = getType(); if (clazz==null) { return "null"; @@ -292,7 +267,8 @@ public class TypeDescriptor { if (collectionType != null) { stringValue.append("<").append(collectionType.getName()).append(">"); } - } else if (isMap()) { + } + else if (isMap()) { Class keyType = getMapKeyType(); Class valType = getMapValueType(); if (keyType != null && valType != null) { @@ -304,6 +280,7 @@ public class TypeDescriptor { return stringValue.toString(); } + // internal helpers private Class wrapperType(Class type) { @@ -331,29 +308,49 @@ public class TypeDescriptor { return type; } } - + private Class getArrayComponentType() { return getType().getComponentType(); } @SuppressWarnings("unchecked") private Class getCollectionElementType() { - if (type != null) { - return GenericCollectionTypeResolver.getCollectionType((Class) type); - } else if (field != null) { - return GenericCollectionTypeResolver.getCollectionFieldType(field); - } else { - return GenericCollectionTypeResolver.getCollectionParameterType(methodParameter); + if (this.type != null) { + return GenericCollectionTypeResolver.getCollectionType((Class) this.type); + } + else if (this.field != null) { + return GenericCollectionTypeResolver.getCollectionFieldType(this.field); + } + else { + return GenericCollectionTypeResolver.getCollectionParameterType(this.methodParameter); } } private boolean isTypeAssignableTo(Class clazz) { Class type = getType(); - if (type != null) { - return clazz.isAssignableFrom(type); - } else { - return false; - } + return (type != null && ClassUtils.isAssignable(clazz, type)); } -} \ No newline at end of file + + // static factory methods + + /** + * Creates a new type descriptor for the given class. + * @param type the class + * @return the type descriptor + */ + public static TypeDescriptor valueOf(Class type) { + // TODO needs a cache for common type descriptors + return new TypeDescriptor(type); + } + + /** + * Creates a new type descriptor for the class of the given object. + * @param object the object + * @return the type descriptor + */ + public static TypeDescriptor forObject(Object object) { + return (object == null ? NULL : valueOf(object.getClass())); + } + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/Converter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/Converter.java index e9e5823a42a..f38a0fd7b06 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/Converter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/Converter.java @@ -1,29 +1,29 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.converter; -import org.springframework.core.convert.ConvertException; -import org.springframework.core.convert.TypeConverter; +package org.springframework.core.convert.converter; /** * A converter converts a source object of type S to a target of type T. - *

- * Implementations of this interface are thread-safe and can be shared. Converters are typically registered with and - * invoked behind a {@link TypeConverter}. They typically should not be called directly. - *

+ * + *

Implementations of this interface are thread-safe and can be shared. + * Converters are typically registered with and invoked behind a + * {@link org.springframework.core.convert.ConversionService}. + * They typically should not be called directly. + * * @author Keith Donald * @since 3.0 */ @@ -34,9 +34,9 @@ public interface Converter { * @param source the source object to convert, which must be an instance of S * @return the converted object, which must be an instance of T * @throws Exception an exception occurred performing the conversion; may be any checked exception, the conversion - * system will handle wrapping the failure in a {@link ConvertException} that provides a consistent type + * system will handle wrapping the failure in a {@link org.springframework.core.convert.ConversionException} that provides a consistent type * conversion error context */ T convert(S source) throws Exception; -} \ No newline at end of file +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterFactory.java b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterFactory.java index 9b6ebb9cc74..675a2a80df8 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterFactory.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterFactory.java @@ -1,12 +1,12 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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. @@ -17,6 +17,7 @@ package org.springframework.core.convert.converter; /** * A factory for "ranged" converters that can convert objects from S to subtypes of R. + * * @author Keith Donald * @since 3.0 * @param The source type converters created by this factory can convert from @@ -32,4 +33,5 @@ public interface ConverterFactory { * @return A converter from S to T */ Converter getConverter(Class targetType); -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterInfo.java b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterInfo.java index 4e4029bc48b..c59a563ffe5 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterInfo.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterInfo.java @@ -1,26 +1,28 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.converter; -import org.springframework.core.convert.TypeConverter; +package org.springframework.core.convert.converter; /** * A meta interface a Converter may implement to describe what types he can convert between. - * Implementing this interface is required when registering converters that do not declare their parameterized types S and T with a {@link TypeConverter}. + * + * Implementing this interface is required when registering converters that do not declare their + * parameterized types S and T with a {@link org.springframework.core.convert.ConversionService}. * Such Converters are often dynamically created by a {@link ConverterFactory}. + * * @author Keith Donald * @since 3.0 * @see Converter @@ -31,11 +33,11 @@ public interface ConverterInfo { /** * The source type the converter converts from. */ - public Class getSourceType(); + Class getSourceType(); /** * The target type the converter converts to. */ - public Class getTargetType(); + Class getTargetType(); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterRegistry.java b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterRegistry.java index bd676427e41..eb1ff6552b0 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterRegistry.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterRegistry.java @@ -1,12 +1,12 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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. @@ -17,6 +17,7 @@ package org.springframework.core.convert.converter; /** * For registering converters with a type conversion system. + * * @author Keith Donald * @since 3.0 */ @@ -38,4 +39,5 @@ public interface ConverterRegistry { * @param targetType the target type */ void removeConverter(Class sourceType, Class targetType); -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/AbstractCollectionConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/AbstractCollectionConverter.java index a12824079ab..edcae3a4cf8 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/AbstractCollectionConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/AbstractCollectionConverter.java @@ -1,40 +1,42 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.TypeDescriptor; /** - * Base class for converters that convert to and from collection types (arrays and java.util.Collection types) + * Base class for converters that convert to and from collection types (arrays and java.util.Collection types). + * * @author Keith Donald * @since 3.0 */ -@SuppressWarnings("unchecked") abstract class AbstractCollectionConverter implements ConversionExecutor { - private GenericTypeConverter conversionService; + private final GenericConversionService conversionService; - private ConversionExecutor elementConverter; - - private TypeDescriptor sourceCollectionType; - - private TypeDescriptor targetCollectionType; - - public AbstractCollectionConverter(TypeDescriptor sourceCollectionType, TypeDescriptor targetCollectionType, GenericTypeConverter conversionService) { + private final TypeDescriptor sourceCollectionType; + + private final TypeDescriptor targetCollectionType; + + private final ConversionExecutor elementConverter; + + + public AbstractCollectionConverter(TypeDescriptor sourceCollectionType, TypeDescriptor targetCollectionType, GenericConversionService conversionService) { this.conversionService = conversionService; this.sourceCollectionType = sourceCollectionType; this.targetCollectionType = targetCollectionType; @@ -43,15 +45,18 @@ abstract class AbstractCollectionConverter implements ConversionExecutor { if (sourceElementType != null && targetElementType != null) { ConversionExecutor executor = conversionService.getConversionExecutor(sourceElementType, TypeDescriptor.valueOf(targetElementType)); if (executor != null) { - elementConverter = executor; - } else { - elementConverter = NoOpConversionExecutor.INSTANCE; + this.elementConverter = executor; } - } else { - elementConverter = NoOpConversionExecutor.INSTANCE; + else { + this.elementConverter = NoOpConversionExecutor.INSTANCE; + } + } + else { + this.elementConverter = NoOpConversionExecutor.INSTANCE; } } + /** * The collection type to convert to. */ @@ -63,11 +68,11 @@ abstract class AbstractCollectionConverter implements ConversionExecutor { * The type of elements in the target collection. */ protected Class getTargetElementType() { - return targetCollectionType.getElementType(); + return this.targetCollectionType.getElementType(); } - protected GenericTypeConverter getConversionService() { - return conversionService; + protected GenericConversionService getConversionService() { + return this.conversionService; } /** @@ -75,20 +80,23 @@ abstract class AbstractCollectionConverter implements ConversionExecutor { * Returns {@link NoOpConversionExecutor#INSTANCE} if no converter could be eagerly resolved from type descriptor metadata. */ protected ConversionExecutor getElementConverter() { - return elementConverter; + return this.elementConverter; } + public Object execute(Object source) { try { return doExecute(source); - } catch (Exception e) { - throw new ConversionFailedException(source, sourceCollectionType.getType(), targetCollectionType.getType(), e); + } + catch (Exception ex) { + throw new ConversionFailedException(source, this.sourceCollectionType.getType(), this.targetCollectionType.getType(), ex); } } /** - * Override to perform collection conversion - * @param sourceCollection the source collection to convert from, an instance of sourceCollectionType, which must be either an array or java.util.Collection type + * Override to perform collection conversion. + * @param sourceCollection the source collection to convert from, an instance of sourceCollectionType, + * which must be either an array or java.util.Collection type. * @return the converted target collection, an instance of targetCollectionType * @throws Exception an exception occurred during the conversion */ diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToArray.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToArray.java index 4aa4d4b7f2d..24781309678 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToArray.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToArray.java @@ -1,12 +1,12 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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. @@ -17,20 +17,19 @@ package org.springframework.core.convert.support; import java.lang.reflect.Array; -import org.springframework.core.convert.TypeConverter; import org.springframework.core.convert.TypeDescriptor; /** * Special one-way converter that converts from a source array to a target array. Supports type conversion of the * individual array elements; for example, the ability to convert a String[] to an Integer[]. Mainly used internally by - * {@link TypeConverter} implementations. + * {@link org.springframework.core.convert.ConversionService} implementations. * @author Keith Donald * @since 3.0 */ @SuppressWarnings("unchecked") class ArrayToArray extends AbstractCollectionConverter { - public ArrayToArray(TypeDescriptor sourceArrayType, TypeDescriptor targetArrayType, GenericTypeConverter conversionService) { + public ArrayToArray(TypeDescriptor sourceArrayType, TypeDescriptor targetArrayType, GenericConversionService conversionService) { super(sourceArrayType, targetArrayType, conversionService); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToCollection.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToCollection.java index fffeefe2178..473c534cb81 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToCollection.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToCollection.java @@ -1,45 +1,47 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import java.lang.reflect.Array; import java.util.Collection; +import org.springframework.core.CollectionFactory; import org.springframework.core.convert.TypeDescriptor; /** * Special converter that converts from a source array to a target collection. Supports the selection of an * "approximate" collection implementation when a target collection interface such as List.class is * specified. Supports type conversion of array elements when a parameterized target collection type descriptor is provided. + * * @author Keith Donald * @since 3.0 */ -@SuppressWarnings("unchecked") class ArrayToCollection extends AbstractCollectionConverter { public ArrayToCollection(TypeDescriptor sourceArrayType, TypeDescriptor targetCollectionType, - GenericTypeConverter conversionService) { + GenericConversionService conversionService) { super(sourceArrayType, targetCollectionType, conversionService); } @Override + @SuppressWarnings("unchecked") protected Object doExecute(Object sourceArray) throws Exception { - Class implClass = ConversionUtils.getCollectionImpl((Class) getTargetCollectionType()); - Collection collection = (Collection) implClass.newInstance(); int length = Array.getLength(sourceArray); + Collection collection = CollectionFactory.createCollection(getTargetCollectionType(), length); ConversionExecutor elementConverter = getElementConverter(); for (int i = 0; i < length; i++) { collection.add(elementConverter.execute(Array.get(sourceArray, i))); @@ -47,4 +49,4 @@ class ArrayToCollection extends AbstractCollectionConverter { return collection; } -} \ No newline at end of file +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CharacterToNumberFactory.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CharacterToNumberFactory.java index 840430fedd6..6f492c974eb 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CharacterToNumberFactory.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CharacterToNumberFactory.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.converter.Converter; @@ -21,9 +22,10 @@ import org.springframework.util.NumberUtils; /** * Converts from a Character to any JDK-standard Number implementation. - *

- * Support Number classes including Byte, Short, Integer, Float, Double, Long, BigInteger, BigDecimal. This class + * + *

Support Number classes including Byte, Short, Integer, Float, Double, Long, BigInteger, BigDecimal. This class * delegates to {@link NumberUtils#convertNumberToTargetClass(Number, Class)} to perform the conversion. + * * @author Keith Donald * @since 3.0 * @see java.lang.Byte @@ -42,9 +44,10 @@ public class CharacterToNumberFactory implements ConverterFactory(targetType); } + private static class CharacterToNumber implements Converter { - private Class targetType; + private final Class targetType; public CharacterToNumber(Class targetType) { this.targetType = targetType; @@ -53,6 +56,6 @@ public class CharacterToNumberFactory implements ConverterFactory) getTargetCollectionType()); - Collection targetCollection = (Collection) implClass.newInstance(); + Collection targetCollection = CollectionFactory.createCollection(getTargetCollectionType(), sourceCollection.size()); ConversionExecutor elementConverter = getElementConverter(sourceCollection); - Iterator it = sourceCollection.iterator(); - while (it.hasNext()) { - targetCollection.add(elementConverter.execute(it.next())); + for (Object aSourceCollection : sourceCollection) { + targetCollection.add(elementConverter.execute(aSourceCollection)); } return targetCollection; } @@ -49,11 +48,10 @@ class CollectionToCollection extends AbstractCollectionConverter { private ConversionExecutor getElementConverter(Collection source) { ConversionExecutor elementConverter = getElementConverter(); if (elementConverter == NoOpConversionExecutor.INSTANCE && getTargetElementType() != null) { - Iterator it = source.iterator(); - while (it.hasNext()) { - Object value = it.next(); + for (Object value : source) { if (value != null) { - elementConverter = getConversionService().getConversionExecutor(value.getClass(), TypeDescriptor.valueOf(getTargetElementType())); + elementConverter = getConversionService().getConversionExecutor( + value.getClass(), TypeDescriptor.valueOf(getTargetElementType())); break; } } @@ -61,4 +59,4 @@ class CollectionToCollection extends AbstractCollectionConverter { return elementConverter; } -} \ No newline at end of file +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionExecutor.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionExecutor.java index 9de83747b2f..5a7f3cae4ed 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionExecutor.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionExecutor.java @@ -1,36 +1,38 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.ConversionFailedException; /** * A command parameterized with the information necessary to perform a conversion of a source input to a - * target output. Encapsulates knowledge about how to convert source objects to a specific target type using a specific - * converter. + * target output. Encapsulates knowledge about how to convert source objects to a specific target type + * using a specific converter. + * * @author Keith Donald * @since 3.0 */ -public interface ConversionExecutor { +interface ConversionExecutor { /** * Convert the source. * @param source the source to convert * @throws ConversionFailedException if an exception occurs during type conversion */ - public Object execute(Object source); + Object execute(Object source); } \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionUtils.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionUtils.java deleted file mode 100644 index 85666d1f534..00000000000 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionUtils.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2004-2009 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.core.convert.support; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.SortedSet; -import java.util.TreeMap; -import java.util.TreeSet; - -/** - * Conversion utility code shared by internal conversion executors in this package. - * @author Keith Donald - * @since 3.0 - */ -public class ConversionUtils { - - /** - * Get the java.util.Collection implementation class that should be used for the given target collection type. - * @param targetCollectionType the target collection type, may be an interface - * @return the collection impl to use - */ - @SuppressWarnings("unchecked") - public static Class getCollectionImpl(Class targetCollectionType) { - if (targetCollectionType.isInterface()) { - if (List.class.equals(targetCollectionType)) { - return ArrayList.class; - } else if (Set.class.equals(targetCollectionType)) { - return LinkedHashSet.class; - } else if (SortedSet.class.equals(targetCollectionType)) { - return TreeSet.class; - } else if (Collection.class.equals(targetCollectionType)) { - return ArrayList.class; - } else { - throw new IllegalArgumentException("Unsupported collection interface [" + targetCollectionType.getName() + "]"); - } - } else { - return targetCollectionType; - } - } - - /** - * Get the java.util.Map implementation class that should be used for the given target map type. - * @param targetMapType the target map type, may be an interface - * @return the map impl to use - */ - @SuppressWarnings("unchecked") - public static Class getMapImpl(Class targetMapType) { - if (targetMapType.isInterface()) { - if (Map.class.equals(targetMapType)) { - return HashMap.class; - } else if (SortedMap.class.equals(targetMapType)) { - return TreeMap.class; - } else { - throw new IllegalArgumentException("Unsupported Map interface [" + targetMapType.getName() + "]"); - } - } else { - return targetMapType; - } - } - -} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultTypeConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java similarity index 70% rename from org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultTypeConverter.java rename to org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java index c5fde2d7c10..c2649ac31e9 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultTypeConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java @@ -1,39 +1,34 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; /** - * Default implementation of a conversion service. Will automatically register from string converters for - * a number of standard Java types like Class, Number, Boolean and so on. + * Default implementation of a conversion service. Will automatically register from string + * converters for a number of standard Java types like Class, Number, Boolean and so on. + * * @author Keith Donald * @since 3.0 */ -public class DefaultTypeConverter extends GenericTypeConverter { +public class DefaultConversionService extends GenericConversionService { /** - * Creates a new default conversion service, installing the default converters. + * Create a new default conversion service, installing the default converters. */ - public DefaultTypeConverter() { - addDefaultConverters(); - } - - /** - * Add all default converters to the conversion service. - */ - protected void addDefaultConverters() { + public DefaultConversionService() { add(new StringToByte()); add(new StringToBoolean()); add(new StringToCharacter()); @@ -52,4 +47,4 @@ public class DefaultTypeConverter extends GenericTypeConverter { add(new CharacterToNumberFactory()); } -} \ No newline at end of file +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericTypeConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java similarity index 69% rename from org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericTypeConverter.java rename to org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java index adc644a05fa..f5a31241d36 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericTypeConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2008 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import java.lang.reflect.ParameterizedType; @@ -26,8 +27,8 @@ import java.util.List; import java.util.Map; import org.springframework.core.GenericTypeResolver; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConverterNotFoundException; -import org.springframework.core.convert.TypeConverter; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.ConverterFactory; @@ -38,58 +39,59 @@ import org.springframework.util.Assert; /** * Base implementation of a conversion service. * Initially empty, e.g. no converters are registered by default. + * * @author Keith Donald + * @author Juergen Hoeller + * @since 3.0 * @see #add(Converter) * @see #add(ConverterFactory) - * @since 3.0 */ -@SuppressWarnings("unchecked") -public class GenericTypeConverter implements TypeConverter, ConverterRegistry { +public class GenericConversionService implements ConversionService, ConverterRegistry { + + private ConversionService parent; /** - * An indexed map of Converters. Each Map.Entry key is a source class (S) that can be converted from. Each Map.Entry - * value is a Map that defines the targetType-to-Converter mappings for that source. + * An indexed map of Converters. Each Map.Entry key is a source class (S) that can be converted from. + * Each Map.Entry value is a Map that defines the targetType-to-Converter mappings for that source. */ - private final Map sourceTypeConverters = new HashMap(); + private final Map> sourceTypeConverters = new HashMap>(); - private TypeConverter parent; - - /** - * Returns the parent of this conversion service. Could be null. - */ - public TypeConverter getParent() { - return parent; - } /** * Set the parent of this conversion service. This is optional. */ - public void setParent(TypeConverter parent) { + public void setParent(ConversionService parent) { this.parent = parent; } + /** + * Returns the parent of this conversion service. Could be null. + */ + public ConversionService getParent() { + return this.parent; + } + + // implementing ConverterRegistry public void add(Converter converter) { - List typeInfo = getRequiredTypeInfo(converter); + List typeInfo = getRequiredTypeInfo(converter); if (typeInfo == null) { throw new IllegalArgumentException("Unable to the determine sourceType and targetType your Converter converts between"); } - Class sourceType = (Class) typeInfo.get(0); - Class targetType = (Class) typeInfo.get(1); - Map sourceMap = getSourceMap(sourceType); - sourceMap.put(targetType, converter); + Class sourceType = typeInfo.get(0); + Class targetType = typeInfo.get(1); + getSourceMap(sourceType).put(targetType, converter); } public void add(ConverterFactory converterFactory) { - List typeInfo = getRequiredTypeInfo(converterFactory); + List typeInfo = getRequiredTypeInfo(converterFactory); if (typeInfo == null) { throw new IllegalArgumentException("Unable to the determine sourceType and targetType your ConverterFactory creates Converters to convert between"); } - Class sourceType = (Class) typeInfo.get(0); - Class targetType = (Class) typeInfo.get(1); - Map sourceMap = getSourceMap(sourceType); - sourceMap.put(targetType, converterFactory); + Class sourceType = typeInfo.get(0); + Class targetType = typeInfo.get(1); + getSourceMap(sourceType).put(targetType, converterFactory); } public void removeConverter(Class sourceType, Class targetType) { @@ -108,40 +110,45 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { } } - // implementing TypeConverter + // implementing ConversionService public boolean canConvert(Class sourceType, Class targetType) { return canConvert(sourceType, TypeDescriptor.valueOf(targetType)); } - public boolean canConvert(Class sourceType, TypeDescriptor targetType) { + public boolean canConvert(Class sourceType, TypeDescriptor targetType) { ConversionExecutor executor = getConversionExecutor(sourceType, targetType); if (executor != null) { return true; - } else { + } + else { if (parent != null) { return parent.canConvert(sourceType, targetType); - } else { + } + else { return false; } } } - public T convert(S source, Class targetType) { - return convert(source, TypeDescriptor.valueOf(targetType)); + @SuppressWarnings("unchecked") + public T convert(Object source, Class targetType) { + return (T) convert(source, TypeDescriptor.valueOf(targetType)); } - public T convert(S source, TypeDescriptor targetType) { + public Object convert(Object source, TypeDescriptor targetType) { if (source == null) { return null; } ConversionExecutor executor = getConversionExecutor(source.getClass(), targetType); if (executor != null) { - return (T) executor.execute(source); - } else { - if (parent != null) { - return parent.convert(source, targetType); - } else { + return executor.execute(source); + } + else { + if (this.parent != null) { + return this.parent.convert(source, targetType); + } + else { throw new ConverterNotFoundException(source.getClass(), targetType.getType(), "No converter found that can convert from sourceType [" + source.getClass().getName() + "] to targetType [" + targetType.getName() + "]"); @@ -149,8 +156,9 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { } } - ConversionExecutor getConversionExecutor(Class sourceClass, TypeDescriptor targetType) + ConversionExecutor getConversionExecutor(Class sourceClass, TypeDescriptor targetType) throws ConverterNotFoundException { + Assert.notNull(sourceClass, "The sourceType to convert from is required"); Assert.notNull(targetType, "The targetType to convert to is required"); if (targetType.getType() == null) { @@ -161,25 +169,30 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { if (sourceType.isArray()) { if (targetType.isArray()) { return new ArrayToArray(sourceType, targetType, this); - } else if (targetType.isCollection()) { + } + else if (targetType.isCollection()) { if (targetType.isAbstractClass()) { throw new IllegalArgumentException("Conversion target class [" + targetType.getName() + "] is invalid; cannot convert to abstract collection types--" + "request an interface or concrete implementation instead"); } return new ArrayToCollection(sourceType, targetType, this); - } else if (targetType.isMap()) { + } + else if (targetType.isMap()) { if (sourceType.getElementType().equals(String.class)) { return new StringArrayToMap(sourceType, targetType, this); - } else { + } + else { // array to map return null; } - } else { - if (targetType.equals(String.class)) { - // array to string; + } + else { + if (targetType.getType().equals(String.class)) { + // array to string return null; - } else { + } + else { // array to object return null; } @@ -188,20 +201,24 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { if (sourceType.isCollection()) { if (targetType.isCollection()) { return new CollectionToCollection(sourceType, targetType, this); - } else if (targetType.isArray()) { + } + else if (targetType.isArray()) { return new CollectionToArray(sourceType, targetType, this); - } else if (targetType.isMap()) { + } + else if (targetType.isMap()) { if (sourceType.getElementType().equals(String.class)) { return new StringCollectionToMap(sourceType, targetType, this); } else { // object collection to map return null; } - } else { - if (targetType.equals(String.class)) { + } + else { + if (targetType.getType().equals(String.class)) { // collection to string; return null; - } else { + } + else { // collection to object return null; } @@ -210,21 +227,26 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { if (sourceType.isMap()) { if (targetType.isMap()) { return new MapToMap(sourceType, targetType, this); - } else if (targetType.isArray()) { + } + else if (targetType.isArray()) { if (targetType.getElementType().equals(String.class)) { - return new MapToStringArray(sourceType, targetType, this); - } else { + return new MapToStringArray(targetType, this); + } + else { // map to object array return null; } - } else if (targetType.isCollection()) { + } + else if (targetType.isCollection()) { if (targetType.getElementType().equals(String.class)) { - return new MapToStringCollection(sourceType, targetType, this); - } else { + return new MapToStringCollection(targetType, this); + } + else { // map to object collection return null; } - } else { + } + else { // map to object return null; } @@ -232,21 +254,24 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { if (targetType.isArray()) { if (sourceType.getType().equals(String.class)) { return new StringToArray(sourceType, targetType, this); - } else { + } + else { return new ObjectToArray(sourceType, targetType, this); } } if (targetType.isCollection()) { if (sourceType.getType().equals(String.class)) { return new StringToCollection(sourceType, targetType, this); - } else { + } + else { return new ObjectToCollection(sourceType, targetType, this); } } if (targetType.isMap()) { if (sourceType.getType().equals(String.class)) { return new StringToMap(sourceType, targetType, this); - } else { + } + else { // object to map return null; } @@ -257,26 +282,29 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { Converter converter = findRegisteredConverter(sourceType.getType(), targetType.getType()); if (converter != null) { return new StaticConversionExecutor(sourceType, targetType, converter); - } else { + } + else { return null; } } - + + // internal helpers - private List getRequiredTypeInfo(Object converter) { - List typeInfo = new ArrayList(2); + private List getRequiredTypeInfo(Object converter) { + List typeInfo = new ArrayList(2); if (converter instanceof ConverterInfo) { ConverterInfo info = (ConverterInfo) converter; typeInfo.add(info.getSourceType()); typeInfo.add(info.getTargetType()); return typeInfo; - } else { + } + else { return getConverterTypeInfo(converter.getClass()); } } - private List getConverterTypeInfo(Class converterClass) { + private List getConverterTypeInfo(Class converterClass) { Class classToIntrospect = converterClass; while (classToIntrospect != null) { Type[] ifcs = classToIntrospect.getGenericInterfaces(); @@ -285,7 +313,7 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { ParameterizedType paramIfc = (ParameterizedType) ifc; Type rawType = paramIfc.getRawType(); if (Converter.class.equals(rawType) || ConverterFactory.class.equals(rawType)) { - List typeInfo = new ArrayList(2); + List typeInfo = new ArrayList(2); Type arg1 = paramIfc.getActualTypeArguments()[0]; if (arg1 instanceof TypeVariable) { arg1 = GenericTypeResolver.resolveTypeVariable((TypeVariable) arg1, converterClass); @@ -317,10 +345,10 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { return null; } - private Map getSourceMap(Class sourceType) { - Map sourceMap = (Map) sourceTypeConverters.get(sourceType); + private Map getSourceMap(Class sourceType) { + Map sourceMap = sourceTypeConverters.get(sourceType); if (sourceMap == null) { - sourceMap = new HashMap(); + sourceMap = new HashMap(); sourceTypeConverters.put(sourceType, sourceMap); } return sourceMap; @@ -328,29 +356,30 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { private Converter findRegisteredConverter(Class sourceType, Class targetType) { if (sourceType.isInterface()) { - LinkedList classQueue = new LinkedList(); + LinkedList classQueue = new LinkedList(); classQueue.addFirst(sourceType); while (!classQueue.isEmpty()) { - Class currentClass = (Class) classQueue.removeLast(); - Map converters = getConvertersForSource(currentClass); + Class currentClass = classQueue.removeLast(); + Map converters = getConvertersForSource(currentClass); System.out.println("Source:" + currentClass); Converter converter = getConverter(converters, targetType); if (converter != null) { return converter; } Class[] interfaces = currentClass.getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - classQueue.addFirst(interfaces[i]); + for (Class ifc : interfaces) { + classQueue.addFirst(ifc); } } - Map objectConverters = getConvertersForSource(Object.class); + Map objectConverters = getConvertersForSource(Object.class); return getConverter(objectConverters, targetType); - } else { - LinkedList classQueue = new LinkedList(); + } + else { + LinkedList classQueue = new LinkedList(); classQueue.addFirst(sourceType); while (!classQueue.isEmpty()) { - Class currentClass = (Class) classQueue.removeLast(); - Map converters = getConvertersForSource(currentClass); + Class currentClass = classQueue.removeLast(); + Map converters = getConvertersForSource(currentClass); Converter converter = getConverter(converters, targetType); if (converter != null) { return converter; @@ -359,41 +388,45 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { classQueue.addFirst(currentClass.getSuperclass()); } Class[] interfaces = currentClass.getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - classQueue.addFirst(interfaces[i]); + for (Class ifc : interfaces) { + classQueue.addFirst(ifc); } } return null; } } - private Map getConvertersForSource(Class sourceType) { - Map converters = (Map) sourceTypeConverters.get(sourceType); - return converters != null ? converters : Collections.emptyMap(); + private Map getConvertersForSource(Class sourceType) { + Map converters = this.sourceTypeConverters.get(sourceType); + if (converters == null) { + converters = Collections.emptyMap(); + } + return converters; } - private Converter getConverter(Map converters, Class targetType) { + private Converter getConverter(Map converters, Class targetType) { if (targetType.isInterface()) { - LinkedList classQueue = new LinkedList(); + LinkedList classQueue = new LinkedList(); classQueue.addFirst(targetType); while (!classQueue.isEmpty()) { - Class currentClass = (Class) classQueue.removeLast(); - Converter converter = getConverterImpl(converters, currentClass, targetType); + Class currentClass = classQueue.removeLast(); + Converter converter = getConverter(converters, currentClass, targetType); if (converter != null) { return converter; } Class[] interfaces = currentClass.getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - classQueue.addFirst(interfaces[i]); + for (Class ifc : interfaces) { + classQueue.addFirst(ifc); } } - return getConverterImpl(converters, Object.class, targetType); - } else { - LinkedList classQueue = new LinkedList(); + return getConverter(converters, Object.class, targetType); + } + else { + LinkedList classQueue = new LinkedList(); classQueue.addFirst(targetType); while (!classQueue.isEmpty()) { - Class currentClass = (Class) classQueue.removeLast(); - Converter converter = getConverterImpl(converters, currentClass, targetType); + Class currentClass = classQueue.removeLast(); + Converter converter = getConverter(converters, currentClass, targetType); if (converter != null) { return converter; } @@ -401,22 +434,24 @@ public class GenericTypeConverter implements TypeConverter, ConverterRegistry { classQueue.addFirst(currentClass.getSuperclass()); } Class[] interfaces = currentClass.getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - classQueue.addFirst(interfaces[i]); + for (Class ifc : interfaces) { + classQueue.addFirst(ifc); } } return null; } } - - private Converter getConverterImpl(Map converters, Class currentClass, Class targetType) { + + @SuppressWarnings("unchecked") + private Converter getConverter(Map converters, Class currentClass, Class targetType) { Object converter = converters.get(currentClass); if (converter == null) { return null; } if (converter instanceof Converter) { return (Converter) converter; - } else { + } + else { return ((ConverterFactory) converter).getConverter(targetType); } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapEntryConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapEntryConverter.java index f443b43502e..7430e6938a7 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapEntryConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapEntryConverter.java @@ -1,57 +1,59 @@ /* - * Copyright 2004-2008 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; /** * A helper for convertering map keys and values. + * * @author Keith Donald * @since 3.0 */ class MapEntryConverter { - public static final MapEntryConverter NO_OP_INSTANCE = new MapEntryConverter(); + public static final MapEntryConverter NO_OP_INSTANCE = new MapEntryConverter(null, null); - private ConversionExecutor keyConverter; - private ConversionExecutor valueConverter; + private final ConversionExecutor keyConverter; + + private final ConversionExecutor valueConverter; + public MapEntryConverter(ConversionExecutor keyConverter, ConversionExecutor valueConverter) { this.keyConverter = keyConverter; this.valueConverter = valueConverter; } + public Object convertKey(Object key) { - if (keyConverter != null) { - return keyConverter.execute(key); - } else { + if (this.keyConverter != null) { + return this.keyConverter.execute(key); + } + else { return key; } } public Object convertValue(Object value) { - if (valueConverter != null) { - return valueConverter.execute(value); - } else { + if (this.valueConverter != null) { + return this.valueConverter.execute(value); + } + else { return value; } } - - // internal - - private MapEntryConverter() { - } -} \ No newline at end of file +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToMap.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToMap.java index 4cf352ef97b..8381b09bfab 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToMap.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToMap.java @@ -1,41 +1,44 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; -import java.util.Iterator; import java.util.Map; +import org.springframework.core.CollectionFactory; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.TypeDescriptor; /** - * Converts from one map to another map, with support for converting individual map elements based on generic type information. + * Converts from one map to another map, with support for converting individual map elements + * based on generic type information. + * * @author Keith Donald * @since 3.0 */ -@SuppressWarnings("unchecked") class MapToMap implements ConversionExecutor { - private TypeDescriptor sourceType; + private final TypeDescriptor sourceType; - private TypeDescriptor targetType; + private final TypeDescriptor targetType; - private GenericTypeConverter conversionService; + private final GenericConversionService conversionService; + + private final MapEntryConverter entryConverter; - private MapEntryConverter entryConverter; /** * Creates a new map-to-map converter @@ -43,38 +46,40 @@ class MapToMap implements ConversionExecutor { * @param targetType the target map type * @param conversionService the conversion service */ - public MapToMap(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + public MapToMap(TypeDescriptor sourceType, TypeDescriptor targetType, GenericConversionService conversionService) { this.sourceType = sourceType; this.targetType = targetType; this.conversionService = conversionService; this.entryConverter = createEntryConverter(); } + private MapEntryConverter createEntryConverter() { - if (sourceType.isMapEntryTypeKnown() && targetType.isMapEntryTypeKnown()) { - ConversionExecutor keyConverter = conversionService.getConversionExecutor(sourceType.getMapKeyType(), - TypeDescriptor.valueOf(targetType.getMapKeyType())); - ConversionExecutor valueConverter = conversionService.getConversionExecutor(sourceType.getMapValueType(), - TypeDescriptor.valueOf(targetType.getMapValueType())); + if (this.sourceType.isMapEntryTypeKnown() && this.targetType.isMapEntryTypeKnown()) { + ConversionExecutor keyConverter = this.conversionService.getConversionExecutor( + this.sourceType.getMapKeyType(), TypeDescriptor.valueOf(this.targetType.getMapKeyType())); + ConversionExecutor valueConverter = this.conversionService.getConversionExecutor( + this.sourceType.getMapValueType(), TypeDescriptor.valueOf(this.targetType.getMapValueType())); return new MapEntryConverter(keyConverter, valueConverter); - } else { + } + else { return MapEntryConverter.NO_OP_INSTANCE; } } + @SuppressWarnings("unchecked") public Object execute(Object source) throws ConversionFailedException { try { - Map map = (Map) source; - Map targetMap = (Map) ConversionUtils.getMapImpl(targetType.getType()).newInstance(); + Map map = (Map) source; + Map targetMap = CollectionFactory.createMap(this.targetType.getType(), map.size()); MapEntryConverter converter = getEntryConverter(map); - Iterator> it = map.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); + for (Map.Entry entry : map.entrySet()) { targetMap.put(converter.convertKey(entry.getKey()), converter.convertValue(entry.getValue())); } return targetMap; - } catch (Exception e) { - throw new ConversionFailedException(source, sourceType.getType(), targetType.getType(), e); + } + catch (Exception ex) { + throw new ConversionFailedException(source, this.sourceType.getType(), this.targetType.getType(), ex); } } @@ -86,18 +91,16 @@ class MapToMap implements ConversionExecutor { if (targetKeyType != null && targetValueType != null) { ConversionExecutor keyConverter = null; ConversionExecutor valueConverter = null; - Iterator it = map.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); + for (Map.Entry entry : map.entrySet()) { Object key = entry.getKey(); Object value = entry.getValue(); if (keyConverter == null && key != null) { - keyConverter = conversionService.getConversionExecutor(key.getClass(), TypeDescriptor - .valueOf(targetKeyType)); + keyConverter = conversionService + .getConversionExecutor(key.getClass(), TypeDescriptor.valueOf(targetKeyType)); } if (valueConverter == null && value != null) { - valueConverter = conversionService.getConversionExecutor(value.getClass(), TypeDescriptor - .valueOf(targetValueType)); + valueConverter = conversionService + .getConversionExecutor(value.getClass(), TypeDescriptor.valueOf(targetValueType)); } if (keyConverter != null && valueConverter != null) { break; diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringArray.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringArray.java index c11aee6f19a..427b11a4331 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringArray.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringArray.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import java.lang.reflect.Array; @@ -24,45 +25,48 @@ import org.springframework.core.convert.TypeDescriptor; /** * Converts a Map to a String array, where each element in the array * is of the format key=value. + * * @author Keith Donald * @since 3.0 */ -@SuppressWarnings("unchecked") class MapToStringArray implements ConversionExecutor { - private TypeDescriptor targetType; + private final TypeDescriptor targetType; - private GenericTypeConverter conversionService; + private final GenericConversionService conversionService; - private MapEntryConverter entryConverter; + private final MapEntryConverter entryConverter; - public MapToStringArray(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + + public MapToStringArray(TypeDescriptor targetType, GenericConversionService conversionService) { this.targetType = targetType; this.conversionService = conversionService; this.entryConverter = createEntryConverter(); } + private MapEntryConverter createEntryConverter() { - if (targetType.isMapEntryTypeKnown()) { - ConversionExecutor keyConverter = conversionService.getConversionExecutor(targetType.getMapKeyType(), + if (this.targetType.isMapEntryTypeKnown()) { + ConversionExecutor keyConverter = this.conversionService.getConversionExecutor(this.targetType.getMapKeyType(), TypeDescriptor.valueOf(String.class)); - ConversionExecutor valueConverter = conversionService.getConversionExecutor(targetType.getMapValueType(), + ConversionExecutor valueConverter = this.conversionService.getConversionExecutor(this.targetType.getMapValueType(), TypeDescriptor.valueOf(String.class)); return new MapEntryConverter(keyConverter, valueConverter); - } else { + } + else { return MapEntryConverter.NO_OP_INSTANCE; } } public Object execute(Object source) throws ConversionFailedException { Map sourceMap = (Map) source; - Object array = Array.newInstance(targetType.getElementType(), sourceMap.size()); + Object array = Array.newInstance(this.targetType.getElementType(), sourceMap.size()); int i = 0; for (Object entry : sourceMap.entrySet()) { Map.Entry mapEntry = (Map.Entry) entry; Object key = mapEntry.getKey(); Object value = mapEntry.getValue(); - String property = entryConverter.convertKey(key) + "=" + entryConverter.convertValue(value); + String property = this.entryConverter.convertKey(key) + "=" + this.entryConverter.convertValue(value); Array.set(array, i, property); i++; } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringCollection.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringCollection.java index f44bfbf3616..3409c797bcb 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringCollection.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringCollection.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import java.util.Map; @@ -23,25 +24,27 @@ import org.springframework.core.convert.TypeDescriptor; /** * Converts a Map to a String collection, where each element in the collection * is of the format key=value. + * * @author Keith Donald * @since 3.0 */ -@SuppressWarnings("unchecked") class MapToStringCollection implements ConversionExecutor { - private MapToStringArray converter; + private final MapToStringArray converter; - private ArrayToCollection collectionConverter; + private final ArrayToCollection collectionConverter; - public MapToStringCollection(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { - converter = new MapToStringArray(sourceType, targetType, conversionService); - collectionConverter = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), targetType, conversionService); + + public MapToStringCollection(TypeDescriptor targetType, GenericConversionService conversionService) { + this.converter = new MapToStringArray(targetType, conversionService); + this.collectionConverter = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), targetType, conversionService); } + public Object execute(Object source) throws ConversionFailedException { Map map = (Map) source; - Object array = converter.execute(map); - return collectionConverter.execute(array); + Object array = this.converter.execute(map); + return this.collectionConverter.execute(array); } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/NoOpConversionExecutor.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/NoOpConversionExecutor.java index c1a62f9535b..8a64f2ba023 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/NoOpConversionExecutor.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/NoOpConversionExecutor.java @@ -1,12 +1,12 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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. @@ -20,18 +20,21 @@ import org.springframework.core.convert.ConversionFailedException; /** * Conversion executor that does nothing. * Access singleton using {@link #INSTANCE}. + * + * @author Keith Donald * @since 3.0 */ class NoOpConversionExecutor implements ConversionExecutor { public static final ConversionExecutor INSTANCE = new NoOpConversionExecutor(); + + private NoOpConversionExecutor() { + } + public Object execute(Object source) throws ConversionFailedException { // does nothing return source; } - private NoOpConversionExecutor() { - } - -} \ No newline at end of file +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/NumberToCharacter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/NumberToCharacter.java index db6657c11bb..1e8693f075d 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/NumberToCharacter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/NumberToCharacter.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.converter.Converter; @@ -20,7 +21,9 @@ import org.springframework.util.NumberUtils; /** * Converts from any JDK-standard Number implementation to a Character. + * * @author Keith Donald + * @since 3.0 * @see java.lang.Character * @see java.lang.Short * @see java.lang.Integer @@ -30,10 +33,11 @@ import org.springframework.util.NumberUtils; * @see java.lang.Double * @see java.math.BigDecimal * @see NumberUtils - * @since 3.0 */ public class NumberToCharacter implements Converter { + public Character convert(Number source) { - return Character.valueOf((char) source.shortValue()); + return (char) source.shortValue(); } -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/NumberToNumberFactory.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/NumberToNumberFactory.java index 979edde49f0..bce1848c85d 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/NumberToNumberFactory.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/NumberToNumberFactory.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.converter.Converter; @@ -21,10 +22,12 @@ import org.springframework.util.NumberUtils; /** * Converts from any JDK-standard Number implementation to any other JDK-standard Number implementation. - *

- * Support Number classes including Byte, Short, Integer, Float, Double, Long, BigInteger, BigDecimal. This class + * + *

Support Number classes including Byte, Short, Integer, Float, Double, Long, BigInteger, BigDecimal. This class * delegates to {@link NumberUtils#convertNumberToTargetClass(Number, Class)} to perform the conversion. + * * @author Keith Donald + * @since 3.0 * @see java.lang.Byte * @see java.lang.Short * @see java.lang.Integer @@ -34,7 +37,6 @@ import org.springframework.util.NumberUtils; * @see java.lang.Double * @see java.math.BigDecimal * @see NumberUtils - * @since 3.0 */ public class NumberToNumberFactory implements ConverterFactory { @@ -42,9 +44,10 @@ public class NumberToNumberFactory implements ConverterFactory { return new NumberToNumber(targetType); } + private static class NumberToNumber implements Converter { - private Class targetType; + private final Class targetType; public NumberToNumber(Class targetType) { this.targetType = targetType; @@ -53,6 +56,6 @@ public class NumberToNumberFactory implements ConverterFactory { public T convert(Number source) throws Exception { return NumberUtils.convertNumberToTargetClass(source, targetType); } - } -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArray.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArray.java index cb15f9ae45d..3bc1baec150 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArray.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArray.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import java.lang.reflect.Array; @@ -23,22 +24,26 @@ import org.springframework.core.convert.TypeDescriptor; /** * Converts an object to a single-element array. * TODO - this class throws cryptic exception if it can't convert to required target array element type. + * * @author Keith Donald * @since 3.0 */ -@SuppressWarnings("unchecked") class ObjectToArray implements ConversionExecutor { - private TypeDescriptor targetArrayType; + private final TypeDescriptor targetArrayType; - private ConversionExecutor elementConverter; + private final ConversionExecutor elementConverter; + public ObjectToArray(TypeDescriptor sourceObjectType, TypeDescriptor targetArrayType, - GenericTypeConverter conversionService) { + GenericConversionService conversionService) { + this.targetArrayType = targetArrayType; - this.elementConverter = conversionService.getConversionExecutor(sourceObjectType.getType(), TypeDescriptor.valueOf(targetArrayType.getElementType())); + this.elementConverter = conversionService.getConversionExecutor( + sourceObjectType.getType(), TypeDescriptor.valueOf(targetArrayType.getElementType())); } + public Object execute(Object source) throws ConversionFailedException { Object array = Array.newInstance(targetArrayType.getElementType(), 1); Object element = elementConverter.execute(source); diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollection.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollection.java index 9cec59f2792..983147d1392 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollection.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollection.java @@ -1,69 +1,58 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import java.util.Collection; +import org.springframework.core.CollectionFactory; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.TypeDescriptor; /** * Converts an object to a single-element collection. + * * @author Keith Donald * @since 3.0 */ -@SuppressWarnings("unchecked") class ObjectToCollection implements ConversionExecutor { - private TypeDescriptor sourceObjectType; - - private TypeDescriptor targetCollectionType; + private final TypeDescriptor targetCollectionType; - private GenericTypeConverter typeConverter; - - private ConversionExecutor elementConverter; + private final ConversionExecutor elementConverter; + public ObjectToCollection(TypeDescriptor sourceObjectType, TypeDescriptor targetCollectionType, - GenericTypeConverter typeConverter) { - this.sourceObjectType = sourceObjectType; + GenericConversionService typeConverter) { + this.targetCollectionType = targetCollectionType; - this.typeConverter = typeConverter; - initElementConverter(); - } - - public Object execute(Object source) throws ConversionFailedException { - Class implClass = ConversionUtils.getCollectionImpl(targetCollectionType.getType()); - Collection collection; - try { - collection = (Collection) implClass.newInstance(); - } catch (InstantiationException e) { - throw new ConversionFailedException(source, sourceObjectType.getType(), targetCollectionType.getType(), e); - } catch (IllegalAccessException e) { - throw new ConversionFailedException(source, sourceObjectType.getType(), targetCollectionType.getType(), e); - } - collection.add(elementConverter.execute(source)); - return collection; - } - - private void initElementConverter() { Class elementType = targetCollectionType.getElementType(); - if (elementType != null) { + if (elementType != null) { this.elementConverter = typeConverter.getConversionExecutor(sourceObjectType.getType(), TypeDescriptor.valueOf(elementType)); - } else { + } + else { this.elementConverter = NoOpConversionExecutor.INSTANCE; } } -} \ No newline at end of file + + @SuppressWarnings("unchecked") + public Object execute(Object source) throws ConversionFailedException { + Collection collection = CollectionFactory.createCollection(this.targetCollectionType.getType(), 1); + collection.add(this.elementConverter.execute(source)); + return collection; + } + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToString.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToString.java index e6c7074d830..85c0de3f67e 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToString.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToString.java @@ -1,30 +1,35 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.converter.Converter; /** * Simply calls {@link Object#toString()} to convert any object to a string. - * Used by the {@link DefaultTypeConverter} as a fallback if there are no other explicit to string converters registered. + * Used by the {@link DefaultConversionService} as a fallback if there are + * no other explicit to string converters registered. + * * @author Keith Donald * @since 3.0 */ public class ObjectToString implements Converter { + public String convert(Object source) { return source.toString(); } + } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StaticConversionExecutor.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StaticConversionExecutor.java index 2622043d2aa..758cae744cf 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StaticConversionExecutor.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StaticConversionExecutor.java @@ -1,31 +1,31 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; -import org.springframework.core.style.ToStringCreator; /** * Default conversion executor implementation for converters. + * * @author Keith Donald * @since 3.0 */ -@SuppressWarnings("unchecked") class StaticConversionExecutor implements ConversionExecutor { private final TypeDescriptor sourceType; @@ -34,41 +34,44 @@ class StaticConversionExecutor implements ConversionExecutor { private final Converter converter; + public StaticConversionExecutor(TypeDescriptor sourceType, TypeDescriptor targetType, Converter converter) { this.sourceType = sourceType; this.targetType = targetType; this.converter = converter; } + + @SuppressWarnings("unchecked") public Object execute(Object source) throws ConversionFailedException { if (source == null) { return null; } - if (sourceType != null && !sourceType.isInstance(source)) { + if (!this.sourceType.isInstance(source)) { throw new ConversionFailedException(source, sourceType.getType(), targetType.getType(), "Source object " + source + " to convert is expected to be an instance of [" + sourceType.getName() + "]"); } try { - return converter.convert(source); - } catch (Exception e) { - throw new ConversionFailedException(source, sourceType.getType(), targetType.getType(), e); + return this.converter.convert(source); + } + catch (Exception ex) { + throw new ConversionFailedException(source, sourceType.getType(), targetType.getType(), ex); } } - public boolean equals(Object o) { - if (!(o instanceof StaticConversionExecutor)) { + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof StaticConversionExecutor)) { return false; } - StaticConversionExecutor other = (StaticConversionExecutor) o; - return sourceType.equals(other.sourceType) && targetType.equals(other.targetType); + StaticConversionExecutor other = (StaticConversionExecutor) obj; + return this.sourceType.equals(other.sourceType) && this.targetType.equals(other.targetType); } public int hashCode() { - return sourceType.hashCode() + targetType.hashCode(); + return this.sourceType.hashCode() + this.targetType.hashCode(); } - public String toString() { - return new ToStringCreator(this).append("sourceClass", sourceType).append("targetClass", targetType) - .toString(); - } -} \ No newline at end of file +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringArrayToMap.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringArrayToMap.java index 49762688560..e8449af7b67 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringArrayToMap.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringArrayToMap.java @@ -1,76 +1,86 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import java.lang.reflect.Array; import java.util.Map; +import org.springframework.core.CollectionFactory; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.TypeDescriptor; /** * Converts a String array to a Map. * Each element in the array must be formatted as key=value. + * * @author Keith Donald * @since 3.0 */ -@SuppressWarnings("unchecked") class StringArrayToMap implements ConversionExecutor { - private TypeDescriptor sourceType; + private final TypeDescriptor sourceType; - private TypeDescriptor targetType; + private final TypeDescriptor targetType; - private GenericTypeConverter conversionService; + private final GenericConversionService conversionService; - private MapEntryConverter entryConverter; + private final MapEntryConverter entryConverter; - public StringArrayToMap(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + + public StringArrayToMap(TypeDescriptor sourceType, TypeDescriptor targetType, GenericConversionService conversionService) { this.sourceType = sourceType; this.targetType = targetType; this.conversionService = conversionService; this.entryConverter = createEntryConverter(); } + private MapEntryConverter createEntryConverter() { - if (targetType.isMapEntryTypeKnown()) { - ConversionExecutor keyConverter = conversionService.getConversionExecutor(String.class, - TypeDescriptor.valueOf(targetType.getMapKeyType())); - ConversionExecutor valueConverter = conversionService.getConversionExecutor(String.class, - TypeDescriptor.valueOf(targetType.getMapValueType())); + if (this.targetType.isMapEntryTypeKnown()) { + ConversionExecutor keyConverter = this.conversionService.getConversionExecutor(String.class, + TypeDescriptor.valueOf(this.targetType.getMapKeyType())); + ConversionExecutor valueConverter = this.conversionService.getConversionExecutor(String.class, + TypeDescriptor.valueOf(this.targetType.getMapValueType())); return new MapEntryConverter(keyConverter, valueConverter); - } else { + } + else { return MapEntryConverter.NO_OP_INSTANCE; } } + @SuppressWarnings("unchecked") public Object execute(Object source) throws ConversionFailedException { try { - Map targetMap = (Map) ConversionUtils.getMapImpl(targetType.getType()).newInstance(); int length = Array.getLength(source); + Map targetMap = CollectionFactory.createMap(this.targetType.getType(), length); for (int i = 0; i < length; i++) { String property = (String) Array.get(source, i); String[] fields = property.split("="); + if (fields.length < 2) { + throw new IllegalArgumentException("Invalid String property: " + property); + } String key = fields[0]; String value = fields[1]; - targetMap.put(entryConverter.convertKey(key), entryConverter.convertValue(value)); + targetMap.put(this.entryConverter.convertKey(key), this.entryConverter.convertValue(value)); } return targetMap; - } catch (Exception e) { - throw new ConversionFailedException(source, sourceType.getType(), targetType.getType(), e); + } + catch (Exception ex) { + throw new ConversionFailedException(source, this.sourceType.getType(), this.targetType.getType(), ex); } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringCollectionToMap.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringCollectionToMap.java index 594bdd96d15..48b4f6ead93 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringCollectionToMap.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringCollectionToMap.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import java.util.Collection; @@ -23,6 +24,7 @@ import org.springframework.core.convert.TypeDescriptor; /** * Converts a String collection to a Map. * Each element in the collection must be formatted as key=value. + * * @author Keith Donald * @since 3.0 */ @@ -31,7 +33,7 @@ class StringCollectionToMap implements ConversionExecutor { private StringArrayToMap converter; - public StringCollectionToMap(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + public StringCollectionToMap(TypeDescriptor sourceType, TypeDescriptor targetType, GenericConversionService conversionService) { converter = new StringArrayToMap(sourceType, targetType, conversionService); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArray.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArray.java index fad8d5d57cb..f55b9180e80 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArray.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArray.java @@ -1,24 +1,26 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.TypeDescriptor; /** * Converts a comma-delimited string to an array. + * * @author Keith Donald * @since 3.0 */ @@ -27,7 +29,7 @@ class StringToArray implements ConversionExecutor { private ArrayToArray converter; - public StringToArray(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + public StringToArray(TypeDescriptor sourceType, TypeDescriptor targetType, GenericConversionService conversionService) { converter = new ArrayToArray(TypeDescriptor.valueOf(String[].class), targetType, conversionService); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBigDecimal.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBigDecimal.java index 27eda24d062..16b8c88e781 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBigDecimal.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBigDecimal.java @@ -1,12 +1,12 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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. @@ -18,14 +18,18 @@ package org.springframework.core.convert.support; import java.math.BigDecimal; import org.springframework.core.convert.converter.Converter; +import org.springframework.util.NumberUtils; /** - * Converts a String to a BigDecimal using {@link BigDecimal#BigDecimal(String). + * Converts a String to a BigDecimal. + * * @author Keith Donald * @since 3.0 */ public class StringToBigDecimal implements Converter { + public BigDecimal convert(String source) { - return new BigDecimal(source); + return NumberUtils.parseNumber(source, BigDecimal.class); } + } \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBigInteger.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBigInteger.java index d3cae701897..c3e58478b61 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBigInteger.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBigInteger.java @@ -1,12 +1,12 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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. @@ -18,14 +18,18 @@ package org.springframework.core.convert.support; import java.math.BigInteger; import org.springframework.core.convert.converter.Converter; +import org.springframework.util.NumberUtils; /** - * Converts a String to a BigInteger using {@link BigInteger#BigInteger(String)}. + * Converts a String to a BigInteger. + * * @author Keith Donald * @since 3.0 */ public class StringToBigInteger implements Converter { + public BigInteger convert(String source) { - return new BigInteger(source); + return NumberUtils.parseNumber(source, BigInteger.class); } + } \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBoolean.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBoolean.java index dd481edb645..678f5b2c808 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBoolean.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBoolean.java @@ -1,12 +1,12 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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. @@ -17,11 +17,10 @@ package org.springframework.core.convert.support; import org.springframework.core.convert.converter.Converter; - /** - * Converts String to a Boolean. The trueString and falseStrings are configurable. + * Converts String to a Boolean.. + * * @author Keith Donald - * @see #StringToBoolean(String, String) * @since 3.0 */ public class StringToBoolean implements Converter { @@ -29,11 +28,13 @@ public class StringToBoolean implements Converter { public Boolean convert(String source) { if (source.equals("true")) { return Boolean.TRUE; - } else if (source.equals("false")) { + } + else if (source.equals("false")) { return Boolean.FALSE; - } else { + } + else { throw new IllegalArgumentException("Invalid boolean string '" + source + "'; expected 'true' or 'false'"); } } - -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToByte.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToByte.java index 4eeceffaa26..7d6217d1271 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToByte.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToByte.java @@ -1,29 +1,34 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.converter.Converter; +import org.springframework.util.NumberUtils; /** - * Converts a String to a Byte and back. + * Converts a String to a Byte. + * * @author Keith Donald * @since 3.0 */ public class StringToByte implements Converter { + public Byte convert(String source) { - return Byte.valueOf(source); + return NumberUtils.parseNumber(source, Byte.class); } + } \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCharacter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCharacter.java index 03b726e24a9..0490a102fd9 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCharacter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCharacter.java @@ -1,32 +1,36 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.converter.Converter; /** * Converts a String to a Character and back. + * * @author Keith Donald * @since 3.0 */ public class StringToCharacter implements Converter { + public Character convert(String source) { if (source.length() != 1) { throw new IllegalArgumentException("To be a Character the String '" + source + "' must have a length of 1"); } - return Character.valueOf(source.charAt(0)); + return source.charAt(0); } -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollection.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollection.java index 42fee8070f8..ee948ca8377 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollection.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollection.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.ConversionFailedException; @@ -28,7 +29,7 @@ class StringToCollection implements ConversionExecutor { private ArrayToCollection converter; - public StringToCollection(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + public StringToCollection(TypeDescriptor sourceType, TypeDescriptor targetType, GenericConversionService conversionService) { converter = new ArrayToCollection(sourceType, targetType, conversionService); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToDouble.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToDouble.java index 68e996d84e9..f453f3dbd22 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToDouble.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToDouble.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 the original author or authors. + * Copyright 2002-2009 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. @@ -13,17 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.core.convert.support; import org.springframework.core.convert.converter.Converter; +import org.springframework.util.NumberUtils; /** - * Converts a String to a Double using {@link Double#valueOf(String)}. + * Converts a String to a Double. + * * @author Keith Donald * @since 3.0 */ public class StringToDouble implements Converter { + public Double convert(String source) { - return Double.valueOf(source); + return NumberUtils.parseNumber(source, Double.class); } -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToEnumFactory.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToEnumFactory.java index 68b9e7082a8..c683a93bdc2 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToEnumFactory.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToEnumFactory.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.converter.Converter; @@ -21,6 +22,7 @@ import org.springframework.core.convert.converter.ConverterInfo; /** * A factory for String to enum converters. + * * @author Keith Donald * @since 3.0 */ @@ -31,9 +33,10 @@ public class StringToEnumFactory implements ConverterFactory { return new StringToEnum(targetType); } - class StringToEnum implements Converter, ConverterInfo { - private Class enumType; + private class StringToEnum implements Converter, ConverterInfo { + + private final Class enumType; public StringToEnum(Class enumType) { this.enumType = enumType; @@ -44,11 +47,15 @@ public class StringToEnumFactory implements ConverterFactory { } public Class getTargetType() { - return enumType; + return this.enumType; } public T convert(String source) throws Exception { - return (T) Enum.valueOf(enumType, source); + if ("".equals(source)) { + // It's an empty enum identifier: reset the enum value to null. + return null; + } + return (T) Enum.valueOf(this.enumType, source.trim()); } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToFloat.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToFloat.java index e2b3a101abe..00b23effd18 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToFloat.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToFloat.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 the original author or authors. + * Copyright 2002-2009 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. @@ -13,17 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.core.convert.support; import org.springframework.core.convert.converter.Converter; +import org.springframework.util.NumberUtils; /** - * Converts a String to Float using {@link Float#valueOf(String)}. + * Converts a String to Float. + * * @author Keith Donald * @since 3.0 */ public class StringToFloat implements Converter { + public Float convert(String source) { - return Float.valueOf(source); + return NumberUtils.parseNumber(source, Float.class); } + } \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToInteger.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToInteger.java index 0d0ae2164ac..7b93c13a300 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToInteger.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToInteger.java @@ -1,29 +1,34 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.converter.Converter; +import org.springframework.util.NumberUtils; /** - * Converts a String to an Integer using {@link Integer#valueOf(String)}. + * Converts a String to an Integer. + * * @author Keith Donald * @since 3.0 */ public class StringToInteger implements Converter { + public Integer convert(String source) { - return Integer.valueOf(source); + return NumberUtils.parseNumber(source, Integer.class); } + } \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToLocale.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToLocale.java index 072e0d1a820..28ec1ba8cd4 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToLocale.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToLocale.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import java.util.Locale; @@ -21,12 +22,15 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.util.StringUtils; /** - * Converts a String to a Locale using {@link StringUtils#parseLocaleString(String)}. + * Converts a String to a Locale. + * * @author Keith Donald * @since 3.0 */ public class StringToLocale implements Converter { + public Locale convert(String source) { return StringUtils.parseLocaleString(source); } -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToLong.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToLong.java index f69d9b82395..df03ddc998a 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToLong.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToLong.java @@ -1,29 +1,34 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.converter.Converter; +import org.springframework.util.NumberUtils; /** - * Converts a String to a Long using {@link Long#valueOf(String)}. + * Converts a String to a Long. + * * @author Keith Donald * @since 3.0 */ public class StringToLong implements Converter { + public Long convert(String source) { - return Long.valueOf(source); + return NumberUtils.parseNumber(source, Long.class); } -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToMap.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToMap.java index feb8da7f27f..66c838ad5c6 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToMap.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToMap.java @@ -1,18 +1,19 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.ConversionFailedException; @@ -27,6 +28,7 @@ import org.springframework.core.convert.TypeDescriptor; * key=value * key=value * + * * @author Keith Donald * @since 3.0 */ @@ -35,7 +37,7 @@ class StringToMap implements ConversionExecutor { private StringArrayToMap converter; - public StringToMap(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + public StringToMap(TypeDescriptor sourceType, TypeDescriptor targetType, GenericConversionService conversionService) { converter = new StringArrayToMap(sourceType, targetType, conversionService); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToShort.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToShort.java index a4d16f87e16..166d6d5c858 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToShort.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToShort.java @@ -1,29 +1,34 @@ /* - * Copyright 2004-2009 the original author or authors. - * + * Copyright 2002-2009 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.core.convert.support; import org.springframework.core.convert.converter.Converter; +import org.springframework.util.NumberUtils; /** - * Converts a String to a Short using {@link Short#valueOf(String)}. + * Converts a String to a Short. + * * @author Keith Donald * @since 3.0 */ public class StringToShort implements Converter { + public Short convert(String source) { - return Short.valueOf(source); + return NumberUtils.parseNumber(source, Short.class); } -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/main/java/org/springframework/util/SharedMap.java b/org.springframework.core/src/main/java/org/springframework/util/SharedMap.java deleted file mode 100644 index 247e341d0dc..00000000000 --- a/org.springframework.core/src/main/java/org/springframework/util/SharedMap.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2004-2009 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.util; - -import java.util.Map; - -/** - * A simple subinterface of {@link Map} that exposes a mutex that application code can synchronize on. - *

- * Expected to be implemented by Maps that are backed by shared objects that require synchronization between multiple threads. - * An example would be the HTTP session map. - * @author Keith Donald - */ -public interface SharedMap extends Map { - - /** - * Returns the shared mutex that may be synchronized on using a synchronized block. The returned mutex is guaranteed - * to be non-null. - * - * Example usage: - * - *

-	 * synchronized (sharedMap.getMutex()) {
-	 * 	// do synchronized work
-	 * }
-	 * 
- * - * @return the mutex - */ - public Object getMutex(); -} \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/util/SharedMapDecorator.java b/org.springframework.core/src/main/java/org/springframework/util/SharedMapDecorator.java deleted file mode 100644 index 0dfba3adba7..00000000000 --- a/org.springframework.core/src/main/java/org/springframework/util/SharedMapDecorator.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2004-2009 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.util; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -import org.springframework.core.style.ToStringCreator; - -/** - * A map decorator that implements SharedMap. - * By default, simply returns the map itself as the mutex. - * Subclasses may override to return a different mutex object. - * @author Keith Donald - */ -@SuppressWarnings("serial") -public class SharedMapDecorator implements SharedMap, Serializable { - - /** - * The wrapped, target map. - */ - private Map map; - - /** - * Creates a new shared map decorator. - * @param map the map that is shared by multiple threads, to be synced - */ - public SharedMapDecorator(Map map) { - this.map = map; - } - - // implementing Map - - public void clear() { - map.clear(); - } - - public boolean containsKey(Object key) { - return map.containsKey(key); - } - - public boolean containsValue(Object value) { - return map.containsValue(value); - } - - public Set> entrySet() { - return map.entrySet(); - } - - public V get(Object key) { - return map.get(key); - } - - public boolean isEmpty() { - return map.isEmpty(); - } - - public Set keySet() { - return map.keySet(); - } - - public V put(K key, V value) { - return map.put(key, value); - } - - public void putAll(Map map) { - this.map.putAll(map); - } - - public V remove(Object key) { - return map.remove(key); - } - - public int size() { - return map.size(); - } - - public Collection values() { - return map.values(); - } - - // implementing SharedMap - - public Object getMutex() { - return map; - } - - public String toString() { - return new ToStringCreator(this).append("map", map).append("mutex", getMutex()).toString(); - } -} \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/util/StringKeyedMapAdapter.java b/org.springframework.core/src/main/java/org/springframework/util/StringKeyedMapAdapter.java index 6b226ed260f..c748243689e 100644 --- a/org.springframework.core/src/main/java/org/springframework/util/StringKeyedMapAdapter.java +++ b/org.springframework.core/src/main/java/org/springframework/util/StringKeyedMapAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 the original author or authors. + * Copyright 2002-2009 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. @@ -35,6 +35,7 @@ public abstract class StringKeyedMapAdapter implements Map { private Set> entrySet; + // implementing Map public void clear() { @@ -109,6 +110,7 @@ public abstract class StringKeyedMapAdapter implements Map { return (values != null) ? values : (values = new Values()); } + // hook methods /** @@ -140,6 +142,7 @@ public abstract class StringKeyedMapAdapter implements Map { */ protected abstract Iterator getAttributeNames(); + // internal helper classes private class KeySet extends AbstractSet { @@ -167,9 +170,9 @@ public abstract class StringKeyedMapAdapter implements Map { public boolean remove(Object o) { return StringKeyedMapAdapter.this.remove(o) != null; } - } + private class KeyIterator implements Iterator { private final Iterator it = getAttributeNames(); @@ -190,9 +193,9 @@ public abstract class StringKeyedMapAdapter implements Map { } StringKeyedMapAdapter.this.remove(currentKey); } - } + private class Values extends AbstractSet { public boolean isEmpty() { @@ -229,6 +232,7 @@ public abstract class StringKeyedMapAdapter implements Map { } } + private class ValuesIterator implements Iterator { private final Iterator it = getAttributeNames(); @@ -250,9 +254,9 @@ public abstract class StringKeyedMapAdapter implements Map { } StringKeyedMapAdapter.this.remove(currentKey); } - } + private class EntrySet extends AbstractSet> { public boolean isEmpty() { @@ -300,6 +304,7 @@ public abstract class StringKeyedMapAdapter implements Map { } } + private class EntryIterator implements Iterator> { private final Iterator it = getAttributeNames(); @@ -324,6 +329,7 @@ public abstract class StringKeyedMapAdapter implements Map { } + private class EntrySetEntry implements Entry { private final String currentKey; @@ -344,4 +350,5 @@ public abstract class StringKeyedMapAdapter implements Map { return StringKeyedMapAdapter.this.put(currentKey, value); } } -} \ No newline at end of file + +} diff --git a/org.springframework.core/src/test/java/org/springframework/core/convert/support/ArrayToArrayTests.java b/org.springframework.core/src/test/java/org/springframework/core/convert/support/ArrayToArrayTests.java index fca7405f16f..43f9852f999 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/convert/support/ArrayToArrayTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/convert/support/ArrayToArrayTests.java @@ -1,21 +1,39 @@ +/* + * Copyright 2002-2009 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.core.convert.support; -import static org.junit.Assert.assertEquals; - +import static org.junit.Assert.*; import org.junit.Test; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.core.convert.support.ArrayToArray; -import org.springframework.core.convert.support.DefaultTypeConverter; +import org.springframework.core.convert.TypeDescriptor; + +/** + * @author Keith Donald + */ public class ArrayToArrayTests { @Test public void testArrayToArrayConversion() { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); ArrayToArray c = new ArrayToArray(TypeDescriptor.valueOf(String[].class), TypeDescriptor.valueOf(Integer[].class), service); Integer[] result = (Integer[]) c.execute(new String[] { "1", "2", "3" }); assertEquals(new Integer(1), result[0]); assertEquals(new Integer(2), result[1]); assertEquals(new Integer(3), result[2]); } + } diff --git a/org.springframework.core/src/test/java/org/springframework/core/convert/support/ArrayToCollectionTests.java b/org.springframework.core/src/test/java/org/springframework/core/convert/support/ArrayToCollectionTests.java index 7eb49534a04..d469e2ebc1c 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/convert/support/ArrayToCollectionTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/convert/support/ArrayToCollectionTests.java @@ -1,6 +1,20 @@ -package org.springframework.core.convert.support; +/* + * Copyright 2002-2009 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.assertEquals; +package org.springframework.core.convert.support; import java.util.Collection; import java.util.LinkedList; @@ -8,26 +22,30 @@ import java.util.List; import java.util.Set; import java.util.SortedSet; +import static org.junit.Assert.*; import org.junit.Test; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.core.convert.support.ArrayToCollection; -import org.springframework.core.convert.support.DefaultTypeConverter; +import org.springframework.core.convert.TypeDescriptor; + +/** + * @author Keith Donald + */ public class ArrayToCollectionTests { @Test public void testArrayToCollectionConversion() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); ArrayToCollection c = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getField("bindTarget")), service); - List result = (List) c.execute(new String[] { "1", "2", "3" }); - assertEquals(new Integer(1), result.get(0)); - assertEquals(new Integer(2), result.get(1)); - assertEquals(new Integer(3), result.get(2)); + Collection result = (Collection) c.execute(new String[] { "1", "2", "3" }); + assertEquals(3, result.size()); + assertTrue(result.contains(1)); + assertTrue(result.contains(2)); + assertTrue(result.contains(3)); } @Test public void testArrayToSetConversion() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); ArrayToCollection c = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getField("setTarget")), service); Set result = (Set) c.execute(new String[] { "1" }); assertEquals("1", result.iterator().next()); @@ -35,7 +53,7 @@ public class ArrayToCollectionTests { @Test public void testArrayToSortedSetConversion() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); ArrayToCollection c = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getField("sortedSetTarget")), service); SortedSet result = (SortedSet) c.execute(new String[] { "1" }); assertEquals(new Integer(1), result.iterator().next()); @@ -43,7 +61,7 @@ public class ArrayToCollectionTests { @Test public void testArrayToCollectionImplConversion() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); ArrayToCollection c = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getField("implTarget")), service); LinkedList result = (LinkedList) c.execute(new String[] { "1" }); assertEquals("1", result.iterator().next()); @@ -51,7 +69,7 @@ public class ArrayToCollectionTests { @Test public void testArrayToNonGenericCollectionConversionNullElement() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); ArrayToCollection c = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getField("listTarget")), service); List result = (List) c.execute(new Integer[] { null, new Integer(1) }); assertEquals(null, result.get(0)); diff --git a/org.springframework.core/src/test/java/org/springframework/core/convert/support/CollectionToArrayTests.java b/org.springframework.core/src/test/java/org/springframework/core/convert/support/CollectionToArrayTests.java index b4aaa4fcb92..461b7388ab3 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/convert/support/CollectionToArrayTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/convert/support/CollectionToArrayTests.java @@ -1,20 +1,37 @@ -package org.springframework.core.convert.support; +/* + * Copyright 2002-2009 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.assertEquals; +package org.springframework.core.convert.support; import java.util.ArrayList; import java.util.Collection; +import static org.junit.Assert.*; import org.junit.Test; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.core.convert.support.CollectionToArray; -import org.springframework.core.convert.support.DefaultTypeConverter; +import org.springframework.core.convert.TypeDescriptor; + +/** + * @author Keith Donald + */ public class CollectionToArrayTests { @Test public void testCollectionToArrayConversion() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); CollectionToArray c = new CollectionToArray(new TypeDescriptor(getClass().getField("bindTarget")), TypeDescriptor.valueOf(Integer[].class), service); bindTarget.add("1"); @@ -28,7 +45,7 @@ public class CollectionToArrayTests { @Test public void testCollectionToArrayConversionNoGenericInfo() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); CollectionToArray c = new CollectionToArray(TypeDescriptor.valueOf(Collection.class), TypeDescriptor .valueOf(Integer[].class), service); bindTarget.add("1"); @@ -42,7 +59,7 @@ public class CollectionToArrayTests { @Test public void testCollectionToArrayConversionNoGenericInfoNullElement() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); CollectionToArray c = new CollectionToArray(TypeDescriptor.valueOf(Collection.class), TypeDescriptor .valueOf(Integer[].class), service); bindTarget.add(null); diff --git a/org.springframework.core/src/test/java/org/springframework/core/convert/support/CollectionToCollectionTests.java b/org.springframework.core/src/test/java/org/springframework/core/convert/support/CollectionToCollectionTests.java index e3945a996db..73ddf8b7f96 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/convert/support/CollectionToCollectionTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/convert/support/CollectionToCollectionTests.java @@ -1,85 +1,104 @@ -package org.springframework.core.convert.support; +/* + * Copyright 2002-2009 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.assertEquals; -import static org.junit.Assert.assertTrue; +package org.springframework.core.convert.support; import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; import java.util.List; +import static org.junit.Assert.*; import org.junit.Test; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.core.convert.support.CollectionToCollection; -import org.springframework.core.convert.support.DefaultTypeConverter; +import org.springframework.core.convert.TypeDescriptor; + +/** + * @author Keith Donald + */ public class CollectionToCollectionTests { @Test public void testCollectionToCollectionConversion() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); CollectionToCollection c = new CollectionToCollection(new TypeDescriptor(getClass().getField("bindTarget")), new TypeDescriptor(getClass().getField("integerTarget")), service); bindTarget.add("1"); bindTarget.add("2"); bindTarget.add("3"); - List result = (List) c.execute(bindTarget); - assertEquals(new Integer(1), result.get(0)); - assertEquals(new Integer(2), result.get(1)); - assertEquals(new Integer(3), result.get(2)); + Collection result = (Collection) c.execute(bindTarget); + assertEquals(3, result.size()); + assertTrue(result.contains(1)); + assertTrue(result.contains(2)); + assertTrue(result.contains(3)); } @Test public void testCollectionToCollectionConversionNoGenericInfo() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); CollectionToCollection c = new CollectionToCollection(TypeDescriptor.valueOf(Collection.class), TypeDescriptor.valueOf(List.class), service); bindTarget.add("1"); bindTarget.add("2"); bindTarget.add("3"); - List result = (List) c.execute(bindTarget); - assertEquals("1", result.get(0)); - assertEquals("2", result.get(1)); - assertEquals("3", result.get(2)); + Collection result = (Collection) c.execute(bindTarget); + assertEquals(3, result.size()); + assertTrue(result.contains("1")); + assertTrue(result.contains("2")); + assertTrue(result.contains("3")); } - + @Test public void testCollectionToCollectionConversionNoGenericInfoSource() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); CollectionToCollection c = new CollectionToCollection(TypeDescriptor.valueOf(Collection.class), new TypeDescriptor(getClass().getField("integerTarget")), service); bindTarget.add("1"); bindTarget.add("2"); bindTarget.add("3"); - List result = (List) c.execute(bindTarget); - assertEquals(new Integer(1), result.get(0)); - assertEquals(new Integer(2), result.get(1)); - assertEquals(new Integer(3), result.get(2)); + Collection result = (Collection) c.execute(bindTarget); + assertEquals(3, result.size()); + assertTrue(result.contains(1)); + assertTrue(result.contains(2)); + assertTrue(result.contains(3)); } - + @Test - public void testCollectionToCollectionConversionNoGenericInfoSourceNullValues() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + public void testCollectionToCollectionConversionNoGenericInfoSourceNullValue() throws Exception { + DefaultConversionService service = new DefaultConversionService(); CollectionToCollection c = new CollectionToCollection(TypeDescriptor.valueOf(Collection.class), new TypeDescriptor(getClass().getField("integerTarget")), service); bindTarget.add(null); bindTarget.add("1"); bindTarget.add("2"); - bindTarget.add(null); bindTarget.add("3"); - List result = (List) c.execute(bindTarget); - assertEquals(null, result.get(0)); - assertEquals(new Integer(1), result.get(1)); - assertEquals(new Integer(2), result.get(2)); - assertEquals(null, result.get(3)); - assertEquals(new Integer(3), result.get(4)); + Collection result = (Collection) c.execute(bindTarget); + Iterator it = result.iterator(); + assertEquals(null, it.next()); + assertEquals(new Integer(1), it.next()); + assertEquals(new Integer(2), it.next()); + assertEquals(new Integer(3), it.next()); } - + @Test public void testCollectionToCollectionConversionNoGenericInfoSourceEmpty() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); CollectionToCollection c = new CollectionToCollection(TypeDescriptor.valueOf(Collection.class), new TypeDescriptor(getClass().getField("integerTarget")), service); - List result = (List) c.execute(bindTarget); + Collection result = (Collection) c.execute(bindTarget); assertTrue(result.isEmpty()); } @@ -87,5 +106,4 @@ public class CollectionToCollectionTests { public Collection bindTarget = new ArrayList(); public List integerTarget = new ArrayList(); - } diff --git a/org.springframework.core/src/test/java/org/springframework/core/convert/support/DefaultTypeConverterTests.java b/org.springframework.core/src/test/java/org/springframework/core/convert/support/DefaultConversionServiceTests.java similarity index 86% rename from org.springframework.core/src/test/java/org/springframework/core/convert/support/DefaultTypeConverterTests.java rename to org.springframework.core/src/test/java/org/springframework/core/convert/support/DefaultConversionServiceTests.java index 02e813ff60a..82bc9af6d07 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/convert/support/DefaultTypeConverterTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/convert/support/DefaultConversionServiceTests.java @@ -1,3 +1,19 @@ +/* + * Copyright 2002-2009 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.core.convert.support; import static org.junit.Assert.assertEquals; @@ -27,8 +43,10 @@ import org.springframework.core.convert.support.StringToShort; /** * Tests for the default converters in the converters package. -s */ -public class DefaultTypeConverterTests { + + * @author Keith Donald + */ +public class DefaultConversionServiceTests { @Test public void testStringToByte() throws Exception { diff --git a/org.springframework.core/src/test/java/org/springframework/core/convert/support/GenericTypeConverterTests.java b/org.springframework.core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java similarity index 92% rename from org.springframework.core/src/test/java/org/springframework/core/convert/support/GenericTypeConverterTests.java rename to org.springframework.core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java index e04520bf8d9..b99698ca6a4 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/convert/support/GenericTypeConverterTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008 the original author or authors. + * Copyright 2002-2009 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. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.core.convert.support; import static junit.framework.Assert.assertEquals; @@ -32,9 +33,12 @@ import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; -public class GenericTypeConverterTests { +/** + * @author Keith Donald + */ +public class GenericConversionServiceTests { - private GenericTypeConverter converter = new GenericTypeConverter(); + private GenericConversionService converter = new GenericConversionService(); @Test public void executeConversion() { @@ -151,7 +155,7 @@ public class GenericTypeConverterTests { @Test public void convertArrayToListGenericTypeConversion() throws Exception { converter.add(new StringToInteger()); - List result = converter.convert(new String[] { "1", "2", "3" }, new TypeDescriptor>(getClass().getDeclaredField("genericList"))); + List result = (List) converter.convert(new String[] { "1", "2", "3" }, new TypeDescriptor(getClass().getDeclaredField("genericList"))); assertEquals(new Integer("1"), result.get(0)); assertEquals(new Integer("2"), result.get(1)); assertEquals(new Integer("3"), result.get(2)); @@ -208,7 +212,7 @@ public class GenericTypeConverterTests { foo.put("2", "BAZ"); converter.add(new StringToInteger()); converter.add(new StringToEnumFactory().getConverter(FooEnum.class)); - Map map = converter.convert(foo, new TypeDescriptor>(getClass().getField("genericMap"))); + Map map = (Map) converter.convert(foo, new TypeDescriptor(getClass().getField("genericMap"))); assertEquals(map.get(1), FooEnum.BAR); assertEquals(map.get(2), FooEnum.BAZ); } diff --git a/org.springframework.core/src/test/java/org/springframework/core/convert/support/MapToMapTests.java b/org.springframework.core/src/test/java/org/springframework/core/convert/support/MapToMapTests.java index c2c338737ff..be85d4752c2 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/convert/support/MapToMapTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/convert/support/MapToMapTests.java @@ -1,3 +1,19 @@ +/* + * Copyright 2002-2009 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.core.convert.support; import static org.junit.Assert.assertEquals; @@ -7,16 +23,19 @@ import java.util.Map; import org.junit.Test; import org.springframework.core.convert.TypeDescriptor; -import org.springframework.core.convert.support.DefaultTypeConverter; +import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.MapToMap; +/** + * @author Keith Donald + */ public class MapToMapTests { @Test public void testMapToMapConversion() throws Exception { - DefaultTypeConverter converter = new DefaultTypeConverter(); - MapToMap c = new MapToMap(new TypeDescriptor>(getClass().getField("source")), - new TypeDescriptor>(getClass().getField("bindTarget")), converter); + DefaultConversionService converter = new DefaultConversionService(); + MapToMap c = new MapToMap(new TypeDescriptor(getClass().getField("source")), + new TypeDescriptor(getClass().getField("bindTarget")), converter); source.put("1", "BAR"); source.put("2", "BAZ"); Map result = (Map) c.execute(source); @@ -26,7 +45,7 @@ public class MapToMapTests { @Test public void testMapToMapConversionNoGenericInfoOnSource() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); MapToMap c = new MapToMap(TypeDescriptor.valueOf(Map.class), new TypeDescriptor(getClass().getField("bindTarget")), service); source.put("1", "BAR"); @@ -38,7 +57,7 @@ public class MapToMapTests { @Test public void testMapToMapConversionNoGenericInfo() throws Exception { - DefaultTypeConverter service = new DefaultTypeConverter(); + DefaultConversionService service = new DefaultConversionService(); MapToMap c = new MapToMap(TypeDescriptor.valueOf(Map.class), TypeDescriptor.valueOf(Map.class), service); source.put("1", "BAR"); diff --git a/org.springframework.core/src/test/java/org/springframework/util/SharedMapDecoratorTests.java b/org.springframework.core/src/test/java/org/springframework/util/SharedMapDecoratorTests.java deleted file mode 100644 index eeadb13b1e9..00000000000 --- a/org.springframework.core/src/test/java/org/springframework/util/SharedMapDecoratorTests.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.springframework.util; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import junit.framework.TestCase; - -/** - * Unit tests for {@link org.springframework.binding.collection.SharedMapDecorator}. - */ -public class SharedMapDecoratorTests extends TestCase { - - private SharedMapDecorator map = new SharedMapDecorator(new HashMap()); - - public void testGetPutRemove() { - assertTrue(map.size() == 0); - assertTrue(map.isEmpty()); - assertNull(map.get("foo")); - assertFalse(map.containsKey("foo")); - map.put("foo", "bar"); - assertTrue(map.size() == 1); - assertFalse(map.isEmpty()); - assertNotNull(map.get("foo")); - assertTrue(map.containsKey("foo")); - assertTrue(map.containsValue("bar")); - assertEquals("bar", map.get("foo")); - map.remove("foo"); - assertTrue(map.size() == 0); - assertNull(map.get("foo")); - } - - public void testPutAll() { - Map all = new HashMap(); - all.put("foo", "bar"); - all.put("bar", "baz"); - map.putAll(all); - assertTrue(map.size() == 2); - } - - public void testEntrySet() { - map.put("foo", "bar"); - map.put("bar", "baz"); - Set entrySet = map.entrySet(); - assertTrue(entrySet.size() == 2); - } - - public void testKeySet() { - map.put("foo", "bar"); - map.put("bar", "baz"); - Set keySet = map.keySet(); - assertTrue(keySet.size() == 2); - } - - public void testValues() { - map.put("foo", "bar"); - map.put("bar", "baz"); - Collection values = map.values(); - assertTrue(values.size() == 2); - } -}