提交 45a0cadf 编写于 作者: J Juergen Hoeller

revised core conversion package for BeanWrapper/BeanFactory integration

上级 e9823b57
......@@ -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
......
......@@ -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> T convertIfNecessary(
Object value, Class<T> 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());
......
/*
* 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.
......
......@@ -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<Class, PropertyEditor> 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
//---------------------------------------------------------------------
......
......@@ -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;
}
/**
......
......@@ -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 <code>null</code>)
*/
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;
......
......@@ -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.
* <p>Such a registrar creates new PropertyEditor instances and registers them
......
......@@ -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<PropertyEditorRegistrar> propertyEditorRegistrars =
new LinkedHashSet<PropertyEditorRegistrar>(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);
}
......
/*
* 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
......
......@@ -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<String, Float>() {
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();
......
......@@ -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 {
......
......@@ -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<Class> approximableCollectionTypes = new HashSet<Class>(10);
private static final Set<Class> approximableMapTypes = new HashSet<Class>(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 <code>true</code> if the type is approximable,
* <code>false</code> 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.
* <p>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.
* <p>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 <code>true</code> if the type is approximable,
* <code>false</code> 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.
* <p>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.
* <p>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.
......
/*
* 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);
}
}
/*
* 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
}
/*
* 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.
* <p>
* Call {@link #convert(Object, Class)} to perform a thread-safe type conversion using this system.<br>
* Call {@link #convert(Object, TypeDescriptor)} to perform a conversion with additional context about the targetType to convert to.
*
* <p>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 <code>null</code> if a null source was provided
* @throws ConvertException if an exception occurred
* @throws ConversionException if an exception occurred
*/
<S, T> T convert(S source, Class<T> targetType);
<T> T convert(Object source, Class<T> 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()}</code>, or <code>null</code> if a null source was provided
* @throws ConvertException if an exception occurred
* @throws ConversionException if an exception occurred
*/
<S, T> T convert(S source, TypeDescriptor<T> targetType);
Object convert(Object source, TypeDescriptor targetType);
}
\ No newline at end of file
}
/*
* 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 final Class<?> sourceType;
private 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;
}
}
/*
* 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<T> {
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<T> {
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<T> {
this.field = field;
}
/**
* Return the wrapped MethodParameter, if any.
* <p>Note: Either MethodParameter or Field is available.
* @return the MethodParameter, or <code>null</code> if none
*/
public MethodParameter getMethodParameter() {
return this.methodParameter;
}
/**
* Return the wrapped Field, if any.
* <p>Note: Either MethodParameter or Field is available.
* @return the Field, or <code>null</code> if none
*/
public Field getField() {
return this.field;
}
/**
* Determine the declared (non-generic) type of the wrapped parameter/field.
* @return the declared type (never <code>null</code>)
*/
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<T> {
Class<?> type = getType();
if (type != null) {
return getType().getName();
} else {
}
else {
return null;
}
}
......@@ -109,11 +132,7 @@ public class TypeDescriptor<T> {
*/
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<T> {
}
/**
* 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<T> {
* 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<T> {
* @return the generic type, or <code>null</code> 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<T> {
* @return the generic type, or <code>null</code> 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<T> {
* 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.
* <p>
* Note: Either MethodParameter or Field is available.
* @return the MethodParameter, or <code>null</code> if none
*/
public MethodParameter getMethodParameter() {
return methodParameter;
}
/**
* Return the wrapped Field, if any.
* <p>
* Note: Either MethodParameter or Field is available.
* @return the Field, or <code>null</code> 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<T> {
*/
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<T> {
* @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 <T> TypeDescriptor<T> valueOf(Class<T> type) {
// TODO needs a cache for common type descriptors
return new TypeDescriptor<T>(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<T> {
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<T> {
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<T> {
return stringValue.toString();
}
// internal helpers
private Class<?> wrapperType(Class<?> type) {
......@@ -331,29 +308,49 @@ public class TypeDescriptor<T> {
return type;
}
}
private Class<?> getArrayComponentType() {
return getType().getComponentType();
}
@SuppressWarnings("unchecked")
private Class<?> getCollectionElementType() {
if (type != null) {
return GenericCollectionTypeResolver.getCollectionType((Class<? extends Collection>) type);
} else if (field != null) {
return GenericCollectionTypeResolver.getCollectionFieldType(field);
} else {
return GenericCollectionTypeResolver.getCollectionParameterType(methodParameter);
if (this.type != null) {
return GenericCollectionTypeResolver.getCollectionType((Class<? extends Collection>) 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));
}
// 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()));
}
}
\ No newline at end of file
}
/*
* 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.
* <p>
* 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.
* </p>
*
* <p>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<S, T> {
* @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
}
/*
* 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 <S> The source type converters created by this factory can convert from
......@@ -32,4 +33,5 @@ public interface ConverterFactory<S, R> {
* @return A converter from S to T
*/
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
}
\ No newline at end of file
}
/*
* 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();
}
/*
* 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
}
/*
* 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 {
this.elementConverter = NoOpConversionExecutor.INSTANCE;
}
} else {
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
*/
......
/*
* 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);
}
......
/*
* 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 <code>List.class</code> 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<? extends Collection>) 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
}
/*
* 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.
* <p>
* Support Number classes including Byte, Short, Integer, Float, Double, Long, BigInteger, BigDecimal. This class
*
* <p>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<Character, Num
return new CharacterToNumber<T>(targetType);
}
private static class CharacterToNumber<T extends Number> implements Converter<Character, T> {
private Class<T> targetType;
private final Class<T> targetType;
public CharacterToNumber(Class<T> targetType) {
this.targetType = targetType;
......@@ -53,6 +56,6 @@ public class CharacterToNumberFactory implements ConverterFactory<Character, Num
public T convert(Character source) throws Exception {
return NumberUtils.convertNumberToTargetClass((short) source.charValue(), targetType);
}
}
}
\ No newline at end of file
}
/*
* 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;
......@@ -26,11 +27,10 @@ import org.springframework.core.convert.TypeDescriptor;
* @author Keith Donald
* @since 3.0
*/
@SuppressWarnings("unchecked")
class CollectionToArray extends AbstractCollectionConverter {
public CollectionToArray(TypeDescriptor sourceCollectionType, TypeDescriptor targetArrayType,
GenericTypeConverter conversionService) {
GenericConversionService conversionService) {
super(sourceCollectionType, targetArrayType, conversionService);
}
......
/*
* 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 java.util.Iterator;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.TypeDescriptor;
/**
......@@ -29,19 +30,17 @@ import org.springframework.core.convert.TypeDescriptor;
class CollectionToCollection extends AbstractCollectionConverter {
public CollectionToCollection(TypeDescriptor sourceCollectionType, TypeDescriptor targetCollectionType,
GenericTypeConverter conversionService) {
GenericConversionService conversionService) {
super(sourceCollectionType, targetCollectionType, conversionService);
}
@Override
protected Object doExecute(Object source) throws Exception {
Collection sourceCollection = (Collection) source;
Class implClass = ConversionUtils.getCollectionImpl((Class<? extends Collection>) 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
}
/*
* 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
/*
* 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<? extends Collection> getCollectionImpl(Class<? extends Collection> 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<? extends Map> getMapImpl(Class<? extends Map> 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;
}
}
}
/*
* 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 <i>from string</i> converters for
* a number of standard Java types like Class, Number, Boolean and so on.
* Default implementation of a conversion service. Will automatically register <i>from string</i>
* 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 {
/**
* Creates a new default conversion service, installing the default converters.
*/
public DefaultTypeConverter() {
addDefaultConverters();
}
public class DefaultConversionService extends GenericConversionService {
/**
* Add all default converters to the conversion service.
* Create a new default conversion service, installing the default converters.
*/
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
}
/*
* 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<Class, Map<Class, Object>> sourceTypeConverters = new HashMap<Class, Map<Class, Object>>();
private TypeConverter parent;
/**
* Returns the parent of this conversion service. Could be null.
* Set the parent of this conversion service. This is optional.
*/
public TypeConverter getParent() {
return parent;
public void setParent(ConversionService parent) {
this.parent = parent;
}
/**
* Set the parent of this conversion service. This is optional.
* Returns the parent of this conversion service. Could be null.
*/
public void setParent(TypeConverter parent) {
this.parent = parent;
public ConversionService getParent() {
return this.parent;
}
// implementing ConverterRegistry
public void add(Converter converter) {
List typeInfo = getRequiredTypeInfo(converter);
List<Class> typeInfo = getRequiredTypeInfo(converter);
if (typeInfo == null) {
throw new IllegalArgumentException("Unable to the determine sourceType <S> and targetType <T> your Converter<S, T> 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<Class> typeInfo = getRequiredTypeInfo(converterFactory);
if (typeInfo == null) {
throw new IllegalArgumentException("Unable to the determine sourceType <S> and targetType <T> your ConverterFactory<S, T> 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 <S, T> T convert(S source, Class<T> targetType) {
return convert(source, TypeDescriptor.valueOf(targetType));
@SuppressWarnings("unchecked")
public <T> T convert(Object source, Class<T> targetType) {
return (T) convert(source, TypeDescriptor.valueOf(targetType));
}
public <S, T> T convert(S source, TypeDescriptor<T> 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<Class> getRequiredTypeInfo(Object converter) {
List<Class> typeInfo = new ArrayList<Class>(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<Class> 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<Class> typeInfo = new ArrayList<Class>(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<Class, Object> getSourceMap(Class sourceType) {
Map<Class, Object> sourceMap = sourceTypeConverters.get(sourceType);
if (sourceMap == null) {
sourceMap = new HashMap();
sourceMap = new HashMap<Class, Object>();
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<Class> classQueue = new LinkedList<Class>();
classQueue.addFirst(sourceType);
while (!classQueue.isEmpty()) {
Class currentClass = (Class) classQueue.removeLast();
Map converters = getConvertersForSource(currentClass);
Class currentClass = classQueue.removeLast();
Map<Class, Object> 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<Class, Object> objectConverters = getConvertersForSource(Object.class);
return getConverter(objectConverters, targetType);
} else {
LinkedList classQueue = new LinkedList();
}
else {
LinkedList<Class> classQueue = new LinkedList<Class>();
classQueue.addFirst(sourceType);
while (!classQueue.isEmpty()) {
Class currentClass = (Class) classQueue.removeLast();
Map converters = getConvertersForSource(currentClass);
Class currentClass = classQueue.removeLast();
Map<Class, Object> 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<Class, Object> getConvertersForSource(Class<?> sourceType) {
Map<Class, Object> converters = this.sourceTypeConverters.get(sourceType);
if (converters == null) {
converters = Collections.emptyMap();
}
return converters;
}
private Converter getConverter(Map converters, Class targetType) {
private Converter getConverter(Map<Class, Object> converters, Class<?> targetType) {
if (targetType.isInterface()) {
LinkedList classQueue = new LinkedList();
LinkedList<Class> classQueue = new LinkedList<Class>();
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<Class> classQueue = new LinkedList<Class>();
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<Class, Object> 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);
}
}
......
/*
* 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 final ConversionExecutor keyConverter;
private final ConversionExecutor valueConverter;
private 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
}
/*
* 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 final TypeDescriptor targetType;
private TypeDescriptor targetType;
private final GenericConversionService conversionService;
private GenericTypeConverter 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<Map.Entry<?, ?>> 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;
......
/*
* 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 final GenericConversionService conversionService;
private GenericTypeConverter conversionService;
private final MapEntryConverter entryConverter;
private 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++;
}
......
/*
* 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);
}
}
/*
* 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
}
/*
* 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<Number, Character> {
public Character convert(Number source) {
return Character.valueOf((char) source.shortValue());
return (char) source.shortValue();
}
}
\ No newline at end of file
}
/*
* 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.
* <p>
* Support Number classes including Byte, Short, Integer, Float, Double, Long, BigInteger, BigDecimal. This class
*
* <p>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<Number, Number> {
......@@ -42,9 +44,10 @@ public class NumberToNumberFactory implements ConverterFactory<Number, Number> {
return new NumberToNumber<T>(targetType);
}
private static class NumberToNumber<T extends Number> implements Converter<Number, T> {
private Class<T> targetType;
private final Class<T> targetType;
public NumberToNumber(Class<T> targetType) {
this.targetType = targetType;
......@@ -53,6 +56,6 @@ public class NumberToNumberFactory implements ConverterFactory<Number, Number> {
public T convert(Number source) throws Exception {
return NumberUtils.convertNumberToTargetClass(source, targetType);
}
}
}
\ No newline at end of file
}
/*
* 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);
......
/*
* 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();
Class<?> elementType = targetCollectionType.getElementType();
if (elementType != null) {
this.elementConverter = typeConverter.getConversionExecutor(sourceObjectType.getType(), TypeDescriptor.valueOf(elementType));
}
else {
this.elementConverter = NoOpConversionExecutor.INSTANCE;
}
}
@SuppressWarnings("unchecked")
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));
Collection collection = CollectionFactory.createCollection(this.targetCollectionType.getType(), 1);
collection.add(this.elementConverter.execute(source));
return collection;
}
private void initElementConverter() {
Class<?> elementType = targetCollectionType.getElementType();
if (elementType != null) {
this.elementConverter = typeConverter.getConversionExecutor(sourceObjectType.getType(), TypeDescriptor.valueOf(elementType));
} else {
this.elementConverter = NoOpConversionExecutor.INSTANCE;
}
}
}
\ No newline at end of file
}
/*
* 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<Object, String> {
public String convert(Object source) {
return source.toString();
}
}
/*
* 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
}
/*
* 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 final TypeDescriptor targetType;
private TypeDescriptor targetType;
private final GenericConversionService conversionService;
private GenericTypeConverter conversionService;
private final MapEntryConverter entryConverter;
private 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);
}
}
......
/*
* 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);
}
......
/*
* 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);
}
......
/*
* 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<String, BigDecimal> {
public BigDecimal convert(String source) {
return new BigDecimal(source);
return NumberUtils.parseNumber(source, BigDecimal.class);
}
}
\ No newline at end of file
/*
* 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<String, BigInteger> {
public BigInteger convert(String source) {
return new BigInteger(source);
return NumberUtils.parseNumber(source, BigInteger.class);
}
}
\ No newline at end of file
/*
* 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<String, Boolean> {
......@@ -29,11 +28,13 @@ public class StringToBoolean implements Converter<String, Boolean> {
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
}
/*
* 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<String, Byte> {
public Byte convert(String source) {
return Byte.valueOf(source);
return NumberUtils.parseNumber(source, Byte.class);
}
}
\ No newline at end of file
/*
* 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<String, Character> {
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
}
/*
* 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);
}
......
/*
* 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<String, Double> {
public Double convert(String source) {
return Double.valueOf(source);
return NumberUtils.parseNumber(source, Double.class);
}
}
\ No newline at end of file
}
/*
* 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<String, Enum> {
return new StringToEnum(targetType);
}
class StringToEnum<T extends Enum> implements Converter<String, T>, ConverterInfo {
private Class<T> enumType;
private class StringToEnum<T extends Enum> implements Converter<String, T>, ConverterInfo {
private final Class<T> enumType;
public StringToEnum(Class<T> enumType) {
this.enumType = enumType;
......@@ -44,11 +47,15 @@ public class StringToEnumFactory implements ConverterFactory<String, Enum> {
}
public Class<T> 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());
}
}
......
/*
* 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<String, Float> {
public Float convert(String source) {
return Float.valueOf(source);
return NumberUtils.parseNumber(source, Float.class);
}
}
\ No newline at end of file
/*
* 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<String, Integer> {
public Integer convert(String source) {
return Integer.valueOf(source);
return NumberUtils.parseNumber(source, Integer.class);
}
}
\ No newline at end of file
/*
* 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<String, Locale> {
public Locale convert(String source) {
return StringUtils.parseLocaleString(source);
}
}
\ No newline at end of file
}
/*
* 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<String, Long> {
public Long convert(String source) {
return Long.valueOf(source);
return NumberUtils.parseNumber(source, Long.class);
}
}
\ No newline at end of file
}
/*
* 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
* </pre>
*
* @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);
}
......
/*
* 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<String, Short> {
public Short convert(String source) {
return Short.valueOf(source);
return NumberUtils.parseNumber(source, Short.class);
}
}
\ No newline at end of file
}
/*
* 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.
* <p>
* 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<K, V> extends Map<K, V> {
/**
* Returns the shared mutex that may be synchronized on using a synchronized block. The returned mutex is guaranteed
* to be non-null.
*
* Example usage:
*
* <pre>
* synchronized (sharedMap.getMutex()) {
* // do synchronized work
* }
* </pre>
*
* @return the mutex
*/
public Object getMutex();
}
\ No newline at end of file
/*
* 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 <code>SharedMap</code>.
* 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<K, V> implements SharedMap<K, V>, Serializable {
/**
* The wrapped, target map.
*/
private Map<K, V> map;
/**
* Creates a new shared map decorator.
* @param map the map that is shared by multiple threads, to be synced
*/
public SharedMapDecorator(Map<K, V> 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<Map.Entry<K, V>> entrySet() {
return map.entrySet();
}
public V get(Object key) {
return map.get(key);
}
public boolean isEmpty() {
return map.isEmpty();
}
public Set<K> keySet() {
return map.keySet();
}
public V put(K key, V value) {
return map.put(key, value);
}
public void putAll(Map<? extends K, ? extends V> map) {
this.map.putAll(map);
}
public V remove(Object key) {
return map.remove(key);
}
public int size() {
return map.size();
}
public Collection<V> 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
/*
* 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<V> implements Map<String, V> {
private Set<Map.Entry<String, V>> entrySet;
// implementing Map
public void clear() {
......@@ -109,6 +110,7 @@ public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
return (values != null) ? values : (values = new Values());
}
// hook methods
/**
......@@ -140,6 +142,7 @@ public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
*/
protected abstract Iterator<String> getAttributeNames();
// internal helper classes
private class KeySet extends AbstractSet<String> {
......@@ -167,9 +170,9 @@ public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
public boolean remove(Object o) {
return StringKeyedMapAdapter.this.remove(o) != null;
}
}
private class KeyIterator implements Iterator<String> {
private final Iterator<String> it = getAttributeNames();
......@@ -190,9 +193,9 @@ public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
}
StringKeyedMapAdapter.this.remove(currentKey);
}
}
private class Values extends AbstractSet<V> {
public boolean isEmpty() {
......@@ -229,6 +232,7 @@ public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
}
}
private class ValuesIterator implements Iterator<V> {
private final Iterator<String> it = getAttributeNames();
......@@ -250,9 +254,9 @@ public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
}
StringKeyedMapAdapter.this.remove(currentKey);
}
}
private class EntrySet extends AbstractSet<Map.Entry<String, V>> {
public boolean isEmpty() {
......@@ -300,6 +304,7 @@ public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
}
}
private class EntryIterator implements Iterator<Map.Entry<String, V>> {
private final Iterator<String> it = getAttributeNames();
......@@ -324,6 +329,7 @@ public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
}
private class EntrySetEntry implements Entry<String, V> {
private final String currentKey;
......@@ -344,4 +350,5 @@ public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
return StringKeyedMapAdapter.this.put(currentKey, value);
}
}
}
\ No newline at end of file
}
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 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;
/**
* @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]);
}
}
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;
/**
* @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));
......
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;
/**
* @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);
......
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;
/**
* @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<String> bindTarget = new ArrayList<String>();
public List<Integer> integerTarget = new ArrayList<Integer>();
}
/*
* 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 {
......
/*
* 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<Integer> result = converter.convert(new String[] { "1", "2", "3" }, new TypeDescriptor<List<Integer>>(getClass().getDeclaredField("genericList")));
List<Integer> result = (List<Integer>) 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<String, FooEnum> map = converter.convert(foo, new TypeDescriptor<Map<String, FooEnum>>(getClass().getField("genericMap")));
Map<String, FooEnum> map = (Map<String, FooEnum>) converter.convert(foo, new TypeDescriptor(getClass().getField("genericMap")));
assertEquals(map.get(1), FooEnum.BAR);
assertEquals(map.get(2), FooEnum.BAZ);
}
......
/*
* 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<Map<String, String>>(getClass().getField("source")),
new TypeDescriptor<Map<String, FooEnum>>(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<String, FooEnum> result = (Map<String, FooEnum>) 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");
......
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);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册