edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators.BasicValidation.java Source code

Java tutorial

Introduction

Here is the source code for edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators.BasicValidation.java

Source

/* $This file is distributed under the terms of the license in /doc/license.txt$ */

package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.hp.hpl.jena.datatypes.RDFDatatype;
import com.hp.hpl.jena.datatypes.TypeMapper;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.ModelFactory;

import edu.cornell.mannlib.vitro.webapp.beans.Datatype;
import edu.cornell.mannlib.vitro.webapp.dao.jena.DatatypeDaoJena;
import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.Field;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditSubmission;

/**
 * User: bdc34
 * Date: Jan 24, 2008
 * Time: 1:55:39 PM
 */
public class BasicValidation {

    Map<String, List<String>> varsToValidations;
    EditConfiguration editConfig;

    public BasicValidation(EditConfiguration editConfig, EditSubmission editSub) {
        this.editConfig = editConfig;
        Map<String, List<String>> validatorsForFields = new HashMap<String, List<String>>();
        for (String fieldName : editConfig.getFields().keySet()) {
            Field field = editConfig.getField(fieldName);
            validatorsForFields.put(fieldName, field.getValidators());
        }
        this.varsToValidations = validatorsForFields;
        checkValidations();
    }

    public BasicValidation(Map<String, List<String>> varsToValidations) {
        this.varsToValidations = varsToValidations;
        checkValidations();
    }

    public Map<String, String> validateUris(Map<String, String> varNamesToValues) {
        HashMap<String, String> errors = new HashMap<String, String>();

        for (String name : varNamesToValues.keySet()) {

            String value = varNamesToValues.get(name);
            List<String> validations = varsToValidations.get(name);
            if (validations != null) {
                for (String validationType : validations) {
                    String validateMsg = validate(validationType, value);
                    if (validateMsg != null) {
                        errors.put(name, validateMsg);
                    }
                }
            }
        }
        return errors;
    }

    public Map<String, String> validateLiterals(Map<String, Literal> varNamesToValues) {
        HashMap<String, String> errors = new HashMap<String, String>();

        for (String name : editConfig.getLiteralsOnForm()) {
            Literal literal = varNamesToValues.get(name);
            List<String> validations = varsToValidations.get(name);
            if (validations != null) {
                // NB this is case-sensitive
                boolean isRequiredField = validations.contains("nonempty");

                for (String validationType : validations) {
                    String value = null;
                    try {
                        if (literal != null) {
                            value = literal.getString();
                        }
                    } catch (Throwable th) {
                        log.debug("could not convert literal to string", th);
                    }
                    // Empty field: if required, include only the empty field
                    // error message, not a format validation message. If non-required, 
                    // don't do format validation, since that is both unnecessary and may 
                    // incorrectly generate errors.
                    if (isEmpty(value)) {
                        if (isRequiredField) {
                            errors.put(name, REQUIRED_FIELD_EMPTY_MSG);
                        }
                        break;
                    }

                    String validateMsg = validate(validationType, value);
                    if (validateMsg != null) {
                        errors.put(name, validateMsg);
                    }
                }
            }
        }
        return errors;
    }

    public Map<String, String> validateFiles(Map<String, List<FileItem>> fileItemMap) {

        HashMap<String, String> errors = new HashMap<String, String>();
        for (String name : editConfig.getFilesOnForm()) {
            List<String> validators = varsToValidations.get(name);
            for (String validationType : validators) {
                String validateMsg = validate(validationType, fileItemMap.get(name));
                if (validateMsg != null) {
                    errors.put(name, validateMsg);
                }
            }
        }
        return errors;
    }

    private String validate(String validationType, List<FileItem> fileItems) {
        if ("nonempty".equalsIgnoreCase(validationType)) {
            if (fileItems == null || fileItems.size() == 0) {
                return "a file must be entered for this field.";
            } else {
                FileItem fileItem = fileItems.get(0);
                if (fileItem == null || fileItem.getName() == null || fileItem.getName().length() < 1
                        || fileItem.getSize() < 0) {
                    return "a file must be entered for this field.";
                }
            }
        }
        return null;
    }

