001 /*
002 * Copyright 2002-2006 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016 package org.springframework.richclient.samples.simple.domain;
017
018 import java.util.Date;
019
020 import org.springframework.rules.constraint.Constraint;
021 import org.springframework.rules.Rules;
022 import org.springframework.rules.support.DefaultRulesSource;
023
024 /**
025 * This class is a source for validation rules associated with the domain objects in this application. This clas is
026 * wired into application via the application context configuration like this:
027 *
028 * <pre>
029 * <bean id="rulesSource"
030 * class="org.springframework.richclient.samples.simple.domain.SimpleValidationRulesSource"/>
031 * </pre>
032 *
033 * With this configuration, validating forms will interrogate the rules source for rules that apply to the class of a
034 * form object (in this case, that's objects of type {@link Contact}.
035 * @author Larry Streepy
036 */
037 public class SimpleValidationRulesSource extends DefaultRulesSource {
038
039 /**
040 * Basic name validator. Note that the "alphabeticConstraint" argument is a message key used to locate the message
041 * to display when this validator fails.
042 */
043 private final Constraint NAME_CONSTRAINT = all(new Constraint[] { required(), minLength(2),
044 regexp("[-'.a-zA-Z ]*", "alphabeticConstraint") });
045
046 /** Zipcode validator, allows NNNNN or NNNNN-NNNN */
047 private final Constraint ZIPCODE_CONSTRAINT = all(new Constraint[] { required(), minLength(5), maxLength(10),
048 regexp("[0-9]{5}(-[0-9]{4})?", "zipcodeConstraint") });
049
050 /** Email validator, simply tests for x@y, wrap in ()? so it is optional */
051 private final Constraint EMAIL_CONSTRAINT = all(new Constraint[] { regexp("([-a-zA-Z0-9.]+@[-a-zA-Z0-9.]+)?",
052 "emailConstraint") });
053
054 /** Phone number validator, must be 123-456-7890, wrap in ()? so it is optional */
055 private final Constraint PHONE_CONSTRAINT = all(new Constraint[] { regexp("([0-9]{3}-[0-9]{3}-[0-9]{4})?",
056 "phoneConstraint") });
057
058 /**
059 * Construct the rules source. Just add all the rules for each class that will be validated.
060 */
061 public SimpleValidationRulesSource() {
062 super();
063
064 // Add the rules specific to the object types we manage
065 addRules(createContactRules());
066 }
067
068 /**
069 * Construct the rules that are used to validate a Contact domain object.
070 * @return validation rules
071 * @see Rules
072 */
073 private Rules createContactRules() {
074 // Construct a Rules object that contains all the constraints we need to apply
075 // to our domain object. The Rules class offers a lot of convenience methods
076 // for creating constraints on named properties.
077
078 return new Rules(Contact.class) {
079 protected void initRules() {
080 add("firstName", NAME_CONSTRAINT);
081 add("lastName", NAME_CONSTRAINT);
082 add(not(eqProperty("firstName", "lastName")));
083
084 // If a DOB is specified, it must be in the past
085 add("dateOfBirth", lt(new Date()));
086
087 add("emailAddress", EMAIL_CONSTRAINT);
088 add("homePhone", PHONE_CONSTRAINT);
089 add("workPhone", PHONE_CONSTRAINT);
090
091 add("contactType", required());
092
093 // Note that you can define constraints on nested properties.
094 // This is useful when the nested object is not displayed in
095 // a form of its own.
096 add("address.address1", required());
097 add("address.city", required());
098 add("address.state", required());
099 add("address.zip", ZIPCODE_CONSTRAINT);
100
101 add("memo", required());
102 }
103 };
104 }
105 }