View Javadoc
1   package org.apache.fulcrum.intake.validator;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.Locale;
25  import java.util.Map;
26  
27  import org.apache.commons.lang3.StringUtils;
28  import org.apache.fulcrum.intake.model.Field;
29  import org.apache.fulcrum.intake.model.Group;
30  import org.apache.fulcrum.intake.validator.FieldReference.Comparison;
31  
32  /**
33   * Validates an int field in dependency on another int field.
34   *
35   * <table>
36   * <caption>Validation rules</caption>
37   * <tr>
38   *   <th>Name</th><th>Valid Values</th><th>Default Value</th>
39   * </tr>
40   * <tr>
41   *   <td>less-than</td>
42   *   <td>&lt;name of other field&gt;</td>
43   *   <td>&nbsp;</td>
44   * </tr>
45   * <tr>
46   *   <td>greater-than</td>
47   *   <td>&lt;name of other field&gt;</td>
48   *   <td>&nbsp;</td>
49   * </tr>
50   * <tr>
51   *   <td>less-than-or-equal</td>
52   *   <td>&lt;name of other field&gt;</td>
53   *   <td>&nbsp;</td>
54   * </tr>
55   * <tr>
56   *   <td>greater-than-or-equal</td>
57   *   <td>&lt;name of other field&gt;</td>
58   *   <td>&nbsp;</td>
59   * </tr>
60   * </table>
61   *
62   * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
63   * @version $Id$
64   */
65  public class IntegerRangeValidator
66          extends IntegerValidator
67  {
68      /** List of FieldReferences for multiple comparisons */
69      List<FieldReference> fieldReferences;
70  
71      /** Callback for the actual compare operation */
72      CompareCallback<Integer> compareCallback;
73  
74      /**
75       *  Default constructor
76       */
77      public IntegerRangeValidator()
78      {
79          super();
80      }
81  
82      /**
83       * Constructor to use when initializing Object
84       *
85       * @param paramMap a map of parameters
86       * @throws InvalidMaskException one of the mask rules is invalid
87       */
88      @Override
89  	public void init(Map<String, ? extends Constraint> paramMap)
90              throws InvalidMaskException
91      {
92          super.init(paramMap);
93  
94          compareCallback = new CompareCallback<Integer>()
95              {
96                  /**
97                   * Compare the given values using the compare operation provided
98                   *
99                   * @param compare type of compare operation
100                  * @param thisValue value of this field
101                  * @param refValue value of the reference field
102                  *
103                  * @return the result of the comparison
104                  */
105                 @Override
106 				public boolean compareValues(Comparison compare, Integer thisValue, Integer refValue)
107                 {
108                     boolean result = true;
109 
110                     switch (compare)
111                     {
112                         case LT:
113                             result = thisValue.compareTo(refValue) < 0;
114                             break;
115 
116                         case LTE:
117                             result = thisValue.compareTo(refValue) <= 0;
118                             break;
119 
120                         case GT:
121                             result = thisValue.compareTo(refValue) > 0;
122                             break;
123 
124                         case GTE:
125                             result = thisValue.compareTo(refValue) >= 0;
126                             break;
127                     }
128 
129                     return result;
130                 }
131             };
132 
133         fieldReferences = new ArrayList<FieldReference>(10);
134 
135         for (Map.Entry<String, ? extends Constraint> entry : paramMap.entrySet())
136         {
137             String key = entry.getKey();
138             Constraint constraint = entry.getValue();
139 
140             Comparison compare = FieldReference.getComparisonType(key);
141 
142             if (compare != null)
143             {
144                 // found matching constraint
145                 FieldReference/FieldReference.html#FieldReference">FieldReference fieldref = new FieldReference();
146                 fieldref.setComparison(compare);
147                 fieldref.setFieldName(constraint.getValue());
148                 fieldref.setMessage(constraint.getMessage());
149 
150                 fieldReferences.add(fieldref);
151             }
152         }
153 
154         if (fieldReferences.isEmpty())
155         {
156             log.warn("No reference field rules have been found.");
157         }
158     }
159 
160     /**
161      * Determine whether a testValue meets the criteria specified
162      * in the constraints defined for this validator
163      *
164      * @param testField a <code>Field</code> to be tested
165      * @throws ValidationException containing an error message if the
166      * testValue did not pass the validation tests.
167      */
168     @Override
169 	public void assertValidity(final Field<Integer> testField)
170         throws ValidationException
171     {
172         super.assertValidity(testField);
173 
174         Group thisGroup = testField.getGroup();
175         Locale locale = testField.getLocale();
176 
177         if (testField.isMultiValued())
178         {
179             String[] stringValues = (String[])testField.getTestValue();
180 
181             for (int i = 0; i < stringValues.length; i++)
182             {
183                 assertValidity(stringValues[i], thisGroup, locale);
184             }
185         }
186         else
187         {
188             String testValue = (String)testField.getTestValue();
189 
190             assertValidity(testValue, thisGroup, locale);
191         }
192     }
193 
194     /**
195      * Determine whether a testValue meets the criteria specified
196      * in the constraints defined for this validator
197      *
198      * @param testValue a <code>String</code> to be tested
199      * @param group the group this field belongs to
200      * @param locale the locale for this field
201      *
202      * @throws ValidationException containing an error message if the
203      * testValue did not pass the validation tests.
204      */
205     public void assertValidity(final String testValue, final Group group, final Locale locale)
206         throws ValidationException
207     {
208         if (required || StringUtils.isNotEmpty(testValue))
209         {
210             Integer testInt;
211 
212 			try
213 			{
214 				testInt = parseNumber(testValue, locale);
215 			}
216 			catch (NumberFormatException e)
217 			{
218 				errorMessage = invalidNumberMessage;
219 				throw new ValidationException(invalidNumberMessage);
220 			}
221 
222             try
223             {
224                 FieldReference.checkReferences(fieldReferences, compareCallback,
225                         testInt, group);
226             }
227             catch (ValidationException e)
228             {
229                 errorMessage = e.getMessage();
230                 throw e;
231             }
232         }
233     }
234 }