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.text.ParseException;
23  import java.util.ArrayList;
24  import java.util.Date;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.commons.lang3.StringUtils;
29  import org.apache.fulcrum.intake.model.Field;
30  import org.apache.fulcrum.intake.model.Group;
31  import org.apache.fulcrum.intake.validator.FieldReference.Comparison;
32  
33  /**
34   * Validates a DateString field in dependency on another DateString field.
35   *
36   * <table>
37   * <caption>Validation rules</caption>
38   * <tr>
39   *   <th>Name</th><th>Valid Values</th><th>Default Value</th>
40   * </tr>
41   * <tr>
42   *   <td>less-than</td>
43   *   <td>&lt;name of other field&gt;</td>
44   *   <td>&nbsp;</td>
45   * </tr>
46   * <tr>
47   *   <td>greater-than</td>
48   *   <td>&lt;name of other field&gt;</td>
49   *   <td>&nbsp;</td>
50   * </tr>
51   * <tr>
52   *   <td>less-than-or-equal</td>
53   *   <td>&lt;name of other field&gt;</td>
54   *   <td>&nbsp;</td>
55   * </tr>
56   * <tr>
57   *   <td>greater-than-or-equal</td>
58   *   <td>&lt;name of other field&gt;</td>
59   *   <td>&nbsp;</td>
60   * </tr>
61   * </table>
62   *
63   * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
64   * @version $Id$
65   */
66  public class DateRangeValidator
67          extends DateStringValidator
68  {
69      /** List of FieldReferences for multiple comparisons */
70      List<FieldReference> fieldReferences;
71  
72      /** Callback for the actual compare operation */
73      CompareCallback<Date> compareCallback;
74  
75      /**
76       *  Default constructor
77       */
78      public DateRangeValidator()
79      {
80          super();
81      }
82  
83      /**
84       * Constructor to use when initializing Object
85       *
86       * @param paramMap a map of parameters
87       * @throws InvalidMaskException one of the mask rules is invalid
88       */
89      @Override
90  	public void init(Map<String, ? extends Constraint> paramMap)
91              throws InvalidMaskException
92      {
93          super.init(paramMap);
94  
95          compareCallback = new CompareCallback<Date>()
96              {
97                  /**
98                   * Compare the given values using the compare operation provided
99                   *
100                  * @param compare type of compare operation
101                  * @param thisValue value of this field
102                  * @param refValue value of the reference field
103                  *
104                  * @return the result of the comparison
105                  */
106                 @Override
107 				public boolean compareValues(Comparison compare, Date thisValue, Date refValue)
108                 {
109                     boolean result = true;
110 
111                     switch (compare)
112                     {
113                         case LT:
114                             result = thisValue.before(refValue);
115                             break;
116 
117                         case LTE:
118                             result = !thisValue.after(refValue);
119                             break;
120 
121                         case GT:
122                             result = thisValue.after(refValue);
123                             break;
124 
125                         case GTE:
126                             result = !thisValue.before(refValue);
127                             break;
128                     }
129 
130                     return result;
131                 }
132             };
133 
134         fieldReferences = new ArrayList<FieldReference>(10);
135 
136         for (Map.Entry<String, ? extends Constraint> entry : paramMap.entrySet())
137         {
138             String key = entry.getKey();
139             Constraint constraint = entry.getValue();
140 
141             Comparison compare = FieldReference.getComparisonType(key);
142 
143             if (compare != null)
144             {
145                 // found matching constraint
146                 FieldReference/FieldReference.html#FieldReference">FieldReference fieldref = new FieldReference();
147                 fieldref.setComparison(compare);
148                 fieldref.setFieldName(constraint.getValue());
149                 fieldref.setMessage(constraint.getMessage());
150 
151                 fieldReferences.add(fieldref);
152             }
153         }
154 
155         if (fieldReferences.isEmpty())
156         {
157             log.warn("No reference field rules have been found.");
158         }
159     }
160 
161     /**
162      * Determine whether a testValue meets the criteria specified
163      * in the constraints defined for this validator
164      *
165      * @param testField a <code>Field</code> to be tested
166      * @throws ValidationException containing an error message if the
167      * testValue did not pass the validation tests.
168      */
169     @Override
170 	public void assertValidity(Field<Date> testField)
171         throws ValidationException
172     {
173         super.assertValidity(testField);
174 
175         Group thisGroup = testField.getGroup();
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);
184             }
185         }
186         else
187         {
188             String testValue = (String)testField.getTestValue();
189 
190             assertValidity(testValue, thisGroup);
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      *
201      * @throws ValidationException containing an error message if the
202      * testValue did not pass the validation tests.
203      */
204     public void assertValidity(final String testValue, final Group group)
205         throws ValidationException
206     {
207         if (required || StringUtils.isNotEmpty(testValue))
208         {
209             Date testDate = null;
210 
211             try
212             {
213                 testDate = parse(testValue);
214             }
215             catch (ParseException e)
216             {
217                 // This should not happen because we succeeded with this before,
218                 // but we need to catch the exception anyway
219                 errorMessage = getDateFormatMessage();
220                 throw new ValidationException(errorMessage);
221             }
222 
223             try
224             {
225                 FieldReference.checkReferences(fieldReferences, compareCallback,
226                         testDate, group);
227             }
228             catch (ValidationException e)
229             {
230                 errorMessage = e.getMessage();
231                 throw e;
232             }
233         }
234     }
235 }