converter system refactoring from community input

This commit is contained in:
Keith Donald 2009-05-14 21:36:49 +00:00
parent a1793457b2
commit 9a261470ad
55 changed files with 296 additions and 905 deletions

View File

@ -22,22 +22,13 @@ import org.springframework.core.style.StylerUtils;
*
* @author Keith Donald
*/
public class ConversionExecutionException extends ConvertException {
public class ConversionException extends ConvertException {
/**
* The value we tried to convert. Transient because we cannot guarantee that the value is Serializable.
*/
private transient Object value;
/**
* The source type we tried to convert the value from.
*/
private Class<?> sourceType;
/**
* The target type we tried to convert the value to.
*/
private TypeDescriptor targetType;
private Class<?> targetType;
/**
* Creates a new conversion exception.
@ -46,7 +37,7 @@ public class ConversionExecutionException extends ConvertException {
* @param targetType the value's target type
* @param cause the cause of the conversion failure
*/
public ConversionExecutionException(Object value, Class<?> sourceType, TypeDescriptor targetType, Throwable cause) {
public ConversionException(Object value, Class<?> sourceType, Class<?> targetType, Throwable cause) {
super(defaultMessage(value, sourceType, targetType, cause), cause);
this.value = value;
this.sourceType = sourceType;
@ -60,7 +51,7 @@ public class ConversionExecutionException extends ConvertException {
* @param targetType the value's target type
* @param message a descriptive message of what went wrong.
*/
public ConversionExecutionException(Object value, Class<?> sourceType, TypeDescriptor targetType, String message) {
public ConversionException(Object value, Class<?> sourceType, Class<?> targetType, String message) {
super(message);
this.value = value;
this.sourceType = sourceType;
@ -84,11 +75,11 @@ public class ConversionExecutionException extends ConvertException {
/**
* Returns the target type we tried to convert the value to.
*/
public TypeDescriptor getTargetType() {
public Class<?> getTargetType() {
return targetType;
}
private static String defaultMessage(Object value, Class<?> sourceType, TypeDescriptor targetType, Throwable cause) {
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() + "'";
}

View File

@ -24,7 +24,7 @@ public class ConverterNotFoundException extends ConvertException {
private Class<?> sourceType;
private TypeDescriptor targetType;
private Class<?> targetType;
/**
* Creates a new conversion executor not found exception.
@ -32,7 +32,7 @@ public class ConverterNotFoundException extends ConvertException {
* @param targetType the target type requested to convert to
* @param message a descriptive message
*/
public ConverterNotFoundException(Class<?> sourceType, TypeDescriptor targetType, String message) {
public ConverterNotFoundException(Class<?> sourceType, Class<?> targetType, String message) {
super(message);
this.sourceType = sourceType;
this.targetType = targetType;
@ -48,7 +48,7 @@ public class ConverterNotFoundException extends ConvertException {
/**
* Returns the target type that was requested to convert to.
*/
public TypeDescriptor getTargetType() {
public Class<?> getTargetType() {
return targetType;
}
}

View File

@ -23,7 +23,7 @@ package org.springframework.core.convert;
*
* @author Keith Donald
*/
public interface ConversionService {
public interface TypeConverter {
/**
* Returns true if objects of sourceType can be converted to targetType.
@ -31,7 +31,7 @@ public interface ConversionService {
* @param targetType context about the target type to convert to
* @return true if a conversion can be performed, false if not
*/
public boolean canConvert(Class<?> sourceType, TypeDescriptor targetType);
boolean canConvert(Class<?> sourceType, TypeDescriptor<?> targetType);
/**
* Convert the source to targetType.
@ -39,8 +39,8 @@ public interface ConversionService {
* @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 during the conversion process
* @throws ConvertException if an exception occurred
*/
public Object convert(Object source, TypeDescriptor targetType);
<S, T> T convert(S source, TypeDescriptor<T> targetType);
}

View File

@ -32,7 +32,7 @@ import org.springframework.util.Assert;
* @author Keith Donald
* @author Andy Clement
*/
public class TypeDescriptor {
public class TypeDescriptor<T> {
/**
* Constant value typeDescriptor for the type of a null value

View File

@ -16,13 +16,13 @@
package org.springframework.core.convert.converter;
import org.springframework.core.convert.ConvertException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeConverter;
/**
* A converter converts a source object of type S to a target of type T and back.
* <p>
* Implementations of this interface are thread-safe and can be shared. Converters are typically registered with and
* accessed through a {@link ConversionService}.
* accessed through a {@link TypeConverter}.
* </p>
* @author Keith Donald
*/
@ -36,6 +36,6 @@ public interface Converter<S, T> {
* system will handle wrapping the failure in a {@link ConvertException} that provides a consistent type
* conversion error context
*/
public T convert(S source) throws Exception;
T convert(S source) throws Exception;
}

View File

@ -15,21 +15,6 @@
*/
package org.springframework.core.convert.converter;
/**
* Converts a String to a Enum using {@link Enum#valueOf(Class, String)}.
*
* @author Keith Donald
* @since 3.0
*/
@SuppressWarnings("unchecked")
public class StringToEnum implements SuperTwoWayConverter<String, Enum> {
public <RT extends Enum> RT convert(String source, Class<RT> targetClass) {
return (RT) Enum.valueOf(targetClass, source);
}
public <RS extends String> RS convertBack(Enum target, Class<RS> sourceClass) {
return (RS) target.name();
}
public interface ConverterFactory<S, R> {
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
}

View File

@ -15,11 +15,11 @@
*/
package org.springframework.core.convert.converter;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeConverter;
/**
* A meta interface a Converter may implement to describe what types he can convert between.
* Implementing this interface is required for converters that do not declare their parameterized types S and T and expect to be registered with a {@link ConversionService}.
* Implementing this interface is required for converters that do not declare their parameterized types S and T and expect to be registered with a {@link TypeConverter}.
* @see Converter
* @see SuperConverter
*/

View File

@ -1,17 +0,0 @@
package org.springframework.core.convert.converter;
import org.springframework.core.convert.service.DefaultConversionService;
/**
* Simply calls {@link Object#toString()} to convert any object to a string.
* Used by the {@link DefaultConversionService} as a fallback if there are no other explicit to string converters registered.
* @author Keith Donald
*/
public class ObjectToString implements SuperConverter<Object, String> {
@SuppressWarnings("unchecked")
public <RT extends String> RT convert(Object source, Class<RT> targetClass) {
return (RT) source.toString();
}
}

View File

@ -1,71 +0,0 @@
/*
* Copyright 2004-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
import org.springframework.util.Assert;
/**
* Converts String to a Boolean. The trueString and falseStrings are configurable.
*
* @see #StringToBoolean(String, String)
* @author Keith Donald
*/
public class StringToBoolean implements TwoWayConverter<String, Boolean> {
private String trueString;
private String falseString;
/**
* Create a StringToBoolean converter with the default 'true' and 'false' strings.
*/
public StringToBoolean() {
this("true", "false");
}
/**
* Create a StringToBoolean converter configured with specific values for true and false strings.
* @param trueString special true string to use (required)
* @param falseString special false string to use (required)
*/
public StringToBoolean(String trueString, String falseString) {
Assert.hasText(trueString, "The true string is required");
Assert.hasText(falseString, "The false string is required");
this.trueString = trueString;
this.falseString = falseString;
}
public Boolean convert(String source) {
if (source.equals(trueString)) {
return Boolean.TRUE;
} else if (source.equals(falseString)) {
return Boolean.FALSE;
} else {
throw new IllegalArgumentException("Invalid boolean string '" + source + "'; expected '" + trueString + "' or '" + falseString + "'");
}
}
public String convertBack(Boolean target) {
if (Boolean.TRUE.equals(target)) {
return trueString;
} else if (Boolean.FALSE.equals(target)) {
return falseString;
} else {
throw new IllegalArgumentException("Invalid boolean value " + target);
}
}
}

View File

@ -1,42 +0,0 @@
/*
* Copyright 2004-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
import org.springframework.core.convert.ConvertException;
import org.springframework.core.convert.ConversionService;
/**
* A super converter converts a source object of type S to a target of class hierarchy T.
* <p>
* Implementations of this interface are thread-safe and can be shared. Converters are typically registered with and
* accessed through a {@link ConversionService}.
* </p>
* @author Keith Donald
*/
public interface SuperConverter<S, T> {
/**
* Convert the source of type S to an instance of type RT.
* @param source the source object to convert, whose class must be equal to or a subclass of S
* @param targetClass the requested target class to convert to (RT), which must be equal to T or extend from T
* @return the converted object, which must be an instance of RT
* @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
* conversion error context
*/
public <RT extends T> RT convert(S source, Class<RT> targetClass) throws Exception;
}

View File

@ -1,42 +0,0 @@
/*
* Copyright 2004-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
import org.springframework.core.convert.ConvertException;
import org.springframework.core.convert.ConversionService;
/**
* A super converter that can also convert a target object of type T to a source of class hierarchy S.
* <p>
* Implementations of this interface are thread-safe and can be shared. Converters are typically registered with and
* accessed through a {@link ConversionService}.
* </p>
* @author Keith Donald
*/
public interface SuperTwoWayConverter<S, T> extends SuperConverter<S, T> {
/**
* Convert the target of type T to an instance of RS.
* @param target the target object to convert, whose class must be equal to or a subclass of T
* @param sourceClass the requested source class to convert to, which must be equal to S or extend from S
* @return the converted object, which must be an instance of RS
* @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
* conversion error context
*/
public <RS extends S> RS convertBack(T target, Class<RS> sourceClass) throws Exception;
}

View File

@ -1,25 +0,0 @@
package org.springframework.core.convert.converter;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.ConvertException;
/**
* A converter that can also convert a target object of type T to a source of class S.
* <p>
* Implementations of this interface are thread-safe and can be shared. Converters are typically registered with and
* accessed through a {@link ConversionService}.
* </p>
* @author Keith Donald
*/
public interface TwoWayConverter<S, T> extends Converter<S, T> {
/**
* Convert the target of type T back to source type S.
* @param target the target object to convert, which must be an instance of T
* @return the converted object, which must be an instance of S
* @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
* conversion error context
*/
public S convertBack(T target) throws Exception;
}

View File

@ -1,7 +1,7 @@
<html>
<body>
<p>
User Converter API and default Converter implementations.
SPI to implement Converters.
</p>
</body>
</html>

View File

@ -1,7 +1,7 @@
<html>
<body>
<p>
Type conversion system SPI.
Type conversion system API.
</p>
</body>
</html>

View File

@ -1,38 +0,0 @@
/*
* Copyright 2004-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
import org.springframework.core.convert.converter.SuperConverter;
import org.springframework.core.convert.converter.SuperTwoWayConverter;
/**
* A super converter that reverses another super converter.
* @author Keith Donald
*/
@SuppressWarnings("unchecked")
class ReverseSuperConverter implements SuperConverter {
private SuperTwoWayConverter converter;
public ReverseSuperConverter(SuperTwoWayConverter converter) {
this.converter = converter;
}
public Object convert(Object source, Class targetClass) throws Exception {
return converter.convertBack(source, targetClass);
}
}

View File

@ -1,73 +0,0 @@
/*
* Copyright 2004-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
import org.springframework.core.convert.ConversionExecutionException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.SuperConverter;
import org.springframework.core.style.ToStringCreator;
/**
* Default conversion executor implementation for super converters.
* @author Keith Donald
*/
@SuppressWarnings("unchecked")
class StaticSuperConversionExecutor implements ConversionExecutor {
private final TypeDescriptor sourceType;
private final TypeDescriptor targetType;
private final SuperConverter converter;
public StaticSuperConversionExecutor(TypeDescriptor sourceType, TypeDescriptor targetType, SuperConverter converter) {
this.sourceType = sourceType;
this.targetType = targetType;
this.converter = converter;
}
public Object execute(Object source) throws ConversionExecutionException {
if (source == null) {
return null;
}
if (!sourceType.isInstance(source)) {
throw new ConversionExecutionException(source, sourceType.getType(), targetType, "Source object "
+ source + " to convert is expected to be an instance of [" + sourceType.getName() + "]");
}
try {
return converter.convert(source, targetType.getType());
} catch (Exception e) {
throw new ConversionExecutionException(source, sourceType.getType(), targetType, e);
}
}
public boolean equals(Object o) {
if (!(o instanceof StaticSuperConversionExecutor)) {
return false;
}
StaticSuperConversionExecutor other = (StaticSuperConversionExecutor) o;
return sourceType.equals(other.sourceType) && targetType.equals(other.targetType);
}
public int hashCode() {
return sourceType.hashCode() + targetType.hashCode();
}
public String toString() {
return new ToStringCreator(this).append("sourceClass", sourceType).append("targetClass", targetType)
.toString();
}
}

View File

@ -1,58 +0,0 @@
/*
* Copyright 2004-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterInfo;
import org.springframework.core.convert.converter.SuperConverter;
import org.springframework.core.convert.converter.SuperTwoWayConverter;
/**
* Adapts a {@link SuperTwoWayConverter} to the {@link Converter} interface in a type safe way. This adapter is useful
* for applying more general {@link SuperConverter} logic to a specific source/target class pair.
*/
@SuppressWarnings("unchecked")
class SuperTwoWayConverterConverter implements Converter, ConverterInfo {
private SuperTwoWayConverter superConverter;
private Class sourceType;
private Class targetType;
public SuperTwoWayConverterConverter(SuperTwoWayConverter superConverter, Class sourceType, Class targetType) {
this.superConverter = superConverter;
this.sourceType = sourceType;
this.targetType = targetType;
}
public Class getSourceType() {
return sourceType;
}
public Class getTargetType() {
return targetType;
}
public Object convert(Object source) throws Exception {
return superConverter.convert(source, targetType);
}
public Object convertBack(Object target) throws Exception {
return superConverter.convertBack(target, sourceType);
}
}

View File

@ -1,7 +0,0 @@
<html>
<body>
<p>
ConversionService implementation.
</p>
</body>
</html>

View File

@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import org.springframework.core.convert.ConversionExecutionException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.TypeDescriptor;
/**
@ -72,11 +71,11 @@ abstract class AbstractCollectionConverter implements ConversionExecutor {
return elementConverter;
}
public Object execute(Object source) throws ConversionExecutionException {
public Object execute(Object source) {
try {
return doExecute(source);
} catch (Exception e) {
throw new ConversionExecutionException(source, sourceCollectionType.getType(), targetCollectionType, e);
throw new ConversionException(source, sourceCollectionType.getType(), targetCollectionType.getType(), e);
}
}

View File

@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import java.lang.reflect.Array;
import org.springframework.core.convert.ConversionService;
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 ConversionService} implementations.
* {@link TypeConverter} implementations.
*
* @author Keith Donald
*/
@ -34,7 +34,7 @@ class ArrayToArray extends AbstractCollectionConverter {
}
@Override
public Object doExecute(Object sourceArray) throws Exception {
public Object doExecute(Object sourceArray) {
int length = Array.getLength(sourceArray);
Object targetArray = Array.newInstance(getTargetElementType(), length);
for (int i = 0; i < length; i++) {

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import java.lang.reflect.Array;
import java.util.Collection;

View File

@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.util.NumberUtils;
/**
* Converts from any JDK-standard Number implementation to a Character and back.
* Converts from a Character to any JDK-standard Number implementation.
*
* 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.
@ -35,15 +37,23 @@ import org.springframework.util.NumberUtils;
*
* @author Keith Donald
*/
public class NumberToCharacter implements SuperTwoWayConverter<Number, Character> {
public class CharacterToNumberFactory implements ConverterFactory<Character, Number> {
@SuppressWarnings("unchecked")
public <RT extends Character> RT convert(Number source, Class<RT> targetClass) {
return (RT) Character.valueOf((char) source.shortValue());
public <T extends Number> Converter<Character, T> getConverter(Class<T> targetType) {
return new CharacterToNumber<T>(targetType);
}
public <RS extends Number> RS convertBack(Character target, Class<RS> sourceClass) {
return NumberUtils.convertNumberToTargetClass((short) target.charValue(), sourceClass);
private static class CharacterToNumber<T extends Number> implements Converter<Character, T> {
private Class<T> targetType;
public CharacterToNumber(Class<T> targetType) {
this.targetType = targetType;
}
public T convert(Character source) throws Exception {
return NumberUtils.convertNumberToTargetClass((short) source.charValue(), targetType);
}
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import java.util.ArrayList;
import java.util.Collection;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import java.lang.reflect.Array;
import java.util.Collection;
@ -57,7 +57,7 @@ class CollectionToArray extends AbstractCollectionConverter {
}
}
}
return elementConverter;
return elementConverter != null ? elementConverter : NoOpConversionExecutor.INSTANCE;
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import java.util.Collection;
import java.util.Iterator;

View File

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import org.springframework.core.convert.ConversionExecutionException;
import org.springframework.core.convert.ConversionException;
/**
* A command parameterized with the information necessary to perform a conversion of a source input to a
@ -29,7 +29,7 @@ public interface ConversionExecutor {
/**
* Convert the source.
* @param source the source to convert
* @throws ConversionExecutionException if an exception occurs during type conversion
* @throws ConversionException if an exception occurs during type conversion
*/
public Object execute(Object source);

View File

@ -13,28 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Locale;
import org.springframework.core.convert.converter.NumberToCharacter;
import org.springframework.core.convert.converter.NumberToNumber;
import org.springframework.core.convert.converter.ObjectToString;
import org.springframework.core.convert.converter.StringToBigDecimal;
import org.springframework.core.convert.converter.StringToBigInteger;
import org.springframework.core.convert.converter.StringToBoolean;
import org.springframework.core.convert.converter.StringToByte;
import org.springframework.core.convert.converter.StringToCharacter;
import org.springframework.core.convert.converter.StringToDouble;
import org.springframework.core.convert.converter.StringToEnum;
import org.springframework.core.convert.converter.StringToFloat;
import org.springframework.core.convert.converter.StringToInteger;
import org.springframework.core.convert.converter.StringToLocale;
import org.springframework.core.convert.converter.StringToLong;
import org.springframework.core.convert.converter.StringToShort;
import org.springframework.core.convert.support.StringToEnumFactory.StringToEnum;
/**
* Default implementation of a conversion service. Will automatically register <i>from string</i> converters for
@ -66,8 +47,6 @@ public class DefaultConversionService extends GenericConversionService {
addConverter(new StringToBigInteger());
addConverter(new StringToBigDecimal());
addConverter(new StringToLocale());
addConverter(new StringToEnum());
addConverter(new NumberToNumber());
addConverter(new NumberToCharacter());
addConverter(new ObjectToString());
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@ -26,14 +26,11 @@ 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.ConverterInfo;
import org.springframework.core.convert.converter.SuperConverter;
import org.springframework.core.convert.converter.SuperTwoWayConverter;
import org.springframework.core.convert.converter.TwoWayConverter;
import org.springframework.util.Assert;
/**
@ -46,7 +43,7 @@ import org.springframework.util.Assert;
* @author Keith Donald
*/
@SuppressWarnings("unchecked")
public class GenericConversionService implements ConversionService {
public class GenericConversionService implements TypeConverter {
/**
* An indexed map of Converters. Each Map.Entry key is a source class (S) that can be converted from. Each Map.Entry
@ -54,28 +51,22 @@ public class GenericConversionService implements ConversionService {
*/
private final Map sourceTypeConverters = new HashMap();
/**
* An indexed map of SuperConverters. 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-SuperConverter mappings for that source.
*/
private final Map sourceTypeSuperConverters = new HashMap();
/**
* An optional parent conversion service.
*/
private ConversionService parent;
private TypeConverter parent;
/**
* Returns the parent of this conversion service. Could be null.
*/
public ConversionService getParent() {
public TypeConverter getParent() {
return parent;
}
/**
* Set the parent of this conversion service. This is optional.
*/
public void setParent(ConversionService parent) {
public void setParent(TypeConverter parent) {
this.parent = parent;
}
@ -90,47 +81,11 @@ public class GenericConversionService implements ConversionService {
// index forward
Map sourceMap = getSourceMap(sourceType);
sourceMap.put(targetType, converter);
if (converter instanceof TwoWayConverter) {
// index reverse
sourceMap = getSourceMap(targetType);
sourceMap.put(sourceType, new ReverseConverter((TwoWayConverter) converter));
}
}
/**
* Register the SuperConverter with this conversion service.
* @param converter the super converter to register
*/
public void addConverter(SuperConverter converter) {
List typeInfo = getRequiredTypeInfo(converter);
Class sourceType = (Class) typeInfo.get(0);
Class targetType = (Class) typeInfo.get(1);
// index forward
Map sourceMap = getSourceSuperConverterMap(sourceType);
sourceMap.put(targetType, converter);
if (converter instanceof SuperTwoWayConverter) {
// index reverse
sourceMap = getSourceSuperConverterMap(targetType);
sourceMap.put(sourceType, new ReverseSuperConverter((SuperTwoWayConverter) converter));
}
}
/**
* Adapts a {@link SuperTwoWayConverter} that converts between BS and BT class hierarchies to a {@link Converter}
* that converts between the specific BS/BT sub types S and T.
* @param sourceType the source class S to convert from, which must be equal or extend BS
* @param targetType the target type T to convert to, which must equal or extend BT
* @param converter the super two way converter
* @return a converter that converts from S to T by delegating to the super converter
*/
public static <S, T> Converter<S, T> converterFor(Class<S> sourceType, Class<T> targetType,
SuperTwoWayConverter converter) {
return new SuperTwoWayConverterConverter(converter, sourceType, targetType);
}
// implementing ConversionService
public boolean canConvert(Class<?> sourceType, TypeDescriptor targetType) {
public boolean canConvert(Class<?> sourceType, TypeDescriptor<?> targetType) {
ConversionExecutor executor = getConversionExecutor(sourceType, targetType);
if (executor != null) {
return true;
@ -147,6 +102,9 @@ public class GenericConversionService implements ConversionService {
if (source == null) {
return null;
}
if (source.getClass().isAssignableFrom(targetType.getType())) {
return source;
}
ConversionExecutor executor = getConversionExecutor(source.getClass(), targetType);
if (executor != null) {
return executor.execute(source);
@ -154,7 +112,7 @@ public class GenericConversionService implements ConversionService {
if (parent != null) {
return parent.convert(source, targetType);
} else {
throw new ConverterNotFoundException(source.getClass(), targetType,
throw new ConverterNotFoundException(source.getClass(), targetType.getType(),
"No converter found that can convert from sourceType [" + source.getClass().getName()
+ "] to targetType [" + targetType.getName() + "]");
}
@ -203,17 +161,9 @@ public class GenericConversionService implements ConversionService {
if (converter != null) {
return new StaticConversionExecutor(sourceType, targetType, converter);
} else {
SuperConverter superConverter = findRegisteredSuperConverter(sourceClass, targetType.getType());
if (superConverter != null) {
return new StaticSuperConversionExecutor(sourceType, targetType, superConverter);
} else {
if (sourceType.isAssignableTo(targetType)) {
return new StaticConversionExecutor(sourceType, targetType, NoOpConverter.INSTANCE);
}
return null;
}
}
}
// internal helpers
@ -231,8 +181,7 @@ public class GenericConversionService implements ConversionService {
for (Type genericInterface : genericInterfaces) {
if (genericInterface instanceof ParameterizedType) {
ParameterizedType pInterface = (ParameterizedType) genericInterface;
if (Converter.class.isAssignableFrom((Class) pInterface.getRawType())
|| SuperConverter.class.isAssignableFrom((Class) pInterface.getRawType())) {
if (Converter.class.isAssignableFrom((Class) pInterface.getRawType())) {
Class s = getParameterClass(pInterface.getActualTypeArguments()[0], converter.getClass());
Class t = getParameterClass(pInterface.getActualTypeArguments()[1], converter.getClass());
typeInfo.add(getParameterClass(s, converter.getClass()));
@ -270,15 +219,6 @@ public class GenericConversionService implements ConversionService {
return sourceMap;
}
private Map getSourceSuperConverterMap(Class sourceType) {
Map sourceMap = (Map) sourceTypeSuperConverters.get(sourceType);
if (sourceMap == null) {
sourceMap = new HashMap();
sourceTypeSuperConverters.put(sourceType, sourceMap);
}
return sourceMap;
}
private Converter findRegisteredConverter(Class<?> sourceType, Class<?> targetType) {
if (sourceType.isInterface()) {
LinkedList classQueue = new LinkedList();
@ -328,89 +268,4 @@ public class GenericConversionService implements ConversionService {
return (Converter) converters.get(targetType);
}
private SuperConverter findRegisteredSuperConverter(Class<?> sourceType, Class<?> targetType) {
if (sourceType.isInterface()) {
LinkedList classQueue = new LinkedList();
classQueue.addFirst(sourceType);
while (!classQueue.isEmpty()) {
Class currentClass = (Class) classQueue.removeLast();
Map converters = getSuperConvertersForSource(currentClass);
SuperConverter converter = findSuperConverter(converters, targetType);
if (converter != null) {
return converter;
}
Class[] interfaces = currentClass.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
classQueue.addFirst(interfaces[i]);
}
}
Map objectConverters = getSuperConvertersForSource(Object.class);
return findSuperConverter(objectConverters, targetType);
} else {
LinkedList classQueue = new LinkedList();
classQueue.addFirst(sourceType);
while (!classQueue.isEmpty()) {
Class currentClass = (Class) classQueue.removeLast();
Map converters = getSuperConvertersForSource(currentClass);
SuperConverter converter = findSuperConverter(converters, targetType);
if (converter != null) {
return converter;
}
if (currentClass.getSuperclass() != null) {
classQueue.addFirst(currentClass.getSuperclass());
}
Class[] interfaces = currentClass.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
classQueue.addFirst(interfaces[i]);
}
}
return null;
}
}
private Map getSuperConvertersForSource(Class sourceType) {
Map converters = (Map) sourceTypeSuperConverters.get(sourceType);
return converters != null ? converters : Collections.emptyMap();
}
private SuperConverter findSuperConverter(Map converters, Class targetType) {
if (converters.isEmpty()) {
return null;
}
if (targetType.isInterface()) {
LinkedList classQueue = new LinkedList();
classQueue.addFirst(targetType);
while (!classQueue.isEmpty()) {
Class currentClass = (Class) classQueue.removeLast();
SuperConverter converter = (SuperConverter) converters.get(currentClass);
if (converter != null) {
return converter;
}
Class[] interfaces = currentClass.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
classQueue.addFirst(interfaces[i]);
}
}
return (SuperConverter) converters.get(Object.class);
} else {
LinkedList classQueue = new LinkedList();
classQueue.addFirst(targetType);
while (!classQueue.isEmpty()) {
Class currentClass = (Class) classQueue.removeLast();
SuperConverter converter = (SuperConverter) converters.get(currentClass);
if (converter != null) {
return converter;
}
if (currentClass.getSuperclass() != null) {
classQueue.addFirst(currentClass.getSuperclass());
}
Class[] interfaces = currentClass.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
classQueue.addFirst(interfaces[i]);
}
}
return null;
}
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import java.util.HashMap;
import java.util.Iterator;
@ -21,8 +21,7 @@ import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.springframework.core.convert.ConversionExecutionException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.TypeDescriptor;
/**
@ -65,7 +64,7 @@ class MapToMap implements ConversionExecutor {
}
@SuppressWarnings("unchecked")
public Object execute(Object source) throws ConversionExecutionException {
public Object execute(Object source) throws ConversionException {
try {
Map map = (Map) source;
Map targetMap = (Map) getImpl(targetType.getType()).newInstance();
@ -77,7 +76,7 @@ class MapToMap implements ConversionExecutor {
}
return targetMap;
} catch (Exception e) {
throw new ConversionExecutionException(source, sourceType.getType(), targetType, e);
throw new ConversionException(source, sourceType.getType(), targetType.getType(), e);
}
}

View File

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import org.springframework.core.convert.ConversionExecutionException;
import org.springframework.core.convert.ConversionException;
/**
* Conversion executor that does nothing. Access singleton at {@link #INSTANCE}.s
@ -28,7 +28,7 @@ class NoOpConversionExecutor implements ConversionExecutor {
}
public Object execute(Object source) throws ConversionExecutionException {
public Object execute(Object source) throws ConversionException {
return source;
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;

View File

@ -0,0 +1,40 @@
/*
* 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 org.springframework.core.convert.converter.Converter;
import org.springframework.util.NumberUtils;
/**
* Converts from any JDK-standard Number implementation to a Character.
*
* @see java.lang.Character
* @see java.lang.Short
* @see java.lang.Integer
* @see java.lang.Long
* @see java.math.BigInteger
* @see java.lang.Float
* @see java.lang.Double
* @see java.math.BigDecimal
* @see NumberUtils
*
* @author Keith Donald
*/
public class NumberToCharacter implements Converter<Number, Character> {
public Character convert(Number source) {
return Character.valueOf((char) source.shortValue());
}
}

View File

@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.util.NumberUtils;
/**
@ -35,10 +37,23 @@ import org.springframework.util.NumberUtils;
*
* @author Keith Donald
*/
public class NumberToNumber implements SuperConverter<Number, Number> {
public class NumberToNumberFactory implements ConverterFactory<Number, Number> {
public <RT extends Number> RT convert(Number source, Class<RT> targetClass) {
return NumberUtils.convertNumberToTargetClass(source, targetClass);
public <T extends Number> Converter<Number, T> getConverter(Class<T> targetType) {
return new NumberToNumber<T>(targetType);
}
private static class NumberToNumber<T extends Number> implements Converter<Number, T> {
private Class<T> targetType;
public NumberToNumber(Class<T> targetType) {
this.targetType = targetType;
}
public T convert(Number source) throws Exception {
return NumberUtils.convertNumberToTargetClass(source, targetType);
}
}
}

View File

@ -0,0 +1,14 @@
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 DefaultConversionService} as a fallback if there are no other explicit to string converters registered.
* @author Keith Donald
*/
public class ObjectToString implements Converter<Object, String> {
public String convert(Object source) {
return source.toString();
}
}

View File

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import org.springframework.core.convert.ConversionExecutionException;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.style.ToStringCreator;
@ -39,18 +39,18 @@ class StaticConversionExecutor implements ConversionExecutor {
this.converter = converter;
}
public Object execute(Object source) throws ConversionExecutionException {
public Object execute(Object source) throws ConversionException {
if (source == null) {
return null;
}
if (sourceType != null && !sourceType.isInstance(source)) {
throw new ConversionExecutionException(source, sourceType.getType(), targetType, "Source object "
throw new ConversionException(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 ConversionExecutionException(source, sourceType.getType(), targetType, e);
throw new ConversionException(source, sourceType.getType(), targetType.getType(), e);
}
}

View File

@ -13,23 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import java.math.BigDecimal;
import org.springframework.core.convert.converter.Converter;
/**
* Converts a String to a BigDecimal using {@link BigDecimal#BigDecimal(String).
*
* @author Keith Donald
*/
public class StringToBigDecimal implements TwoWayConverter<String, BigDecimal> {
public class StringToBigDecimal implements Converter<String, BigDecimal> {
public BigDecimal convert(String source) {
return new BigDecimal(source);
}
public String convertBack(BigDecimal target) {
return target.toString();
}
}

View File

@ -13,23 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import java.math.BigInteger;
import org.springframework.core.convert.converter.Converter;
/**
* Converts a String to a BigInteger using {@link BigInteger#BigInteger(String)}.
*
* @author Keith Donald
*/
public class StringToBigInteger implements TwoWayConverter<String, BigInteger> {
public class StringToBigInteger implements Converter<String, BigInteger> {
public BigInteger convert(String source) {
return new BigInteger(source);
}
public String convertBack(BigInteger target) {
return target.toString();
}
}

View File

@ -13,26 +13,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.TwoWayConverter;
/**
* A converter that reverses another converter.
* Converts String to a Boolean. The trueString and falseStrings are configurable.
*
* @see #StringToBoolean(String, String)
* @author Keith Donald
*/
@SuppressWarnings("unchecked")
class ReverseConverter implements Converter {
public class StringToBoolean implements Converter<String, Boolean> {
private TwoWayConverter converter;
public ReverseConverter(TwoWayConverter converter) {
this.converter = converter;
public Boolean convert(String source) {
if (source.equals("true")) {
return Boolean.TRUE;
} else if (source.equals("false")) {
return Boolean.FALSE;
} else {
throw new IllegalArgumentException("Invalid boolean string '" + source + "'; expected 'true' or 'false'");
}
public Object convert(Object source) throws Exception {
return converter.convertBack(source);
}
}

View File

@ -13,21 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
/**
* Converts a String to a Byte and back.
*
* @author Keith Donald
*/
public class StringToByte implements TwoWayConverter<String, Byte> {
public class StringToByte implements Converter<String, Byte> {
public Byte convert(String source) {
return Byte.valueOf(source);
}
public String convertBack(Byte target) {
return target.toString();
}
}

View File

@ -13,24 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
/**
* Converts a String to a Character and back.
*
* @author Keith Donald
*/
public class StringToCharacter implements TwoWayConverter<String, Character> {
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));
}
public String convertBack(Character target) {
return target.toString();
}
}

View File

@ -13,21 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
/**
* Converts a String to a Double using {@link Double#valueOf(String)}.
*
* @author Keith Donald
*/
public class StringToDouble implements TwoWayConverter<String, Double> {
public class StringToDouble implements Converter<String, Double> {
public Double convert(String source) {
return Double.valueOf(source);
}
public String convertBack(Double target) {
return target.toString();
}
}

View File

@ -0,0 +1,26 @@
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
@SuppressWarnings("unchecked")
public class StringToEnumFactory implements ConverterFactory<String, Enum> {
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToEnum(targetType);
}
class StringToEnum<T extends Enum> implements Converter<String, T> {
private Class<T> enumType;
public StringToEnum(Class<T> enumType) {
this.enumType = enumType;
}
public T convert(String source) throws Exception {
return Enum.valueOf(enumType, source);
}
}
}

View File

@ -13,21 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
/**
* Converts a String to Float using {@link Float#valueOf(String)}.
*
* @author Keith Donald
*/
public class StringToFloat implements TwoWayConverter<String, Float> {
public class StringToFloat implements Converter<String, Float> {
public Float convert(String source) {
return Float.valueOf(source);
}
public String convertBack(Float target) {
return target.toString();
}
}

View File

@ -13,21 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
/**
* Converts a String to an Integer using {@link Integer#valueOf(String)}.
*
* @author Keith Donald
*/
public class StringToInteger implements TwoWayConverter<String, Integer> {
public class StringToInteger implements Converter<String, Integer> {
public Integer convert(String source) {
return Integer.valueOf(source);
}
public String convertBack(Integer target) {
return target.toString();
}
}

View File

@ -13,25 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import java.util.Locale;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.StringUtils;
/**
* Converts a String to a Locale using {@link StringUtils#parseLocaleString(String)}.
*
* @author Keith Donald
*/
public class StringToLocale implements TwoWayConverter<String, Locale> {
public class StringToLocale implements Converter<String, Locale> {
public Locale convert(String source) {
return StringUtils.parseLocaleString(source);
}
public String convertBack(Locale target) {
return target.toString();
}
}

View File

@ -13,21 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
/**
* Converts a String to a Long using {@link Long#valueOf(String)}.
*
* @author Keith Donald
*/
public class StringToLong implements TwoWayConverter<String, Long> {
public class StringToLong implements Converter<String, Long> {
public Long convert(String source) {
return Long.valueOf(source);
}
public String convertBack(Long target) {
return target.toString();
}
}

View File

@ -13,21 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.converter;
package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
/**
* Converts a String to a Short using {@link Short#valueOf(String)}.
*
* @author Keith Donald
*/
public class StringToShort implements TwoWayConverter<String, Short> {
public class StringToShort implements Converter<String, Short> {
public Short convert(String source) {
return Short.valueOf(source);
}
public String convertBack(Short target) {
return target.toString();
}
}

View File

@ -0,0 +1,7 @@
<html>
<body>
<p>
TypeConverter system implementation.
</p>
</body>
</html>

View File

@ -8,21 +8,22 @@ import java.math.BigInteger;
import java.util.Locale;
import org.junit.Test;
import org.springframework.core.convert.converter.NumberToCharacter;
import org.springframework.core.convert.converter.NumberToNumber;
import org.springframework.core.convert.converter.ObjectToString;
import org.springframework.core.convert.converter.StringToBigDecimal;
import org.springframework.core.convert.converter.StringToBigInteger;
import org.springframework.core.convert.converter.StringToBoolean;
import org.springframework.core.convert.converter.StringToByte;
import org.springframework.core.convert.converter.StringToCharacter;
import org.springframework.core.convert.converter.StringToDouble;
import org.springframework.core.convert.converter.StringToEnum;
import org.springframework.core.convert.converter.StringToFloat;
import org.springframework.core.convert.converter.StringToInteger;
import org.springframework.core.convert.converter.StringToLocale;
import org.springframework.core.convert.converter.StringToLong;
import org.springframework.core.convert.converter.StringToShort;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.NumberToCharacter;
import org.springframework.core.convert.support.NumberToNumberFactory;
import org.springframework.core.convert.support.ObjectToString;
import org.springframework.core.convert.support.StringToBigDecimal;
import org.springframework.core.convert.support.StringToBigInteger;
import org.springframework.core.convert.support.StringToBoolean;
import org.springframework.core.convert.support.StringToByte;
import org.springframework.core.convert.support.StringToCharacter;
import org.springframework.core.convert.support.StringToDouble;
import org.springframework.core.convert.support.StringToEnumFactory;
import org.springframework.core.convert.support.StringToFloat;
import org.springframework.core.convert.support.StringToInteger;
import org.springframework.core.convert.support.StringToLocale;
import org.springframework.core.convert.support.StringToLong;
import org.springframework.core.convert.support.StringToShort;
/**
* Tests for the default converters in the converters package.
@ -33,14 +34,12 @@ public class DefaultConverterTests {
public void testStringToByte() throws Exception {
StringToByte b = new StringToByte();
assertEquals(Byte.valueOf("1"), b.convert("1"));
assertEquals("1", b.convertBack(Byte.valueOf("1")));
}
@Test
public void testStringToCharacter() {
StringToCharacter c = new StringToCharacter();
assertEquals(Character.valueOf('1'), c.convert("1"));
assertEquals("1", c.convertBack(Character.valueOf('1')));
}
@Test
@ -48,84 +47,54 @@ public class DefaultConverterTests {
StringToBoolean c = new StringToBoolean();
assertEquals(Boolean.valueOf(true), c.convert("true"));
assertEquals(Boolean.valueOf(false), c.convert("false"));
assertEquals("true", c.convertBack(Boolean.TRUE));
assertEquals("false", c.convertBack(Boolean.FALSE));
}
@Test
public void testStringToBooleanCustomString() {
StringToBoolean c = new StringToBoolean("yes", "no");
assertEquals(Boolean.valueOf(true), c.convert("yes"));
assertEquals(Boolean.valueOf(false), c.convert("no"));
assertEquals("yes", c.convertBack(Boolean.TRUE));
assertEquals("no", c.convertBack(Boolean.FALSE));
}
@Test
public void testStringToBooleanInvalidValue() {
StringToBoolean c = new StringToBoolean("yes", "no");
try {
c.convert("true");
fail("Should have failed");
} catch (IllegalArgumentException e) {
}
}
@Test
public void testStringToShort() {
StringToShort c = new StringToShort();
assertEquals(Short.valueOf("1"), c.convert("1"));
assertEquals("1", c.convertBack(Short.valueOf("1")));
}
@Test
public void testStringToInteger() {
StringToInteger c = new StringToInteger();
assertEquals(Integer.valueOf("1"), c.convert("1"));
assertEquals("1", c.convertBack(Integer.valueOf("1")));
}
@Test
public void testStringToLong() {
StringToLong c = new StringToLong();
assertEquals(Long.valueOf("1"), c.convert("1"));
assertEquals("1", c.convertBack(Long.valueOf("1")));
}
@Test
public void testStringToFloat() {
StringToFloat c = new StringToFloat();
assertEquals(Float.valueOf("1.0"), c.convert("1.0"));
assertEquals("1.0", c.convertBack(Float.valueOf("1.0")));
}
@Test
public void testStringToDouble() {
StringToDouble c = new StringToDouble();
assertEquals(Double.valueOf("1.0"), c.convert("1.0"));
assertEquals("1.0", c.convertBack(Double.valueOf("1.0")));
}
@Test
public void testStringToBigInteger() {
StringToBigInteger c = new StringToBigInteger();
assertEquals(new BigInteger("1"), c.convert("1"));
assertEquals("1", c.convertBack(new BigInteger("1")));
}
@Test
public void testStringToBigDouble() {
StringToBigDecimal c = new StringToBigDecimal();
assertEquals(new BigDecimal("1.0"), c.convert("1.0"));
assertEquals("1.0", c.convertBack(new BigDecimal("1.0")));
}
@Test
public void testStringToEnum() {
StringToEnum c = new StringToEnum();
assertEquals(Foo.BAR, c.convert("BAR", Foo.class));
assertEquals("BAR", c.convertBack(Foo.BAR, String.class));
public void testStringToEnum() throws Exception {
Converter<String, Foo> c = new StringToEnumFactory().getConverter(Foo.class);
assertEquals(Foo.BAR, c.convert("BAR"));
}
public static enum Foo {
@ -136,20 +105,19 @@ public class DefaultConverterTests {
public void testStringToLocale() {
StringToLocale c = new StringToLocale();
assertEquals(Locale.ENGLISH, c.convert("en"));
assertEquals("en", c.convertBack(Locale.ENGLISH));
}
@Test
public void testNumberToNumber() {
NumberToNumber n = new NumberToNumber();
assertEquals(Long.valueOf(1), n.convert(Integer.valueOf(1), Long.class));
public void testNumberToNumber() throws Exception {
Converter<Number, Long> c = new NumberToNumberFactory().getConverter(Long.class);
assertEquals(Long.valueOf(1), c.convert(Integer.valueOf(1)));
}
@Test
public void testNumberToNumberNotSupportedNumber() {
NumberToNumber n = new NumberToNumber();
public void testNumberToNumberNotSupportedNumber() throws Exception {
Converter<Number, CustomNumber> c = new NumberToNumberFactory().getConverter(CustomNumber.class);
try {
n.convert(Integer.valueOf(1), CustomNumber.class);
c.convert(Integer.valueOf(1));
fail("Should have failed");
} catch (IllegalArgumentException e) {
@ -159,14 +127,13 @@ public class DefaultConverterTests {
@Test
public void testNumberToCharacter() {
NumberToCharacter n = new NumberToCharacter();
assertEquals(Character.valueOf('A'), n.convert(Integer.valueOf(65), Character.class));
assertEquals(Integer.valueOf(65), n.convertBack(Character.valueOf('A'), Integer.class));
assertEquals(Character.valueOf('A'), n.convert(Integer.valueOf(65)));
}
@Test
public void testObjectToString() {
ObjectToString o = new ObjectToString();
assertEquals("3", o.convert(3, String.class));
assertEquals("3", o.convert(3));
}
public static class CustomNumber extends Number {

View File

@ -1,9 +1,11 @@
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.ArrayToArray;
import org.springframework.core.convert.support.DefaultConversionService;
public class ArrayToArrayTests {

View File

@ -1,4 +1,4 @@
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import static org.junit.Assert.assertEquals;
@ -10,6 +10,8 @@ import java.util.SortedSet;
import org.junit.Test;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.ArrayToCollection;
import org.springframework.core.convert.support.DefaultConversionService;
public class ArrayToCollectionTests {

View File

@ -1,4 +1,4 @@
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import static org.junit.Assert.assertEquals;
@ -7,6 +7,8 @@ import java.util.Collection;
import org.junit.Test;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.CollectionToArray;
import org.springframework.core.convert.support.DefaultConversionService;
public class CollectionToArrayTests {

View File

@ -1,4 +1,4 @@
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@ -9,6 +9,8 @@ import java.util.List;
import org.junit.Test;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.CollectionToCollection;
import org.springframework.core.convert.support.DefaultConversionService;
public class CollectionToCollectionTests {

View File

@ -13,11 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.fail;
import java.util.AbstractList;
@ -30,13 +29,10 @@ import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.core.convert.ConversionExecutionException;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.NumberToNumber;
import org.springframework.core.convert.converter.StringToEnum;
import org.springframework.core.convert.converter.StringToInteger;
public class GenericConversionServiceTests {
@ -59,27 +55,13 @@ public class GenericConversionServiceTests {
}
@Test
public void executeCompatibleSource2() {
assertEquals(3, service.getConversionExecutor(Integer.class, TypeDescriptor.valueOf(int.class)).execute(new Integer(3)));
assertEquals(3, service.getConversionExecutor(int.class, TypeDescriptor.valueOf(Integer.class)).execute(3));
}
@Test
public void converterConvertForwardIndex() {
public void converterConvert() {
service.addConverter(new StringToInteger());
ConversionExecutor executor = service.getConversionExecutor(String.class, type(Integer.class));
Integer three = (Integer) executor.execute("3");
assertEquals(3, three.intValue());
}
@Test
public void convertReverseIndex() {
service.addConverter(new StringToInteger());
ConversionExecutor executor = service.getConversionExecutor(Integer.class, type(String.class));
String threeString = (String) executor.execute(new Integer(3));
assertEquals("3", threeString);
}
@Test
public void convertExecutorNotFound() {
try {
@ -107,12 +89,6 @@ public class GenericConversionServiceTests {
}
}
@Test
public void convertCompatibleTypes() {
String source = "foo";
assertSame(source, service.getConversionExecutor(String.class, type(String.class)).execute(source));
}
@Test
public void convertNull() {
service.addConverter(new StringToInteger());
@ -123,11 +99,10 @@ public class GenericConversionServiceTests {
@Test
public void convertWrongTypeArgument() {
service.addConverter(new StringToInteger());
ConversionExecutor executor = service.getConversionExecutor(Integer.class, type(String.class));
try {
executor.execute("BOGUS");
service.convert("BOGUS", type(Integer.class));
fail("Should have failed");
} catch (ConversionExecutionException e) {
} catch (ConversionException e) {
}
}
@ -265,12 +240,13 @@ public class GenericConversionServiceTests {
public Map<Integer, FooEnum> genericMap = new HashMap<Integer, FooEnum>();
@Test
@Ignore
public void convertMapToMap() throws Exception {
Map<String, String> foo = new HashMap<String, String>();
foo.put("1", "BAR");
foo.put("2", "BAZ");
service.addConverter(new StringToInteger());
service.addConverter(new StringToEnum());
service.addConverter(new StringToEnumFactory().getConverter(FooEnum.class));
service.convert(foo, new TypeDescriptor(getClass().getField("genericMap")));
}
@ -297,71 +273,6 @@ public class GenericConversionServiceTests {
BAR, BAZ
}
@Test
public void superConverterConvertForwardIndex() {
service.addConverter(new StringToEnum());
ConversionExecutor executor = service.getConversionExecutor(String.class, type(FooEnum.class));
assertEquals(FooEnum.BAR, executor.execute("BAR"));
}
@Test
public void superTwoWayConverterConvertReverseIndex() {
service.addConverter(new StringToEnum());
ConversionExecutor executor = service.getConversionExecutor(FooEnum.class, type(String.class));
assertEquals("BAR", executor.execute(FooEnum.BAR));
}
@Test
public void superConverterConvertNotConvertibleAbstractType() {
service.addConverter(new StringToEnum());
ConversionExecutor executor = service.getConversionExecutor(String.class, type(Enum.class));
try {
executor.execute("WHATEV");
fail("Should have failed");
} catch (ConversionExecutionException e) {
}
}
@Test
public void superConverterConvertNotConvertibleAbstractType2() {
service.addConverter(new NumberToNumber());
Number customNumber = new Number() {
@Override
public double doubleValue() {
return 0;
}
@Override
public float floatValue() {
return 0;
}
@Override
public int intValue() {
return 0;
}
@Override
public long longValue() {
return 0;
}
};
ConversionExecutor executor = service.getConversionExecutor(Integer.class, type(customNumber.getClass()));
try {
executor.execute(3);
fail("Should have failed");
} catch (ConversionExecutionException e) {
}
}
@Test
public void testSuperTwoWayConverterConverterAdaption() {
service.addConverter(GenericConversionService.converterFor(String.class, FooEnum.class, new StringToEnum()));
assertEquals(FooEnum.BAR, service.convert("BAR", type(FooEnum.class)));
}
private TypeDescriptor type(Class<?> clazz) {
return TypeDescriptor.valueOf(clazz);
}

View File

@ -1,4 +1,4 @@
package org.springframework.core.convert.service;
package org.springframework.core.convert.support;
import static org.junit.Assert.assertEquals;
@ -7,6 +7,8 @@ import java.util.Map;
import org.junit.Test;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.MapToMap;
public class MapToMapTests {