001    package org.apache.fulcrum.intake.validator;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.math.BigDecimal;
023    import java.text.NumberFormat;
024    import java.text.ParseException;
025    import java.util.Locale;
026    import java.util.Map;
027    
028    import org.apache.commons.lang.StringUtils;
029    import org.apache.fulcrum.intake.model.Field;
030    
031    /**
032     * Validates BigDecimals with the following constraints in addition to those
033     * listed in NumberValidator and DefaultValidator.
034     *
035     * <table>
036     * <tr><th>Name</th><th>Valid Values</th><th>Default Value</th></tr>
037     * <tr><td>minValue</td><td>greater than BigDecimal minValue</td>
038     * <td>&nbsp;</td></tr>
039     * <tr><td>maxValue</td><td>less than BigDecimal maxValue</td>
040     * <td>&nbsp;</td></tr>
041     * <tr><td>invalidNumberMessage</td><td>Some text</td>
042     * <td>Entry was not a valid number</td></tr>
043     * </table>
044     *
045     * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
046     * @author <a href="mailto:Colin.Chalmers@maxware.nl">Colin Chalmers</a>
047     * @author <a href="mailto:jh@byteaction.de">J&uuml;rgen Hoffmann</a>
048     * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
049     * @version $Id: BigDecimalValidator.java 812827 2009-09-09 08:46:27Z tv $
050     */
051    public class BigDecimalValidator
052            extends NumberValidator
053    {
054        private BigDecimal minValue = null;
055        private BigDecimal maxValue = null;
056    
057        /**
058         * Constructor to use when initialising Object
059         *
060         * @param paramMap
061         * @throws InvalidMaskException
062         */
063        public BigDecimalValidator(Map paramMap)
064                throws InvalidMaskException
065        {
066            this();
067            init(paramMap);
068        }
069    
070        /**
071         * Default Constructor
072         */
073        public BigDecimalValidator()
074        {
075            invalidNumberMessage = "Entry was not a valid BigDecimal";
076        }
077    
078        /**
079         * Method to initialise Object
080         *
081         * @param paramMap
082         * @throws InvalidMaskException
083         */
084        public void init(Map paramMap)
085                throws InvalidMaskException
086        {
087            super.init(paramMap);
088    
089            Constraint constraint = (Constraint) paramMap.get(MIN_VALUE_RULE_NAME);
090            if (constraint != null)
091            {
092                String param = constraint.getValue();
093                minValue = new BigDecimal(param);
094                minValueMessage = constraint.getMessage();
095            }
096    
097            constraint = (Constraint) paramMap.get(MAX_VALUE_RULE_NAME);
098            if (constraint != null)
099            {
100                String param = constraint.getValue();
101                maxValue = new BigDecimal(param);
102                maxValueMessage = constraint.getMessage();
103            }
104        }
105    
106        /**
107         * Determine whether a field meets the criteria specified
108         * in the constraints defined for this validator
109         *
110         * @param field a <code>Field</code> to be tested
111         * @exception ValidationException containing an error message if the
112         * testValue did not pass the validation tests.
113         */
114        public void assertValidity(Field field)
115                throws ValidationException
116        {
117            Locale locale = field.getLocale();
118    
119            if (field.isMultiValued())
120            {
121                String[] stringValues = (String[])field.getTestValue();
122    
123                for (int i = 0; i < stringValues.length; i++)
124                {
125                    assertValidity(stringValues[i], locale);
126                }
127            }
128            else
129            {
130                assertValidity((String)field.getTestValue(), locale);
131            }
132        }
133    
134        /**
135         * Determine whether a testValue meets the criteria specified
136         * in the constraints defined for this validator
137         *
138         * @param testValue a <code>String</code> to be tested
139         * @param locale the Locale of the associated field
140         * @exception ValidationException containing an error message if the
141         * testValue did not pass the validation tests.
142         */
143        public void assertValidity(String testValue, Locale locale)
144                throws ValidationException
145        {
146            super.assertValidity(testValue);
147    
148            if (required || StringUtils.isNotEmpty(testValue))
149            {
150                BigDecimal bd = null;
151                NumberFormat nf = NumberFormat.getInstance(locale);
152                try
153                {
154                    Number number = nf.parse(testValue);
155                    bd = new BigDecimal(number.doubleValue());
156                }
157                catch (ParseException e)
158                {
159                    errorMessage = invalidNumberMessage;
160                    throw new ValidationException(invalidNumberMessage);
161                }
162    
163                if (minValue != null && bd.compareTo(minValue) < 0)
164                {
165                    errorMessage = minValueMessage;
166                    throw new ValidationException(minValueMessage);
167                }
168                if (maxValue != null && bd.compareTo(maxValue) > 0)
169                {
170                    errorMessage = maxValueMessage;
171                    throw new ValidationException(maxValueMessage);
172                }
173            }
174        }
175    
176    
177        // ************************************************************
178        // **                Bean accessor methods                   **
179        // ************************************************************
180    
181        /**
182         * Get the value of minValue.
183         *
184         * @return value of minValue.
185         */
186        public BigDecimal getMinValue()
187        {
188            return minValue;
189        }
190    
191        /**
192         * Set the value of minValue.
193         *
194         * @param minValue  Value to assign to minValue.
195         */
196        public void setMinValue(BigDecimal minValue)
197        {
198            this.minValue = minValue;
199        }
200    
201        /**
202         * Get the value of maxValue.
203         *
204         * @return value of maxValue.
205         */
206        public BigDecimal getMaxValue()
207        {
208            return maxValue;
209        }
210    
211        /**
212         * Set the value of maxValue.
213         *
214         * @param maxValue  Value to assign to maxValue.
215         */
216        public void setMaxValue(BigDecimal maxValue)
217        {
218            this.maxValue = maxValue;
219        }
220    }