    /* null indicates success. A returned string is the validation
    error message.
     */
    public String validate(String validationType, String value) {
        // Required field validation.
        // For literals, testing empty required values in validateLiterals.
        // This case may be needed for validation of other field types.
        if ("nonempty".equalsIgnoreCase(validationType)) {
            if (isEmpty(value))
                return REQUIRED_FIELD_EMPTY_MSG;
        }
        // Format validation
        else if ("isDate".equalsIgnoreCase(validationType)) {
            if (isDate(value))
                return SUCCESS;
            else
                return "must be in valid date format mm/dd/yyyy.";
        } else if (validationType.indexOf("datatype:") == 0) {
            String datatypeURI = validationType.substring(9);
            String errorMsg = validateAgainstDatatype(value, datatypeURI);
            if (errorMsg == null) {
                return SUCCESS;
            } else {
                return errorMsg;
            }
        } else if ("httpUrl".equalsIgnoreCase(validationType)) {
            //check if it has http or https, we could do more but for now this is all.
            if (!value.startsWith("http://") && !value.startsWith("https://")) {
                return "This URL must start with http:// or https://";
            } else {
                return SUCCESS;
            }
        }
        //Date not past validation
        else if ("dateNotPast".equalsIgnoreCase(validationType)) {
            //if( ! past (value) )
            // return "date must not be in the past";
            //Current date
            Calendar c = Calendar.getInstance();
            //Input
            Calendar inputC = Calendar.getInstance();
            String yearParamStr, monthParamStr, dayParamStr;
            int yearDash = value.indexOf("-");
            int monthDash = value.lastIndexOf("-");
            if (yearDash != -1 && yearDash != monthDash) {
                yearParamStr = value.substring(0, yearDash);
                monthParamStr = value.substring(yearDash + 1, monthDash);
                dayParamStr = value.substring(monthDash + 1, value.length());
                inputC.set(Integer.parseInt(yearParamStr), Integer.parseInt(monthParamStr) - 1,
                        Integer.parseInt(dayParamStr));
                if (inputC.before(c)) {
                    return this.DATE_NOT_PAST_MSG;
                    //Returning null makes the error message "field is empty" display instead
                    //return null;
                } else {
                    return SUCCESS;
                }
            }
        }
        return null; //
    }

    private boolean isDate(String in) {
        return datePattern.matcher(in).matches();
    }

    private static DatatypeDaoJena ddao = null;

    public static synchronized String validateAgainstDatatype(String value, String datatypeURI) {
        if ((datatypeURI != null) && (datatypeURI.length() > 0)) {
            RDFDatatype datatype = TypeMapper.getInstance().getSafeTypeByName(datatypeURI);
            if (datatype == null) {
                throw new RuntimeException(datatypeURI + " is not a recognized datatype");
            }
            if (datatype.isValid(value)) {
                return null;
            } else {
                // TODO: better way of getting more friendly names for common datatypes
                if (ddao == null) {
                    ddao = new DatatypeDaoJena(
                            new WebappDaoFactoryJena(ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM)));
                }
                Datatype dtype = ddao.getDatatypeByURI(datatypeURI);
                String dtypeMsg = (dtype != null) ? dtype.getName() : datatypeURI;
                return " Please correct this value: must be a valid " + dtypeMsg + ".";
            }
        }
        return null;
    }

    private void checkValidations() {
        List<String> unknown = new ArrayList<String>();
        for (String key : varsToValidations.keySet()) {
            for (String validator : varsToValidations.get(key)) {
                if (!basicValidations.contains(validator)) {
                    if (!((validator != null) && (validator.indexOf("datatype:") == 0))) {
                        unknown.add(validator);
                    }
                }
            }
        }
        if (unknown.isEmpty())
            return;

        throw new Error("Unknown basic validators: " + unknown.toArray());
    }

    private static boolean isEmpty(String value) {
        return (value == null || value.trim().length() == 0);
    }

    private static Pattern urlRX = Pattern.compile(
            "(([a-zA-Z][0-9a-zA-Z+\\-\\.]*:)/{0,2}[0-9a-zA-Z;/?:@&=+$\\.\\-_!~*'()%]+)(#[0-9a-zA-Z;/?:@&=+$\\.\\-_!~*'()%]+)?");

    /** we use null to indicate success */
    public final static String SUCCESS = null;
    public final static String REQUIRED_FIELD_EMPTY_MSG = "This field must not be empty.";
    public final static String DATE_NOT_PAST_MSG = "Please enter a future target date for publication (past dates are invalid).";
    //public final static String MIN_FIELDS_NOT_POPULATED = "Please enter values for at least ";
    //public final static String FORM_ERROR_FIELD_ID = "formannotationerrors";
    /** regex for strings like "12/31/2004" */
    private final String dateRegex = "((1[012])|([1-9]))/((3[10])|([12][0-9])|([1-9]))/[\\d]{4}";
    private final Pattern datePattern = Pattern.compile(dateRegex);

    static final List<String> basicValidations;
    static {
        basicValidations = Arrays.asList("nonempty", "isDate", "dateNotPast", "httpUrl");
    }

    private Log log = LogFactory.getLog(BasicValidation.class);
}