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 }