| /* Copyright 2004-2005 the original author or authors. |
| * |
| * 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 org.codehaus.groovy.grails.validation; |
| |
| |
| import groovy.lang.MissingPropertyException; |
| import groovy.lang.Range; |
| |
| import java.lang.reflect.Array; |
| import java.text.MessageFormat; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.ResourceBundle; |
| |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.commons.lang.builder.ToStringBuilder; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.commons.validator.EmailValidator; |
| import org.apache.commons.validator.UrlValidator; |
| import org.codehaus.groovy.grails.validation.exceptions.ConstraintException; |
| import org.springframework.validation.Errors; |
| |
| /** |
| * Provides the ability to set contraints against a properties of a class. Constraints can either be |
| * set via the property setters or via the <pre>applyConstraint(String constraintName, Object constrainingValue)</pre> |
| * in combination with a constraint constant. Example: |
| * |
| * <code> |
| * ... |
| * |
| * ConstrainedProperty cp = new ConstrainedProperty(owningClass, propertyName, propertyType); |
| * if(cp.supportsConstraint( ConstrainedProperty.EMAIL_CONSTRAINT ) ) { |
| * cp.applyConstraint( ConstrainedProperty.EMAIL_CONSTRAINT, new Boolean(true) ); |
| * } |
| * </code> |
| * |
| * @author Graeme Rocher |
| * @since 07-Nov-2005 |
| */ |
| public class ConstrainedProperty { |
| |
| public static final String EMAIL_CONSTRAINT = "email"; |
| public static final String BLANK_CONSTRAINT = "blank"; |
| public static final String RANGE_CONSTRAINT = "range"; |
| public static final String IN_LIST_CONSTRAINT = "inList"; |
| public static final String URL_CONSTRAINT = "url"; |
| public static final String MATCHES_CONSTRAINT = "matches"; |
| public static final String LENGTH_CONSTRAINT = "length"; |
| public static final String SIZE_CONSTRAINT = "size"; |
| public static final String MIN_CONSTRAINT = "min"; |
| public static final String MAX_CONSTRAINT = "max"; |
| public static final String MAX_SIZE_CONSTRAINT = "maxSize"; |
| public static final String MIN_SIZE_CONSTRAINT = "minSize"; |
| public static final String MAX_LENGTH_CONSTRAINT = "maxLength"; |
| public static final String MIN_LENGTH_CONSTRAINT = "minLength"; |
| public static final String NOT_EQUAL_CONSTRAINT = "notEqual"; |
| public static final String NULLABLE_CONSTRAINT = "nullable"; |
| |
| protected static final String INVALID_SUFFIX = ".invalid"; |
| protected static Map constraints = new HashMap(); |
| |
| static { |
| constraints.put( EMAIL_CONSTRAINT, EmailConstraint.class ); |
| constraints.put( BLANK_CONSTRAINT, BlankConstraint.class ); |
| constraints.put( RANGE_CONSTRAINT, RangeConstraint.class ); |
| constraints.put( IN_LIST_CONSTRAINT, InListConstraint.class ); |
| constraints.put( URL_CONSTRAINT, UrlConstraint.class ); |
| constraints.put( LENGTH_CONSTRAINT, SizeConstraint.class ); |
| constraints.put( SIZE_CONSTRAINT, SizeConstraint.class ); |
| constraints.put( MATCHES_CONSTRAINT, MatchesConstraint.class ); |
| constraints.put( MIN_CONSTRAINT, MinConstraint.class ); |
| constraints.put( MAX_CONSTRAINT, MaxConstraint.class ); |
| constraints.put( MAX_SIZE_CONSTRAINT, MaxSizeConstraint.class ); |
| constraints.put( MAX_LENGTH_CONSTRAINT, MaxSizeConstraint.class ); |
| constraints.put( MIN_SIZE_CONSTRAINT, MinSizeConstraint.class ); |
| constraints.put( MIN_LENGTH_CONSTRAINT, MinSizeConstraint.class ); |
| constraints.put( NULLABLE_CONSTRAINT, NullableConstraint.class ); |
| constraints.put( NOT_EQUAL_CONSTRAINT, NotEqualConstraint.class ); |
| } |
| |
| protected static final ResourceBundle bundle = ResourceBundle.getBundle( "org.codehaus.groovy.grails.validation.DefaultErrorMessages" ); |
| protected static final Log LOG = LogFactory.getLog(ConstrainedProperty.class); |
| |
| private static final String DEFAULT_BLANK_MESSAGE = bundle.getString( "default.blank.message" ); |
| private static final String DEFAULT_DOESNT_MATCH_MESSAGE = bundle.getString( "default.doesnt.match.message" ); |
| private static final String DEFAULT_INVALID_URL_MESSAGE = bundle.getString( "default.invalid.url.message" ); |
| //private static final String DEFAULT_INVALID_MESSAGE = bundle.getString( "default.invalid.message" ); |
| private static final String DEFAULT_INVALID_EMAIL_MESSAGE = bundle.getString( "default.invalid.email.message" ); |
| private static final String DEFAULT_INVALID_RANGE_MESSAGE = bundle.getString( "default.invalid.range.message" ); |
| private static final String DEFAULT_NOT_IN_LIST_MESSAGE = bundle.getString( "default.not.inlist.message" ); |
| private static final String DEFAULT_INVALID_SIZE_MESSAGE = bundle.getString( "default.invalid.size.message" ); |
| private static final String DEFAULT_INVALID_MAX_MESSAGE = bundle.getString( "default.invalid.max.message" ); |
| private static final String DEFAULT_INVALID_MIN_MESSAGE = bundle.getString( "default.invalid.min.message" ); |
| private static final String DEFAULT_NOT_EQUAL_MESSAGE = bundle.getString( "default.not.equal.message" ); |
| private static final String DEFAULT_INVALID_MAX_LENGTH_MESSAGE = bundle.getString( "default.invalid.max.length.message" ); |
| private static final String DEFAULT_INVALID_MAX_SIZE_MESSAGE = bundle.getString( "default.invalid.max.size.message" ); |
| private static final String DEFAULT_INVALID_MIN_LENGTH_MESSAGE = bundle.getString( "default.invalid.min.length.message" ); |
| private static final String DEFAULT_INVALID_MIN_SIZE_MESSAGE = bundle.getString( "default.invalid.min.size.message" ); |
| private static final String DEFAULT_NULL_MESSAGE = bundle.getString( "default.null.message" ); |
| // move these to subclass |
| |
| protected String propertyName; |
| protected Class propertyType; |
| |
| protected Map appliedConstraints = new HashMap(); |
| protected Class owningClass; |
| |
| /** |
| * |
| * Abstract class for constraints to implement |
| */ |
| abstract protected static class AbstractConstraint implements Constraint { |
| protected String constraintPropertyName; |
| protected Class constraintOwningClass; |
| protected Object constraintParameter; |
| /** |
| * @param constraintOwningClass The constraintOwningClass to set. |
| */ |
| public void setOwningClass(Class constraintOwningClass) { |
| this.constraintOwningClass = constraintOwningClass; |
| } |
| /** |
| * @param constraintPropertyName The constraintPropertyName to set. |
| */ |
| public void setPropertyName(String constraintPropertyName) { |
| this.constraintPropertyName = constraintPropertyName; |
| } |
| /** |
| * @param constraintParameter The constraintParameter to set. |
| */ |
| public void setParameter(Object constraintParameter) { |
| this.constraintParameter = constraintParameter; |
| } |
| public void validate(Object propertyValue, Errors errors) { |
| //ValidationUtils.rejectIfEmpty( errors, constraintPropertyName, constraintPropertyName+".empty" ); |
| if(StringUtils.isBlank(this.constraintPropertyName)) |
| throw new IllegalStateException("Property 'propertyName' must be set on the constraint"); |
| if(constraintOwningClass == null) |
| throw new IllegalStateException("Property 'owningClass' must be set on the constraint"); |
| if(constraintParameter == null) |
| throw new IllegalStateException("Property 'constraintParameter' must be set on the constraint"); |
| |
| processValidate(propertyValue, errors); |
| } |
| public void rejectValue(Errors errors, String code,String defaultMessage) { |
| errors.rejectValue(constraintPropertyName, constraintPropertyName + '.' + code, defaultMessage); |
| } |
| public void rejectValue(Errors errors, String code,Object[] args,String defaultMessage) { |
| errors.rejectValue(constraintPropertyName, constraintPropertyName + '.' + code, args,defaultMessage); |
| } |
| protected abstract void processValidate(Object propertyValue, Errors errors); |
| |
| /* (non-Javadoc) |
| * @see java.lang.Object#toString() |
| */ |
| public String toString() { |
| return new ToStringBuilder(this) |
| .append( constraintParameter ) |
| .toString(); |
| } |
| |
| |
| } |
| |
| /** |
| * A Constraint that validates not equal to something |
| */ |
| static class NotEqualConstraint extends AbstractConstraint { |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| return true; |
| } |
| |
| /** |
| * @return Returns the notEqualTo. |
| */ |
| public Object getNotEqualTo() { |
| return this.constraintParameter; |
| } |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| if(!this.constraintParameter.equals( propertyValue )) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, constraintParameter }; |
| super.rejectValue( errors, NOT_EQUAL_CONSTRAINT,args, MessageFormat.format( DEFAULT_NOT_EQUAL_MESSAGE, args ) ); |
| } |
| } |
| |
| } |
| /** |
| * A Constraint that validates not equal to something |
| */ |
| static class NullableConstraint extends AbstractConstraint { |
| |
| private boolean nullable; |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| return true; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof Boolean)) |
| throw new IllegalArgumentException("Parameter for constraint ["+NULLABLE_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be a boolean value"); |
| |
| this.nullable = ((Boolean)constraintParameter).booleanValue(); |
| super.setParameter(constraintParameter); |
| } |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| if(!nullable && propertyValue == null) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass}; |
| super.rejectValue( errors, NULLABLE_CONSTRAINT,args, MessageFormat.format( DEFAULT_NULL_MESSAGE, args ) ); |
| } |
| } |
| |
| } |
| /** |
| * A Constraint that validates a string is not blank |
| */ |
| static class BlankConstraint extends AbstractConstraint { |
| |
| private boolean blank; |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| if(type == null) |
| return false; |
| |
| return String.class.isAssignableFrom(type); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof Boolean)) |
| throw new IllegalArgumentException("Parameter for constraint ["+BLANK_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be a boolean value"); |
| |
| this.blank = ((Boolean)constraintParameter).booleanValue(); |
| super.setParameter(constraintParameter); |
| } |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| |
| if(!blank) { |
| if(propertyValue instanceof String) { |
| if(StringUtils.isBlank((String)propertyValue)) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass }; |
| super.rejectValue( errors, BLANK_CONSTRAINT,args, MessageFormat.format( DEFAULT_BLANK_MESSAGE, args ) ); |
| } |
| } |
| } |
| } |
| } |
| /** |
| * |
| * A Constraint that validates an email address |
| */ |
| static class EmailConstraint extends AbstractConstraint { |
| |
| private boolean email; |
| |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| if(type == null) |
| return false; |
| |
| return String.class.isAssignableFrom(type); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof Boolean)) |
| throw new IllegalArgumentException("Parameter for constraint ["+EMAIL_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be a boolean value"); |
| |
| this.email = ((Boolean)constraintParameter).booleanValue(); |
| super.setParameter(constraintParameter); |
| } |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| if(email) { |
| EmailValidator emailValidator = EmailValidator.getInstance(); |
| if(!emailValidator.isValid(propertyValue.toString()) ) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue }; |
| super.rejectValue(errors,EMAIL_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_EMAIL_MESSAGE, args )); |
| } |
| } |
| } |
| } |
| |
| /** |
| * |
| * A Constraint that validates a url |
| */ |
| static class UrlConstraint extends AbstractConstraint { |
| |
| private boolean url; |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| if(type == null) |
| return false; |
| |
| return String.class.isAssignableFrom(type); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof Boolean)) |
| throw new IllegalArgumentException("Parameter for constraint ["+URL_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be a boolean value"); |
| |
| this.url = ((Boolean)constraintParameter).booleanValue(); |
| super.setParameter(constraintParameter); |
| } |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| if(url) { |
| UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_ALL_SCHEMES + UrlValidator.ALLOW_2_SLASHES); |
| |
| if(!urlValidator.isValid(propertyValue.toString())) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue }; |
| super.rejectValue(errors,URL_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_URL_MESSAGE, args )); |
| } |
| } |
| } |
| |
| } |
| /** |
| * |
| * A Constraint that validates a range |
| */ |
| static class RangeConstraint extends AbstractConstraint { |
| Range range; |
| /** |
| * @return Returns the range. |
| */ |
| public Range getRange() { |
| return range; |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| if(type == null) |
| return false; |
| |
| return Comparable.class.isAssignableFrom(type) || |
| Number.class.isAssignableFrom(type); |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof Range)) |
| throw new IllegalArgumentException("Parameter for constraint ["+RANGE_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be a of type [groovy.lang.Range]"); |
| |
| this.range = (Range)constraintParameter; |
| super.setParameter(constraintParameter); |
| } |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| if(!this.range.contains(propertyValue)) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, range.getFrom(), range.getTo() }; |
| super.rejectValue(errors,RANGE_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_RANGE_MESSAGE, args )); |
| } |
| } |
| } |
| |
| /** |
| * |
| * A Constraint that implements a maximum value constraint |
| */ |
| static class MaxConstraint extends AbstractConstraint { |
| |
| private Comparable maxValue; |
| |
| /** |
| * @return Returns the maxValue. |
| */ |
| public Comparable getMaxValue() { |
| return maxValue; |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| if(type == null) |
| return false; |
| |
| return Comparable.class.isAssignableFrom(type) || |
| Number.class.isAssignableFrom(type); |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof Comparable)) |
| throw new IllegalArgumentException("Parameter for constraint ["+MAX_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must implement the interface [java.lang.Comparable]"); |
| |
| this.maxValue = (Comparable)constraintParameter; |
| super.setParameter(constraintParameter); |
| } |
| |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| if(maxValue.compareTo((Comparable)propertyValue) > 0) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, maxValue }; |
| super.rejectValue(errors,MAX_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_MAX_MESSAGE, args )); |
| } |
| } |
| } |
| |
| /** |
| * |
| * A Constraint that implements a minimum value constraint |
| */ |
| static class MinConstraint extends AbstractConstraint { |
| |
| private Comparable minValue; |
| |
| |
| /** |
| * @return Returns the minValue. |
| */ |
| public Comparable getMinValue() { |
| return minValue; |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| if(type == null) |
| return false; |
| |
| return Comparable.class.isAssignableFrom(type) || |
| Number.class.isAssignableFrom(type); |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof Comparable)) |
| throw new IllegalArgumentException("Parameter for constraint ["+MIN_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must implement the interface [java.lang.Comparable]"); |
| |
| this.minValue = (Comparable)constraintParameter; |
| super.setParameter(constraintParameter); |
| } |
| |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| if(minValue.compareTo((Comparable)propertyValue) < 0) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, minValue }; |
| super.rejectValue(errors,MIN_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_MIN_MESSAGE, args )); |
| } |
| } |
| } |
| /** |
| * A constraint that validates the property is contained within the supplied list |
| */ |
| static class InListConstraint extends AbstractConstraint { |
| |
| List list; |
| |
| /** |
| * @return Returns the list. |
| */ |
| public List getList() { |
| return list; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| return true; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof List)) |
| throw new IllegalArgumentException("Parameter for constraint ["+IN_LIST_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must implement the interface [java.util.List]"); |
| |
| this.list = (List)constraintParameter; |
| super.setParameter(constraintParameter); |
| } |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| if(!this.list.contains(propertyValue)) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, list }; |
| super.rejectValue(errors,IN_LIST_CONSTRAINT,args,MessageFormat.format( DEFAULT_NOT_IN_LIST_MESSAGE,args )); |
| } |
| } |
| |
| } |
| |
| /** |
| * A constraint that validates the property against a supplied regular expression |
| */ |
| static class MatchesConstraint extends AbstractConstraint { |
| |
| private String regex; |
| |
| /** |
| * @return Returns the regex. |
| */ |
| public String getRegex() { |
| return regex; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| if(type == null) |
| return false; |
| |
| return String.class.isAssignableFrom(type); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof String)) |
| throw new IllegalArgumentException("Parameter for constraint ["+MATCHES_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be of type [java.lang.String]"); |
| |
| this.regex = (String)constraintParameter; |
| super.setParameter(constraintParameter); |
| } |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| if(propertyValue.toString().matches( regex )) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, regex }; |
| super.rejectValue(errors,MATCHES_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_DOESNT_MATCH_MESSAGE, args )); |
| } |
| |
| } |
| |
| } |
| |
| /** |
| * A constraint that validates size of the property, for strings and arrays this is the length, collections |
| * the size and numbers the value |
| */ |
| static class SizeConstraint extends AbstractConstraint { |
| |
| private Range sizeRange; |
| |
| /** |
| * @return Returns the sizeRange. |
| */ |
| public Range getSizeRange() { |
| return sizeRange; |
| } |
| |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| if(type == null) |
| return false; |
| |
| return Comparable.class.isAssignableFrom(type) || |
| Number.class.isAssignableFrom(type) || |
| Collection.class.isAssignableFrom(type) || |
| type.isArray(); |
| } |
| |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof Range)) |
| throw new IllegalArgumentException("Parameter for constraint ["+SIZE_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be a of type [groovy.lang.Range]"); |
| |
| this.sizeRange = (Range)constraintParameter; |
| super.setParameter(constraintParameter); |
| } |
| |
| |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, sizeRange.getFrom(), sizeRange.getTo() }; |
| if(propertyValue.getClass().isArray()) { |
| Integer length = new Integer(Array.getLength( propertyValue )); |
| if(!sizeRange.contains(length)) { |
| super.rejectValue(errors,SIZE_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_SIZE_MESSAGE, args )); |
| } |
| } |
| if(propertyValue instanceof Collection) { |
| if(!sizeRange.contains( new Integer(((Collection)propertyValue).size()) ) ) { |
| super.rejectValue(errors,SIZE_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_SIZE_MESSAGE, args )); |
| } |
| } |
| else if(propertyValue instanceof Number) { |
| if(!sizeRange.contains(propertyValue)) { |
| super.rejectValue(errors,SIZE_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_SIZE_MESSAGE, args )); |
| } |
| } |
| else if(propertyValue instanceof String) { |
| if(!sizeRange.contains( new Integer(((String)propertyValue ).length()))) { |
| super.rejectValue(errors,SIZE_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_SIZE_MESSAGE, args )); |
| } |
| } |
| } |
| } |
| |
| /** |
| * A constraint that validates maximum size of the property, for strings and arrays this is the length, collections |
| * the size and numbers the value |
| */ |
| static class MaxSizeConstraint extends AbstractConstraint { |
| |
| private int maxSize; |
| |
| /** |
| * @return Returns the maxSize. |
| */ |
| public int getMaxSize() { |
| return maxSize; |
| } |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof Integer)) |
| throw new IllegalArgumentException("Parameter for constraint ["+MAX_SIZE_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be a of type [java.lang.Integer]"); |
| |
| this.maxSize = ((Integer)constraintParameter).intValue(); |
| super.setParameter(constraintParameter); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| if(type == null) |
| return false; |
| |
| return Comparable.class.isAssignableFrom(type) || |
| Number.class.isAssignableFrom(type) || |
| Collection.class.isAssignableFrom(type) || |
| type.isArray(); |
| } |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, new Integer(maxSize) }; |
| if(propertyValue.getClass().isArray()) { |
| int length = Array.getLength( propertyValue ); |
| if(length > maxSize) { |
| super.rejectValue(errors,MAX_LENGTH_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_MAX_LENGTH_MESSAGE, args )); |
| } |
| } |
| if(propertyValue instanceof Collection) { |
| if( ((Collection)propertyValue).size() > maxSize ) { |
| super.rejectValue(errors,MAX_SIZE_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_MAX_SIZE_MESSAGE, args )); |
| } |
| } |
| else if(propertyValue instanceof Number) { |
| int numberSize = ((Number)propertyValue).intValue(); |
| if( numberSize > maxSize ) { |
| super.rejectValue(errors,MAX_SIZE_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_MAX_SIZE_MESSAGE, args )); |
| } |
| } |
| else if(propertyValue instanceof String) { |
| if(((String)propertyValue ).length() > maxSize) { |
| super.rejectValue(errors,MAX_LENGTH_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_MAX_LENGTH_MESSAGE, args )); |
| } |
| } |
| } |
| } |
| |
| /** |
| * A constraint that validates minimum size or length of the property, for strings and arrays this is the length, collections |
| * the size and numbers the value |
| */ |
| static class MinSizeConstraint extends AbstractConstraint { |
| |
| private int minSize; |
| |
| |
| /** |
| * @return Returns the minSize. |
| */ |
| public int getMinSize() { |
| return minSize; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) |
| */ |
| public void setParameter(Object constraintParameter) { |
| if(!(constraintParameter instanceof Integer)) |
| throw new IllegalArgumentException("Parameter for constraint ["+MIN_SIZE_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be a of type [java.lang.Integer]"); |
| |
| this.minSize = ((Integer)constraintParameter).intValue(); |
| super.setParameter(constraintParameter); |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.codehaus.groovy.grails.validation.Constraint#supports(java.lang.Class) |
| */ |
| public boolean supports(Class type) { |
| if(type == null) |
| return false; |
| |
| return Comparable.class.isAssignableFrom(type) || |
| Number.class.isAssignableFrom(type) || |
| Collection.class.isAssignableFrom(type) || |
| type.isArray(); |
| } |
| |
| protected void processValidate(Object propertyValue, Errors errors) { |
| Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, new Integer(minSize) }; |
| if(propertyValue.getClass().isArray()) { |
| int length = Array.getLength( propertyValue ); |
| if(length < minSize) { |
| super.rejectValue(errors,MIN_LENGTH_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_MIN_LENGTH_MESSAGE, args )); |
| } |
| } |
| if(propertyValue instanceof Collection) { |
| if( ((Collection)propertyValue).size() < minSize ) { |
| super.rejectValue(errors,MIN_SIZE_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_MIN_SIZE_MESSAGE, args )); |
| } |
| } |
| else if(propertyValue instanceof Number) { |
| int numberSize = ((Number)propertyValue).intValue(); |
| if( numberSize < minSize ) { |
| super.rejectValue(errors,MIN_SIZE_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_MIN_SIZE_MESSAGE, args )); |
| } |
| } |
| else if(propertyValue instanceof String) { |
| if(((String)propertyValue ).length() < minSize) { |
| super.rejectValue(errors,MIN_LENGTH_CONSTRAINT + INVALID_SUFFIX,args,MessageFormat.format( DEFAULT_INVALID_MIN_LENGTH_MESSAGE, args )); |
| } |
| } |
| } |
| } |
| |
| public ConstrainedProperty(Class clazz,String propertyName, Class propertyType) { |
| super(); |
| this.owningClass = clazz; |
| this.propertyName = propertyName; |
| this.propertyType = propertyType; |
| } |
| |
| |
| /** |
| * @return Returns the appliedConstraints. |
| */ |
| public Collection getAppliedConstraints() { |
| return appliedConstraints.values(); |
| } |
| |
| /** |
| * @return Returns the propertyType. |
| */ |
| public Class getPropertyType() { |
| return propertyType; |
| } |
| |
| |
| /** |
| * @return Returns the max. |
| */ |
| public Comparable getMax() { |
| MaxConstraint c = (MaxConstraint)this.appliedConstraints.get( MAX_CONSTRAINT ); |
| if(c == null) { |
| Range r = getRange(); |
| if(r == null) { |
| return null; |
| } |
| else { |
| return r.getTo(); |
| } |
| } |
| return c.getMaxValue(); |
| } |
| |
| |
| /** |
| * @param max The max to set. |
| */ |
| public void setMax(Comparable max) { |
| if(!propertyType.equals( max.getClass() )) { |
| throw new MissingPropertyException(MAX_CONSTRAINT,propertyType); |
| } |
| if(max == null) { |
| this.appliedConstraints.remove( MAX_CONSTRAINT ); |
| return; |
| } |
| Range r = getRange(); |
| if(r != null) { |
| LOG.warn("Range constraint already set ignoring constraint ["+MAX_CONSTRAINT+"] for value ["+max+"]"); |
| return; |
| } |
| Constraint c = (MaxConstraint)this.appliedConstraints.get( MAX_CONSTRAINT ); |
| if(c != null) { |
| c.setParameter(max); |
| } |
| else { |
| c = new MaxConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(max); |
| this.appliedConstraints.put( MAX_CONSTRAINT, c ); |
| } |
| } |
| |
| |
| /** |
| * @return Returns the min. |
| */ |
| public Comparable getMin() { |
| MinConstraint c = (MinConstraint)this.appliedConstraints.get( MIN_CONSTRAINT ); |
| if(c == null) { |
| Range r = getRange(); |
| if(r == null) { |
| return null; |
| } |
| else { |
| return r.getFrom(); |
| } |
| } |
| return c.getMinValue(); |
| } |
| |
| |
| /** |
| * @param min The min to set. |
| */ |
| public void setMin(Comparable min) { |
| if(!propertyType.equals( min.getClass() )) { |
| throw new MissingPropertyException(MIN_CONSTRAINT,propertyType); |
| } |
| if(min == null) { |
| this.appliedConstraints.remove( MIN_CONSTRAINT ); |
| return; |
| } |
| Range r = getRange(); |
| if(r != null) { |
| LOG.warn("Range constraint already set ignoring constraint ["+MIN_CONSTRAINT+"] for value ["+min+"]"); |
| return; |
| } |
| Constraint c = (MinConstraint)this.appliedConstraints.get( MIN_CONSTRAINT ); |
| if(c != null) { |
| c.setParameter(min); |
| } |
| else { |
| c = new MinConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(min); |
| this.appliedConstraints.put( MIN_CONSTRAINT, c ); |
| } |
| } |
| |
| |
| /** |
| * @return Returns the inList. |
| */ |
| public List getInList() { |
| InListConstraint c = (InListConstraint)this.appliedConstraints.get( IN_LIST_CONSTRAINT ); |
| if(c == null) |
| return null; |
| |
| return c.getList(); |
| } |
| |
| /** |
| * @param inList The inList to set. |
| */ |
| public void setInList(List inList) { |
| Constraint c = (Constraint)this.appliedConstraints.get( IN_LIST_CONSTRAINT ); |
| if(inList == null) { |
| this.appliedConstraints.remove( IN_LIST_CONSTRAINT ); |
| } |
| else { |
| if(c != null) { |
| c.setParameter(inList); |
| } |
| else { |
| c = new InListConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(inList); |
| this.appliedConstraints.put( IN_LIST_CONSTRAINT, c ); |
| } |
| } |
| } |
| |
| /** |
| * @return Returns the range. |
| */ |
| public Range getRange() { |
| RangeConstraint c = (RangeConstraint)this.appliedConstraints.get( RANGE_CONSTRAINT ); |
| if(c == null) |
| return null; |
| |
| return c.getRange(); |
| } |
| |
| /** |
| * @param range The range to set. |
| */ |
| public void setRange(Range range) { |
| if(this.appliedConstraints.containsKey( MAX_CONSTRAINT )) { |
| LOG.warn("Setting range constraint on property ["+propertyName+"] of class ["+owningClass+"] forced removal of max constraint"); |
| this.appliedConstraints.remove( MAX_CONSTRAINT ); |
| } |
| if(this.appliedConstraints.containsKey( MIN_CONSTRAINT )) { |
| LOG.warn("Setting range constraint on property ["+propertyName+"] of class ["+owningClass+"] forced removal of min constraint"); |
| this.appliedConstraints.remove( MIN_CONSTRAINT ); |
| } |
| if(range == null) { |
| this.appliedConstraints.remove( RANGE_CONSTRAINT ); |
| } |
| else { |
| Constraint c = (Constraint)this.appliedConstraints.get(RANGE_CONSTRAINT); |
| if(c != null) { |
| c.setParameter(range); |
| } |
| else { |
| c = new RangeConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(range); |
| |
| this.appliedConstraints.put( RANGE_CONSTRAINT,c); |
| } |
| } |
| } |
| |
| /** |
| * @return Returns the length. |
| */ |
| public Range getLength() { |
| if(!String.class.isInstance( propertyType ) || !propertyType.isArray()) { |
| throw new MissingPropertyException("Length constraint only applies to a String or Array property",LENGTH_CONSTRAINT,owningClass); |
| } |
| SizeConstraint c = (SizeConstraint)this.appliedConstraints.get( LENGTH_CONSTRAINT ); |
| if(c == null) |
| return null; |
| |
| return c.getSizeRange(); |
| } |
| |
| /** |
| * @param length The length to set. |
| */ |
| public void setLength(Range length) { |
| if(!String.class.isInstance( propertyType ) || !propertyType.isArray()) { |
| throw new MissingPropertyException("Length constraint can only be applied to a String or Array property",LENGTH_CONSTRAINT,owningClass); |
| } |
| Constraint c = (Constraint)this.appliedConstraints.get( LENGTH_CONSTRAINT ); |
| if(length == null) { |
| this.appliedConstraints.remove( LENGTH_CONSTRAINT ); |
| } |
| else { |
| if(c != null) { |
| c.setParameter(length); |
| } |
| else { |
| c = new SizeConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(length); |
| this.appliedConstraints.put( LENGTH_CONSTRAINT, c ); |
| } |
| } |
| } |
| |
| |
| /** |
| * @return Returns the size. |
| */ |
| public Range getSize() { |
| SizeConstraint c = (SizeConstraint)this.appliedConstraints.get( SIZE_CONSTRAINT ); |
| if(c == null) |
| return null; |
| |
| return c.getSizeRange(); |
| } |
| |
| |
| /** |
| * @param size The size to set. |
| */ |
| public void setSize(Range size) { |
| Constraint c = (Constraint)this.appliedConstraints.get( SIZE_CONSTRAINT ); |
| if(size == null) { |
| this.appliedConstraints.remove( SIZE_CONSTRAINT ); |
| } |
| else { |
| if(c != null) { |
| c.setParameter(size); |
| } |
| else { |
| c = new SizeConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(size); |
| this.appliedConstraints.put( SIZE_CONSTRAINT, c ); |
| } |
| } |
| } |
| |
| |
| /** |
| * @return Returns the blank. |
| */ |
| public boolean isBlank() { |
| return this.appliedConstraints.containsKey(BLANK_CONSTRAINT); |
| } |
| |
| /** |
| * @param blank The blank to set. |
| */ |
| public void setBlank(boolean blank) { |
| if(!String.class.isInstance( propertyType )) { |
| throw new MissingPropertyException("Blank constraint can only be applied to a String property",BLANK_CONSTRAINT,owningClass); |
| } |
| |
| Constraint c = (Constraint)this.appliedConstraints.get( BLANK_CONSTRAINT ); |
| if(c != null) { |
| c.setParameter( new Boolean(blank) ); |
| } |
| else { |
| c = new BlankConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(new Boolean(blank)); |
| this.appliedConstraints.put( BLANK_CONSTRAINT,c ); |
| } |
| |
| } |
| |
| |
| |
| /** |
| * @return Returns the email. |
| */ |
| public boolean isEmail() { |
| if(!String.class.isInstance( propertyType )) { |
| throw new MissingPropertyException("Email constraint only applies to a String property",EMAIL_CONSTRAINT,owningClass); |
| } |
| |
| return this.appliedConstraints.containsKey( EMAIL_CONSTRAINT ); |
| } |
| |
| /** |
| * @param email The email to set. |
| */ |
| public void setEmail(boolean email) { |
| if(!String.class.isInstance( propertyType )) { |
| throw new MissingPropertyException("Email constraint can only be applied to a String property",EMAIL_CONSTRAINT,owningClass); |
| } |
| |
| Constraint c = (Constraint)this.appliedConstraints.get( EMAIL_CONSTRAINT ); |
| if(email) { |
| if(c != null) { |
| c.setParameter( new Boolean(email) ); |
| } |
| else { |
| c = new EmailConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(new Boolean(email)); |
| this.appliedConstraints.put( EMAIL_CONSTRAINT,c ); |
| } |
| } |
| else { |
| if(c != null) { |
| this.appliedConstraints.remove( EMAIL_CONSTRAINT ); |
| } |
| } |
| |
| } |
| |
| |
| |
| /** |
| * @return Returns the matches. |
| */ |
| public String getMatches() { |
| if(!String.class.isInstance( propertyType )) { |
| throw new MissingPropertyException("Matches constraint only applies to a String property",MATCHES_CONSTRAINT,owningClass); |
| } |
| MatchesConstraint c = (MatchesConstraint)this.appliedConstraints.get( MATCHES_CONSTRAINT ); |
| if(c == null) |
| return null; |
| |
| return c.getRegex(); |
| } |
| |
| /** |
| * @param matches The matches to set. |
| */ |
| public void setMatches(String regex) { |
| if(!String.class.isInstance( propertyType )) { |
| throw new MissingPropertyException("Matches constraint can only be applied to a String property",MATCHES_CONSTRAINT,owningClass); |
| } |
| |
| Constraint c = (Constraint)this.appliedConstraints.get( MATCHES_CONSTRAINT ); |
| if(regex == null) { |
| this.appliedConstraints.remove( MATCHES_CONSTRAINT ); |
| } |
| else { |
| if(c != null) { |
| c.setParameter( regex ); |
| } |
| else { |
| c = new MatchesConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(regex); |
| this.appliedConstraints.put( MATCHES_CONSTRAINT,c ); |
| } |
| } |
| } |
| |
| |
| /** |
| * @return Returns the maxLength. |
| */ |
| public int getMaxLength() { |
| MaxSizeConstraint c = (MaxSizeConstraint)this.appliedConstraints.get( MAX_LENGTH_CONSTRAINT ); |
| if(c == null) |
| return Integer.MAX_VALUE; |
| |
| return c.getMaxSize(); |
| } |
| |
| /** |
| * @param maxLength The maxLength to set. |
| */ |
| public void setMaxLength(int maxLength) { |
| Constraint c = (MaxSizeConstraint)this.appliedConstraints.get( MAX_LENGTH_CONSTRAINT ); |
| if( c != null) { |
| c.setParameter( new Integer(maxLength)); |
| } |
| else { |
| c = new MaxSizeConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(new Integer(maxLength)); |
| this.appliedConstraints.put( MAX_LENGTH_CONSTRAINT,c ); |
| } |
| } |
| |
| |
| |
| |
| /** |
| * @return Returns the minLength. |
| */ |
| public int getMinLength() { |
| MinSizeConstraint c = (MinSizeConstraint)this.appliedConstraints.get( MIN_LENGTH_CONSTRAINT ); |
| if(c == null) |
| return 0; |
| |
| return c.getMinSize(); |
| } |
| |
| |
| /** |
| * @param minLength The minLength to set. |
| */ |
| public void setMinLength(int minLength) { |
| Constraint c = (MinSizeConstraint)this.appliedConstraints.get( MIN_LENGTH_CONSTRAINT ); |
| if( c != null) { |
| c.setParameter( new Integer(minLength)); |
| } |
| else { |
| c = new MinSizeConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(new Integer(minLength)); |
| this.appliedConstraints.put( MIN_LENGTH_CONSTRAINT,c ); |
| } |
| } |
| |
| |
| |
| |
| /** |
| * @return Returns the notEqual. |
| */ |
| public Object getNotEqual() { |
| NotEqualConstraint c = (NotEqualConstraint)this.appliedConstraints.get( NOT_EQUAL_CONSTRAINT ); |
| if(c == null) |
| return null; |
| |
| return c.getNotEqualTo(); |
| } |
| |
| /** |
| * @return Returns the maxSize. |
| */ |
| public int getMaxSize() { |
| MaxSizeConstraint c = (MaxSizeConstraint)this.appliedConstraints.get( MAX_SIZE_CONSTRAINT ); |
| if(c == null) |
| return Integer.MAX_VALUE; |
| |
| return c.getMaxSize(); |
| } |
| |
| /** |
| * @param maxLength The mazSize to set. |
| */ |
| public void setMaxSize(int mazSize) { |
| Constraint c = (MaxSizeConstraint)this.appliedConstraints.get( MAX_SIZE_CONSTRAINT ); |
| if( c != null) { |
| c.setParameter( new Integer(mazSize)); |
| } |
| else { |
| c = new MaxSizeConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(new Integer(mazSize)); |
| this.appliedConstraints.put( MAX_SIZE_CONSTRAINT,c ); |
| } |
| } |
| |
| |
| |
| |
| /** |
| * @return Returns the minSize. |
| */ |
| public int getMinSize() { |
| MinSizeConstraint c = (MinSizeConstraint)this.appliedConstraints.get( MIN_SIZE_CONSTRAINT ); |
| if(c == null) |
| return Integer.MIN_VALUE; |
| |
| return c.getMinSize(); |
| } |
| |
| |
| /** |
| * @param minLength The minLength to set. |
| */ |
| public void setMinSize(int minSize) { |
| Constraint c = (MinSizeConstraint)this.appliedConstraints.get( MIN_SIZE_CONSTRAINT ); |
| if( c != null) { |
| c.setParameter( new Integer(minSize)); |
| } |
| else { |
| c = new MinSizeConstraint(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter(new Integer(minSize)); |
| this.appliedConstraints.put( MIN_SIZE_CONSTRAINT,c ); |
| } |
| } |
| /** |
| * @param notEqual The notEqual to set. |
| */ |
| public void setNotEqual(Object notEqual) { |
| if(notEqual == null) { |
| this.appliedConstraints.remove( NOT_EQUAL_CONSTRAINT ); |
| } |
| else { |
| Constraint c = new NotEqualConstraint(); |
| c.setOwningClass(owningClass); |
| c.setPropertyName(propertyName); |
| c.setParameter(notEqual); |
| this.appliedConstraints.put( NOT_EQUAL_CONSTRAINT, c ); |
| } |
| } |
| |
| |
| |
| /** |
| * @return Returns the nullable. |
| */ |
| public boolean isNullable() { |
| return this.appliedConstraints.containsKey(NULLABLE_CONSTRAINT); |
| } |
| |
| |
| /** |
| * @param nullable The nullable to set. |
| */ |
| public void setNullable(boolean nullable) { |
| if(nullable) { |
| this.appliedConstraints.remove(NULLABLE_CONSTRAINT); |
| } |
| else { |
| Constraint c = new NullableConstraint(); |
| c.setOwningClass(owningClass); |
| c.setPropertyName(propertyName); |
| c.setParameter(new Boolean(nullable)); |
| this.appliedConstraints.put( NULLABLE_CONSTRAINT, c ); |
| } |
| } |
| |
| |
| /** |
| * @return Returns the propertyName. |
| */ |
| public String getPropertyName() { |
| return propertyName; |
| } |
| |
| /** |
| * @param propertyName The propertyName to set. |
| */ |
| public void setPropertyName(String propertyName) { |
| this.propertyName = propertyName; |
| } |
| |
| |
| /** |
| * @return Returns the url. |
| */ |
| public boolean isUrl() { |
| if(!String.class.isInstance( propertyType )) { |
| throw new MissingPropertyException("URL constraint can only be applied to a String property",URL_CONSTRAINT,owningClass); |
| } |
| return this.appliedConstraints.containsKey( URL_CONSTRAINT ); |
| } |
| |
| /** |
| * @param url The url to set. |
| */ |
| public void setUrl(boolean url) { |
| if(!String.class.isInstance( propertyType )) { |
| throw new MissingPropertyException("URL constraint can only be applied to a String property",URL_CONSTRAINT,owningClass); |
| } |
| Constraint c = (Constraint)this.appliedConstraints.get( URL_CONSTRAINT ); |
| if(url) { |
| if(c != null) { |
| c.setParameter(new Boolean(url)); |
| } |
| else { |
| c = new UrlConstraint(); |
| c.setOwningClass(owningClass); |
| c.setPropertyName(propertyName); |
| c.setParameter(new Boolean(url)); |
| this.appliedConstraints.put( URL_CONSTRAINT, c ); |
| } |
| } |
| else { |
| if(c != null) { |
| this.appliedConstraints.remove( URL_CONSTRAINT ); |
| } |
| } |
| } |
| |
| /** |
| * Validate this constrainted property against specified property value |
| * |
| * @param propertyValue |
| * @param errors |
| */ |
| public void validate(Object propertyValue, Errors errors) { |
| |
| for (Iterator i = this.appliedConstraints.values().iterator(); i.hasNext();) { |
| Constraint c = (Constraint) i.next(); |
| c.validate( propertyValue, errors); |
| } |
| } |
| |
| /** |
| * Checks with this ConstraintedProperty instance supports applying the specified constraint |
| * |
| * @param constraintName The name of the constraint |
| * @return True if the constraint is supported |
| */ |
| public boolean supportsContraint(String constraintName) { |
| if(!constraints.containsKey(constraintName)) |
| return false; |
| |
| Class constraintClass = (Class)constraints.get(constraintName); |
| try { |
| Constraint c = (Constraint)constraintClass.newInstance(); |
| return c.supports(propertyType); |
| |
| } catch (Exception e) { |
| LOG.error("Exception thrown instantiating constraint ["+constraintName+"] to class ["+owningClass+"]", e); |
| throw new ConstraintException("Exception thrown instantiating constraint ["+constraintName+"] to class ["+owningClass+"]"); |
| } |
| } |
| |
| /** |
| * Applies a constraint for the specified name and consraint value |
| * |
| * @param constraintName The name of the constraint |
| * @param constrainingValue The constraining value |
| * |
| * @throws ConstraintException Thrown when the specified constraint is not supported by this ConstrainedProperty. Use <code>supportsContraint(String constraintName)</code> to check before calling |
| */ |
| public void applyConstraint(String constraintName, Object constrainingValue) { |
| |
| if(constraints.containsKey(constraintName)) { |
| if(constrainingValue == null) { |
| this.appliedConstraints.remove(constraintName); |
| } |
| else { |
| Class constraintClass = (Class)constraints.get(constraintName); |
| try { |
| Constraint c = (Constraint)constraintClass.newInstance(); |
| c.setOwningClass(this.owningClass); |
| c.setPropertyName(this.propertyName); |
| c.setParameter( constrainingValue ); |
| this.appliedConstraints.put( constraintName, c ); |
| } catch (Exception e) { |
| LOG.error("Exception thrown applying constraint ["+constraintName+"] to class ["+owningClass+"] for value ["+constrainingValue+"]: " + e.getMessage(), e); |
| throw new ConstraintException("Exception thrown applying constraint ["+constraintName+"] to class ["+owningClass+"] for value ["+constrainingValue+"]: " + e.getMessage()); |
| } |
| } |
| } |
| else { |
| throw new ConstraintException("Constraint ["+constraintName+"] is not supported for property ["+propertyName+"] of class ["+owningClass+"] with type ["+propertyType+"]"); |
| } |
| |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see java.lang.Object#toString() |
| */ |
| public String toString() { |
| return new ToStringBuilder(this) |
| .append( this.owningClass ) |
| .append( this.propertyName ) |
| .append( this.propertyType ) |
| .append( this.appliedConstraints ) |
| .toString(); |
| } |
| |
| |
| } |