1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.commons.validator.routines;
22
23 import java.text.DecimalFormat;
24 import java.text.Format;
25
26 /***
27 * <p><b>Currency Validation</b> and Conversion routines (<code>java.math.BigDecimal</code>).</p>
28 *
29 * <p>This is one implementation of a currency validator that has the following features:</p>
30 * <ul>
31 * <li>It is <i>lenient</i> about the the presence of the <i>currency symbol</i></li>
32 * <li>It converts the currency to a <code>java.math.BigDecimal</code></li>
33 * </ul>
34 *
35 * <p>However any of the <i>number</i> validators can be used for <i>currency</i> validation.
36 * For example, if you wanted a <i>currency</i> validator that converts to a
37 * <code>java.lang.Integer</code> then you can simply instantiate an
38 * <code>IntegerValidator</code> with the appropriate <i>format type</i>:</p>
39 *
40 * <p><code>... = new IntegerValidator(false, IntegerValidator.CURRENCY_FORMAT);</code></p>
41 *
42 * <p>Pick the appropriate validator, depending on the type (e.g Float, Double, Integer, Long etc)
43 * you want the currency converted to. One thing to note - only the CurrencyValidator
44 * implements <i>lenient</i> behaviour regarding the currency symbol.</p>
45 *
46 * @version $Revision: 386637 $ $Date: 2006-03-17 13:22:26 +0000 (Fri, 17 Mar 2006) $
47 * @since Validator 1.3.0
48 */
49 public class CurrencyValidator extends BigDecimalValidator {
50
51 private static final CurrencyValidator VALIDATOR = new CurrencyValidator();
52
53 /*** DecimalFormat's currency symbol */
54 private static final char CURRENCY_SYMBOL = '\u00A4';
55
56 /***
57 * Return a singleton instance of this validator.
58 * @return A singleton instance of the CurrencyValidator.
59 */
60 public static BigDecimalValidator getInstance() {
61 return VALIDATOR;
62 }
63
64 /***
65 * Construct a <i>strict</i> instance.
66 */
67 public CurrencyValidator() {
68 this(true, true);
69 }
70
71 /***
72 * Construct an instance with the specified strict setting.
73 *
74 * @param strict <code>true</code> if strict
75 * <code>Format</code> parsing should be used.
76 * @param allowFractions <code>true</code> if fractions are
77 * allowed or <code>false</code> if integers only.
78 */
79 public CurrencyValidator(boolean strict, boolean allowFractions) {
80 super(strict, CURRENCY_FORMAT, allowFractions);
81 }
82
83 /***
84 * <p>Parse the value with the specified <code>Format</code>.</p>
85 *
86 * <p>This implementation is lenient whether the currency symbol
87 * is present or not. The default <code>NumberFormat</code>
88 * behaviour is for the parsing to "fail" if the currency
89 * symbol is missing. This method re-parses with a format
90 * without the currency symbol if it fails initially.</p>
91 *
92 * @param value The value to be parsed.
93 * @param formatter The Format to parse the value with.
94 * @return The parsed value if valid or <code>null</code> if invalid.
95 */
96 protected Object parse(String value, Format formatter) {
97
98
99 Object parsedValue = super.parse(value, formatter);
100 if (parsedValue != null || !(formatter instanceof DecimalFormat)) {
101 return parsedValue;
102 }
103
104
105 DecimalFormat decimalFormat = (DecimalFormat)formatter;
106 String pattern = decimalFormat.toPattern();
107 if (pattern.indexOf(CURRENCY_SYMBOL) >= 0) {
108 StringBuffer buffer = new StringBuffer(pattern.length());
109 for (int i = 0; i < pattern.length(); i++) {
110 if (pattern.charAt(i) != CURRENCY_SYMBOL) {
111 buffer.append(pattern.charAt(i));
112 }
113 }
114 decimalFormat.applyPattern(buffer.toString());
115 parsedValue = super.parse(value, decimalFormat);
116 }
117 return parsedValue;
118 }
119 }