001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.format.number; 018 019import java.math.BigDecimal; 020import java.math.RoundingMode; 021import java.text.DecimalFormat; 022import java.text.NumberFormat; 023import java.text.ParseException; 024import java.util.Currency; 025import java.util.Locale; 026 027/** 028 * A BigDecimal formatter for number values in currency style. 029 * 030 * <p>Delegates to {@link java.text.NumberFormat#getCurrencyInstance(Locale)}. 031 * Configures BigDecimal parsing so there is no loss of precision. 032 * Can apply a specified {@link java.math.RoundingMode} to parsed values. 033 * 034 * @author Keith Donald 035 * @author Juergen Hoeller 036 * @since 4.2 037 * @see #setLenient 038 * @see #setRoundingMode 039 */ 040public class CurrencyStyleFormatter extends AbstractNumberFormatter { 041 042 private int fractionDigits = 2; 043 044 private RoundingMode roundingMode; 045 046 private Currency currency; 047 048 private String pattern; 049 050 051 /** 052 * Specify the desired number of fraction digits. 053 * Default is 2. 054 */ 055 public void setFractionDigits(int fractionDigits) { 056 this.fractionDigits = fractionDigits; 057 } 058 059 /** 060 * Specify the rounding mode to use for decimal parsing. 061 * Default is {@link java.math.RoundingMode#UNNECESSARY}. 062 */ 063 public void setRoundingMode(RoundingMode roundingMode) { 064 this.roundingMode = roundingMode; 065 } 066 067 /** 068 * Specify the currency, if known. 069 */ 070 public void setCurrency(Currency currency) { 071 this.currency = currency; 072 } 073 074 /** 075 * Specify the pattern to use to format number values. 076 * If not specified, the default DecimalFormat pattern is used. 077 * @see java.text.DecimalFormat#applyPattern(String) 078 */ 079 public void setPattern(String pattern) { 080 this.pattern = pattern; 081 } 082 083 084 @Override 085 public BigDecimal parse(String text, Locale locale) throws ParseException { 086 BigDecimal decimal = (BigDecimal) super.parse(text, locale); 087 if (decimal != null) { 088 if (this.roundingMode != null) { 089 decimal = decimal.setScale(this.fractionDigits, this.roundingMode); 090 } 091 else { 092 decimal = decimal.setScale(this.fractionDigits); 093 } 094 } 095 return decimal; 096 } 097 098 @Override 099 protected NumberFormat getNumberFormat(Locale locale) { 100 DecimalFormat format = (DecimalFormat) NumberFormat.getCurrencyInstance(locale); 101 format.setParseBigDecimal(true); 102 format.setMaximumFractionDigits(this.fractionDigits); 103 format.setMinimumFractionDigits(this.fractionDigits); 104 if (this.roundingMode != null) { 105 format.setRoundingMode(this.roundingMode); 106 } 107 if (this.currency != null) { 108 format.setCurrency(this.currency); 109 } 110 if (this.pattern != null) { 111 format.applyPattern(this.pattern); 112 } 113 return format; 114 } 115 116}