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 successfully 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   * @since 1.3.0
67   */
68  public class BigDecimalValidator extends AbstractNumberValidator {
69  
70      private static final long serialVersionUID = -670320911490506772L;
71  
72      private static final BigDecimalValidator VALIDATOR = new BigDecimalValidator();
73  
74      /**
75       * Return a singleton instance of this validator.
76       * @return A singleton instance of the BigDecimalValidator.
77       */
78      public static BigDecimalValidator getInstance() {
79          return VALIDATOR;
80      }
81  
82      /**
83       * Constructs a <i>strict</i> instance.
84       */
85      public BigDecimalValidator() {
86          this(true);
87      }
88  
89      /**
90       * <p>Construct an instance with the specified strict setting.</p>
91       *
92       * @param strict {@code true} if strict
93       *        <code>Format</code> parsing should be used.
94       */
95      public BigDecimalValidator(final boolean strict) {
96          this(strict, STANDARD_FORMAT, true);
97      }
98  
99      /**
100      * <p>Construct an instance with the specified strict setting
101      *    and format type.</p>
102      *
103      * <p>The <code>formatType</code> specified what type of
104      *    <code>NumberFormat</code> is created - valid types
105      *    are:</p>
106      *    <ul>
107      *       <li>AbstractNumberValidator.STANDARD_FORMAT -to create
108      *           <i>standard</i> number formats (the default).</li>
109      *       <li>AbstractNumberValidator.CURRENCY_FORMAT -to create
110      *           <i>currency</i> number formats.</li>
111      *       <li>AbstractNumberValidator.PERCENT_FORMAT -to create
112      *           <i>percent</i> number formats (the default).</li>
113      *    </ul>
114      *
115      * @param strict {@code true} if strict
116      *        <code>Format</code> parsing should be used.
117      * @param formatType The <code>NumberFormat</code> type to
118      *        create for validation, default is STANDARD_FORMAT.
119      * @param allowFractions {@code true} if fractions are
120      *        allowed or {@code false} if integers only.
121      */
122     protected BigDecimalValidator(final boolean strict, final int formatType,
123             final boolean allowFractions) {
124         super(strict, formatType, allowFractions);
125     }
126 
127     /**
128      * Check if the value is within a specified range.
129      *
130      * @param value The <code>Number</code> value to check.
131      * @param min The minimum value of the range.
132      * @param max The maximum value of the range.
133      * @return {@code true} if the value is within the
134      *         specified range.
135      */
136     public boolean isInRange(final BigDecimal value, final double min, final double max) {
137         return value.doubleValue() >= min && value.doubleValue() <= max;
138     }
139 
140     /**
141      * Check if the value is less than or equal to a maximum.
142      *
143      * @param value The value validation is being performed on.
144      * @param max The maximum value.
145      * @return {@code true} if the value is less than
146      *         or equal to the maximum.
147      */
148     public boolean maxValue(final BigDecimal value, final double max) {
149         return value.doubleValue() <= max;
150     }
151 
152     /**
153      * Check if the value is greater than or equal to a minimum.
154      *
155      * @param value The value validation is being performed on.
156      * @param min The minimum value.
157      * @return {@code true} if the value is greater than
158      *         or equal to the minimum.
159      */
160     public boolean minValue(final BigDecimal value, final double min) {
161         return value.doubleValue() >= min;
162     }
163 
164     /**
165      * Convert the parsed value to a <code>BigDecimal</code>.
166      *
167      * @param value The parsed <code>Number</code> object created.
168      * @param formatter The Format used to parse the value with.
169      * @return The parsed <code>Number</code> converted to a
170      *         <code>BigDecimal</code>.
171      */
172     @Override
173     protected Object processParsedValue(final Object value, final Format formatter) {
174         BigDecimal decimal;
175         if (value instanceof Long) {
176             decimal = BigDecimal.valueOf(((Long)value).longValue());
177         } else {
178             decimal = new BigDecimal(value.toString());
179         }
180 
181         final int scale = determineScale((NumberFormat)formatter);
182         if (scale >= 0) {
183             decimal = decimal.setScale(scale, BigDecimal.ROUND_DOWN);
184         }
185 
186         return decimal;
187     }
188 
189     /**
190      * <p>Validate/convert a <code>BigDecimal</code> using the default
191      *    <code>Locale</code>.
192      *
193      * @param value The value validation is being performed on.
194      * @return The parsed <code>BigDecimal</code> if valid or <code>null</code>
195      *  if invalid.
196      */
197     public BigDecimal validate(final String value) {
198         return (BigDecimal)parse(value, (String)null, (Locale)null);
199     }
200 
201     /**
202      * <p>Validate/convert a <code>BigDecimal</code> using the
203      *    specified <code>Locale</code>.
204      *
205      * @param value The value validation is being performed on.
206      * @param locale The locale to use for the number format, system default if null.
207      * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
208      */
209     public BigDecimal validate(final String value, final Locale locale) {
210         return (BigDecimal)parse(value, (String)null, locale);
211     }
212 
213     /**
214      * <p>Validate/convert a <code>BigDecimal</code> using the
215      *    specified <i>pattern</i>.
216      *
217      * @param value The value validation is being performed on.
218      * @param pattern The pattern used to validate the value against, or the
219      *        default for the <code>Locale</code> if <code>null</code>.
220      * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
221      */
222     public BigDecimal validate(final String value, final String pattern) {
223         return (BigDecimal)parse(value, pattern, (Locale)null);
224     }
225 
226     /**
227      * <p>Validate/convert a <code>BigDecimal</code> using the
228      *    specified pattern and/ or <code>Locale</code>.
229      *
230      * @param value The value validation is being performed on.
231      * @param pattern The pattern used to validate the value against, or the
232      *        default for the <code>Locale</code> if <code>null</code>.
233      * @param locale The locale to use for the date format, system default if null.
234      * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
235      */
236     public BigDecimal validate(final String value, final String pattern, final Locale locale) {
237         return (BigDecimal)parse(value, pattern, locale);
238     }
239 }