diff --git a/build.gradle b/build.gradle index 3ceafa549ab..f4171e56372 100644 --- a/build.gradle +++ b/build.gradle @@ -460,6 +460,7 @@ project("spring-context") { optional("javax.inject:javax.inject:1") optional("javax.ejb:ejb-api:3.0") optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0") + optional("javax.money:money-api:1.0-RC3") optional("org.eclipse.persistence:javax.persistence:2.0.0") optional("javax.validation:validation-api:1.0.0.GA") optional("org.hibernate:hibernate-validator:${hibval4Version}") @@ -469,6 +470,7 @@ project("spring-context") { optional("org.beanshell:bsh:2.0b4") optional("org.jruby:jruby:1.7.19") testCompile("javax.inject:javax.inject-tck:1") + testCompile("org.javamoney:moneta:1.0-RC3") testCompile("commons-dbcp:commons-dbcp:1.4") testCompile("org.apache.commons:commons-pool2:2.2") testCompile("org.slf4j:slf4j-api:${slf4jVersion}") diff --git a/spring-context/src/main/java/org/springframework/format/annotation/NumberFormat.java b/spring-context/src/main/java/org/springframework/format/annotation/NumberFormat.java index 7418ec6b2f1..5e42d3b23a3 100644 --- a/spring-context/src/main/java/org/springframework/format/annotation/NumberFormat.java +++ b/spring-context/src/main/java/org/springframework/format/annotation/NumberFormat.java @@ -28,15 +28,19 @@ import java.lang.annotation.Target; *

Supports formatting by style or custom pattern string. * Can be applied to any JDK {@code java.lang.Number} type. * - *

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 #, ###.##}. + *

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 #, ###.##}. * - *

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}. + *

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. - *

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. + *

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. */ diff --git a/spring-context/src/main/java/org/springframework/format/number/AbstractNumberFormatter.java b/spring-context/src/main/java/org/springframework/format/number/AbstractNumberFormatter.java index aa9e85177a6..8b0297e7cd3 100644 --- a/spring-context/src/main/java/org/springframework/format/number/AbstractNumberFormatter.java +++ b/spring-context/src/main/java/org/springframework/format/number/AbstractNumberFormatter.java @@ -35,6 +35,7 @@ public abstract class AbstractNumberFormatter implements Formatter { private boolean lenient = false; + /** * Specify whether or not parsing is to be lenient. Default is false. *

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 { this.lenient = lenient; } + @Override public String print(Number number, Locale locale) { return getNumberFormat(locale).format(number); diff --git a/spring-context/src/main/java/org/springframework/format/number/CurrencyFormatter.java b/spring-context/src/main/java/org/springframework/format/number/CurrencyFormatter.java index 739f9c4343b..fb7033efbef 100644 --- a/spring-context/src/main/java/org/springframework/format/number/CurrencyFormatter.java +++ b/spring-context/src/main/java/org/springframework/format/number/CurrencyFormatter.java @@ -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. * - *

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 { } diff --git a/spring-context/src/main/java/org/springframework/format/number/CurrencyStyleFormatter.java b/spring-context/src/main/java/org/springframework/format/number/CurrencyStyleFormatter.java new file mode 100644 index 00000000000..0dbe143d084 --- /dev/null +++ b/spring-context/src/main/java/org/springframework/format/number/CurrencyStyleFormatter.java @@ -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. + * + *

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; + } + +} diff --git a/spring-context/src/main/java/org/springframework/format/number/NumberFormatAnnotationFormatterFactory.java b/spring-context/src/main/java/org/springframework/format/number/NumberFormatAnnotationFormatterFactory.java index 33e40386b75..2f508a7a0b1 100644 --- a/spring-context/src/main/java/org/springframework/format/number/NumberFormatAnnotationFormatterFactory.java +++ b/spring-context/src/main/java/org/springframework/format/number/NumberFormatAnnotationFormatterFactory.java @@ -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 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(); } } } diff --git a/spring-context/src/main/java/org/springframework/format/number/NumberFormatter.java b/spring-context/src/main/java/org/springframework/format/number/NumberFormatter.java index 5111c17bab7..6a1a704af9a 100644 --- a/spring-context/src/main/java/org/springframework/format/number/NumberFormatter.java +++ b/spring-context/src/main/java/org/springframework/format/number/NumberFormatter.java @@ -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. * - *

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); } } diff --git a/spring-context/src/main/java/org/springframework/format/number/NumberStyleFormatter.java b/spring-context/src/main/java/org/springframework/format/number/NumberStyleFormatter.java new file mode 100644 index 00000000000..15b7ee107cd --- /dev/null +++ b/spring-context/src/main/java/org/springframework/format/number/NumberStyleFormatter.java @@ -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. + * + *

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; + } + +} diff --git a/spring-context/src/main/java/org/springframework/format/number/PercentFormatter.java b/spring-context/src/main/java/org/springframework/format/number/PercentFormatter.java index 8058b020eb2..e791bbf9705 100644 --- a/spring-context/src/main/java/org/springframework/format/number/PercentFormatter.java +++ b/spring-context/src/main/java/org/springframework/format/number/PercentFormatter.java @@ -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. * - *

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 { } diff --git a/spring-context/src/main/java/org/springframework/format/number/PercentStyleFormatter.java b/spring-context/src/main/java/org/springframework/format/number/PercentStyleFormatter.java new file mode 100644 index 00000000000..2f538230349 --- /dev/null +++ b/spring-context/src/main/java/org/springframework/format/number/PercentStyleFormatter.java @@ -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. + * + *

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; + } + +} diff --git a/spring-context/src/main/java/org/springframework/format/number/money/CurrencyUnitFormatter.java b/spring-context/src/main/java/org/springframework/format/number/money/CurrencyUnitFormatter.java new file mode 100644 index 00000000000..e98e2e3c2b8 --- /dev/null +++ b/spring-context/src/main/java/org/springframework/format/number/money/CurrencyUnitFormatter.java @@ -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 { + + @Override + public String print(CurrencyUnit object, Locale locale) { + return object.getCurrencyCode(); + } + + @Override + public CurrencyUnit parse(String text, Locale locale) { + return MonetaryCurrencies.getCurrency(text); + } + +} diff --git a/spring-context/src/main/java/org/springframework/format/number/money/Jsr354NumberFormatAnnotationFormatterFactory.java b/spring-context/src/main/java/org/springframework/format/number/money/Jsr354NumberFormatAnnotationFormatterFactory.java new file mode 100644 index 00000000000..4061fe74ed3 --- /dev/null +++ b/spring-context/src/main/java/org/springframework/format/number/money/Jsr354NumberFormatAnnotationFormatterFactory.java @@ -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 { + + @Override + @SuppressWarnings("unchecked") + public Set> getFieldTypes() { + return (Set) Collections.singleton(MonetaryAmount.class); + } + + @Override + public Printer getPrinter(NumberFormat annotation, Class fieldType) { + return configureFormatterFrom(annotation); + } + + @Override + public Parser getParser(NumberFormat annotation, Class fieldType) { + return configureFormatterFrom(annotation); + } + + + private Formatter 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 { + + private final Formatter numberFormatter; + + private final String pattern; + + public NumberDecoratingFormatter(Formatter numberFormatter, String pattern) { + this.numberFormatter = numberFormatter; + this.pattern = pattern; + } + + @Override + public String print(MonetaryAmount object, Locale locale) { + Formatter 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 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(); + } + } + +} diff --git a/spring-context/src/main/java/org/springframework/format/number/money/MonetaryAmountFormatter.java b/spring-context/src/main/java/org/springframework/format/number/money/MonetaryAmountFormatter.java new file mode 100644 index 00000000000..8d949ac45d8 --- /dev/null +++ b/spring-context/src/main/java/org/springframework/format/number/money/MonetaryAmountFormatter.java @@ -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 { + + 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. + *

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. + *

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); + } + } + +} diff --git a/spring-context/src/main/java/org/springframework/format/number/money/package-info.java b/spring-context/src/main/java/org/springframework/format/number/money/package-info.java new file mode 100644 index 00000000000..d19fccfc37c --- /dev/null +++ b/spring-context/src/main/java/org/springframework/format/number/money/package-info.java @@ -0,0 +1,4 @@ +/** + * Integration with the JSR-354 javax.money package. + */ +package org.springframework.format.number.money; diff --git a/spring-context/src/main/java/org/springframework/format/support/DefaultFormattingConversionService.java b/spring-context/src/main/java/org/springframework/format/support/DefaultFormattingConversionService.java index 6670071d503..e3e97fcaddd 100644 --- a/spring-context/src/main/java/org/springframework/format/support/DefaultFormattingConversionService.java +++ b/spring-context/src/main/java/org/springframework/format/support/DefaultFormattingConversionService.java @@ -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); diff --git a/spring-context/src/test/java/org/springframework/format/datetime/DateFormatterTests.java b/spring-context/src/test/java/org/springframework/format/datetime/DateFormatterTests.java index a978b7b8390..adbb9e4fa30 100644 --- a/spring-context/src/test/java/org/springframework/format/datetime/DateFormatterTests.java +++ b/spring-context/src/test/java/org/springframework/format/datetime/DateFormatterTests.java @@ -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. @@ -43,10 +43,11 @@ import static org.junit.Assert.*; */ public class DateFormatterTests { + private static final TimeZone UTC = TimeZone.getTimeZone("UTC"); + @Rule public ExpectedException thown = ExpectedException.none(); - private static final TimeZone UTC = TimeZone.getTimeZone("UTC"); @Test public void shouldPrintAndParseDefault() throws Exception { @@ -210,12 +211,12 @@ public class DateFormatterTests { assertThat("uses style", formatter.print(date, Locale.US), is("6/1/09")); } + private Date getDate(int year, int month, int dayOfMonth) { return getDate(year, month, dayOfMonth, 0, 0, 0, 0); } - private Date getDate(int year, int month, int dayOfMonth, int hour, int minute, - int second, int millisecond) { + private Date getDate(int year, int month, int dayOfMonth, int hour, int minute, int second, int millisecond) { Calendar cal = Calendar.getInstance(Locale.US); cal.setTimeZone(UTC); cal.clear(); diff --git a/spring-context/src/test/java/org/springframework/format/datetime/DateFormattingTests.java b/spring-context/src/test/java/org/springframework/format/datetime/DateFormattingTests.java index 91f6b2b242d..8ee7cc684ca 100644 --- a/spring-context/src/test/java/org/springframework/format/datetime/DateFormattingTests.java +++ b/spring-context/src/test/java/org/springframework/format/datetime/DateFormattingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 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. @@ -46,10 +46,11 @@ import static org.junit.Assert.*; */ public class DateFormattingTests { - private FormattingConversionService conversionService = new FormattingConversionService(); + private final FormattingConversionService conversionService = new FormattingConversionService(); private DataBinder binder; + @Before public void setUp() { DateFormatterRegistrar registrar = new DateFormatterRegistrar(); @@ -73,6 +74,7 @@ public class DateFormattingTests { LocaleContextHolder.setLocale(null); } + @Test public void testBindDate() { MutablePropertyValues propertyValues = new MutablePropertyValues(); diff --git a/spring-context/src/test/java/org/springframework/format/number/CurrencyFormatterTests.java b/spring-context/src/test/java/org/springframework/format/number/CurrencyStyleFormatterTests.java similarity index 90% rename from spring-context/src/test/java/org/springframework/format/number/CurrencyFormatterTests.java rename to spring-context/src/test/java/org/springframework/format/number/CurrencyStyleFormatterTests.java index b41327a45d7..ec9e6a7e21f 100644 --- a/spring-context/src/test/java/org/springframework/format/number/CurrencyFormatterTests.java +++ b/spring-context/src/test/java/org/springframework/format/number/CurrencyStyleFormatterTests.java @@ -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. @@ -28,9 +28,10 @@ import static org.junit.Assert.*; /** * @author Keith Donald */ -public class CurrencyFormatterTests { +public class CurrencyStyleFormatterTests { + + private final CurrencyStyleFormatter formatter = new CurrencyStyleFormatter(); - private CurrencyFormatter formatter = new CurrencyFormatter(); @Test public void formatValue() { diff --git a/spring-context/src/test/java/org/springframework/format/number/NumberFormattingTests.java b/spring-context/src/test/java/org/springframework/format/number/NumberFormattingTests.java index 6cbb561e835..d5032deff67 100644 --- a/spring-context/src/test/java/org/springframework/format/number/NumberFormattingTests.java +++ b/spring-context/src/test/java/org/springframework/format/number/NumberFormattingTests.java @@ -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. @@ -41,10 +41,11 @@ import static org.junit.Assert.*; */ public class NumberFormattingTests { - private FormattingConversionService conversionService = new FormattingConversionService(); + private final FormattingConversionService conversionService = new FormattingConversionService(); private DataBinder binder; + @Before public void setUp() { DefaultConversionService.addDefaultConverters(conversionService); @@ -53,12 +54,13 @@ public class NumberFormattingTests { public String resolveStringValue(String strVal) { if ("${pattern}".equals(strVal)) { return "#,##.00"; - } else { + } + else { return strVal; } } }); - conversionService.addFormatterForFieldType(Number.class, new NumberFormatter()); + conversionService.addFormatterForFieldType(Number.class, new NumberStyleFormatter()); conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); LocaleContextHolder.setLocale(Locale.US); binder = new DataBinder(new TestBean()); @@ -70,6 +72,7 @@ public class NumberFormattingTests { LocaleContextHolder.setLocale(null); } + @Test public void testDefaultNumberFormatting() { MutablePropertyValues propertyValues = new MutablePropertyValues(); @@ -172,6 +175,7 @@ public class NumberFormattingTests { assertEquals("1,25.00,2,35.00", binder.getBindingResult().getFieldValue("patternList2")); } + @SuppressWarnings("unused") private static class TestBean { @@ -261,7 +265,6 @@ public class NumberFormattingTests { public void setPatternList2(List patternList2) { this.patternList2 = patternList2; } - } } diff --git a/spring-context/src/test/java/org/springframework/format/number/NumberFormatterTests.java b/spring-context/src/test/java/org/springframework/format/number/NumberStyleFormatterTests.java similarity index 88% rename from spring-context/src/test/java/org/springframework/format/number/NumberFormatterTests.java rename to spring-context/src/test/java/org/springframework/format/number/NumberStyleFormatterTests.java index 73783f30294..1633982aa7a 100644 --- a/spring-context/src/test/java/org/springframework/format/number/NumberFormatterTests.java +++ b/spring-context/src/test/java/org/springframework/format/number/NumberStyleFormatterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 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. @@ -27,9 +27,10 @@ import static org.junit.Assert.*; /** * @author Keith Donald */ -public class NumberFormatterTests { +public class NumberStyleFormatterTests { + + private final NumberStyleFormatter formatter = new NumberStyleFormatter(); - private NumberFormatter formatter = new NumberFormatter(); @Test public void formatValue() { diff --git a/spring-context/src/test/java/org/springframework/format/number/PercentFormatterTests.java b/spring-context/src/test/java/org/springframework/format/number/PercentStyleFormatterTests.java similarity index 87% rename from spring-context/src/test/java/org/springframework/format/number/PercentFormatterTests.java rename to spring-context/src/test/java/org/springframework/format/number/PercentStyleFormatterTests.java index 1d77ca3ca4c..d631f4a8cb7 100644 --- a/spring-context/src/test/java/org/springframework/format/number/PercentFormatterTests.java +++ b/spring-context/src/test/java/org/springframework/format/number/PercentStyleFormatterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 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. @@ -27,9 +27,10 @@ import static org.junit.Assert.*; /** * @author Keith Donald */ -public class PercentFormatterTests { +public class PercentStyleFormatterTests { + + private final PercentStyleFormatter formatter = new PercentStyleFormatter(); - private PercentFormatter formatter = new PercentFormatter(); @Test public void formatValue() { @@ -38,8 +39,7 @@ public class PercentFormatterTests { @Test public void parseValue() throws ParseException { - assertEquals(new BigDecimal(".2356"), formatter.parse("23.56%", - Locale.US)); + assertEquals(new BigDecimal(".2356"), formatter.parse("23.56%", Locale.US)); } @Test(expected = ParseException.class) diff --git a/spring-context/src/test/java/org/springframework/format/number/money/MoneyFormattingTests.java b/spring-context/src/test/java/org/springframework/format/number/money/MoneyFormattingTests.java new file mode 100644 index 00000000000..8a3801a5d38 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/format/number/money/MoneyFormattingTests.java @@ -0,0 +1,244 @@ +/* + * 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.MonetaryAmount; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.beans.MutablePropertyValues; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.format.annotation.NumberFormat; +import org.springframework.format.support.DefaultFormattingConversionService; +import org.springframework.format.support.FormattingConversionService; +import org.springframework.validation.DataBinder; + +import static org.junit.Assert.*; + +/** + * @author Juergen Hoeller + * @since 4.2 + */ +public class MoneyFormattingTests { + + private final FormattingConversionService conversionService = new DefaultFormattingConversionService(); + + + @Before + public void setUp() { + LocaleContextHolder.setLocale(Locale.US); + } + + @After + public void tearDown() { + LocaleContextHolder.setLocale(null); + } + + + @Test + public void testAmountAndUnit() { + DataBinder binder = new DataBinder(new MoneyHolder()); + binder.setConversionService(conversionService); + MutablePropertyValues propertyValues = new MutablePropertyValues(); + propertyValues.add("amount", "USD 10.50"); + propertyValues.add("unit", "USD"); + binder.bind(propertyValues); + assertEquals(0, binder.getBindingResult().getErrorCount()); + assertEquals("USD10.50", binder.getBindingResult().getFieldValue("amount")); + assertEquals("USD", binder.getBindingResult().getFieldValue("unit")); + } + + @Test + public void testAmountWithNumberFormat1() { + DataBinder binder = new DataBinder(new FormattedMoneyHolder1()); + binder.setConversionService(conversionService); + + MutablePropertyValues propertyValues = new MutablePropertyValues(); + propertyValues.add("amount", "$10.50"); + binder.bind(propertyValues); + assertEquals(0, binder.getBindingResult().getErrorCount()); + assertEquals("$10.50", binder.getBindingResult().getFieldValue("amount")); + + /* TODO: preserve currency from given value + LocaleContextHolder.setLocale(Locale.CANADA); + binder.bind(propertyValues); + LocaleContextHolder.setLocale(Locale.US); + assertEquals(0, binder.getBindingResult().getErrorCount()); + assertEquals("$10.50", binder.getBindingResult().getFieldValue("amount")); + */ + } + + @Test + public void testAmountWithNumberFormat2() { + DataBinder binder = new DataBinder(new FormattedMoneyHolder2()); + binder.setConversionService(conversionService); + + MutablePropertyValues propertyValues = new MutablePropertyValues(); + propertyValues.add("amount", "10.50"); + binder.bind(propertyValues); + assertEquals(0, binder.getBindingResult().getErrorCount()); + assertEquals("10.5", binder.getBindingResult().getFieldValue("amount")); + } + + @Test + public void testAmountWithNumberFormat3() { + DataBinder binder = new DataBinder(new FormattedMoneyHolder3()); + binder.setConversionService(conversionService); + + MutablePropertyValues propertyValues = new MutablePropertyValues(); + propertyValues.add("amount", "10%"); + binder.bind(propertyValues); + assertEquals(0, binder.getBindingResult().getErrorCount()); + assertEquals("10%", binder.getBindingResult().getFieldValue("amount")); + } + + @Test + public void testAmountWithNumberFormat4() { + DataBinder binder = new DataBinder(new FormattedMoneyHolder4()); + binder.setConversionService(conversionService); + + MutablePropertyValues propertyValues = new MutablePropertyValues(); + propertyValues.add("amount", "010.500"); + binder.bind(propertyValues); + assertEquals(0, binder.getBindingResult().getErrorCount()); + assertEquals("010.500", binder.getBindingResult().getFieldValue("amount")); + } + + @Test + public void testAmountWithNumberFormat5() { + DataBinder binder = new DataBinder(new FormattedMoneyHolder5()); + binder.setConversionService(conversionService); + + MutablePropertyValues propertyValues = new MutablePropertyValues(); + propertyValues.add("amount", "$ 10.50"); + binder.bind(propertyValues); + assertEquals(0, binder.getBindingResult().getErrorCount()); + assertEquals("$ 010.500", binder.getBindingResult().getFieldValue("amount")); + + /* TODO: preserve currency from given value + LocaleContextHolder.setLocale(Locale.CANADA); + binder.bind(propertyValues); + LocaleContextHolder.setLocale(Locale.US); + assertEquals(0, binder.getBindingResult().getErrorCount()); + assertEquals("$ 010.500", binder.getBindingResult().getFieldValue("amount")); + */ + } + + + public static class MoneyHolder { + + private MonetaryAmount amount; + + private CurrencyUnit unit; + + public MonetaryAmount getAmount() { + return amount; + } + + public void setAmount(MonetaryAmount amount) { + this.amount = amount; + } + + public CurrencyUnit getUnit() { + return unit; + } + + public void setUnit(CurrencyUnit unit) { + this.unit = unit; + } + } + + + public static class FormattedMoneyHolder1 { + + @NumberFormat + private MonetaryAmount amount; + + public MonetaryAmount getAmount() { + return amount; + } + + public void setAmount(MonetaryAmount amount) { + this.amount = amount; + } + } + + + public static class FormattedMoneyHolder2 { + + @NumberFormat(style = NumberFormat.Style.NUMBER) + private MonetaryAmount amount; + + public MonetaryAmount getAmount() { + return amount; + } + + public void setAmount(MonetaryAmount amount) { + this.amount = amount; + } + } + + + public static class FormattedMoneyHolder3 { + + @NumberFormat(style = NumberFormat.Style.PERCENT) + private MonetaryAmount amount; + + public MonetaryAmount getAmount() { + return amount; + } + + public void setAmount(MonetaryAmount amount) { + this.amount = amount; + } + } + + + public static class FormattedMoneyHolder4 { + + @NumberFormat(pattern = "#000.000#") + private MonetaryAmount amount; + + public MonetaryAmount getAmount() { + return amount; + } + + public void setAmount(MonetaryAmount amount) { + this.amount = amount; + } + } + + + public static class FormattedMoneyHolder5 { + + @NumberFormat(pattern = "\u00A4 #000.000#") + private MonetaryAmount amount; + + public MonetaryAmount getAmount() { + return amount; + } + + public void setAmount(MonetaryAmount amount) { + this.amount = amount; + } + } + +} diff --git a/spring-context/src/test/java/org/springframework/format/support/FormattingConversionServiceTests.java b/spring-context/src/test/java/org/springframework/format/support/FormattingConversionServiceTests.java index cc1b36ec279..a6f5779b848 100644 --- a/spring-context/src/test/java/org/springframework/format/support/FormattingConversionServiceTests.java +++ b/spring-context/src/test/java/org/springframework/format/support/FormattingConversionServiceTests.java @@ -28,7 +28,6 @@ import java.util.Properties; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormat; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -53,7 +52,7 @@ import org.springframework.format.annotation.NumberFormat; import org.springframework.format.datetime.joda.DateTimeParser; import org.springframework.format.datetime.joda.JodaDateTimeFormatAnnotationFormatterFactory; import org.springframework.format.datetime.joda.ReadablePartialPrinter; -import org.springframework.format.number.NumberFormatter; +import org.springframework.format.number.NumberStyleFormatter; import static org.junit.Assert.*; @@ -67,6 +66,7 @@ public class FormattingConversionServiceTests { private FormattingConversionService formattingService; + @Before public void setUp() { formattingService = new FormattingConversionService(); @@ -79,9 +79,10 @@ public class FormattingConversionServiceTests { LocaleContextHolder.setLocale(null); } + @Test public void testFormatFieldForTypeWithFormatter() throws ParseException { - formattingService.addFormatterForFieldType(Number.class, new NumberFormatter()); + formattingService.addFormatterForFieldType(Number.class, new NumberStyleFormatter()); String formatted = formattingService.convert(3, String.class); assertEquals("3", formatted); Integer i = formattingService.convert("3", Integer.class); @@ -239,26 +240,26 @@ public class FormattingConversionServiceTests { @Test public void testPrintNull() throws ParseException { - formattingService.addFormatterForFieldType(Number.class, new NumberFormatter()); + formattingService.addFormatterForFieldType(Number.class, new NumberStyleFormatter()); assertEquals("", formattingService.convert(null, TypeDescriptor.valueOf(Integer.class), TypeDescriptor.valueOf(String.class))); } @Test public void testParseNull() throws ParseException { - formattingService.addFormatterForFieldType(Number.class, new NumberFormatter()); + formattingService.addFormatterForFieldType(Number.class, new NumberStyleFormatter()); assertNull(formattingService .convert(null, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class))); } @Test public void testParseEmptyString() throws ParseException { - formattingService.addFormatterForFieldType(Number.class, new NumberFormatter()); + formattingService.addFormatterForFieldType(Number.class, new NumberStyleFormatter()); assertNull(formattingService.convert("", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class))); } @Test public void testParseBlankString() throws ParseException { - formattingService.addFormatterForFieldType(Number.class, new NumberFormatter()); + formattingService.addFormatterForFieldType(Number.class, new NumberStyleFormatter()); assertNull(formattingService.convert(" ", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class))); } @@ -270,7 +271,7 @@ public class FormattingConversionServiceTests { @Test(expected=ConversionFailedException.class) public void testParseNullPrimitiveProperty() throws ParseException { - formattingService.addFormatterForFieldType(Integer.class, new NumberFormatter()); + formattingService.addFormatterForFieldType(Integer.class, new NumberStyleFormatter()); assertNull(formattingService.convert(null, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(int.class))); } diff --git a/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java b/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java index daf3d2d6ad5..4e3a2b46b3d 100644 --- a/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java +++ b/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java @@ -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. @@ -48,7 +48,7 @@ import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.context.support.StaticMessageSource; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.format.Formatter; -import org.springframework.format.number.NumberFormatter; +import org.springframework.format.number.NumberStyleFormatter; import org.springframework.format.support.FormattingConversionService; import org.springframework.tests.sample.beans.BeanWithObjectProperty; import org.springframework.tests.sample.beans.DerivedTestBean; @@ -332,7 +332,7 @@ public class DataBinderTests extends TestCase { DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); DefaultConversionService.addDefaultConverters(conversionService); - conversionService.addFormatterForFieldType(Float.class, new NumberFormatter()); + conversionService.addFormatterForFieldType(Float.class, new NumberStyleFormatter()); binder.setConversionService(conversionService); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("myFloat", "1,2"); @@ -363,7 +363,7 @@ public class DataBinderTests extends TestCase { DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); DefaultConversionService.addDefaultConverters(conversionService); - conversionService.addFormatterForFieldType(Float.class, new NumberFormatter()); + conversionService.addFormatterForFieldType(Float.class, new NumberStyleFormatter()); binder.setConversionService(conversionService); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("myFloat", "1x2"); @@ -409,7 +409,7 @@ public class DataBinderTests extends TestCase { DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); DefaultConversionService.addDefaultConverters(conversionService); - conversionService.addFormatterForFieldType(Float.class, new NumberFormatter()); + conversionService.addFormatterForFieldType(Float.class, new NumberStyleFormatter()); binder.setConversionService(conversionService); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("integerList[0]", "1"); @@ -430,7 +430,7 @@ public class DataBinderTests extends TestCase { DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); DefaultConversionService.addDefaultConverters(conversionService); - conversionService.addFormatterForFieldType(Float.class, new NumberFormatter()); + conversionService.addFormatterForFieldType(Float.class, new NumberStyleFormatter()); binder.setConversionService(conversionService); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("integerList[0]", "1x2"); @@ -452,7 +452,7 @@ public class DataBinderTests extends TestCase { DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); DefaultConversionService.addDefaultConverters(conversionService); - conversionService.addFormatterForFieldType(Float.class, new NumberFormatter()); + conversionService.addFormatterForFieldType(Float.class, new NumberStyleFormatter()); binder.setConversionService(conversionService); binder.initDirectFieldAccess(); MutablePropertyValues pvs = new MutablePropertyValues(); @@ -485,7 +485,7 @@ public class DataBinderTests extends TestCase { binder.initDirectFieldAccess(); FormattingConversionService conversionService = new FormattingConversionService(); DefaultConversionService.addDefaultConverters(conversionService); - conversionService.addFormatterForFieldType(Float.class, new NumberFormatter()); + conversionService.addFormatterForFieldType(Float.class, new NumberStyleFormatter()); binder.setConversionService(conversionService); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("myFloat", "1x2"); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java index 796ada5053f..78665e815c5 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 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. @@ -26,7 +26,7 @@ import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.env.MapPropertySource; import org.springframework.format.annotation.NumberFormat; import org.springframework.format.annotation.NumberFormat.Style; -import org.springframework.format.number.PercentFormatter; +import org.springframework.format.number.PercentStyleFormatter; import org.springframework.format.support.FormattingConversionServiceFactoryBean; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.mock.web.test.MockPageContext; @@ -71,7 +71,7 @@ public class EvalTagTests extends AbstractTagTests { } public void testPrintFormattedScopedAttributeResult() throws Exception { - PercentFormatter formatter = new PercentFormatter(); + PercentStyleFormatter formatter = new PercentStyleFormatter(); tag.setExpression("bean.formattable"); int action = tag.doStartTag(); assertEquals(Tag.EVAL_BODY_INCLUDE, action); @@ -98,7 +98,8 @@ public class EvalTagTests extends AbstractTagTests { assertEquals(Tag.EVAL_BODY_INCLUDE, action); action = tag.doEndTag(); assertEquals(Tag.EVAL_PAGE, action); - assertEquals("function foo() { alert(\\\"hi\\\") }", ((MockHttpServletResponse)context.getResponse()).getContentAsString()); + assertEquals("function foo() { alert(\\\"hi\\\") }", + ((MockHttpServletResponse)context.getResponse()).getContentAsString()); } public void testSetFormattedScopedAttributeResult() throws Exception {