Skip to content

Commit e25fbf2

Browse files
author
Keith Donald
committed
added symmetry to ToString converters: SPR-8306
1 parent e11d7c3 commit e25fbf2

File tree

8 files changed

+129
-41
lines changed

8 files changed

+129
-41
lines changed

org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.core.convert.support;
1818

19+
import java.util.Locale;
20+
1921
/**
2022
* A specialization of {@link GenericConversionService} configured by default with
2123
* converters appropriate for most applications.
@@ -65,19 +67,28 @@ public static void addDefaultConverters(GenericConversionService conversionServi
6567
conversionService.addConverter(new StringToPropertiesConverter());
6668

6769
conversionService.addConverter(new StringToBooleanConverter());
70+
conversionService.addConverter(Boolean.class, String.class, new ObjectToStringConverter());
71+
6872
conversionService.addConverter(new StringToCharacterConverter());
73+
conversionService.addConverter(Character.class, String.class, new ObjectToStringConverter());
74+
6975
conversionService.addConverter(new StringToLocaleConverter());
76+
conversionService.addConverter(Locale.class, String.class, new ObjectToStringConverter());
77+
7078
conversionService.addConverterFactory(new StringToNumberConverterFactory());
79+
conversionService.addConverter(Number.class, String.class, new ObjectToStringConverter());
80+
7181
conversionService.addConverterFactory(new StringToEnumConverterFactory());
72-
82+
conversionService.addConverter(Enum.class, String.class, new EnumToStringConverter());
83+
7384
conversionService.addConverter(new NumberToCharacterConverter());
7485
conversionService.addConverterFactory(new CharacterToNumberFactory());
7586

7687
conversionService.addConverterFactory(new NumberToNumberConverterFactory());
7788

78-
conversionService.addConverter(new ObjectToStringConverter());
7989
conversionService.addConverter(new ObjectToObjectConverter());
8090
conversionService.addConverter(new IdToEntityConverter(conversionService));
91+
conversionService.addConverter(new FallbackObjectToStringConverter());
8192
}
8293

8394
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2002-2009 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.core.convert.support;
18+
19+
import org.springframework.core.convert.converter.Converter;
20+
21+
/**
22+
* Simply calls {@link Enum#name()} to convert a source Enum to a String.
23+
* @author Keith Donald
24+
* @since 3.0
25+
*/
26+
final class EnumToStringConverter implements Converter<Enum<?>, String> {
27+
28+
public String convert(Enum<?> source) {
29+
return source.name();
30+
}
31+
32+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2002-2009 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.core.convert.support;
17+
18+
import java.io.StringWriter;
19+
import java.util.Collections;
20+
import java.util.Set;
21+
22+
import org.springframework.core.convert.TypeDescriptor;
23+
import org.springframework.core.convert.converter.ConditionalGenericConverter;
24+
25+
/**
26+
* Simply calls {@link Object#toString()} to convert any supported Object to a String.
27+
* Supports CharSequence, StringWriter, and any class with a String constructor or <code>valueOf(String)</code> method.
28+
*
29+
* <p>Used by the default ConversionService as a fallback if there are no other explicit
30+
* to-String converters registered.
31+
*
32+
* @author Keith Donald
33+
* @author Juergen Hoeller
34+
* @since 3.0
35+
*/
36+
final class FallbackObjectToStringConverter implements ConditionalGenericConverter {
37+
38+
public Set<ConvertiblePair> getConvertibleTypes() {
39+
return Collections.singleton(new ConvertiblePair(Object.class, String.class));
40+
}
41+
42+
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
43+
Class<?> sourceClass = sourceType.getObjectType();
44+
return CharSequence.class.isAssignableFrom(sourceClass) || StringWriter.class.isAssignableFrom(sourceClass) ||
45+
ObjectToObjectConverter.hasValueOfMethodOrConstructor(sourceClass, String.class);
46+
}
47+
48+
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
49+
return (source != null ? source.toString() : null);
50+
}
51+
52+
}

org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,17 @@ public String toString() {
8888
new ConcurrentHashMap<ConverterCacheKey, GenericConverter>();
8989

9090

91+
/**
92+
* Add a converter to the register indexed under the explicit source and target types.
93+
* 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.
94+
* Not yet part of the ConverterRegistry interface.
95+
* @since 3.1
96+
*/
97+
public void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter) {
98+
GenericConverter.ConvertiblePair typeInfo = new GenericConverter.ConvertiblePair(sourceType, targetType);
99+
addConverter(new ConverterAdapter(typeInfo, converter));
100+
}
101+
91102
// implementing ConverterRegistry
92103

