/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program is distributed
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.util.validator.common;
import java.io.InputStream;
import java.io.IOException;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Locale;
import java.util.Iterator;
import java.text.MessageFormat;
import org.apache.commons.validator.Field;
import org.apache.commons.validator.Form;
import org.apache.commons.validator.Validator;
import org.apache.commons.validator.ValidatorResults;
import org.apache.commons.validator.ValidatorResources;
import org.apache.commons.validator.ValidatorResult;
import org.apache.commons.validator.ValidatorException;
import org.apache.commons.validator.ValidatorAction;
import org.xml.sax.SAXException;
/**
* Encapsulates most of specific jakarta commons validator logic and
* provides access to validation results.
* <p>NOTE: Very heavily commented so as to persuade others to use and
* extend. The commons validation logic is a little bulky and awkward
* so consider this as a good place to put any further wrapper methods.</p>
*/
public class CommonValidator {
private ResourceBundle _properties = null; // message strings
private ValidatorResults _validatorResults = null; // results of validation
private String _resourceName = null; // current xml resource.
private ValidatorResources _validatorResources = null; // commons-v object
/**
* Simple constructor with property resourcebundle containing localized
* messages
**/
public CommonValidator(ResourceBundle properties) {
_properties = properties;
}
private void setResourceName (String rName) {
_resourceName = rName;
}
private void setValidatorResults(ValidatorResults results) {
_validatorResults = results;
}
public ValidatorResults getValidatorResults () {
return _validatorResults;
}
public String getResourceName () {
return _resourceName;
}
/**
* Simple getter for current Validator Resources. null until validate
* is first run
**/
public ValidatorResources getValidatorResources () {
return _validatorResources;
}
/**
* Gets and/or initializes validatorResources before returning it. Init-
* ialization is expensive so only perform it if necessary.
* Note: (1) CALLER's responsibility to close InputStream.
* (2) XML Resources always looked for in same package as Bean.
**/
private void setValidatorResources (String resourceName, Object bean,
InputStream in)
throws IOException, SAXException
{
if (getResourceName()==null ||
!getResourceName().equals(resourceName)) {
// remember this resource
setResourceName(resourceName);
// Read in the XMLfile
in = bean.getClass().getResourceAsStream(resourceName);
// create a new "validator" resources object. This thing contains
// FormSets stored against locale.
_validatorResources = new ValidatorResources(in);
}
}
/**
* Perform all form-specific the validation. All form specific validation
* is performed and then finally a CommonValidatorException object will be
* thrown if (AND ONLY IF) validation errors were detected. The exception
* object will contain a collection of error Strings see
* {@ref CommonValidatorException}.
*
* @param validationMappingRes A String containing the name of the
* mapping resource file.
* @param formName A String containing the name of the form containing
* the validation action references.
* @param beanInstance An instance of the bean to apply validation on.
* @throws CommonValidatorException - Exception containing collection of
* messages.
**/
public void validate (String validationMappingRes, String formName,
Object beanInstance)
throws CommonValidatorException, SAXException
{
InputStream xmlStream = null;
CommonValidatorException cve = null;
ValidatorResults results;
try {
// Start by setting the "ValidatorResources" object. Its only
// created if necessary. Contains FormSets stored against locale.
setValidatorResources(validationMappingRes, beanInstance, xmlStream);
// Get the form for the current locale and Bean.
Form form = _validatorResources.getForm(Locale.getDefault(), formName);
// Instantiate the validator (coordinates the validation
// while the ValidatorResources implements the validation)
Validator validator = new Validator(_validatorResources, formName);
// Tell the validator which bean to validate against.
validator.setParameter(Validator.BEAN_PARAM, beanInstance);
// Get the results
results = validator.validate();
// Localize a reference for future access.
setValidatorResults(results);
// Iterate over each of the properties of the Bean which had messages.
Iterator propertyNames = results.getPropertyNames().iterator();
while (propertyNames.hasNext()) {
// There were errors. Instantiate CVE
String propertyName = (String) propertyNames.next();
// Get the Field associated with that property in the Form
Field field = (Field) form.getField(propertyName);
// Look up the formatted name of the field from the Field arg0
String prettyFieldName = _properties.getString(field.getArg(0).getKey());
// Get the result of validating the property.
ValidatorResult result =
results.getValidatorResult(propertyName);
// Get all the actions run against the property, and iterate
// over their names. Check for invalid results.
Map actionMap = result.getActionMap();
Iterator keys = actionMap.keySet().iterator();
while (keys.hasNext()) {
String actName = (String) keys.next();
// Get the Action for that name.
ValidatorAction action =
_validatorResources.getValidatorAction(actName);
if (!result.isValid(actName)) {
String message = _properties.getString(action.getMsg());
Object[] args = { prettyFieldName };
if (cve == null) {
cve = new CommonValidatorException();
}
cve.addMessage(MessageFormat.format(message, args));
}
}
}
} catch (IOException ex) {
// Note: This exception shouldn't be reported to user since it
// wasn't likely caused by user input.
ex.printStackTrace(); //log this
} catch (ValidatorException ex) {
// Note: This exception shouldn't bubble up to user since it
// wasn't likely caused by user input.
ex.printStackTrace(); //log this
} finally {
// Make sure we close the input stream.
if (xmlStream != null)
try { xmlStream.close(); } catch (Exception e) {}
// Lastly, if we had any invalid fields, throw CVE.
if (cve != null)
throw cve;
}
}
}