001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.validator;
018    
019    import java.io.Serializable;
020    import java.util.HashMap;
021    import java.util.Locale;
022    import java.util.Map;
023    
024    /**
025     * Validations are processed by the validate method. An instance of
026     * <code>ValidatorResources</code> is used to define the validators
027     * (validation methods) and the validation rules for a JavaBean.
028     *
029     * @version $Revision: 493905 $ $Date: 2007-01-08 03:11:38 +0100 (Mo, 08. Jan 2007) $
030     */
031    public class Validator implements Serializable {
032    
033        /**
034         * Resources key the JavaBean is stored to perform validation on.
035         */
036        public static final String BEAN_PARAM = "java.lang.Object";
037    
038        /**
039         * Resources key the <code>ValidatorAction</code> is stored under.
040         * This will be automatically passed into a validation method
041         * with the current <code>ValidatorAction</code> if it is
042         * specified in the method signature.
043         */
044        public static final String VALIDATOR_ACTION_PARAM =
045                "org.apache.commons.validator.ValidatorAction";
046                
047        /**
048         * Resources key the <code>ValidatorResults</code> is stored under.
049         * This will be automatically passed into a validation method
050         * with the current <code>ValidatorResults</code> if it is
051         * specified in the method signature.
052         */
053        public static final String VALIDATOR_RESULTS_PARAM =
054                "org.apache.commons.validator.ValidatorResults";        
055    
056        /**
057         * Resources key the <code>Form</code> is stored under.
058         * This will be automatically passed into a validation method
059         * with the current <code>Form</code> if it is
060         * specified in the method signature.
061         */
062        public static final String FORM_PARAM = "org.apache.commons.validator.Form";
063                
064        /**
065         * Resources key the <code>Field</code> is stored under.
066         * This will be automatically passed into a validation method
067         * with the current <code>Field</code> if it is
068         * specified in the method signature.
069         */
070        public static final String FIELD_PARAM = "org.apache.commons.validator.Field";
071    
072        /**
073         * Resources key the <code>Validator</code> is stored under.
074         * This will be automatically passed into a validation method
075         * with the current <code>Validator</code> if it is
076         * specified in the method signature.
077         */
078        public static final String VALIDATOR_PARAM =
079                "org.apache.commons.validator.Validator";
080                
081        /**
082         * Resources key the <code>Locale</code> is stored.
083         * This will be used to retrieve the appropriate
084         * <code>FormSet</code> and <code>Form</code> to be
085         * processed.
086         */
087        public static final String LOCALE_PARAM = "java.util.Locale";
088    
089        /**
090         * The Validator Resources.
091         */
092        protected ValidatorResources resources = null;
093    
094        /**
095         * The name of the form to validate
096         */
097        protected String formName = null;
098        
099        /**
100         * The name of the field on the form to validate
101         * @since 1.2.0
102         */
103        protected String fieldName = null;
104    
105        /**
106         * Maps validation method parameter class names to the objects to be passed
107         * into the method.
108         */
109        protected Map parameters = new HashMap();
110    
111        /**
112         * The current page number to validate.
113         */
114        protected int page = 0;
115    
116        /**
117         * The class loader to use for instantiating application objects.
118         * If not specified, the context class loader, or the class loader
119         * used to load Digester itself, is used, based on the value of the
120         * <code>useContextClassLoader</code> variable.
121         */
122        protected ClassLoader classLoader = null;
123    
124        /**
125         * Whether or not to use the Context ClassLoader when loading classes
126         * for instantiating new objects.  Default is <code>false</code>.
127         */
128        protected boolean useContextClassLoader = false;
129    
130        /**
131         * Set this to true to not return Fields that pass validation.  Only return failures.
132         */
133        protected boolean onlyReturnErrors = false;
134    
135        /**
136         * Construct a <code>Validator</code> that will
137         * use the <code>ValidatorResources</code>
138         * passed in to retrieve pluggable validators
139         * the different sets of validation rules.
140         *
141         * @param resources <code>ValidatorResources</code> to use during validation.
142         */
143        public Validator(ValidatorResources resources) {
144            this(resources, null);
145        }
146    
147        /**
148         * Construct a <code>Validator</code> that will
149         * use the <code>ValidatorResources</code>
150         * passed in to retrieve pluggable validators
151         * the different sets of validation rules.
152         *
153         * @param resources <code>ValidatorResources</code> to use during validation.
154         * @param formName Key used for retrieving the set of validation rules.
155         */
156        public Validator(ValidatorResources resources, String formName) {
157            if (resources == null) {
158                throw new IllegalArgumentException("Resources cannot be null.");
159            }
160    
161            this.resources = resources;
162            this.formName = formName;
163        }
164        
165        /**
166         * Construct a <code>Validator</code> that will
167         * use the <code>ValidatorResources</code>
168         * passed in to retrieve pluggable validators
169         * the different sets of validation rules.
170         *
171         * @param resources <code>ValidatorResources</code> to use during validation.
172         * @param formName Key used for retrieving the set of validation rules.
173         * @param fieldName Key used for retrieving the set of validation rules for a field
174         * @since 1.2.0
175         */
176        public Validator(ValidatorResources resources, String formName, String fieldName) {
177            if (resources == null) {
178                throw new IllegalArgumentException("Resources cannot be null.");
179            }
180    
181            this.resources = resources;
182            this.formName = formName;
183            this.fieldName = fieldName;
184        }
185    
186        /**
187         * Set a parameter of a pluggable validation method.
188         *
189         * @param parameterClassName The full class name of the parameter of the
190         * validation method that corresponds to the value/instance passed in with it.
191         *
192         * @param parameterValue The instance that will be passed into the
193         * validation method.
194         */
195        public void setParameter(String parameterClassName, Object parameterValue) {
196            this.parameters.put(parameterClassName, parameterValue);
197        }
198    
199        /**
200         * Returns the value of the specified parameter that will be used during the
201         * processing of validations.
202         *
203         * @param parameterClassName The full class name of the parameter of the
204         * validation method that corresponds to the value/instance passed in with it.
205         * @return value of the specified parameter.
206         */
207        public Object getParameterValue(String parameterClassName) {
208            return this.parameters.get(parameterClassName);
209        }
210    
211        /**
212         * Gets the form name which is the key to a set of validation rules.
213         * @return the name of the form.
214         */
215        public String getFormName() {
216            return formName;
217        }
218    
219        /**
220         * Sets the form name which is the key to a set of validation rules.
221         * @param formName the name of the form.
222         */
223        public void setFormName(String formName) {
224            this.formName = formName;
225        }
226        
227        /**
228         * Sets the name of the field to validate in a form (optional)
229         *
230         * @param fieldName The name of the field in a form set
231         * @since 1.2.0
232         */
233        public void setFieldName(String fieldName) {
234            this.fieldName = fieldName;
235        }
236    
237        /**
238         * Gets the page.  This in conjunction with the page property of
239         * a <code>Field<code> can control the processing of fields. If the field's
240         * page is less than or equal to this page value, it will be processed.
241         * @return the page number.
242         */
243        public int getPage() {
244            return page;
245        }
246    
247        /**
248         * Sets the page.  This in conjunction with the page property of
249         * a <code>Field<code> can control the processing of fields. If the field's page
250         * is less than or equal to this page value, it will be processed.
251         * @param page the page number.
252         */
253        public void setPage(int page) {
254            this.page = page;
255        }
256    
257        /**
258         * Clears the form name, resources that were added, and the page that was
259         * set (if any).  This can be called to reinitialize the Validator instance
260         * so it can be reused.  The form name (key to set of validation rules) and any
261         * resources needed, like the JavaBean being validated, will need to
262         * set and/or added to this instance again.  The
263         * <code>ValidatorResources</code> will not be removed since it can be used
264         * again and is thread safe.
265         */
266        public void clear() {
267            this.formName = null;
268            this.fieldName = null;
269            this.parameters = new HashMap();
270            this.page = 0;
271        }
272    
273        /**
274         * Return the boolean as to whether the context classloader should be used.
275         * @return whether the context classloader should be used.
276         */
277        public boolean getUseContextClassLoader() {
278            return this.useContextClassLoader;
279        }
280    
281        /**
282         * Determine whether to use the Context ClassLoader (the one found by
283         * calling <code>Thread.currentThread().getContextClassLoader()</code>)
284         * to resolve/load classes that are defined in various rules.  If not
285         * using Context ClassLoader, then the class-loading defaults to
286         * using the calling-class' ClassLoader.
287         *
288         * @param use determines whether to use Context ClassLoader.
289         */
290        public void setUseContextClassLoader(boolean use) {
291            this.useContextClassLoader = use;
292        }
293    
294        /**
295         * Return the class loader to be used for instantiating application objects
296         * when required.  This is determined based upon the following rules:
297         * <ul>
298         * <li>The class loader set by <code>setClassLoader()</code>, if any</li>
299         * <li>The thread context class loader, if it exists and the
300         *     <code>useContextClassLoader</code> property is set to true</li>
301         * <li>The class loader used to load the Digester class itself.
302         * </ul>
303         * @return the class loader.
304         */
305        public ClassLoader getClassLoader() {
306            if (this.classLoader != null) {
307                return this.classLoader;
308            }
309    
310            if (this.useContextClassLoader) {
311                ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
312                if (contextLoader != null) {
313                    return contextLoader;
314                }
315            }
316    
317            return this.getClass().getClassLoader();
318        }
319    
320        /**
321         * Set the class loader to be used for instantiating application objects
322         * when required.
323         *
324         * @param classLoader The new class loader to use, or <code>null</code>
325         *  to revert to the standard rules
326         */
327        public void setClassLoader(ClassLoader classLoader) {
328            this.classLoader = classLoader;
329        }
330    
331        /**
332         * Performs validations based on the configured resources.
333         *
334         * @return The <code>Map</code> returned uses the property of the
335         * <code>Field</code> for the key and the value is the number of error the
336         * field had.
337         * @throws ValidatorException If an error occurs during validation
338         */
339        public ValidatorResults validate() throws ValidatorException {
340            Locale locale = (Locale) this.getParameterValue(LOCALE_PARAM);
341    
342            if (locale == null) {
343                locale = Locale.getDefault();
344            }
345    
346            this.setParameter(VALIDATOR_PARAM, this);
347    
348            Form form = this.resources.getForm(locale, this.formName);
349            if (form != null) {
350                this.setParameter(FORM_PARAM, form);
351                return form.validate(
352                    this.parameters,
353                    this.resources.getValidatorActions(),
354                    this.page,
355                    this.fieldName);
356            }
357    
358            return new ValidatorResults();
359        }
360    
361        /**
362         * Returns true if the Validator is only returning Fields that fail validation.
363         * @return whether only failed fields are returned.
364         */
365        public boolean getOnlyReturnErrors() {
366            return onlyReturnErrors;
367        }
368    
369        /**
370         * Configures which Fields the Validator returns from the validate() method.  Set this
371         * to true to only return Fields that failed validation.  By default, validate() returns
372         * all fields.
373         * @param onlyReturnErrors whether only failed fields are returned.
374         */
375        public void setOnlyReturnErrors(boolean onlyReturnErrors) {
376            this.onlyReturnErrors = onlyReturnErrors;
377        }
378    
379    }