001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.validator.routines;
018    
019    import java.math.BigDecimal;
020    import java.text.Format;
021    import java.text.NumberFormat;
022    import java.util.Locale;
023    
024    /**
025     * <p><b>BigDecimal Validation</b> and Conversion routines (<code>java.math.BigDecimal</code>).</p>
026     *
027     * <p>This validator provides a number of methods for
028     *    validating/converting a <code>String</code> value to
029     *    a <code>BigDecimal</code> using <code>java.text.NumberFormat</code>
030     *    to parse either:</p>
031     *    <ul>
032     *       <li>using the default format for the default <code>Locale</code></li>
033     *       <li>using a specified pattern with the default <code>Locale</code></li>
034     *       <li>using the default format for a specified <code>Locale</code></li>
035     *       <li>using a specified pattern with a specified <code>Locale</code></li>
036     *    </ul>
037     *    
038     * <p>Use one of the <code>isValid()</code> methods to just validate or
039     *    one of the <code>validate()</code> methods to validate and receive a
040     *    <i>converted</i> <code>BigDecimal</code> value.</p>
041     * 
042     * <p>Fraction/decimal values are automatically trimmed to the appropriate length.</p>
043     * 
044     * <p>Once a value has been sucessfully converted the following
045     *    methods can be used to perform minimum, maximum and range checks:</p>
046     *    <ul>
047     *       <li><code>minValue()</code> checks whether the value is greater
048     *           than or equal to a specified minimum.</li>
049     *       <li><code>maxValue()</code> checks whether the value is less
050     *           than or equal to a specified maximum.</li>
051     *       <li><code>isInRange()</code> checks whether the value is within
052     *           a specified range of values.</li>
053     *    </ul>
054     * 
055     * <p>So that the same mechanism used for parsing an <i>input</i> value 
056     *    for validation can be used to format <i>output</i>, corresponding
057     *    <code>format()</code> methods are also provided. That is you can 
058     *    format either:</p>
059     *    <ul>
060     *       <li>using the default format for the default <code>Locale</code></li>
061     *       <li>using a specified pattern with the default <code>Locale</code></li>
062     *       <li>using the default format for a specified <code>Locale</code></li>
063     *       <li>using a specified pattern with a specified <code>Locale</code></li>
064     *    </ul>
065     * 
066     * @version $Revision: 493905 $ $Date: 2007-01-08 03:11:38 +0100 (Mo, 08. Jan 2007) $
067     * @since Validator 1.3.0
068     */
069    public class BigDecimalValidator extends AbstractNumberValidator {
070    
071        private static final BigDecimalValidator VALIDATOR = new BigDecimalValidator();
072    
073        /**
074         * Return a singleton instance of this validator.
075         * @return A singleton instance of the BigDecimalValidator.
076         */
077        public static BigDecimalValidator getInstance() {
078            return VALIDATOR;
079        }
080    
081        /**
082         * Construct a <i>strict</i> instance.
083         */
084        public BigDecimalValidator() {
085            this(true);
086        }
087    
088        /**
089         * <p>Construct an instance with the specified strict setting.</p>
090         * 
091         * @param strict <code>true</code> if strict 
092         *        <code>Format</code> parsing should be used.
093         */
094        public BigDecimalValidator(boolean strict) {
095            this(strict, STANDARD_FORMAT, true);
096        }
097    
098        /**
099         * <p>Construct an instance with the specified strict setting
100         *    and format type.</p>
101         *    
102         * <p>The <code>formatType</code> specified what type of
103         *    <code>NumberFormat</code> is created - valid types
104         *    are:</p>
105         *    <ul>
106         *       <li>AbstractNumberValidator.STANDARD_FORMAT -to create
107         *           <i>standard</i> number formats (the default).</li>
108         *       <li>AbstractNumberValidator.CURRENCY_FORMAT -to create
109         *           <i>currency</i> number formats.</li>
110         *       <li>AbstractNumberValidator.PERCENT_FORMAT -to create
111         *           <i>percent</i> number formats (the default).</li>
112         *    </ul>
113         * 
114         * @param strict <code>true</code> if strict 
115         *        <code>Format</code> parsing should be used.
116         * @param formatType The <code>NumberFormat</code> type to
117         *        create for validation, default is STANDARD_FORMAT.
118         * @param allowFractions <code>true</code> if fractions are
119         *        allowed or <code>false</code> if integers only.
120         */
121        protected BigDecimalValidator(boolean strict, int formatType, 
122                boolean allowFractions) {
123            super(strict, formatType, allowFractions);
124        }
125    
126        /**
127         * <p>Validate/convert a <code>BigDecimal</code> using the default
128         *    <code>Locale</code>. 
129         *
130         * @param value The value validation is being performed on.
131         * @return The parsed <code>BigDecimal</code> if valid or <code>null</code>
132         *  if invalid.
133         */
134        public BigDecimal validate(String value) {
135            return (BigDecimal)parse(value, (String)null, (Locale)null);
136        }
137    
138        /**
139         * <p>Validate/convert a <code>BigDecimal</code> using the
140         *    specified <i>pattern</i>. 
141         *
142         * @param value The value validation is being performed on.
143         * @param pattern The pattern used to validate the value against, or the
144         *        default for the <code>Locale</code> if <code>null</code>.
145         * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
146         */
147        public BigDecimal validate(String value, String pattern) {
148            return (BigDecimal)parse(value, pattern, (Locale)null);
149        }
150    
151        /**
152         * <p>Validate/convert a <code>BigDecimal</code> using the
153         *    specified <code>Locale</code>. 
154         *
155         * @param value The value validation is being performed on.
156         * @param locale The locale to use for the number format, system default if null.
157         * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
158         */
159        public BigDecimal validate(String value, Locale locale) {
160            return (BigDecimal)parse(value, (String)null, locale);
161        }
162    
163        /**
164         * <p>Validate/convert a <code>BigDecimal</code> using the
165         *    specified pattern and/ or <code>Locale</code>. 
166         *
167         * @param value The value validation is being performed on.
168         * @param pattern The pattern used to validate the value against, or the
169         *        default for the <code>Locale</code> if <code>null</code>.
170         * @param locale The locale to use for the date format, system default if null.
171         * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
172         */
173        public BigDecimal validate(String value, String pattern, Locale locale) {
174            return (BigDecimal)parse(value, pattern, locale);
175        }
176    
177        /**
178         * Check if the value is within a specified range.
179         * 
180         * @param value The <code>Number</code> value to check.
181         * @param min The minimum value of the range.
182         * @param max The maximum value of the range.
183         * @return <code>true</code> if the value is within the
184         *         specified range.
185         */
186        public boolean isInRange(BigDecimal value, double min, double max) {
187            return (value.doubleValue() >= min && value.doubleValue() <= max);
188        }
189    
190        /**
191         * Check if the value is greater than or equal to a minimum.
192         * 
193         * @param value The value validation is being performed on.
194         * @param min The minimum value.
195         * @return <code>true</code> if the value is greater than
196         *         or equal to the minimum.
197         */
198        public boolean minValue(BigDecimal value, double min) {
199            return (value.doubleValue() >= min);
200        }
201    
202        /**
203         * Check if the value is less than or equal to a maximum.
204         * 
205         * @param value The value validation is being performed on.
206         * @param max The maximum value.
207         * @return <code>true</code> if the value is less than
208         *         or equal to the maximum.
209         */
210        public boolean maxValue(BigDecimal value, double max) {
211            return (value.doubleValue() <= max);
212        }
213    
214        /**
215         * Convert the parsed value to a <code>BigDecimal</code>.
216         * 
217         * @param value The parsed <code>Number</code> object created.
218         * @param formatter The Format used to parse the value with.
219         * @return The parsed <code>Number</code> converted to a 
220         *         <code>BigDecimal</code>.
221         */
222        protected Object processParsedValue(Object value, Format formatter) {
223            BigDecimal decimal = null;
224            if (value instanceof Long) {
225                decimal = BigDecimal.valueOf(((Long)value).longValue());
226            } else {
227                decimal = new BigDecimal(value.toString());
228            }
229    
230            int scale = determineScale((NumberFormat)formatter);
231            if (scale >= 0) {
232                decimal = decimal.setScale(scale, BigDecimal.ROUND_DOWN);
233            }
234    
235            return decimal;
236        }
237    }