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
This commit is contained in:
parent
a89bfffd8c
commit
5e505ce3a9
|
@ -29,6 +29,24 @@ import org.springframework.core.convert.converter.ConverterRegistry;
|
|||
*/
|
||||
public interface FormatterRegistry extends ConverterRegistry {
|
||||
|
||||
/**
|
||||
* Adds a Printer to print fields of a specific type.
|
||||
* The field type is implied by the parameterized Printer instance.
|
||||
* @param printer the printer to add
|
||||
* @since 5.2
|
||||
* @see #addFormatter(Formatter)
|
||||
*/
|
||||
void addPrinter(Printer<?> printer);
|
||||
|
||||
/**
|
||||
* Adds a Parser to parse fields of a specific type.
|
||||
* The field type is implied by the parameterized Parser instance.
|
||||
* @param parser the parser to add
|
||||
* @since 5.2
|
||||
* @see #addFormatter(Formatter)
|
||||
*/
|
||||
void addParser(Parser<?> parser);
|
||||
|
||||
/**
|
||||
* Adds a Formatter to format fields of a specific type.
|
||||
* The field type is implied by the parameterized Formatter instance.
|
||||
|
|
|
@ -37,6 +37,8 @@ import org.springframework.format.FormatterRegistry;
|
|||
import org.springframework.format.Parser;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
|
@ -65,6 +67,18 @@ public class FormattingConversionService extends GenericConversionService
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addPrinter(Printer<?> printer) {
|
||||
Class<?> fieldType = getFieldType(printer, Printer.class);
|
||||
addConverter(new PrinterConverter(fieldType, printer, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParser(Parser<?> parser) {
|
||||
Class<?> fieldType = getFieldType(parser, Parser.class);
|
||||
addConverter(new ParserConverter(fieldType, parser, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormatter(Formatter<?> formatter) {
|
||||
addFormatterForFieldType(getFieldType(formatter), formatter);
|
||||
|
@ -97,15 +111,18 @@ public class FormattingConversionService extends GenericConversionService
|
|||
|
||||
|
||||
static Class<?> getFieldType(Formatter<?> formatter) {
|
||||
Class<?> fieldType = GenericTypeResolver.resolveTypeArgument(formatter.getClass(), Formatter.class);
|
||||
if (fieldType == null && formatter instanceof DecoratingProxy) {
|
||||
return getFieldType(formatter, Formatter.class);
|
||||
}
|
||||
|
||||
private static <T> Class<?> getFieldType(T instance, Class<T> genericInterface) {
|
||||
Class<?> fieldType = GenericTypeResolver.resolveTypeArgument(instance.getClass(), genericInterface);
|
||||
if (fieldType == null && instance instanceof DecoratingProxy) {
|
||||
fieldType = GenericTypeResolver.resolveTypeArgument(
|
||||
((DecoratingProxy) formatter).getDecoratedClass(), Formatter.class);
|
||||
}
|
||||
if (fieldType == null) {
|
||||
throw new IllegalArgumentException("Unable to extract the parameterized field type from Formatter [" +
|
||||
formatter.getClass().getName() + "]; does the class parameterize the <T> generic type?");
|
||||
((DecoratingProxy) instance).getDecoratedClass(), genericInterface);
|
||||
}
|
||||
Assert.notNull(fieldType, () -> "Unable to extract the parameterized field type from " +
|
||||
ClassUtils.getShortName(genericInterface) + " [" + instance.getClass().getName() +
|
||||
"]; does the class parameterize the <T> generic type?");
|
||||
return fieldType;
|
||||
}
|
||||
|
||||
|
|
|
@ -346,8 +346,25 @@ public class FormattingConversionServiceTests {
|
|||
|
||||
@Test
|
||||
public void introspectedFormatter() throws ParseException {
|
||||
formattingService.addFormatter(new NumberStyleFormatter());
|
||||
assertThat(formattingService.convert(null, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class))).isNull();
|
||||
formattingService.addFormatter(new NumberStyleFormatter("#,#00.0#"));
|
||||
assertThat(formattingService.convert(123, String.class)).isEqualTo("123.0");
|
||||
assertThat(formattingService.convert("123.0", Integer.class)).isEqualTo(123);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void introspectedPrinter() throws ParseException {
|
||||
formattingService.addPrinter(new NumberStyleFormatter("#,#00.0#"));
|
||||
assertThat(formattingService.convert(123, String.class)).isEqualTo("123.0");
|
||||
assertThatExceptionOfType(ConversionFailedException.class).isThrownBy(() ->
|
||||
assertThat(formattingService.convert("123.0", Integer.class)).isNull())
|
||||
.withCauseInstanceOf(NumberFormatException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void introspectedParser() throws ParseException {
|
||||
formattingService.addParser(new NumberStyleFormatter("#,#00.0#"));
|
||||
assertThat(formattingService.convert("123.0", Integer.class)).isEqualTo(123);
|
||||
assertThat(formattingService.convert(123, String.class)).isEqualTo("123");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue