Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Redistribution and use of this software and associated documentation ("Software"), with or
* without modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright statements and notices. Redistributions
* must also contain a copy of this document.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
* without prior written permission of Intalio, Inc. For written permission, please contact
* [email protected].
*
* 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
* their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
* Intalio, Inc.
*
* 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
*
* THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Copyright 2000-2004 (C) Intalio, Inc. All Rights Reserved.
*
* $Id$
*/
package org.exolab.castor.xml;
import java.lang.reflect.Array;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
import org.exolab.castor.mapping.FieldHandler;
import org.exolab.castor.xml.location.XPathLocation;
/**
* Handles field validation.
*
* @author Keith Visco
* @version $Revision$ $Date: 2004-10-08 22:58:55 -0600 (Fri, 08 Oct 2004) $
*/
public class FieldValidator extends Validator {
/**
* Default value for descriptor names. If a Descriptor XML name value is set to this, then no name
* has been assigned yet.
*/
private static final String ERROR_NAME = "-error-if-this-is-used-";
/** Default minimum occurrance. */
private static final int DEFAULT_MIN = 0;
/** Default maximum occurrance. */
private static final int DEFAULT_MAX = -1;
/** Minimum number of occurrences for this element to pass validation. */
private int _minOccurs = DEFAULT_MIN;
/** Maximum number of occurrences for this element to pass validation. */
private int _maxOccurs = DEFAULT_MAX;
/** The Field Descriptor describing the field we validate. */
private XMLFieldDescriptor _descriptor = null;
/**
* The actual type validator which is used to validate single instances of the field.
*/
private TypeValidator _validator = null;
/**
* Creates a default FieldValidator.
*/
public FieldValidator() {
super();
}
/**
* Creates a new FieldValidator using the given TypeValidator.
*
* @param validator the TypeValidator to delegate validation to
*/
public FieldValidator(final TypeValidator validator) {
super();
this._validator = validator;
}
/**
* Returns the mimimum number of occurances for a given object.
*
* @return The mimimum number of occurances for a given object. A zero value denotes no lower
* bound (ie. the object is optional).
*/
public int getMinOccurs() {
return _minOccurs;
}
/**
* Returns the maximum number of occurances for a given object.
*
* @return The maximum number of occurances for a given object. A negative value denotes no upper
* bound.
*/
public int getMaxOccurs() {
return _maxOccurs;
}
/**
* Returns the TypeValidator.
*
* @return the TypeValidator.
*/
public TypeValidator getTypeValidator() {
return _validator;
}
/**
* Returns true if a TypeValidator has been set.
*
* @return true if a TypeValidator has been set.
*/
public boolean hasTypeValidator() {
return _validator != null;
}
/**
* Sets the mimimum number of occurances for a given object. A zero, or negative value denotes no
* lower bound (i.e., the object is optional).
*
* @param minOccurs the minimum number of times an object must occur in order to be valid.
*/
public void setMinOccurs(final int minOccurs) {
this._minOccurs = (minOccurs < 0) ? 0 : minOccurs;
}
/**
* Sets the maximum number of occurances for a given object. A negative value denotes no upper
* bound.
*
* @param maxOccurs the maximum number of times an object may occur.
*/
public void setMaxOccurs(final int maxOccurs) {
this._maxOccurs = maxOccurs;
}
/**
* Sets the field descriptor to use for obtaining information about the field to validate, such as
* the field name, the field handler, etc.
*
* @param descriptor the field descriptor for the field to validate
*/
public void setDescriptor(final XMLFieldDescriptor descriptor) {
this._descriptor = descriptor;
}
public void setValidator(final TypeValidator validator) {
this._validator = validator;
}
/**
* Validates the given Object.
*
* @param object the Object that contains the field to validate
* @param context the ValidationContext
* @throws ValidationException if validation fails
*/
public void validate(final Object object, final ValidationContext context)
throws ValidationException {
if (_descriptor == null || object == null || context.isValidated(object)) {
return;
}
// Don't validate "transient" fields.
if (_descriptor.isTransient()) {
return;
}
FieldHandler handler = _descriptor.getHandler();
if (handler == null) {
return;
}
// Get the value of the field
Object value = handler.getValue(object);
if (value == null) {
if (!_descriptor.isRequired() || _descriptor.isNillable()) {
return;
}
// deal with lenient id/idref validation accordingly, skipping exception handling
// in this case
if (_descriptor.isRequired() && _descriptor.getSchemaType() != null
&& _descriptor.getSchemaType().equals("IDREF")
&& context.getInternalContext().getLenientIdValidation()) {
return;
}
StringBuilder buff = new StringBuilder();
if (!ERROR_NAME.equals(_descriptor.getXMLName())) {
buff.append(MessageFormat.format(
resourceBundle.getString("validatorField.error.required.field.whose"),
new Object[] {_descriptor.getFieldName(), object.getClass().getName(),
_descriptor.getXMLName()}));
} else {
buff.append(
MessageFormat.format(resourceBundle.getString("validatorField.error.required.field"),
new Object[] {_descriptor.getFieldName(), object.getClass().getName()}));
}
throw new ValidationException(buff.toString());
}
if (_descriptor.isReference()) {
if (_validator != null) {
_validator.validate(value, context);
}
return;
}
// Prevent endless loop! Have we seen this object yet?
if (context != null) {
if (context.isValidated(object)) {
return;
}
// -- mark object as processed
context.addValidated(object);
}
// We are now ready to do actual validation
Class type = value.getClass();
int size = 1;
long occurence = -1;
try {
if (type.isArray()) {
// We don't validate Byte array types
if (type.getComponentType() != Byte.TYPE) {
size = Array.getLength(value);
if (_validator != null) {
for (int i = 0; i < size; i++) {
occurence = i + 1;
_validator.validate(Array.get(value, i), context);
}
} else {
for (int i = 0; i < size; i++) {
super.validate(Array.get(value, i), context);
}
}
}
} else if (value instanceof Enumeration) {
//
// The following code should be changed to use CollectionHandler
//
size = 0;
for (Enumeration enumeration = (Enumeration) value; enumeration.hasMoreElements();) {
++size;
validateInstance(context, enumeration.nextElement());
}
} else if (value instanceof Vector) {
Vector vector = (Vector) value;
size = vector.size();
for (int i = 0; i < size; i++) {
occurence = i + 1;
validateInstance(context, vector.elementAt(i));
}
} else if (value instanceof List) {
List list = (List) value;
size = list.size();
for (int i = 0; i < size; i++) {
occurence = i + 1;
validateInstance(context, list.get(i));
}
} else {
validateInstance(context, value);
}
} catch (ValidationException vx) {
// -- add additional validation information
String err = MessageFormat.format(resourceBundle.getString("validatorField.error.exception"),
new Object[] {_descriptor.getFieldName(), object.getClass().getName()});
ValidationException validationException = new ValidationException(err, vx);
addLocationInformation(_descriptor, validationException, occurence);
throw validationException;
}
// Check sizes of collection
// Check minimum.
// If any items exist (size != 0) or the descriptor is marked as
// required then we need to report the error. Otherwise size == 0 and
// field is not required, so no error.
if (size < _minOccurs && (size != 0 || _descriptor.isRequired())) {
StringBuilder buff = new StringBuilder();
if (!ERROR_NAME.equals(_descriptor.getXMLName())) {
buff.append(MessageFormat.format(
resourceBundle.getString("validatorField.error.exception.min.occurs.whose"),
new Object[] {_minOccurs, _descriptor.getFieldName(), object.getClass().getName(),
_descriptor.getXMLName()}));
} else {
buff.append(MessageFormat.format(
resourceBundle.getString("validatorField.error.exception.min.occurs"),
new Object[] {_minOccurs, _descriptor.getFieldName(), object.getClass().getName()}));
}
throw new ValidationException(buff.toString());
}
// Check maximum.
if (_maxOccurs >= 0 && size > _maxOccurs) {
StringBuilder buff = new StringBuilder();
if (!ERROR_NAME.equals(_descriptor.getXMLName())) {
buff.append(MessageFormat.format(
resourceBundle.getString("validatorField.error.exception.max.occurs.whose"),
new Object[] {_maxOccurs, _descriptor.getFieldName(), object.getClass().getName(),
_descriptor.getXMLName()}));
} else {
buff.append(MessageFormat.format(
resourceBundle.getString("validatorField.error.exception.max.occurs"),
new Object[] {_maxOccurs, _descriptor.getFieldName(), object.getClass().getName()}));
}
throw new ValidationException(buff.toString());
}
if (context != null) {
context.removeValidated(object);
}
}
/**
* Validate an individual instance.
*
* @param context the validation context.
* @param value The instance to validate.
* @throws ValidationException if validation fails
*/
private void validateInstance(final ValidationContext context, final Object value)
throws ValidationException {
if (_validator != null) {
_validator.validate(value, context);
} else {
super.validate(value, context);
}
}
/**
* Adds location information to the {@link ValidationException} instance.
*
* @param fieldDescriptor The {@link XMLFieldDescriptor} instance whose has been responsible for
* generating the error.
* @param e The {@link ValidationException} to enrich.
* @param occurence If greater than 0, denotes the position of the invalid collection value.
*/
private void addLocationInformation(final XMLFieldDescriptor fieldDescriptor,
final ValidationException e, final long occurence) {
XPathLocation loc = (XPathLocation) e.getLocation();
if (loc == null) {
loc = new XPathLocation();
e.setLocation(loc);
String xmlName = fieldDescriptor.getXMLName();
if (occurence > 0) {
xmlName += "[" + occurence + "]";
}
if (fieldDescriptor.getNodeType() == NodeType.Attribute) {
loc.addAttribute(xmlName);
} else {
loc.addChild(xmlName);
}
}
}
}