93104
public void addConverter(Converter<?, ?> converter) {

org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,16 @@
4343
*/
4444
final class ObjectToObjectConverter implements ConditionalGenericConverter {
4545

46+
public Set<ConvertiblePair> getConvertibleTypes() {
47+
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
48+
}
49+
4650
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
4751
Class<?> source = sourceType.getObjectType();
4852
Class<?> target = targetType.getObjectType();
4953
return (!source.equals(target) && hasValueOfMethodOrConstructor(target, source));
5054
}
5155

52-
public Set<ConvertiblePair> getConvertibleTypes() {
53-
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
54-
}
55-
5656
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
5757
Class<?> sourceClass = sourceType.getObjectType();
5858
Class<?> targetClass = targetType.getObjectType();

org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToStringConverter.java

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,17 @@
1616

1717
package org.springframework.core.convert.support;
1818

19-
import java.io.StringWriter;
20-
import java.util.Collections;
21-
import java.util.Set;
22-
23-
import org.springframework.core.convert.TypeDescriptor;
24-
import org.springframework.core.convert.converter.ConditionalGenericConverter;
19+
import org.springframework.core.convert.converter.Converter;
2520

2621
/**
27-
* Simply calls {@link Object#toString()} to convert any supported Object to a String.
28-
* Supports Number, Boolean, Character, CharSequence, StringWriter, any enum,
29-
* and any class with a String constructor or <code>valueOf(String)</code> method.
30-
*
31-
* <p>Used by the default ConversionService as a fallback if there are no other explicit
32-
* to-String converters registered.
33-
*
22+
* Simply calls {@link Object#toString()} to convert a source Object to a String.
3423
* @author Keith Donald
35-
* @author Juergen Hoeller
3624
* @since 3.0
3725
*/
38-
final class ObjectToStringConverter implements ConditionalGenericConverter {
39-
40-
public Set<ConvertiblePair> getConvertibleTypes() {
41-
return Collections.singleton(new ConvertiblePair(Object.class, String.class));
42-
}
43-
44-
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
45-
Class<?> sourceClass = sourceType.getObjectType();
46-
return CharSequence.class.isAssignableFrom(sourceClass) || Number.class.isAssignableFrom(sourceClass) ||
47-
Boolean.class.equals(sourceClass) || Character.class.equals(sourceClass) || StringWriter.class.isAssignableFrom(sourceClass) ||
48-
sourceClass.isEnum() || ObjectToObjectConverter.hasValueOfMethodOrConstructor(sourceClass, String.class);
49-
}
26+
final class ObjectToStringConverter implements Converter<Object, String> {
5027

51-
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
52-
return (source != null ? source.toString() : null);
28+
public String convert(Object source) {
29+
return source.toString();
5330
}
5431

5532
}

org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToBooleanConverter.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,13 @@ final class StringToBooleanConverter implements Converter<String, Boolean> {
3636

3737
static {
3838
trueValues.add("true");
39-
falseValues.add("false");
40-
4139
trueValues.add("on");
42-
falseValues.add("off");
43-
4440
trueValues.add("yes");
45-
falseValues.add("no");
46-
4741
trueValues.add("1");
42+
43+
falseValues.add("false");
44+
falseValues.add("off");
45+
falseValues.add("no");
4846
falseValues.add("0");
4947
}
5048

@@ -53,7 +51,8 @@ public Boolean convert(String source) {
5351
if (value.length() == 0) {
5452
return null;
5553
}
56-
else if (trueValues.contains(value)) {
54+
value = value.toLowerCase();
55+
if (trueValues.contains(value)) {
5756
return Boolean.TRUE;
5857
}
5958
else if (falseValues.contains(value)) {

org.springframework.core/src/test/java/org/springframework/core/convert/support/DefaultConversionTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ public void testStringToBooleanTrue() {
7979
assertEquals(Boolean.valueOf(true), conversionService.convert("on", Boolean.class));
8080
assertEquals(Boolean.valueOf(true), conversionService.convert("yes", Boolean.class));
8181
assertEquals(Boolean.valueOf(true), conversionService.convert("1", Boolean.class));
82+
assertEquals(Boolean.valueOf(true), conversionService.convert("TRUE", Boolean.class));
83+
assertEquals(Boolean.valueOf(true), conversionService.convert("ON", Boolean.class));
84+
assertEquals(Boolean.valueOf(true), conversionService.convert("YES", Boolean.class));
8285
}
8386

8487
@Test
@@ -87,6 +90,9 @@ public void testStringToBooleanFalse() {
8790
assertEquals(Boolean.valueOf(false), conversionService.convert("off", Boolean.class));
8891
assertEquals(Boolean.valueOf(false), conversionService.convert("no", Boolean.class));
8992
assertEquals(Boolean.valueOf(false), conversionService.convert("0", Boolean.class));
93+
assertEquals(Boolean.valueOf(false), conversionService.convert("FALSE", Boolean.class));
94+
assertEquals(Boolean.valueOf(false), conversionService.convert("OFF", Boolean.class));
95+
assertEquals(Boolean.valueOf(false), conversionService.convert("NO", Boolean.class));
9096
}
9197

9298
@Test

0 commit comments

Comments
 (0)