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.Map;
23  
24  import org.apache.avalon.framework.logger.LogEnabled;
25  import org.apache.avalon.framework.logger.Logger;
26  import org.apache.commons.lang3.StringUtils;
27  import org.apache.fulcrum.intake.model.Field;
28  
29  /**
30   * DefaultValidator that will compare a testValue against the following
31   * constraints:
32   *
33   * <table>
34   * <caption>Validation rules</caption>
35   * <tr><th>Name</th><th>Valid Values</th><th>Default Value</th></tr>
36   * <tr><td>required</td><td>true|false</td><td>false</td></tr>
37   * <tr><td>mask</td><td>regexp</td><td>&nbsp;</td></tr>
38   * <tr><td>minLength</td><td>integer</td><td>0</td></tr>
39   * <tr><td>maxLength</td><td>integer</td><td>&nbsp;</td></tr>
40   * </table>
41   *
42   * This validator can serve as the base class for more specific validators
43   *
44   * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
45   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
46   * @author <a href="mailto:Colin.Chalmers@maxware.nl">Colin Chalmers</a>
47   * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
48   * @version $Id$
49   */
50  abstract public class DefaultValidator<T>
51          implements Validator<T>, InitableByConstraintMap, LogEnabled
52  {
53      /** A boolean value to signify if the field is definitely required or not */
54      protected boolean required = false;
55  
56      /** The message to show if field fails required test */
57      protected String requiredMessage = null;
58  
59      /** The minimum length of the field */
60      protected int minLength = 0;
61  
62      /** The message to show if field fails min-length test */
63      protected String minLengthMessage = null;
64  
65      /** The maximum length of the field */
66      protected int maxLength = 0;
67  
68      /** The message to show if field fails max-length test */
69      protected String maxLengthMessage = null;
70  
71      /** Error message pertaining to Rule that was broken */
72      protected String errorMessage = null;
73  
74      /** Logging */
75      protected Logger log;
76  
77      /**
78       * Default constructor
79       */
80      public DefaultValidator()
81      {
82          //
83      }
84  
85      /**
86  	 * Enable Avalon Logging
87  	 */
88  	@Override
89  	public void enableLogging(Logger logger)
90  	{
91  		this.log = logger.getChildLogger(getClass().getSimpleName());
92  	}
93  
94      /**
95       * Extract the relevant parameters from the constraints listed
96       * in &lt;rule&gt; tags within the intake.xml file.
97       *
98       * @param paramMap a <code>Map</code> of <code>Rule</code>'s
99       * containing constraints on the input.
100      * @throws InvalidMaskException An invalid mask was specified for one of the rules
101      */
102     @Override
103 	public void init(Map<String, ? extends Constraint> paramMap)
104             throws InvalidMaskException
105     {
106         Constraint constraint = paramMap.get(REQUIRED_RULE_NAME);
107         if (constraint != null)
108         {
109             String param = constraint.getValue();
110             required = Boolean.valueOf(param).booleanValue();
111             requiredMessage = constraint.getMessage();
112         }
113 
114         constraint = paramMap.get(MIN_LENGTH_RULE_NAME);
115         if (constraint != null)
116         {
117             String param = constraint.getValue();
118             minLength = Integer.parseInt(param);
119             minLengthMessage = constraint.getMessage();
120         }
121 
122         constraint = paramMap.get(MAX_LENGTH_RULE_NAME);
123         if (constraint != null)
124         {
125             String param = constraint.getValue();
126             maxLength = Integer.parseInt(param);
127             maxLengthMessage = constraint.getMessage();
128         }
129     }
130 
131     /**
132      * Determine whether a field meets the criteria specified
133      * in the constraints defined for this validator
134      *
135      * @param field a <code>Field</code> to be tested
136      * @return true if valid, false otherwise
137      */
138     @Override
139 	public boolean isValid(Field<T> field)
140     {
141         boolean valid = false;
142         try
143         {
144             assertValidity(field);
145             valid = true;
146         }
147         catch (ValidationException ve)
148         {
149             valid = false;
150         }
151         return valid;
152     }
153 
154     /**
155      * Determine whether a field meets the criteria specified
156      * in the constraints defined for this validator
157      *
158      * @param field a <code>Field</code> to be tested
159      * @throws ValidationException containing an error message if the
160      * testValue did not pass the validation tests.
161      */
162     @Override
163 	public void assertValidity(Field<T> field)
164             throws ValidationException
165     {
166     	if (field.isMultiValued())
167     	{
168     		String[] stringValues = (String[])field.getTestValue();
169 
170     		for (int i = 0; i < stringValues.length; i++)
171     		{
172     			assertValidity(stringValues[i]);
173     		}
174     	}
175     	else
176     	{
177     		assertValidity((String)field.getTestValue());
178     	}
179     }
180 
181     /**
182      * Determine whether a testValue meets the criteria specified
183      * in the constraints defined for this validator
184      *
185      * @param testValue a <code>String</code> to be tested
186      * @return true if valid, false otherwise
187      *
188      * @deprecated use isValid(Field) instead
189      */
190     @Deprecated
191     @Override
192 	public boolean isValid(String testValue)
193     {
194         boolean valid = false;
195         try
196         {
197             assertValidity(testValue);
198             valid = true;
199         }
200         catch (ValidationException ve)
201         {
202             valid = false;
203         }
204         return valid;
205     }
206 
207     /**
208      * Determine whether a testValue meets the criteria specified
209      * in the constraints defined for this validator
210      *
211      * @param testValue a <code>String</code> to be tested
212      * @throws ValidationException containing an error message if the
213      * testValue did not pass the validation tests.
214      */
215     @Override
216 	public void assertValidity(String testValue)
217             throws ValidationException
218     {
219         if (!required && StringUtils.isEmpty(testValue))
220         {
221             return;
222         }
223         if (required && StringUtils.isEmpty(testValue))
224         {
225             errorMessage = requiredMessage;
226             throw new ValidationException(requiredMessage);
227         }
228 
229         if (minLength > 0 && testValue.length() < minLength)
230         {
231             errorMessage = minLengthMessage;
232             throw new ValidationException(minLengthMessage);
233         }
234         if (maxLength > 0 && testValue.length() > maxLength)
235         {
236             errorMessage = maxLengthMessage;
237             throw new ValidationException(maxLengthMessage);
238         }
239     }
240 
241 
242     /**
243      * Get the error message resulting from invalid input.
244      *
245      * @return a <code>String</code> message, or the empty String "".
246      */
247     @Override
248 	public String getMessage()
249     {
250         String retValue = "";
251 
252         if(errorMessage != null)
253         {
254             retValue = errorMessage;
255         }
256 
257         return retValue;
258     }
259 
260     // ************************************************************
261     // **                Bean accessor methods                   **
262     // ************************************************************
263 
264     /**
265      * Get the value of required.
266      *
267      * @return value of required.
268      */
269     public boolean isRequired()
270     {
271         return required;
272     }
273 
274     /**
275      * Set the value of required.
276      *
277      * @param required  Value to assign to required.
278      */
279     public void setRequired(boolean required)
280     {
281         this.required = required;
282     }
283 
284     /**
285      * Get the value of requiredMessage.
286      *
287      * @return value of requiredMessage.
288      */
289     public String getRequiredMessage()
290     {
291         return requiredMessage;
292     }
293 
294     /**
295      * Set the value of requiredMessage.
296      *
297      * @param requiredMessage  Value to assign to requiredMessage.
298      */
299     public void setRequiredMessage(String requiredMessage)
300     {
301         this.requiredMessage = requiredMessage;
302     }
303 
304     /**
305      * Get the value of minLength.
306      *
307      * @return value of minLength.
308      */
309     public int getMinLength()
310     {
311         return minLength;
312     }
313 
314     /**
315      * Set the value of minLength.
316      *
317      * @param minLength  Value to assign to minLength.
318      */
319     public void setMinLength(int minLength)
320     {
321         this.minLength = minLength;
322     }
323 
324     /**
325      * Get the value of minLengthMessage.
326      *
327      * @return value of minLengthMessage.
328      */
329     public String getMinLengthMessage()
330     {
331         return minLengthMessage;
332     }
333 
334     /**
335      * Set the value of minLengthMessage.
336      *
337      * @param minLengthMessage  Value to assign to minLengthMessage.
338      */
339     public void setMinLengthMessage(String minLengthMessage)
340     {
341         this.minLengthMessage = minLengthMessage;
342     }
343 
344     /**
345      * Get the value of maxLength.
346      *
347      * @return value of maxLength.
348      */
349     public int getMaxLength()
350     {
351         return maxLength;
352     }
353 
354     /**
355      * Set the value of maxLength.
356      *
357      * @param maxLength  Value to assign to maxLength.
358      */
359     public void setMaxLength(int maxLength)
360     {
361         this.maxLength = maxLength;
362     }
363 
364     /**
365      * Get the value of maxLengthMessage.
366      *
367      * @return value of maxLengthMessage.
368      */
369     public String getMaxLengthMessage()
370     {
371         return maxLengthMessage;
372     }
373 
374     /**
375      * Set the value of maxLengthMessage.
376      *
377      * @param maxLengthMessage  Value to assign to maxLengthMessage.
378      */
379     public void setMaxLengthMessage(String maxLengthMessage)
380     {
381         this.maxLengthMessage = maxLengthMessage;
382     }
383 }