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.util.ArrayList;
023    import java.util.Iterator;
024    import java.util.List;
025    import java.util.Map;
026    
027    import org.apache.commons.lang.StringUtils;
028    import org.apache.fulcrum.intake.IntakeException;
029    import org.apache.fulcrum.intake.model.Field;
030    import org.apache.fulcrum.intake.model.Group;
031    
032    /**
033     * Validates an int field in dependency on another int field.
034     *
035     * <table>
036     * <tr>
037     *   <th>Name</th><th>Valid Values</th><th>Default Value</th>
038     * </tr>
039     * <tr>
040     *   <td>less-than</td>
041     *   <td>&lt;name of other field&gt;</td>
042     *   <td>&nbsp;</td>
043     * </tr>
044     * <tr>
045     *   <td>greater-than</td>
046     *   <td>&lt;name of other field&gt;</td>
047     *   <td>&nbsp;</td>
048     * </tr>
049     * <tr>
050     *   <td>less-than-or-equal</td>
051     *   <td>&lt;name of other field&gt;</td>
052     *   <td>&nbsp;</td>
053     * </tr>
054     * <tr>
055     *   <td>greater-than-or-equal</td>
056     *   <td>&lt;name of other field&gt;</td>
057     *   <td>&nbsp;</td>
058     * </tr>
059     * </table>
060     *
061     * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
062     * @version $Id: DateStringValidator.java 534527 2007-05-02 16:10:59Z tv $
063     */
064    public class IntegerRangeValidator
065            extends IntegerValidator
066    {
067        /** List of FieldReferences for multiple comparisons */
068        List fieldReferences; 
069    
070        /** Callback for the actual compare operation */
071        CompareCallback compareCallback; 
072    
073        public IntegerRangeValidator(final Map paramMap)
074                throws IntakeException
075        {
076            this();
077            init(paramMap);
078        }
079    
080        /**
081         *  Default constructor
082         */
083        public IntegerRangeValidator()
084        {
085            super();
086        }
087    
088        /**
089         * Constructor to use when initialising Object
090         *
091         * @param paramMap
092         * @throws InvalidMaskException
093         */
094        public void init(final Map paramMap)
095                throws InvalidMaskException
096        {
097            super.init(paramMap);
098            
099            compareCallback = new CompareCallback()
100                {
101                    /**
102                     * Compare the given values using the compare operation provided
103                     * 
104                     * @param compare type of compare operation
105                     * @param thisValue value of this field
106                     * @param refValue value of the reference field
107                     * 
108                     * @return the result of the comparison
109                     */
110                    public boolean compareValues(int compare, Object thisValue, Object refValue)
111                        throws ClassCastException
112                    {
113                        boolean result = true;
114                        
115                        Integer thisInt = (Integer)thisValue;
116                        Integer otherInt = (Integer)refValue;
117                        
118                        switch (compare)
119                        {
120                            case FieldReference.COMPARE_LT:
121                                result = thisInt.compareTo(otherInt) < 0;
122                                break;
123                                
124                            case FieldReference.COMPARE_LTE:
125                                result = thisInt.compareTo(otherInt) <= 0;
126                                break;
127                                
128                            case FieldReference.COMPARE_GT:
129                                result = thisInt.compareTo(otherInt) > 0;
130                                break;
131                                
132                            case FieldReference.COMPARE_GTE:
133                                result = thisInt.compareTo(otherInt) >= 0;
134                                break;
135                        }
136                        
137                        return result;
138                    }
139                };
140            
141            fieldReferences = new ArrayList(10);
142    
143            for (Iterator i = paramMap.entrySet().iterator(); i.hasNext();)
144            {
145                Map.Entry entry = (Map.Entry)i.next();
146                String key = (String)entry.getKey();
147                Constraint constraint = (Constraint)entry.getValue();
148    
149                int compare = FieldReference.getCompareType(key);
150                
151                if (compare != 0)
152                {
153                    // found matching constraint
154                    FieldReference fieldref = new FieldReference();
155                    fieldref.setCompare(compare);
156                    fieldref.setFieldName(constraint.getValue());
157                    fieldref.setMessage(constraint.getMessage());
158                    
159                    fieldReferences.add(fieldref);
160                }
161            }
162            
163            if (fieldReferences.isEmpty())
164            {
165                log.warn("No reference field rules have been found.");
166            }
167        }
168        
169        /**
170         * Determine whether a testValue meets the criteria specified
171         * in the constraints defined for this validator
172         *
173         * @param testField a <code>Field</code> to be tested
174         * @exception ValidationException containing an error message if the
175         * testValue did not pass the validation tests.
176         */
177        public void assertValidity(final Field testField)
178            throws ValidationException
179        {
180            super.assertValidity(testField);
181            
182            Group thisGroup = testField.getGroup();
183    
184            if (testField.isMultiValued())
185            {
186                String[] stringValues = (String[])testField.getTestValue();
187    
188                for (int i = 0; i < stringValues.length; i++)
189                {
190                    assertValidity(stringValues[i], thisGroup);
191                }
192            }
193            else
194            {
195                String testValue = (String)testField.getTestValue();
196            
197                assertValidity(testValue, thisGroup);
198            }
199        }
200    
201        /**
202         * Determine whether a testValue meets the criteria specified
203         * in the constraints defined for this validator
204         *
205         * @param testValue a <code>String</code> to be tested
206         * @param group the group this field belongs to
207         * 
208         * @exception ValidationException containing an error message if the
209         * testValue did not pass the validation tests.
210         */
211        public void assertValidity(final String testValue, final Group group)
212            throws ValidationException
213        {
214            if (required || StringUtils.isNotEmpty(testValue))
215            {
216                Integer testInt = new Integer(testValue);
217                
218                try
219                {
220                    FieldReference.checkReferences(fieldReferences, compareCallback, 
221                            testInt, group);
222                }
223                catch (ValidationException e)
224                {
225                    errorMessage = e.getMessage();
226                    throw e;
227                }
228            }
229        }
230    }