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