    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$
    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>
    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<>();
    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}