Skip to content

Commit 5e505ce

Browse files
committed
Add FormatterRegistry addPrinter/addParser methods
Update `FormatterRegistry` with `addPrinter` and `addParser` methods that can be used to register Printer or Parser implementations in a similar way to the existing `addFormatter` method. Closes gh-23110
1 parent a89bfff commit 5e505ce

File tree

3 files changed

+61
-9
lines changed

3 files changed

+61
-9
lines changed

spring-context/src/main/java/org/springframework/format/FormatterRegistry.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@
2929
*/
3030
public interface FormatterRegistry extends ConverterRegistry {
3131

32+
/**
33+
* Adds a Printer to print fields of a specific type.
34+
* The field type is implied by the parameterized Printer instance.
35+
* @param printer the printer to add
36+
* @since 5.2
37+
* @see #addFormatter(Formatter)
38+
*/
39+
void addPrinter(Printer<?> printer);
40+
41+
/**
42+
* Adds a Parser to parse fields of a specific type.
43+
* The field type is implied by the parameterized Parser instance.
44+
* @param parser the parser to add
45+
* @since 5.2
46+
* @see #addFormatter(Formatter)
47+
*/
48+
void addParser(Parser<?> parser);
49+
3250
/**
3351
* Adds a Formatter to format fields of a specific type.
3452
* The field type is implied by the parameterized Formatter instance.

spring-context/src/main/java/org/springframework/format/support/FormattingConversionService.java

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
import org.springframework.format.Parser;
3838
import org.springframework.format.Printer;
3939
import org.springframework.lang.Nullable;
40+
import org.springframework.util.Assert;
41+
import org.springframework.util.ClassUtils;
4042
import org.springframework.util.StringUtils;
4143
import org.springframework.util.StringValueResolver;
4244

@@ -65,6 +67,18 @@ public void setEmbeddedValueResolver(StringValueResolver resolver) {
6567
}
6668

6769

70+
@Override
71+
public void addPrinter(Printer<?> printer) {
72+
Class<?> fieldType = getFieldType(printer, Printer.class);
73+
addConverter(new PrinterConverter(fieldType, printer, this));
74+
}
75+
76+
@Override
77+
public void addParser(Parser<?> parser) {
78+
Class<?> fieldType = getFieldType(parser, Parser.class);
79+
addConverter(new ParserConverter(fieldType, parser, this));
80+
}
81+
6882
@Override
6983
public void addFormatter(Formatter<?> formatter) {
7084
addFormatterForFieldType(getFieldType(formatter), formatter);
@@ -97,15 +111,18 @@ public void addFormatterForFieldAnnotation(AnnotationFormatterFactory<? extends
97111

98112

99113
static Class<?> getFieldType(Formatter<?> formatter) {
100-
Class<?> fieldType = GenericTypeResolver.resolveTypeArgument(formatter.getClass(), Formatter.class);
101-
if (fieldType == null && formatter instanceof DecoratingProxy) {
114+
return getFieldType(formatter, Formatter.class);
115+
}
116+
117+
private static <T> Class<?> getFieldType(T instance, Class<T> genericInterface) {
118+
Class<?> fieldType = GenericTypeResolver.resolveTypeArgument(instance.getClass(), genericInterface);
119+
if (fieldType == null && instance instanceof DecoratingProxy) {
102120
fieldType = GenericTypeResolver.resolveTypeArgument(
103-
((DecoratingProxy) formatter).getDecoratedClass(), Formatter.class);
104-
}
105-
if (fieldType == null) {
106-
throw new IllegalArgumentException("Unable to extract the parameterized field type from Formatter [" +
107-
formatter.getClass().getName() + "]; does the class parameterize the <T> generic type?");
121+
((DecoratingProxy) instance).getDecoratedClass(), genericInterface);
108122
}
123+
Assert.notNull(fieldType, () -> "Unable to extract the parameterized field type from " +
124+
ClassUtils.getShortName(genericInterface) + " [" + instance.getClass().getName() +
125+
"]; does the class parameterize the <T> generic type?");
109126
return fieldType;
110127
}
111128

spring-context/src/test/java/org/springframework/format/support/FormattingConversionServiceTests.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,25 @@ public String toString() {
346346

347347
@Test
348348
public void introspectedFormatter() throws ParseException {
349-
formattingService.addFormatter(new NumberStyleFormatter());
350-
assertThat(formattingService.convert(null, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class))).isNull();
349+
formattingService.addFormatter(new NumberStyleFormatter("#,#00.0#"));
350+
assertThat(formattingService.convert(123, String.class)).isEqualTo("123.0");
351+
assertThat(formattingService.convert("123.0", Integer.class)).isEqualTo(123);
352+
}
353+
354+
@Test
355+
public void introspectedPrinter() throws ParseException {
356+
formattingService.addPrinter(new NumberStyleFormatter("#,#00.0#"));
357+
assertThat(formattingService.convert(123, String.class)).isEqualTo("123.0");
358+
assertThatExceptionOfType(ConversionFailedException.class).isThrownBy(() ->
359+
assertThat(formattingService.convert("123.0", Integer.class)).isNull())
360+
.withCauseInstanceOf(NumberFormatException.class);
361+
}
362+
363+
@Test
364+
public void introspectedParser() throws ParseException {
365+
formattingService.addParser(new NumberStyleFormatter("#,#00.0#"));
366+
assertThat(formattingService.convert("123.0", Integer.class)).isEqualTo(123);
367+
assertThat(formattingService.convert(123, String.class)).isEqualTo("123");
351368
}
352369

353370
@Test

0 commit comments

Comments
 (0)