Initial support for JSR-354 Money & Currency

Issue: SPR-12209
This commit is contained in:
Juergen Hoeller
2015-03-13 19:40:00 +01:00
parent bc6a98c144
commit 6c169bd644
25 changed files with 878 additions and 204 deletions

View File

@@ -28,15 +28,19 @@ import java.lang.annotation.Target;
* <p>Supports formatting by style or custom pattern string.
* Can be applied to any JDK {@code java.lang.Number} type.
*
* <p>For style-based formatting, set the {@link #style} attribute to be the desired {@link Style}.
* For custom formatting, set the {@link #pattern} attribute to be the number pattern, such as {@code #, ###.##}.
* <p>For style-based formatting, set the {@link #style} attribute to be the
* desired {@link Style}. For custom formatting, set the {@link #pattern}
* attribute to be the number pattern, such as {@code #, ###.##}.
*
* <p>Each attribute is mutually exclusive, so only set one attribute per annotation instance
* (the one most convenient one for your formatting needs). When the pattern attribute is specified,
* it takes precedence over the style attribute. When no annotation attributes are specified,
* the default format applied is style-based with a style of {@link Style#NUMBER}.
* <p>Each attribute is mutually exclusive, so only set one attribute per
* annotation instance (the one most convenient one for your formatting needs).
* When the {@link #pattern} attribute is specified, it takes precedence over
* the {@link #style} attribute. When no annotation attributes are specified,
* the default format applied is style-based for either number of currency,
* depending on the annotated field type.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
* @see java.text.NumberFormat
*/
@@ -47,11 +51,12 @@ public @interface NumberFormat {
/**
* The style pattern to use to format the field.
* <p>Defaults to {@link Style#NUMBER} for general-purpose number formatter.
* Set this attribute when you wish to format your field in accordance with a
* common style other than the default style.
* <p>Defaults to {@link Style#DEFAULT} for general-purpose number formatting
* for most annotated types, except for money types which default to currency
* formatting. Set this attribute when you wish to format your field in
* accordance with a common style other than the default style.
*/
Style style() default Style.NUMBER;
Style style() default Style.DEFAULT;
/**
* The custom pattern to use to format the field.
@@ -67,6 +72,13 @@ public @interface NumberFormat {
*/
public enum Style {
/**
* The default format for the annotated type: typically number
* but possibly currency for a money type.
* @since 4.2
*/
DEFAULT,
/**
* The general-purpose number format for the current locale.
*/

View File

@@ -35,6 +35,7 @@ public abstract class AbstractNumberFormatter implements Formatter<Number> {
private boolean lenient = false;
/**
* Specify whether or not parsing is to be lenient. Default is false.
* <p>With lenient parsing, the parser may allow inputs that do not precisely match the format.
@@ -44,6 +45,7 @@ public abstract class AbstractNumberFormatter implements Formatter<Number> {
this.lenient = lenient;
}
@Override
public String print(Number number, Locale locale) {
return getNumberFormat(locale).format(number);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -16,92 +16,16 @@
package org.springframework.format.number;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Currency;
import java.util.Locale;
import org.springframework.util.ClassUtils;
/**
* A BigDecimal formatter for currency values.
*
* <p>Delegates to {@link NumberFormat#getCurrencyInstance(Locale)}.
* Configures BigDecimal parsing so there is no loss of precision.
* Can apply a specified {@link RoundingMode} to parsed values.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
* @see #setLenient
* @see #setRoundingMode
* @since 4.2
* @deprecated as of Spring 4.2, in favor of the more clearly named
* {@link CurrencyStyleFormatter}
*/
public class CurrencyFormatter extends AbstractNumberFormatter {
private static final boolean roundingModeOnDecimalFormat =
ClassUtils.hasMethod(DecimalFormat.class, "setRoundingMode", RoundingMode.class);
private int fractionDigits = 2;
private RoundingMode roundingMode;
private Currency currency;
/**
* Specify the desired number of fraction digits.
* Default is 2.
*/
public void setFractionDigits(int fractionDigits) {
this.fractionDigits = fractionDigits;
}
/**
* Specify the rounding mode to use for decimal parsing.
* Default is {@link RoundingMode#UNNECESSARY}.
*/
public void setRoundingMode(RoundingMode roundingMode) {
this.roundingMode = roundingMode;
}
/**
* Specify the currency, if known.
*/
public void setCurrency(Currency currency) {
this.currency = currency;
}
@Override
public BigDecimal parse(String text, Locale locale) throws ParseException {
BigDecimal decimal = (BigDecimal) super.parse(text, locale);
if (decimal != null) {
if (this.roundingMode != null) {
decimal = decimal.setScale(this.fractionDigits, this.roundingMode);
}
else {
decimal = decimal.setScale(this.fractionDigits);
}
}
return decimal;
}
@Override
protected NumberFormat getNumberFormat(Locale locale) {
DecimalFormat format = (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
format.setParseBigDecimal(true);
format.setMaximumFractionDigits(this.fractionDigits);
format.setMinimumFractionDigits(this.fractionDigits);
if (this.roundingMode != null && roundingModeOnDecimalFormat) {
format.setRoundingMode(this.roundingMode);
}
if (this.currency != null) {
format.setCurrency(this.currency);
}
return format;
}
@Deprecated
public class CurrencyFormatter extends CurrencyStyleFormatter {
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2002-2015 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.format.number;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Currency;
import java.util.Locale;
/**
* A BigDecimal formatter for number values in currency style.
*
* <p>Delegates to {@link java.text.NumberFormat#getCurrencyInstance(Locale)}.
* Configures BigDecimal parsing so there is no loss of precision.
* Can apply a specified {@link java.math.RoundingMode} to parsed values.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 4.2
* @see #setLenient
* @see #setRoundingMode
*/
public class CurrencyStyleFormatter extends AbstractNumberFormatter {
private int fractionDigits = 2;
private RoundingMode roundingMode;
private Currency currency;
private String pattern;
/**
* Specify the desired number of fraction digits.
* Default is 2.
*/
public void setFractionDigits(int fractionDigits) {
this.fractionDigits = fractionDigits;
}
/**
* Specify the rounding mode to use for decimal parsing.
* Default is {@link java.math.RoundingMode#UNNECESSARY}.
*/
public void setRoundingMode(RoundingMode roundingMode) {
this.roundingMode = roundingMode;
}
/**
* Specify the currency, if known.
*/
public void setCurrency(Currency currency) {
this.currency = currency;
}
/**
* Sets the pattern to use to format number values.
* If not specified, the default DecimalFormat pattern is used.
* @see java.text.DecimalFormat#applyPattern(String)
*/
public void setPattern(String pattern) {
this.pattern = pattern;
}
@Override
public BigDecimal parse(String text, Locale locale) throws ParseException {
BigDecimal decimal = (BigDecimal) super.parse(text, locale);
if (decimal != null) {
if (this.roundingMode != null) {
decimal = decimal.setScale(this.fractionDigits, this.roundingMode);
}
else {
decimal = decimal.setScale(this.fractionDigits);
}
}
return decimal;
}
@Override
protected NumberFormat getNumberFormat(Locale locale) {
DecimalFormat format = (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
format.setParseBigDecimal(true);
format.setMaximumFractionDigits(this.fractionDigits);
format.setMinimumFractionDigits(this.fractionDigits);
if (this.roundingMode != null) {
format.setRoundingMode(this.roundingMode);
}
if (this.currency != null) {
format.setCurrency(this.currency);
}
if (this.pattern != null) {
format.applyPattern(this.pattern);
}
return format;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@@ -57,18 +57,18 @@ public class NumberFormatAnnotationFormatterFactory extends EmbeddedValueResolut
private Formatter<Number> configureFormatterFrom(NumberFormat annotation) {
if (StringUtils.hasLength(annotation.pattern())) {
return new NumberFormatter(resolveEmbeddedValue(annotation.pattern()));
return new NumberStyleFormatter(resolveEmbeddedValue(annotation.pattern()));
}
else {
Style style = annotation.style();
if (style == Style.PERCENT) {
return new PercentFormatter();
return new PercentStyleFormatter();
}
else if (style == Style.CURRENCY) {
return new CurrencyFormatter();
return new CurrencyStyleFormatter();
}
else {
return new NumberFormatter();
return new NumberStyleFormatter();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -16,28 +16,17 @@
package org.springframework.format.number;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
/**
* A general-purpose Number formatter.
*
* <p>Delegates to {@link NumberFormat#getInstance(Locale)}.
* Configures BigDecimal parsing so there is no loss in precision.
* Allows configuration over the decimal number pattern.
* The {@link #parse(String, Locale)} routine always returns a BigDecimal.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
* @see #setPattern
* @see #setLenient
* @deprecated as of Spring 4.2, in favor of the more clearly named
* {@link NumberStyleFormatter}
*/
public class NumberFormatter extends AbstractNumberFormatter {
private String pattern;
@Deprecated
public class NumberFormatter extends NumberStyleFormatter {
/**
* Create a new NumberFormatter without a pattern.
@@ -51,35 +40,7 @@ public class NumberFormatter extends AbstractNumberFormatter {
* @see #setPattern
*/
public NumberFormatter(String pattern) {
this.pattern = pattern;
}
/**
* Sets the pattern to use to format number values.
* If not specified, the default DecimalFormat pattern is used.
* @see DecimalFormat#applyPattern(String)
*/
public void setPattern(String pattern) {
this.pattern = pattern;
}
@Override
public NumberFormat getNumberFormat(Locale locale) {
NumberFormat format = NumberFormat.getInstance(locale);
if (!(format instanceof DecimalFormat)) {
if (this.pattern != null) {
throw new IllegalStateException("Cannot support pattern for non-DecimalFormat: " + format);
}
return format;
}
DecimalFormat decimalFormat = (DecimalFormat) format;
decimalFormat.setParseBigDecimal(true);
if (this.pattern != null) {
decimalFormat.applyPattern(this.pattern);
}
return decimalFormat;
super(pattern);
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2002-2015 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.format.number;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
/**
* A general-purpose number formatter using NumberFormat's number style.
*
* <p>Delegates to {@link java.text.NumberFormat#getInstance(Locale)}.
* Configures BigDecimal parsing so there is no loss in precision.
* Allows configuration over the decimal number pattern.
* The {@link #parse(String, Locale)} routine always returns a BigDecimal.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 4.2
* @see #setPattern
* @see #setLenient
*/
public class NumberStyleFormatter extends AbstractNumberFormatter {
private String pattern;
/**
* Create a new NumberStyleFormatter without a pattern.
*/
public NumberStyleFormatter() {
}
/**
* Create a new NumberStyleFormatter with the specified pattern.
* @param pattern the format pattern
* @see #setPattern
*/
public NumberStyleFormatter(String pattern) {
this.pattern = pattern;
}
/**
* Sets the pattern to use to format number values.
* If not specified, the default DecimalFormat pattern is used.
* @see java.text.DecimalFormat#applyPattern(String)
*/
public void setPattern(String pattern) {
this.pattern = pattern;
}
@Override
public NumberFormat getNumberFormat(Locale locale) {
NumberFormat format = NumberFormat.getInstance(locale);
if (!(format instanceof DecimalFormat)) {
if (this.pattern != null) {
throw new IllegalStateException("Cannot support pattern for non-DecimalFormat: " + format);
}
return format;
}
DecimalFormat decimalFormat = (DecimalFormat) format;
decimalFormat.setParseBigDecimal(true);
if (this.pattern != null) {
decimalFormat.applyPattern(this.pattern);
}
return decimalFormat;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -16,31 +16,16 @@
package org.springframework.format.number;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
/**
* A Number formatter for percent values.
*
* <p>Delegates to {@link NumberFormat#getPercentInstance(Locale)}.
* Configures BigDecimal parsing so there is no loss in precision.
* The {@link #parse(String, Locale)} routine always returns a BigDecimal.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
* @see #setLenient
* @deprecated as of Spring 4.2, in favor of the more clearly named
* {@link PercentStyleFormatter}
*/
public class PercentFormatter extends AbstractNumberFormatter {
@Override
protected NumberFormat getNumberFormat(Locale locale) {
NumberFormat format = NumberFormat.getPercentInstance(locale);
if (format instanceof DecimalFormat) {
((DecimalFormat) format).setParseBigDecimal(true);
}
return format;
}
@Deprecated
public class PercentFormatter extends PercentStyleFormatter {
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2015 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.format.number;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
/**
* A formatter for number values in percent style.
*
* <p>Delegates to {@link java.text.NumberFormat#getPercentInstance(Locale)}.
* Configures BigDecimal parsing so there is no loss in precision.
* The {@link #parse(String, Locale)} routine always returns a BigDecimal.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 4.2
* @see #setLenient
*/
public class PercentStyleFormatter extends AbstractNumberFormatter {
@Override
protected NumberFormat getNumberFormat(Locale locale) {
NumberFormat format = NumberFormat.getPercentInstance(locale);
if (format instanceof DecimalFormat) {
((DecimalFormat) format).setParseBigDecimal(true);
}
return format;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2002-2015 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.format.number.money;
import java.util.Locale;
import javax.money.CurrencyUnit;
import javax.money.MonetaryCurrencies;
import org.springframework.format.Formatter;
/**
* Formatter for JSR-354 {@link javax.money.CurrencyUnit} values,
* from and to currency code Strings.
*
* @author Juergen Hoeller
* @since 4.2
*/
public class CurrencyUnitFormatter implements Formatter<CurrencyUnit> {
@Override
public String print(CurrencyUnit object, Locale locale) {
return object.getCurrencyCode();
}
@Override
public CurrencyUnit parse(String text, Locale locale) {
return MonetaryCurrencies.getCurrency(text);
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright 2002-2015 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.format.number.money;
import java.text.ParseException;
import java.util.Collections;
import java.util.Currency;
import java.util.Locale;
import java.util.Set;
import javax.money.CurrencyUnit;
import javax.money.MonetaryAmount;
import javax.money.MonetaryAmounts;
import javax.money.MonetaryCurrencies;
import org.springframework.context.support.EmbeddedValueResolutionSupport;
import org.springframework.format.AnnotationFormatterFactory;
import org.springframework.format.Formatter;
import org.springframework.format.Parser;
import org.springframework.format.Printer;
import org.springframework.format.annotation.NumberFormat;
import org.springframework.format.annotation.NumberFormat.Style;
import org.springframework.format.number.CurrencyStyleFormatter;
import org.springframework.format.number.NumberStyleFormatter;
import org.springframework.format.number.PercentStyleFormatter;
import org.springframework.util.StringUtils;
/**
* Formats {@link javax.money.MonetaryAmount} fields annotated
* with Spring's common {@link NumberFormat} annotation.
*
* @author Juergen Hoeller
* @since 4.2
* @see NumberFormat
*/
public class Jsr354NumberFormatAnnotationFormatterFactory extends EmbeddedValueResolutionSupport
implements AnnotationFormatterFactory<NumberFormat> {
@Override
@SuppressWarnings("unchecked")
public Set<Class<?>> getFieldTypes() {
return (Set) Collections.singleton(MonetaryAmount.class);
}
@Override
public Printer<MonetaryAmount> getPrinter(NumberFormat annotation, Class<?> fieldType) {
return configureFormatterFrom(annotation);
}
@Override
public Parser<MonetaryAmount> getParser(NumberFormat annotation, Class<?> fieldType) {
return configureFormatterFrom(annotation);
}
private Formatter<MonetaryAmount> configureFormatterFrom(NumberFormat annotation) {
if (StringUtils.hasLength(annotation.pattern())) {
return new NumberDecoratingFormatter(null, resolveEmbeddedValue(annotation.pattern()));
}
else {
Style style = annotation.style();
if (style == Style.PERCENT) {
return new NumberDecoratingFormatter(new PercentStyleFormatter(), null);
}
else if (style == Style.NUMBER) {
return new NumberDecoratingFormatter(new NumberStyleFormatter(), null);
}
else {
return new NumberDecoratingFormatter(null, null);
}
}
}
private static class NumberDecoratingFormatter implements Formatter<MonetaryAmount> {
private final Formatter<Number> numberFormatter;
private final String pattern;
public NumberDecoratingFormatter(Formatter<Number> numberFormatter, String pattern) {
this.numberFormatter = numberFormatter;
this.pattern = pattern;
}
@Override
public String print(MonetaryAmount object, Locale locale) {
Formatter<Number> formatterToUse = this.numberFormatter;
if (formatterToUse == null) {
CurrencyStyleFormatter formatter = new CurrencyStyleFormatter();
formatter.setCurrency(Currency.getInstance(object.getCurrency().getCurrencyCode()));
formatter.setPattern(this.pattern);
formatterToUse = formatter;
}
return formatterToUse.print(object.getNumber(), locale);
}
@Override
public MonetaryAmount parse(String text, Locale locale) throws ParseException {
Currency currency = Currency.getInstance(locale);
Formatter<Number> formatterToUse = this.numberFormatter;
if (formatterToUse == null) {
CurrencyStyleFormatter formatter = new CurrencyStyleFormatter();
formatter.setCurrency(currency);
formatter.setPattern(this.pattern);
formatterToUse = formatter;
}
Number numberValue = formatterToUse.parse(text, locale);
CurrencyUnit currencyUnit = MonetaryCurrencies.getCurrency(currency.getCurrencyCode());
return MonetaryAmounts.getDefaultAmountFactory().setNumber(numberValue).setCurrency(currencyUnit).create();
}
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2002-2015 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.format.number.money;
import java.util.Locale;
import javax.money.MonetaryAmount;
import javax.money.format.MonetaryAmountFormat;
import javax.money.format.MonetaryFormats;
import org.springframework.format.Formatter;
/**
* Formatter for JSR-354 {@link javax.money.MonetaryAmount} values,
* delegating to {@link javax.money.format.MonetaryAmountFormat#format}
* and {@link javax.money.format.MonetaryAmountFormat#parse}.
*
* @author Juergen Hoeller
* @since 4.2
* @see #getMonetaryAmountFormat
*/
public class MonetaryAmountFormatter implements Formatter<MonetaryAmount> {
private String formatName;
/**
* Create a locale-driven MonetaryAmountFormatter.
*/
public MonetaryAmountFormatter() {
}
/**
* Create a new MonetaryAmountFormatter for the given format name.
* @param formatName the format name, to be resolved by the JSR-354
* provider at runtime
*/
public MonetaryAmountFormatter(String formatName) {
this.formatName = formatName;
}
/**
* Specify the format name, to be resolved by the JSR-354 provider
* at runtime.
* <p>Default is none, obtaining a {@link MonetaryAmountFormat}
* based on the current locale.
*/
public void setFormatName(String formatName) {
this.formatName = formatName;
}
@Override
public String print(MonetaryAmount object, Locale locale) {
return getMonetaryAmountFormat(locale).format(object);
}
@Override
public MonetaryAmount parse(String text, Locale locale) {
return getMonetaryAmountFormat(locale).parse(text);
}
/**
* Obtain a MonetaryAmountFormat for the given locale.
* <p>The default implementation simply calls
* {@link javax.money.format.MonetaryFormats#getAmountFormat}
* with either the configured format name or the given locale.
* @param locale the current locale
* @return the MonetaryAmountFormat (never {@code null})
* @see #setFormatName
*/
protected MonetaryAmountFormat getMonetaryAmountFormat(Locale locale) {
if (this.formatName != null) {
return MonetaryFormats.getAmountFormat(this.formatName);
}
else {
return MonetaryFormats.getAmountFormat(locale);
}
}
}

View File

@@ -0,0 +1,4 @@
/**
* Integration with the JSR-354 <code>javax.money</code> package.
*/
package org.springframework.format.number.money;

View File

@@ -21,6 +21,9 @@ import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.DateFormatterRegistrar;
import org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
import org.springframework.format.number.money.CurrencyUnitFormatter;
import org.springframework.format.number.money.Jsr354NumberFormatAnnotationFormatterFactory;
import org.springframework.format.number.money.MonetaryAmountFormatter;
import org.springframework.format.number.NumberFormatAnnotationFormatterFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringValueResolver;
@@ -40,6 +43,9 @@ import org.springframework.util.StringValueResolver;
*/
public class DefaultFormattingConversionService extends FormattingConversionService {
private static final boolean jsr354Present = ClassUtils.isPresent(
"javax.money.MonetaryAmount", DefaultFormattingConversionService.class.getClassLoader());
private static final boolean jsr310Present = ClassUtils.isPresent(
"java.time.LocalDate", DefaultFormattingConversionService.class.getClassLoader());
@@ -91,7 +97,17 @@ public class DefaultFormattingConversionService extends FormattingConversionServ
* @param formatterRegistry the service to register default formatters against
*/
public static void addDefaultFormatters(FormatterRegistry formatterRegistry) {
// Default handling of number values
formatterRegistry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
// Default handling of monetary values
if (jsr354Present) {
formatterRegistry.addFormatter(new CurrencyUnitFormatter());
formatterRegistry.addFormatter(new MonetaryAmountFormatter());
formatterRegistry.addFormatterForFieldAnnotation(new Jsr354NumberFormatAnnotationFormatterFactory());
}
// Default handling of date-time values
if (jsr310Present) {
// just handling JSR-310 specific date and time types
new DateTimeFormatterRegistrar().registerFormatters(formatterRegistry);