Revision: 455
http://svn.sourceforge.net/stripes/?rev=455&view=rev
Author: tfenne
Date: 2006-10-27 04:32:19 -0700 (Fri, 27 Oct 2006)
Log Message:
-----------
Working towards STS-240 and STS-260. Validation metadata is now stored
internally in a standalone, non-annotation class, that can be manufactured
dynamically. Still need to add interface methods to allow this to be exposed
and manipulated dynamically.
Modified Paths:
--------------
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java
trunk/stripes/src/net/sourceforge/stripes/controller/StripesConstants.java
Added Paths:
-----------
trunk/stripes/src/net/sourceforge/stripes/validation/ValidationMetadata.java
Modified:
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java
===================================================================
---
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java
2006-10-26 01:11:45 UTC (rev 454)
+++
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java
2006-10-27 11:32:19 UTC (rev 455)
@@ -20,22 +20,9 @@
import net.sourceforge.stripes.action.Wizard;
import net.sourceforge.stripes.config.Configuration;
import net.sourceforge.stripes.exception.StripesRuntimeException;
-import net.sourceforge.stripes.util.CryptoUtil;
-import net.sourceforge.stripes.util.HtmlUtil;
-import net.sourceforge.stripes.util.Log;
-import net.sourceforge.stripes.util.ReflectUtil;
-import net.sourceforge.stripes.util.CollectionUtil;
-import net.sourceforge.stripes.util.bean.ExpressionException;
-import net.sourceforge.stripes.util.bean.NoSuchPropertyException;
-import net.sourceforge.stripes.util.bean.PropertyExpression;
-import net.sourceforge.stripes.util.bean.PropertyExpressionEvaluation;
-import net.sourceforge.stripes.util.bean.BeanUtil;
-import net.sourceforge.stripes.validation.ScopedLocalizableError;
-import net.sourceforge.stripes.validation.TypeConverter;
-import net.sourceforge.stripes.validation.Validate;
-import net.sourceforge.stripes.validation.ValidateNestedProperties;
-import net.sourceforge.stripes.validation.ValidationError;
-import net.sourceforge.stripes.validation.ValidationErrors;
+import net.sourceforge.stripes.util.*;
+import net.sourceforge.stripes.util.bean.*;
+import net.sourceforge.stripes.validation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.PageContext;
@@ -43,25 +30,9 @@
import javax.servlet.jsp.el.Expression;
import javax.servlet.jsp.el.ExpressionEvaluator;
import javax.servlet.jsp.el.VariableResolver;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Type;
+import java.lang.reflect.*;
import java.security.GeneralSecurityException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.regex.Pattern;
+import java.util.*;
/**
* <p>Implementation of the ActionBeanPropertyBinder interface that uses
Stripes' built in
@@ -78,28 +49,14 @@
* @since Stripes 1.4
*/
public class DefaultActionBeanPropertyBinder implements
ActionBeanPropertyBinder {
- private static Log log =
Log.getInstance(DefaultActionBeanPropertyBinder.class);
- private static Set<String> SPECIAL_KEYS = new HashSet<String>();
+ private static final Log log =
Log.getInstance(DefaultActionBeanPropertyBinder.class);
- static {
- SPECIAL_KEYS.add(StripesConstants.URL_KEY_SOURCE_PAGE);
- SPECIAL_KEYS.add(StripesConstants.URL_KEY_FIELDS_PRESENT);
- SPECIAL_KEYS.add(StripesConstants.URL_KEY_FLASH_SCOPE_ID);
- }
-
/** Map of validation annotations that is built at startup. */
- private Map<Class<? extends ActionBean>, Map<String,Validate>> validations;
+ private Map<Class<? extends ActionBean>, Map<String, ValidationMetadata>>
validations;
- /**
- * Map of validation annotations to the set of events they should be run
on. Note that
- * the events may be prepended with "!", so watch out!
- */
- private Map<Validate,Set<String>> validationEventMap;
-
/** Configuration instance passed in at initialization time. */
private Configuration configuration;
-
/**
* Looks up and caches in a useful form the metadata necessary to perform
validations as
* properties are bound to the bean.
@@ -107,40 +64,22 @@
public void init(Configuration configuration) throws Exception {
this.configuration = configuration;
Set<Class<? extends ActionBean>> beanClasses =
ActionClassCache.getInstance().getActionBeanClasses();
- this.validations = new HashMap<Class<? extends ActionBean>,
Map<String,Validate>>();
- this.validationEventMap = new HashMap<Validate,Set<String>>();
+ this.validations = new HashMap<Class<? extends ActionBean>,
Map<String,ValidationMetadata>>();
for (Class<? extends ActionBean> beanClass : beanClasses) {
- Map<String, Validate> fieldValidations = new HashMap<String,
Validate>();
+ Map<String, ValidationMetadata> fieldValidations = new
HashMap<String, ValidationMetadata>();
processClassAnnotations(beanClass, fieldValidations);
this.validations.put(beanClass, fieldValidations);
- // Go through and put the list of events for this validation into
- // a quicker to access structure
- for (Validate info : fieldValidations.values()) {
- Set<String> events = null;
- if (info.on().length == 0) {
- events = Collections.emptySet();
- }
- else {
- events = new HashSet<String>();
- for (String event : info.on()) {
- events.add(event);
- }
- }
-
- this.validationEventMap.put(info, events);
- }
-
// Print out a pretty debug message showing what validations got
configured
StringBuilder builder = new StringBuilder(128);
- for (Map.Entry<String,Validate> entry :
fieldValidations.entrySet()) {
+ for (Map.Entry<String,ValidationMetadata> entry :
fieldValidations.entrySet()) {
if (builder.length() > 0) {
builder.append(", ");
}
builder.append(entry.getKey());
builder.append("->");
- builder.append(ReflectUtil.toString(entry.getValue()));
+ builder.append(entry.getValue());
}
log.debug("Loaded validations for ActionBean ",
beanClass.getSimpleName(), ": ",
@@ -154,9 +93,9 @@
* inheritance hierarchy take precedence over those higher up.
*
* @param clazz the ActionBean subclasses (or parent thereof) in question
- * @param fieldValidations a map of fieldname->Validate in which to store
validations
+ * @param fieldValidations a map of fieldname->ValidationMetadata in which
to store validations
*/
- protected void processClassAnnotations(Class clazz, Map<String,Validate>
fieldValidations) {
+ protected void processClassAnnotations(Class clazz,
Map<String,ValidationMetadata> fieldValidations) {
Class superclass = clazz.getSuperclass();
if (superclass != null) {
processClassAnnotations(superclass, fieldValidations);
@@ -169,52 +108,51 @@
continue; // only public methods!
}
- Validate validation = method.getAnnotation(Validate.class);
- if (validation != null) {
- String fieldName = getPropertyName(method.getName());
- fieldValidations.put(fieldName, validation);
- }
-
- ValidateNestedProperties nested =
method.getAnnotation(ValidateNestedProperties.class);
- if (nested != null) {
- String fieldName = getPropertyName(method.getName());
- Validate[] validations = nested.value();
- for (Validate nestedValidate : validations) {
- if ( "".equals(nestedValidate.field()) ) {
- log.warn("Nested validation used without field name:
", validation);
- }
- else {
- fieldValidations.put(fieldName + "." +
nestedValidate.field(),
- nestedValidate);
- }
- }
- }
+ processPropertyAnnotations(getPropertyName(method.getName()),
+ method.getAnnotation(Validate.class),
+
method.getAnnotation(ValidateNestedProperties.class),
+ fieldValidations);
}
// Process the fields for validation annotations
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
- Validate validation = field.getAnnotation(Validate.class);
- if (validation != null) {
- fieldValidations.put(field.getName(), validation);
- }
+ processPropertyAnnotations(field.getName(),
+ field.getAnnotation(Validate.class),
+
field.getAnnotation(ValidateNestedProperties.class),
+ fieldValidations);
+ }
+ }
- ValidateNestedProperties nested =
field.getAnnotation(ValidateNestedProperties.class);
- if (nested != null) {
- Validate[] validations = nested.value();
- for (Validate nestedValidate : validations) {
- if ( "".equals(nestedValidate.field()) ) {
- log.warn("Nested validation used without field name:
", validation);
- }
- else {
- fieldValidations.put(field.getName() + "." +
nestedValidate.field(),
- nestedValidate);
- }
+ /**
+ * Helper method that takes the name of a property on the ActionBean along
with the
+ * property's (potentially null) Validate and ValidateNestedProperties
annotations
+ * and stores the information in to the internval cache of validation
information.
+ */
+ protected void processPropertyAnnotations(String name, Validate validate,
+ ValidateNestedProperties nested,
+ Map<String,ValidationMetadata>
fieldValidations) {
+ if (validate != null) {
+ fieldValidations.put(name, new ValidationMetadata(name, validate));
+ }
+
+ if (nested != null) {
+ Validate[] validations = nested.value();
+ for (Validate nestedValidate : validations) {
+ if ( "".equals(nestedValidate.field()) ) {
+ log.warn("Nested validation on field ", name, " used
without nested field name: ",
+ ReflectUtil.toString(nestedValidate));
}
+ else {
+ String nestedName = name + "." + nestedValidate.field();
+ fieldValidations.put(nestedName, new
ValidationMetadata(nestedName, nestedValidate));
+ }
}
}
+
}
+
/**
* <p>Loops through the parameters contained in the request and attempts
to bind each one to the
* supplied ActionBean. Invokes validation for each of the properties on
the bean before
@@ -252,12 +190,13 @@
try {
String pname = name.getName(); // exact name of the param in
the request
- if (!SPECIAL_KEYS.contains(pname) &&
!pname.equals(context.getEventName())
- && !fieldErrors.containsKey(pname)) {
+ if (!StripesConstants.SPECIAL_URL_KEYS.contains(pname)
+ && !pname.equals(context.getEventName()) &&
!fieldErrors.containsKey(pname)) {
log.trace("Running binding for property with name: ",
name);
// Determine the target type
- Validate validationInfo =
this.validations.get(bean.getClass()).get(name.getStrippedName());
+ ValidationMetadata validationInfo =
+
this.validations.get(bean.getClass()).get(name.getStrippedName());
PropertyExpressionEvaluation eval =
new
PropertyExpressionEvaluation(PropertyExpression.getExpression(pname), bean);
Class type = eval.getType();
@@ -553,7 +492,10 @@
* three characters and makes the next character lower case.
*/
protected String getPropertyName(String methodName) {
- return methodName.substring(3,4).toLowerCase() +
methodName.substring(4);
+ if (methodName.length() > 3)
+ return methodName.substring(3,4).toLowerCase() +
methodName.substring(4);
+ else
+ return "";
}
@@ -577,21 +519,21 @@
}
}
- Map<String,Validate> validationInfos =
this.validations.get(bean.getClass());
+ Map<String,ValidationMetadata> validationInfos =
this.validations.get(bean.getClass());
StripesRequestWrapper req =
StripesRequestWrapper.findStripesWrapper(bean.getContext().getRequest());
if (validationInfos != null) {
boolean wizard = bean.getClass().getAnnotation(Wizard.class) !=
null;
Collection<String> fieldsOnPage = getFieldsPresentInfo(bean);
- for (Map.Entry<String,Validate> entry :
validationInfos.entrySet()) {
+ for (Map.Entry<String,ValidationMetadata> entry :
validationInfos.entrySet()) {
String propertyName = entry.getKey();
- Validate validationInfo = entry.getValue();
+ ValidationMetadata validationInfo = entry.getValue();
// If the field is required, and we don't have index params
that collapse
// to that property name, check that it was supplied
- if (validationInfo.required() &&
!indexedParams.contains(propertyName)
- && applies(validationInfo, bean.getContext())) {
+ if (validationInfo.requiredOn(bean.getContext().getEventName())
+ && !indexedParams.contains(propertyName)) {
// Make the added check that if the form is a wizard, the
required field is
// in the set of fields that were on the page
@@ -628,12 +570,10 @@
for (Map.Entry<ParameterName,String[]> entry :
row.entrySet()) {
ParameterName name = entry.getKey();
String[] values = entry.getValue();
- Validate validationInfo =
validationInfos.get(name.getStrippedName());
+ ValidationMetadata validationInfo =
validationInfos.get(name.getStrippedName());
- if (validationInfo != null && validationInfo.required()
- && applies(validationInfo, bean.getContext()))
{
- checkSingleRequiredField
- (name.getName(), name.getStrippedName(),
values, req, errors);
+ if (validationInfo != null &&
validationInfo.requiredOn(bean.getContext().getEventName())) {
+ checkSingleRequiredField(name.getName(),
name.getStrippedName(), values, req, errors);
}
}
}
@@ -703,18 +643,18 @@
*
* @param propertyName the name of the property being validated (used for
constructing errors)
* @param values the String[] of values from the request being validated
- * @param validationInfo the Valiate annotation that was decorating the
property being validated
+ * @param validationInfo the ValidationMetadata for the property being
validated
* @param errors a collection of errors to be populated with any
validation errors discovered
*/
protected void doPreConversionValidations(ParameterName propertyName,
String[] values,
- Validate validationInfo,
+ ValidationMetadata
validationInfo,
List<ValidationError> errors) {
for (String value : values) {
// Only run validations when there are non-empty values
if (value != null && value.length() > 0) {
- if (validationInfo.minlength() != -1 && value.length() <
validationInfo.minlength()) {
+ if (validationInfo.minlength() != null && value.length() <
validationInfo.minlength()) {
ValidationError error =
new ScopedLocalizableError ("validation.minlength",
"valueTooShort",
@@ -724,7 +664,7 @@
errors.add( error );
}
- if (validationInfo.maxlength() != -1 && value.length() >
validationInfo.maxlength()) {
+ if (validationInfo.maxlength() != null && value.length() >
validationInfo.maxlength()) {
ValidationError error =
new ScopedLocalizableError("validation.maxlength",
"valueTooLong",
@@ -733,8 +673,7 @@
errors.add( error );
}
- if ( validationInfo.mask().length() > 0 &&
-
!Pattern.compile(validationInfo.mask()).matcher(value).matches() ) {
+ if ( validationInfo.mask() != null &&
!validationInfo.mask().matcher(value).matches() ) {
ValidationError error =
new ScopedLocalizableError("validation.mask",
@@ -764,7 +703,8 @@
// Sort out what we need to validate this field
ParameterName name = entry.getKey();
List<Object> values = entry.getValue();
- Validate validationInfo =
this.validations.get(bean.getClass()).get(name.getStrippedName());
+ ValidationMetadata validationInfo =
+
this.validations.get(bean.getClass()).get(name.getStrippedName());
if (values.size() == 0 || validationInfo == null) {
continue;
@@ -776,7 +716,7 @@
if (value instanceof Number) {
Number number = (Number) value;
- if (validationInfo.minvalue() != Double.MIN_VALUE &&
+ if (validationInfo.minvalue() != null &&
number.doubleValue() < validationInfo.minvalue() )
{
ValidationError error = new
ScopedLocalizableError("validation.minvalue",
"valueBelowMinimum",
@@ -785,7 +725,7 @@
errors.add(name.getName(), error);
}
- if (validationInfo.maxvalue() != Double.MAX_VALUE &&
+ if (validationInfo.maxvalue() != null &&
number.doubleValue() > validationInfo.maxvalue() )
{
ValidationError error = new
ScopedLocalizableError("validation.maxvalue",
"valueAboveMaximum",
@@ -810,19 +750,19 @@
* @param bean the ActionBean who's property is being validated
* @param name the name of the property being validated
* @param values the non-null post-conversion values for the property
- * @param validationInfo the validation annotation for the property
+ * @param validationInfo the validation metadata for the property
* @param errors the validation errors object to add errors to
*/
protected void doExpressionValidation(ActionBean bean,
ParameterName name,
List<Object> values,
- Validate validationInfo,
+ ValidationMetadata validationInfo,
ValidationErrors errors) {
// If a validation expression was supplied, see if we can process it!
Expression expr = null;
DelegatingVariableResolver resolver = null;
- if ( !"".equals(validationInfo.expression()) ) {
+ if (validationInfo.expression() != null) {
final PageContext context = DispatcherHelper.getPageContext();
if (context == null) {
@@ -835,10 +775,6 @@
try {
// If this turns out to be slow we could probably cache
the parsed expression
String expression = validationInfo.expression();
- if (!expression.startsWith("${")) {
- expression = "${" + expression + "}";
- }
-
ExpressionEvaluator evaluator =
context.getExpressionEvaluator();
expr = evaluator.parseExpression(expression,
Boolean.class, null);
resolver = new DelegatingVariableResolver(bean,
context.getVariableResolver());
@@ -875,29 +811,6 @@
}
/**
- * Determines whether or not a specific validation applies to the current
event or not.
- *
- * @param info the ValidationInfo being looked at
- * @param context the current ActionBeanContext
- * @return true if the Validation should be executed, false otherwise
- */
- protected boolean applies(Validate info, ActionBeanContext context) {
- Set<String> events = this.validationEventMap.get(info);
- String current = context.getEventName();
-
- if (info.on().length == 0 || current == null) {
- return true;
- }
-
- if (info.on()[0].startsWith("!")) {
- return !events.contains("!" + current);
- }
- else {
- return events.contains(current);
- }
- }
-
- /**
* <p>Converts the String[] of values for a given parameter in the
HttpServletRequest into the
* desired type of Object. If a converter is declared using an annotation
for the property
* (or getter/setter) then that converter will be used - if it does not
convert to the right
@@ -916,7 +829,7 @@
* @param values a String array of values to attempt conversion of
* @param errors a List into which ValidationError objects will be
populated for any errors
* discovered during conversion.
- * @param validationInfo the @Validate annotation for the property if one
exists
+ * @param validationInfo the validation metadata for the property if
defined
* @return List<Object> a List of objects containing only objects of the
desired type. It is
* not guaranteed to be the same length as the values array passed
in.
*/
@@ -924,14 +837,14 @@
ParameterName propertyName,
String[] values,
Class propertyType,
- Validate validationInfo,
+ ValidationMetadata validationInfo,
List<ValidationError> errors) throws
Exception {
List<Object> returns = new ArrayList<Object>();
// Dig up the type converter
TypeConverter converter = null;
- if (validationInfo != null && validationInfo.converter() !=
TypeConverter.class) {
+ if (validationInfo != null && validationInfo.converter() != null) {
converter = this.configuration.getTypeConverterFactory()
.getInstance(validationInfo.converter(),
bean.getContext().getRequest().getLocale());
}
Modified:
trunk/stripes/src/net/sourceforge/stripes/controller/StripesConstants.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/controller/StripesConstants.java
2006-10-26 01:11:45 UTC (rev 454)
+++ trunk/stripes/src/net/sourceforge/stripes/controller/StripesConstants.java
2006-10-27 11:32:19 UTC (rev 455)
@@ -14,6 +14,11 @@
*/
package net.sourceforge.stripes.controller;
+import net.sourceforge.stripes.util.Literal;
+
+import java.util.Set;
+import java.util.Collections;
+
/**
* Container for constant values that are used across more than one class in
Stripes.
*
@@ -39,6 +44,22 @@
String URL_KEY_EVENT_NAME = "_eventName";
/**
+ * The name of a URL parameter that is used to tell Stripes that a flash
scope exists
+ * for the current request.
+ */
+ String URL_KEY_FLASH_SCOPE_ID = "__fsk";
+
+ /**
+ * An immutable set of URL keys or request parameters that have special
meaning to Stripes and
+ * as a result should not be referenced in binding, validation or other
other places that
+ * work on the full set of request parameters.
+ */
+ Set<String> SPECIAL_URL_KEYS = Collections.unmodifiableSet(
+ Literal.set(StripesConstants.URL_KEY_SOURCE_PAGE,
+ StripesConstants.URL_KEY_FIELDS_PRESENT,
+ StripesConstants.URL_KEY_FLASH_SCOPE_ID,
+ StripesConstants.URL_KEY_EVENT_NAME));
+ /**
* The name under which the ActionBean for a request is stored as a
request attribute before
* forwarding to the JSP.
*/
@@ -64,12 +85,6 @@
String REQ_ATTR_TAG_STACK = "__stripes_tag_stack";
/**
- * The name of a URL parameter that is used to tell Stripes that a flash
scope exists
- * for the current request.
- */
- String URL_KEY_FLASH_SCOPE_ID = "__fsk";
-
- /**
* The name of a request parameter that holds a Map of flash scopes keyed
by the
* hashcode of the request that generated them.
*/
Added:
trunk/stripes/src/net/sourceforge/stripes/validation/ValidationMetadata.java
===================================================================
---
trunk/stripes/src/net/sourceforge/stripes/validation/ValidationMetadata.java
(rev 0)
+++
trunk/stripes/src/net/sourceforge/stripes/validation/ValidationMetadata.java
2006-10-27 11:32:19 UTC (rev 455)
@@ -0,0 +1,216 @@
+/* Copyright 2005-2006 Tim Fennell
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sourceforge.stripes.validation;
+
+import java.util.Set;
+import java.util.HashSet;
+import java.util.regex.Pattern;
+
+/**
+ * <p>Encapsulates the validation metadata for a single property of a single
class. Structure
+ * is purposely very similar to the @Validate annotation. This class is used
internally
+ * to store and manipulate validation metadata, the source of which is often
validation
+ * annotations.</p>
+ *
+ * <p>However, since this class is not an annotation it has the added benefits
of being
+ * able to contain behaviour, being subclassable, and of being able to be
instantiated at
+ * runtime - i.e. it can contain non-static validation information.</p>
+ *
+ * @author Tim Fennell
+ * @since Stripes 1.5
+ */
+public class ValidationMetadata {
+ String property;
+ boolean required;
+ private Set<String> on;
+ private boolean onIsPositive;
+ private boolean ignore;
+ private Integer minlength, maxlength;
+ private Double minvalue, maxvalue;
+ private Pattern mask;
+ private String expression;
+ Class<? extends TypeConverter> converter;
+
+ /**
+ * Constructs a ValidationMetadata object for the specified property.
Further constraints
+ * can be specified by calling individual methods, e.g.
+ * [EMAIL PROTECTED] new
ValidationMetadata("username").minlength(5).maxlength(10);}
+ *
+ * @param property the name of the property to be validated. If the
property is a nested
+ * property then the fully path should be included, e.g. [EMAIL
PROTECTED] user.address.city}
+ */
+ public ValidationMetadata(String property) {
+ this.property = property;
+ }
+
+ /**
+ * Essentially a copy constructor that constructs a ValidationMetadata
object from
+ * an @Validate annotation declared on a property.
+ *
+ * @param validate
+ */
+ public ValidationMetadata(String property, Validate validate) {
+ // Copy over all the simple values
+ this.property = property;
+ required(validate.required());
+ ignore(ignore());
+ if (validate.minlength() != -1) minlength(validate.minlength());
+ if (validate.maxlength() != -1) maxlength(validate.maxlength());
+ if (validate.minvalue() != Double.MIN_VALUE)
minvalue(validate.minvalue());
+ if (validate.maxvalue() != Double.MAX_VALUE)
maxvalue(validate.maxvalue());
+ if (!"".equals(validate.mask())) mask(validate.mask());
+ if (validate.converter() != TypeConverter.class)
converter(validate.converter());
+ if (!"".equals(validate.expression()))
expression(validate.expression());
+ if (validate.on().length > 0) on(validate.on());
+ }
+
+ /** Returns the name of the property this validation metadata represents.
*/
+ public String getProperty() {
+ return this.property;
+ }
+
+ /** Sets the required-ness of this field. True = required, false = not
required. */
+ public ValidationMetadata required(boolean required) {
+ this.required = required;
+ return this;
+ }
+
+ /** Returns true if the field in question is required. */
+ public boolean required() { return this.required; }
+
+ /** Returns true if the field is required when processing the specified
event. */
+ public boolean requiredOn(String event) {
+ return this.required && (
+ (this.on == null) ||
+ (this.onIsPositive && this.on.contains(event)) ||
+ (!this.onIsPositive && !this.on.contains(event))
+ );
+ }
+
+ /** Sets whether or not this field should be ignored during binding and
validation. */
+ public ValidationMetadata ignore(boolean ignore) {
+ this.ignore = ignore;
+ return this;
+ }
+
+ /** Returns true if this field should be ignored in binding and
validation. */
+ public boolean ignore() { return this.ignore; }
+
+ /** Sets the minimum acceptable length for property values. */
+ public ValidationMetadata minlength(Integer minlength) {
+ this.minlength = minlength;
+ return this;
+ }
+
+ /** Returns the minimum acceptable length for values, or null if there is
none. */
+ public Integer minlength() { return this.minlength; }
+
+ /** Sets the maximum acceptable length for property values. */
+ public ValidationMetadata maxlength(Integer maxlength) {
+ this.maxlength = maxlength;
+ return this;
+ }
+
+ /** Returns the maximum acceptable length for values, or null if there is
none. */
+ public Integer maxlength() { return this.maxlength; }
+
+ /** Sets the minimum acceptable <b>value</b> for numeric property values.
*/
+ public ValidationMetadata minvalue(Double minvalue) {
+ this.minvalue = minvalue;
+ return this;
+ }
+
+ /** Returns the minimum acceptable value for numeric properties, or null
if there is none. */
+ public Double minvalue() { return this.minvalue; }
+
+ /** Sets the maximum acceptable <b>value</b> for numeric property values.
*/
+ public ValidationMetadata maxvalue(Double maxvalue) {
+ this.maxvalue = maxvalue;
+ return this;
+ }
+
+ /** Returns the maximum acceptable value for numeric properties, or null
if there is none. */
+ public Double maxvalue() { return this.maxvalue; }
+
+ /** Sets the mask which the String form of the property must match. */
+ public ValidationMetadata mask(String mask) {
+ this.mask = Pattern.compile(mask);
+ return this;
+ }
+
+ /** Returns the mask Pattern property values must match, or null if there
is none. */
+ public Pattern mask() { return this.mask; }
+
+ /** Sets the overridden TypeConveter to use to convert values. */
+ public ValidationMetadata converter(Class<? extends TypeConverter>
converter) {
+ this.converter = converter;
+ return this;
+ }
+
+ /** Returns the overridden TypeConverter if there is one, or null. */
+ public Class<? extends TypeConverter> converter() { return this.converter;
}
+
+ /** Sets the expression that should be used to validate values. */
+ public ValidationMetadata expression(String expression) {
+ this.expression = expression;
+ if (!this.expression.startsWith("${")) this.expression = "${" +
this.expression + "}";
+ return this;
+ }
+
+ /** Returns the overridden TypeConverter if there is one, or null. */
+ public String expression() { return this.expression; }
+
+ /** Sets the set of events for which the field in question is required, if
it is at all. */
+ public ValidationMetadata on(String... on) {
+ if (on.length == 0) {
+ this.on = null;
+ }
+ else {
+ this.on = new HashSet<String>();
+ this.onIsPositive = !(on[0].charAt(0) == '!');
+ for (String s : on) {
+ if (this.onIsPositive) {
+ this.on.add(s);
+ }
+ else {
+ this.on.add(s.substring(1));
+ }
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Overidden toString() that only outputs the constraints that are
specified by
+ * the instance of validation metadata (i.e. omits nulls, defaults etc.)
+ *
+ * @return a human readable string form of the metadata
+ */
+ public String toString() {
+ return "ValidationMetadata{" +
+ (required ? "required=" + required : "") +
+ (ignore ? ", ignore=" + ignore : "" ) +
+ (minlength != null ? ", minlength=" + minlength : "") +
+ (maxlength != null ? ", maxlength=" + maxlength : "") +
+ (minvalue != null ? ", minvalue=" + minvalue : "") +
+ (maxvalue != null ? ", maxvalue=" + maxvalue : "") +
+ (mask != null ? ", mask=" + mask : "" ) +
+ (expression != null ? ", expression='" + expression + '\'' :
"") +
+ (converter != null ? ", converter=" +
converter.getSimpleName() : "") +
+ '}';
+ }
+}
+
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development