com.redhat.rhn.common.validator.Validator.java Source code

Java tutorial

Introduction

Here is the source code for com.redhat.rhn.common.validator.Validator.java

Source

/**
 * Copyright (c) 2009--2012 Red Hat, Inc.
 *
 * This software is licensed to you under the GNU General Public License,
 * version 2 (GPLv2). There is NO WARRANTY for this software, express or
 * implied, including the implied warranties of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
 * along with this software; if not, see
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * Red Hat trademarks are not licensed under GPLv2. No permission is
 * granted to use or replicate Red Hat trademarks that are incorporated
 * in this software or its documentation.
 */
package com.redhat.rhn.common.validator;

import com.redhat.rhn.common.localization.LocalizationService;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * The <code>Validator</code> class allows an application component or client
 * to provide data, and determine if the data is valid for the requested type.
 * </p>
 *
 * This code was copied from:
 *
 * http://www.javaworld.com/javaworld/jw-09-2000/jw-0908-validation.html
 *
 * There were no appearent license restrictions on this code, the Author
 * indicated it was free and available to be used by readers of the article.
 *
 * @version $Rev$
 */
public class Validator {

    private static Logger log = Logger.getLogger(Validator.class);

    /** The instances of this class for use (singleton design pattern) */
    private static Map instances = null;

    /** The URL of the XML Schema for this <code>Validator</code> */
    private URL schemaURL;

    /** The constraints for this XML Schema */
    private Map constraints;

    /**
     * <p>
     * This constructor is private so that the class cannot be instantiated
     * directly, but instead only through <code>{@link #getInstance()}</code>.
     * </p>
     *
     * @param schemaURLIn <code>URL</code> to parse the schema at.
     * @throws IOException - when errors in parsing occur.
     */
    private Validator(URL schemaURLIn) throws IOException {
        this.schemaURL = schemaURLIn;

        // parse the XML Schema and create the constraints
        SchemaParser parser = new SchemaParser(schemaURL);
        constraints = parser.getConstraints();
    }

    /**
     * <p>
     * This will return the instance for the specific XML Schema URL. If a
     * schema exists, it is returned (as parsing will already be done);
     * otherwise, a new instance is created, and then returned.
     * </p>
     *
     * @param schemaURL <code>URL</code> of schema to validate against.
     * @return <code>Validator</code>- the instance, ready to use.
     * @throws IOException when errors in parsing occur.
     */
    public static synchronized Validator getInstance(URL schemaURL) throws IOException {
        if (instances != null) {
            if (instances.containsKey(schemaURL.toString())) {
                return (Validator) instances.get(schemaURL.toString());
            }
            Validator validator = new Validator(schemaURL);
            instances.put(schemaURL.toString(), validator);
            return validator;
        }
        instances = new HashMap();
        Validator validator = new Validator(schemaURL);
        instances.put(schemaURL.toString(), validator);
        return validator;
    }

    /**
     * <p>
     * This will validate a data value (in <code>String</code> format) against
     * a specific constraint, and return <code>true</code> if that value is
     * valid for the constraint.
     * </p>
     *
     * @param constraintName the identifier in the constraints to validate this
     * data against.
     * @param objToValidate <code>String</code> data to validate.
     * @return ValidatorError whether the data is valid or not.
     * TODO: rename this method to something other than isValid()
     */
    public ValidatorError isValid(String constraintName, Object objToValidate) {
        // Validate against the correct constraint
        Object o = constraints.get(constraintName);

        log.debug("Validating: " + constraintName);

        // If no constraint, then everything is valid
        if (o == null) {
            log.debug("No constraint found for " + constraintName);
            return null;
        }

        ParsedConstraint constraint = (ParsedConstraint) o;
        // Get the field we want to check
        Object value = null;
        try {
            value = PropertyUtils.getProperty(objToValidate, constraint.getIdentifier());
        } catch (Exception e) {
            String errorMessage = "Exception trying to get bean property: " + e.toString();
            log.error(errorMessage, e);
            throw new ValidatorException(errorMessage, e);
        }
        // TODO: Get rid of the toString and determine the type
        String data = (value == null) ? null : value.toString();

        ValidatorError validationMessage = null;

        log.debug("Data: " + data);
        log.debug("Constraint: " + constraint);

        boolean required = !constraint.getOptional() || (value != null && !value.equals(""));
        if (required) {
            boolean checkConstraint = true;
            if (constraint instanceof RequiredIfConstraint) {
                checkConstraint = ((RequiredIfConstraint) constraint).isRequired(data, objToValidate);
                log.debug("RequiredIf indicates:" + required);
            }
            if (checkConstraint) {
                // Validate data type
                validationMessage = correctDataType(data, constraint);
                if (validationMessage != null) {
                    log.debug("Not the right datatype.. " + validationMessage);
                    return validationMessage;
                }
                validationMessage = constraint.checkConstraint(data);
                if (validationMessage != null) {
                    log.debug("Failed: " + validationMessage);
                    return validationMessage;
                }
            }
        }

        log.debug("All is OK, returning true ...");
        return null;
    }

    /**
     * Get the list of Contraints associated with this Validator
     *
     * @return List of Constraint objects
     */
    public List getConstraints() {
        return new LinkedList(constraints.values());
    }

    /**
     * <p>
     * This will test the supplied data to see if it can be converted to the
     * Java data type given in <code>Constraint.dataType</code>.
     * </p>
     *
     * @param data <code>String</code> to test data type of.
     * @param constraint <code>Constraint</code> Constraint to be checked.
     * @return <code>ValidatorError</code>- or null, if there are no errors.
     */
    private ValidatorError correctDataType(String data, Constraint constraint) {

        ValidatorError validationMessage = null;
        String dataType = constraint.getDataType();
        String identifier = LocalizationService.getInstance().getMessage(constraint.getIdentifier());

        /* code does not change anything, leaving just for demonstration
        if ((dataType.equals("String")) || (dataType.equals("java.lang.String"))) {
        validationMessage = null;
        }
        else
        */

        if ((dataType.equals("int")) || (dataType.equals("java.lang.Integer"))) {
            try {
                Integer.parseInt(data);
            } catch (NumberFormatException e) {
                validationMessage = new ValidatorError("errors.integer", identifier);
            }
        } else if ((dataType.equals("long")) || (dataType.equals("java.lang.Long"))) {
            try {
                Long.parseLong(data);
            } catch (NumberFormatException e) {
                validationMessage = new ValidatorError("errors.long", identifier);
            }
        } else if ((dataType.equals("float")) || (dataType.equals("java.lang.Float"))) {
            try {
                Float.parseFloat(data);
            } catch (NumberFormatException e) {
                validationMessage = new ValidatorError("errors.float", identifier);
            }
        } else if ((dataType.equals("double")) || (dataType.equals("java.lang.Double"))) {
            try {
                Double.parseDouble(data);
            } catch (NumberFormatException e) {
                validationMessage = new ValidatorError("errors.double", identifier);
            }
        }

        else if (dataType.equals("java.lang.Boolean")) {
            if ((data.equalsIgnoreCase("true")) || (data.equalsIgnoreCase("false"))
                    || (data.equalsIgnoreCase("yes")) || (data.equalsIgnoreCase("no"))) {
                // empty
                // validationMessage = null;
            } else {
                validationMessage = new ValidatorError("errors.invalid", identifier);
            }
        }

        return validationMessage;
    }

}