View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.validator.routines;
18  
19  import java.math.BigDecimal;
20  import java.text.Format;
21  import java.text.NumberFormat;
22  import java.util.Locale;
23  
24  /**
25   * <p><b>BigDecimal Validation</b> and Conversion routines (<code>java.math.BigDecimal</code>).</p>
26   *
27   * <p>This validator provides a number of methods for
28   *    validating/converting a <code>String</code> value to
29   *    a <code>BigDecimal</code> using <code>java.text.NumberFormat</code>
30   *    to parse either:</p>
31   *    <ul>
32   *       <li>using the default format for the default <code>Locale</code></li>
33   *       <li>using a specified pattern with the default <code>Locale</code></li>
34   *       <li>using the default format for a specified <code>Locale</code></li>
35   *       <li>using a specified pattern with a specified <code>Locale</code></li>
36   *    </ul>
37   *
38   * <p>Use one of the <code>isValid()</code> methods to just validate or
39   *    one of the <code>validate()</code> methods to validate and receive a
40   *    <i>converted</i> <code>BigDecimal</code> value.</p>
41   *
42   * <p>Fraction/decimal values are automatically trimmed to the appropriate length.</p>
43   *
44   * <p>Once a value has been sucessfully converted the following
45   *    methods can be used to perform minimum, maximum and range checks:</p>
46   *    <ul>
47   *       <li><code>minValue()</code> checks whether the value is greater
48   *           than or equal to a specified minimum.</li>
49   *       <li><code>maxValue()</code> checks whether the value is less
50   *           than or equal to a specified maximum.</li>
51   *       <li><code>isInRange()</code> checks whether the value is within
52   *           a specified range of values.</li>
53   *    </ul>
54   *
55   * <p>So that the same mechanism used for parsing an <i>input</i> value
56   *    for validation can be used to format <i>output</i>, corresponding
57   *    <code>format()</code> methods are also provided. That is you can
58   *    format either:</p>
59   *    <ul>
60   *       <li>using the default format for the default <code>Locale</code></li>
61   *       <li>using a specified pattern with the default <code>Locale</code></li>
62   *       <li>using the default format for a specified <code>Locale</code></li>
63   *       <li>using a specified pattern with a specified <code>Locale</code></li>
64   *    </ul>
65   *
66   * @version $Revision: 1227719 $ $Date: 2012-01-05 12:45:51 -0500 (Thu, 05 Jan 2012) $
67   * @since Validator 1.3.0
68   */
69  public class BigDecimalValidator extends AbstractNumberValidator {
70  
71      private static final long serialVersionUID = -670320911490506772L;
72  
73      private static final BigDecimalValidator VALIDATOR = new BigDecimalValidator();
74  
75      /**
76       * Return a singleton instance of this validator.
77       * @return A singleton instance of the BigDecimalValidator.
78       */
79      public static BigDecimalValidator getInstance() {
80          return VALIDATOR;
81      }
82  
83      /**
84       * Construct a <i>strict</i> instance.
85       */
86      public BigDecimalValidator() {
87          this(true);
88      }
89  
90      /**
91       * <p>Construct an instance with the specified strict setting.</p>
92       *
93       * @param strict <code>true</code> if strict
94       *        <code>Format</code> parsing should be used.
95       */
96      public BigDecimalValidator(boolean strict) {
97          this(strict, STANDARD_FORMAT, true);
98      }
99  
100     /**
101      * <p>Construct an instance with the specified strict setting
102      *    and format type.</p>
103      *
104      * <p>The <code>formatType</code> specified what type of
105      *    <code>NumberFormat</code> is created - valid types
106      *    are:</p>
107      *    <ul>
108      *       <li>AbstractNumberValidator.STANDARD_FORMAT -to create
109      *           <i>standard</i> number formats (the default).</li>
110      *       <li>AbstractNumberValidator.CURRENCY_FORMAT -to create
111      *           <i>currency</i> number formats.</li>
112      *       <li>AbstractNumberValidator.PERCENT_FORMAT -to create
113      *           <i>percent</i> number formats (the default).</li>
114      *    </ul>
115      *
116      * @param strict <code>true</code> if strict
117      *        <code>Format</code> parsing should be used.
118      * @param formatType The <code>NumberFormat</code> type to
119      *        create for validation, default is STANDARD_FORMAT.
120      * @param allowFractions <code>true</code> if fractions are
121      *        allowed or <code>false</code> if integers only.
122      */
123     protected BigDecimalValidator(boolean strict, int formatType,
124             boolean allowFractions) {
125         super(strict, formatType, allowFractions);
126     }
127 
128     /**
129      * <p>Validate/convert a <code>BigDecimal</code> using the default
130      *    <code>Locale</code>.
131      *
132      * @param value The value validation is being performed on.
133      * @return The parsed <code>BigDecimal</code> if valid or <code>null</code>
134      *  if invalid.
135      */
136     public BigDecimal validate(String value) {
137         return (BigDecimal)parse(value, (String)null, (Locale)null);
138     }
139 
140     /**
141      * <p>Validate/convert a <code>BigDecimal</code> using the
142      *    specified <i>pattern</i>.
143      *
144      * @param value The value validation is being performed on.
145      * @param pattern The pattern used to validate the value against, or the
146      *        default for the <code>Locale</code> if <code>null</code>.
147      * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
148      */
149     public BigDecimal validate(String value, String pattern) {
150         return (BigDecimal)parse(value, pattern, (Locale)null);
151     }
152 
153     /**
154      * <p>Validate/convert a <code>BigDecimal</code> using the
155      *    specified <code>Locale</code>.
156      *
157      * @param value The value validation is being performed on.
158      * @param locale The locale to use for the number format, system default if null.
159      * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
160      */
161     public BigDecimal validate(String value, Locale locale) {
162         return (BigDecimal)parse(value, (String)null, locale);
163     }
164 
165     /**
166      * <p>Validate/convert a <code>BigDecimal</code> using the
167      *    specified pattern and/ or <code>Locale</code>.
168      *
169      * @param value The value validation is being performed on.
170      * @param pattern The pattern used to validate the value against, or the
171      *        default for the <code>Locale</code> if <code>null</code>.
172      * @param locale The locale to use for the date format, system default if null.
173      * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
174      */
175     public BigDecimal validate(String value, String pattern, Locale locale) {
176         return (BigDecimal)parse(value, pattern, locale);
177     }
178 
179     /**
180      * Check if the value is within a specified range.
181      *
182      * @param value The <code>Number</code> value to check.
183      * @param min The minimum value of the range.
184      * @param max The maximum value of the range.
185      * @return <code>true</code> if the value is within the
186      *         specified range.
187      */
188     public boolean isInRange(BigDecimal value, double min, double max) {
189         return (value.doubleValue() >= min && value.doubleValue() <= max);
190     }
191 
192     /**
193      * Check if the value is greater than or equal to a minimum.
194      *
195      * @param value The value validation is being performed on.
196      * @param min The minimum value.
197      * @return <code>true</code> if the value is greater than
198      *         or equal to the minimum.
199      */
200     public boolean minValue(BigDecimal value, double min) {
201         return (value.doubleValue() >= min);
202     }
203 
204     /**
205      * Check if the value is less than or equal to a maximum.
206      *
207      * @param value The value validation is being performed on.
208      * @param max The maximum value.
209      * @return <code>true</code> if the value is less than
210      *         or equal to the maximum.
211      */
212     public boolean maxValue(BigDecimal value, double max) {
213         return (value.doubleValue() <= max);
214     }
215 
216     /**
217      * Convert the parsed value to a <code>BigDecimal</code>.
218      *
219      * @param value The parsed <code>Number</code> object created.
220      * @param formatter The Format used to parse the value with.
221      * @return The parsed <code>Number</code> converted to a
222      *         <code>BigDecimal</code>.
223      */
224     protected Object processParsedValue(Object value, Format formatter) {
225         BigDecimal decimal = null;
226         if (value instanceof Long) {
227             decimal = BigDecimal.valueOf(((Long)value).longValue());
228         } else {
229             decimal = new BigDecimal(value.toString());
230         }
231 
232         int scale = determineScale((NumberFormat)formatter);
233         if (scale >= 0) {
234             decimal = decimal.setScale(scale, BigDecimal.ROUND_DOWN);
235         }
236 
237         return decimal;
238     }
239 }