added symmetry to ToString converters: SPR-8306
This commit is contained in:
parent
e11d7c328f
commit
e25fbf2533
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.core.convert.support;
|
package org.springframework.core.convert.support;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A specialization of {@link GenericConversionService} configured by default with
|
* A specialization of {@link GenericConversionService} configured by default with
|
||||||
* converters appropriate for most applications.
|
* converters appropriate for most applications.
|
||||||
|
|
@ -65,19 +67,28 @@ public class DefaultConversionService extends GenericConversionService {
|
||||||
conversionService.addConverter(new StringToPropertiesConverter());
|
conversionService.addConverter(new StringToPropertiesConverter());
|
||||||
|
|
||||||
conversionService.addConverter(new StringToBooleanConverter());
|
conversionService.addConverter(new StringToBooleanConverter());
|
||||||
|
conversionService.addConverter(Boolean.class, String.class, new ObjectToStringConverter());
|
||||||
|
|
||||||
conversionService.addConverter(new StringToCharacterConverter());
|
conversionService.addConverter(new StringToCharacterConverter());
|
||||||
|
conversionService.addConverter(Character.class, String.class, new ObjectToStringConverter());
|
||||||
|
|
||||||
conversionService.addConverter(new StringToLocaleConverter());
|
conversionService.addConverter(new StringToLocaleConverter());
|
||||||
|
conversionService.addConverter(Locale.class, String.class, new ObjectToStringConverter());
|
||||||
|
|
||||||
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
||||||
|
conversionService.addConverter(Number.class, String.class, new ObjectToStringConverter());
|
||||||
|
|
||||||
conversionService.addConverterFactory(new StringToEnumConverterFactory());
|
conversionService.addConverterFactory(new StringToEnumConverterFactory());
|
||||||
|
conversionService.addConverter(Enum.class, String.class, new EnumToStringConverter());
|
||||||
|
|
||||||
conversionService.addConverter(new NumberToCharacterConverter());
|
conversionService.addConverter(new NumberToCharacterConverter());
|
||||||
conversionService.addConverterFactory(new CharacterToNumberFactory());
|
conversionService.addConverterFactory(new CharacterToNumberFactory());
|
||||||
|
|
||||||
conversionService.addConverterFactory(new NumberToNumberConverterFactory());
|
conversionService.addConverterFactory(new NumberToNumberConverterFactory());
|
||||||
|
|
||||||
conversionService.addConverter(new ObjectToStringConverter());
|
|
||||||
conversionService.addConverter(new ObjectToObjectConverter());
|
conversionService.addConverter(new ObjectToObjectConverter());
|
||||||
conversionService.addConverter(new IdToEntityConverter(conversionService));
|
conversionService.addConverter(new IdToEntityConverter(conversionService));
|
||||||
|
conversionService.addConverter(new FallbackObjectToStringConverter());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* 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 Enum#name()} to convert a source Enum to a String.
|
||||||
|
* @author Keith Donald
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
final class EnumToStringConverter implements Converter<Enum<?>, String> {
|
||||||
|
|
||||||
|
public String convert(Enum<?> source) {
|
||||||
|
return source.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.io.StringWriter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simply calls {@link Object#toString()} to convert any supported Object to a String.
|
||||||
|
* Supports CharSequence, StringWriter, and any class with a String constructor or <code>valueOf(String)</code> method.
|
||||||
|
*
|
||||||
|
* <p>Used by the default ConversionService as a fallback if there are no other explicit
|
||||||
|
* to-String converters registered.
|
||||||
|
*
|
||||||
|
* @author Keith Donald
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
final class FallbackObjectToStringConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
|
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||||
|
return Collections.singleton(new ConvertiblePair(Object.class, String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
|
Class<?> sourceClass = sourceType.getObjectType();
|
||||||
|
return CharSequence.class.isAssignableFrom(sourceClass) || StringWriter.class.isAssignableFrom(sourceClass) ||
|
||||||
|
ObjectToObjectConverter.hasValueOfMethodOrConstructor(sourceClass, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
|
return (source != null ? source.toString() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -88,6 +88,17 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||||
new ConcurrentHashMap<ConverterCacheKey, GenericConverter>();
|
new ConcurrentHashMap<ConverterCacheKey, GenericConverter>();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a converter to the register indexed under the explicit source and target types.
|
||||||
|
* Allows for a general converter to be reused for multiple distinct source-to-target convertible pairs without having to create a Converter class for each pair.
|
||||||
|
* Not yet part of the ConverterRegistry interface.
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
public void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter) {
|
||||||
|
GenericConverter.ConvertiblePair typeInfo = new GenericConverter.ConvertiblePair(sourceType, targetType);
|
||||||
|
addConverter(new ConverterAdapter(typeInfo, converter));
|
||||||
|
}
|
||||||
|
|
||||||
// implementing ConverterRegistry
|
// implementing ConverterRegistry
|
||||||
|
|
||||||
public void addConverter(Converter<?, ?> converter) {
|
public void addConverter(Converter<?, ?> converter) {
|
||||||
|
|
|
||||||
|
|
@ -43,16 +43,16 @@ import org.springframework.util.ReflectionUtils;
|
||||||
*/
|
*/
|
||||||
final class ObjectToObjectConverter implements ConditionalGenericConverter {
|
final class ObjectToObjectConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
|
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||||
|
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
|
||||||
|
}
|
||||||
|
|
||||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
Class<?> source = sourceType.getObjectType();
|
Class<?> source = sourceType.getObjectType();
|
||||||
Class<?> target = targetType.getObjectType();
|
Class<?> target = targetType.getObjectType();
|
||||||
return (!source.equals(target) && hasValueOfMethodOrConstructor(target, source));
|
return (!source.equals(target) && hasValueOfMethodOrConstructor(target, source));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
|
||||||
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
Class<?> sourceClass = sourceType.getObjectType();
|
Class<?> sourceClass = sourceType.getObjectType();
|
||||||
Class<?> targetClass = targetType.getObjectType();
|
Class<?> targetClass = targetType.getObjectType();
|
||||||
|
|
|
||||||
|
|
@ -16,40 +16,17 @@
|
||||||
|
|
||||||
package org.springframework.core.convert.support;
|
package org.springframework.core.convert.support;
|
||||||
|
|
||||||
import java.io.StringWriter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simply calls {@link Object#toString()} to convert any supported Object to a String.
|
* Simply calls {@link Object#toString()} to convert a source Object to a String.
|
||||||
* Supports Number, Boolean, Character, CharSequence, StringWriter, any enum,
|
|
||||||
* and any class with a String constructor or <code>valueOf(String)</code> method.
|
|
||||||
*
|
|
||||||
* <p>Used by the default ConversionService as a fallback if there are no other explicit
|
|
||||||
* to-String converters registered.
|
|
||||||
*
|
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @author Juergen Hoeller
|
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
final class ObjectToStringConverter implements ConditionalGenericConverter {
|
final class ObjectToStringConverter implements Converter<Object, String> {
|
||||||
|
|
||||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
public String convert(Object source) {
|
||||||
return Collections.singleton(new ConvertiblePair(Object.class, String.class));
|
return source.toString();
|
||||||
}
|
|
||||||
|
|
||||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
|
||||||
Class<?> sourceClass = sourceType.getObjectType();
|
|
||||||
return CharSequence.class.isAssignableFrom(sourceClass) || Number.class.isAssignableFrom(sourceClass) ||
|
|
||||||
Boolean.class.equals(sourceClass) || Character.class.equals(sourceClass) || StringWriter.class.isAssignableFrom(sourceClass) ||
|
|
||||||
sourceClass.isEnum() || ObjectToObjectConverter.hasValueOfMethodOrConstructor(sourceClass, String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
|
||||||
return (source != null ? source.toString() : null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,15 +36,13 @@ final class StringToBooleanConverter implements Converter<String, Boolean> {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
trueValues.add("true");
|
trueValues.add("true");
|
||||||
falseValues.add("false");
|
|
||||||
|
|
||||||
trueValues.add("on");
|
trueValues.add("on");
|
||||||
falseValues.add("off");
|
|
||||||
|
|
||||||
trueValues.add("yes");
|
trueValues.add("yes");
|
||||||
falseValues.add("no");
|
|
||||||
|
|
||||||
trueValues.add("1");
|
trueValues.add("1");
|
||||||
|
|
||||||
|
falseValues.add("false");
|
||||||
|
falseValues.add("off");
|
||||||
|
falseValues.add("no");
|
||||||
falseValues.add("0");
|
falseValues.add("0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +51,8 @@ final class StringToBooleanConverter implements Converter<String, Boolean> {
|
||||||
if (value.length() == 0) {
|
if (value.length() == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else if (trueValues.contains(value)) {
|
value = value.toLowerCase();
|
||||||
|
if (trueValues.contains(value)) {
|
||||||
return Boolean.TRUE;
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
else if (falseValues.contains(value)) {
|
else if (falseValues.contains(value)) {
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,9 @@ public class DefaultConversionTests {
|
||||||
assertEquals(Boolean.valueOf(true), conversionService.convert("on", Boolean.class));
|
assertEquals(Boolean.valueOf(true), conversionService.convert("on", Boolean.class));
|
||||||
assertEquals(Boolean.valueOf(true), conversionService.convert("yes", Boolean.class));
|
assertEquals(Boolean.valueOf(true), conversionService.convert("yes", Boolean.class));
|
||||||
assertEquals(Boolean.valueOf(true), conversionService.convert("1", Boolean.class));
|
assertEquals(Boolean.valueOf(true), conversionService.convert("1", Boolean.class));
|
||||||
|
assertEquals(Boolean.valueOf(true), conversionService.convert("TRUE", Boolean.class));
|
||||||
|
assertEquals(Boolean.valueOf(true), conversionService.convert("ON", Boolean.class));
|
||||||
|
assertEquals(Boolean.valueOf(true), conversionService.convert("YES", Boolean.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -87,6 +90,9 @@ public class DefaultConversionTests {
|
||||||
assertEquals(Boolean.valueOf(false), conversionService.convert("off", Boolean.class));
|
assertEquals(Boolean.valueOf(false), conversionService.convert("off", Boolean.class));
|
||||||
assertEquals(Boolean.valueOf(false), conversionService.convert("no", Boolean.class));
|
assertEquals(Boolean.valueOf(false), conversionService.convert("no", Boolean.class));
|
||||||
assertEquals(Boolean.valueOf(false), conversionService.convert("0", Boolean.class));
|
assertEquals(Boolean.valueOf(false), conversionService.convert("0", Boolean.class));
|
||||||
|
assertEquals(Boolean.valueOf(false), conversionService.convert("FALSE", Boolean.class));
|
||||||
|
assertEquals(Boolean.valueOf(false), conversionService.convert("OFF", Boolean.class));
|
||||||
|
assertEquals(Boolean.valueOf(false), conversionService.convert("NO", Boolean.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue