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.math.BigDecimal;
24 import java.text.Format;
25 import java.text.NumberFormat;
26 import java.util.Locale;
27
28 /***
29 * <p><b>BigDecimal Validation</b> and Conversion routines (<code>java.math.BigDecimal</code>).</p>
30 *
31 * <p>This validator provides a number of methods for
32 * validating/converting a <code>String</code> value to
33 * a <code>BigDecimal</code> using <code>java.text.NumberFormat</code>
34 * to parse either:</p>
35 * <ul>
36 * <li>using the default format for the default <code>Locale</code></li>
37 * <li>using a specified pattern with the default <code>Locale</code></li>
38 * <li>using the default format for a specified <code>Locale</code></li>
39 * <li>using a specified pattern with a specified <code>Locale</code></li>
40 * </ul>
41 *
42 * <p>Use one of the <code>isValid()</code> methods to just validate or
43 * one of the <code>validate()</code> methods to validate and receive a
44 * <i>converted</i> <code>BigDecimal</code> value.</p>
45 *
46 * <p>Fraction/decimal values are automatically trimmed to the appropriate length.</p>
47 *
48 * <p>Once a value has been sucessfully converted the following
49 * methods can be used to perform minimum, maximum and range checks:</p>
50 * <ul>
51 * <li><code>minValue()</code> checks whether the value is greater
52 * than or equal to a specified minimum.</li>
53 * <li><code>maxValue()</code> checks whether the value is less
54 * than or equal to a specified maximum.</li>
55 * <li><code>isInRange()</code> checks whether the value is within
56 * a specified range of values.</li>
57 * </ul>
58 *
59 * <p>So that the same mechanism used for parsing an <i>input</i> value
60 * for validation can be used to format <i>output</i>, corresponding
61 * <code>format()</code> methods are also provided. That is you can
62 * format either:</p>
63 * <ul>
64 * <li>using the default format for the default <code>Locale</code></li>
65 * <li>using a specified pattern with the default <code>Locale</code></li>
66 * <li>using the default format for a specified <code>Locale</code></li>
67 * <li>using a specified pattern with a specified <code>Locale</code></li>
68 * </ul>
69 *
70 * @version $Revision: 386637 $ $Date: 2006-03-17 13:22:26 +0000 (Fri, 17 Mar 2006) $
71 * @since Validator 1.3.0
72 */
73 public class BigDecimalValidator extends AbstractNumberValidator {
74
75 private static final BigDecimalValidator VALIDATOR = new BigDecimalValidator();
76
77 /***
78 * Return a singleton instance of this validator.
79 * @return A singleton instance of the BigDecimalValidator.
80 */
81 public static BigDecimalValidator getInstance() {
82 return VALIDATOR;
83 }
84
85 /***
86 * Construct a <i>strict</i> instance.
87 */
88 public BigDecimalValidator() {
89 this(true);
90 }
91
92 /***
93 * <p>Construct an instance with the specified strict setting.</p>
94 *
95 * @param strict <code>true</code> if strict
96 * <code>Format</code> parsing should be used.
97 */
98 public BigDecimalValidator(boolean strict) {
99 this(strict, STANDARD_FORMAT, true);
100 }
101
102 /***
103 * <p>Construct an instance with the specified strict setting
104 * and format type.</p>
105 *
106 * <p>The <code>formatType</code> specified what type of
107 * <code>NumberFormat</code> is created - valid types
108 * are:</p>
109 * <ul>
110 * <li>AbstractNumberValidator.STANDARD_FORMAT -to create
111 * <i>standard</i> number formats (the default).</li>
112 * <li>AbstractNumberValidator.CURRENCY_FORMAT -to create
113 * <i>currency</i> number formats.</li>
114 * <li>AbstractNumberValidator.PERCENT_FORMAT -to create
115 * <i>percent</i> number formats (the default).</li>
116 * </ul>
117 *
118 * @param strict <code>true</code> if strict
119 * <code>Format</code> parsing should be used.
120 * @param formatType The <code>NumberFormat</code> type to
121 * create for validation, default is STANDARD_FORMAT.
122 * @param allowFractions <code>true</code> if fractions are
123 * allowed or <code>false</code> if integers only.
124 */
125 protected BigDecimalValidator(boolean strict, int formatType,
126 boolean allowFractions) {
127 super(strict, formatType, allowFractions);
128 }
129
130 /***
131 * <p>Validate/convert a <code>BigDecimal</code> using the default
132 * <code>Locale</code>.
133 *
134 * @param value The value validation is being performed on.
135 * @return The parsed <code>BigDecimal</code> if valid or <code>null</code>
136 * if invalid.
137 */
138 public BigDecimal validate(String value) {
139 return (BigDecimal)parse(value, (String)null, (Locale)null);
140 }
141
142 /***
143 * <p>Validate/convert a <code>BigDecimal</code> using the
144 * specified <i>pattern</i>.
145 *
146 * @param value The value validation is being performed on.
147 * @param pattern The pattern used to validate the value against, or the
148 * default for the <code>Locale</code> if <code>null</code>.
149 * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
150 */
151 public BigDecimal validate(String value, String pattern) {
152 return (BigDecimal)parse(value, pattern, (Locale)null);
153 }
154
155 /***
156 * <p>Validate/convert a <code>BigDecimal</code> using the
157 * specified <code>Locale</code>.
158 *
159 * @param value The value validation is being performed on.
160 * @param locale The locale to use for the number format, system default if null.
161 * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
162 */
163 public BigDecimal validate(String value, Locale locale) {
164 return (BigDecimal)parse(value, (String)null, locale);
165 }
166
167 /***
168 * <p>Validate/convert a <code>BigDecimal</code> using the
169 * specified pattern and/ or <code>Locale</code>.
170 *
171 * @param value The value validation is being performed on.
172 * @param pattern The pattern used to validate the value against, or the
173 * default for the <code>Locale</code> if <code>null</code>.
174 * @param locale The locale to use for the date format, system default if null.
175 * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
176 */
177 public BigDecimal validate(String value, String pattern, Locale locale) {
178 return (BigDecimal)parse(value, pattern, locale);
179 }
180
181 /***
182 * Check if the value is within a specified range.
183 *
184 * @param value The <code>Number</code> value to check.
185 * @param min The minimum value of the range.
186 * @param max The maximum value of the range.
187 * @return <code>true</code> if the value is within the
188 * specified range.
189 */
190 public boolean isInRange(BigDecimal value, double min, double max) {
191 return (value.doubleValue() >= min && value.doubleValue() <= max);
192 }
193
194 /***
195 * Check if the value is greater than or equal to a minimum.
196 *
197 * @param value The value validation is being performed on.
198 * @param min The minimum value.
199 * @return <code>true</code> if the value is greater than
200 * or equal to the minimum.
201 */
202 public boolean minValue(BigDecimal value, double min) {
203 return (value.doubleValue() >= min);
204 }
205
206 /***
207 * Check if the value is less than or equal to a maximum.
208 *
209 * @param value The value validation is being performed on.
210 * @param max The maximum value.
211 * @return <code>true</code> if the value is less than
212 * or equal to the maximum.
213 */
214 public boolean maxValue(BigDecimal value, double max) {
215 return (value.doubleValue() <= max);
216 }
217
218 /***
219 * Convert the parsed value to a <code>BigDecimal</code>.
220 *
221 * @param value The parsed <code>Number</code> object created.
222 * @param formatter The Format used to parse the value with.
223 * @return The parsed <code>Number</code> converted to a
224 * <code>BigDecimal</code>.
225 */
226 protected Object processParsedValue(Object value, Format formatter) {
227 BigDecimal decimal = null;
228 if (value instanceof Long) {
229 decimal = BigDecimal.valueOf(((Long)value).longValue());
230 } else {
231 decimal = new BigDecimal(value.toString());
232 }
233
234 int scale = determineScale((NumberFormat)formatter);
235 if (scale >= 0) {
236 decimal = decimal.setScale(scale, BigDecimal.ROUND_DOWN);
237 }
238
239 return decimal;
240 }
241 }