001: /*
002: * Copyright (c) 2002-2007 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.xwork.validator;
006:
007: /**
008: * <!-- START SNIPPET: validatorFlavours -->
009: * <p>The validators supplied by the Xwork distribution (and any validators you
010: * might write yourself) come in two different flavors:</p>
011: *
012: * <ol>
013: * <li> Plain Validators / Non-Field validators </li>
014: * <li> FieldValidators </li>
015: * </ol>
016: *
017: * <p>Plain Validators (such as the ExpressionValidator) perform validation checks
018: * that are not inherently tied to a single specified field. When you declare a
019: * plain Validator in your -validation.xml file you do not associate a fieldname
020: * attribute with it. (You should avoid using plain Validators within the
021: * <field-validator> syntax described below.)</p>
022: *
023: * <p>FieldValidators (such as the EmailValidator) are designed to perform
024: * validation checks on a single field. They require that you specify a fieldname
025: * attribute in your -validation.xml file. There are two different (but equivalent)
026: * XML syntaxes you can use to declare FieldValidators (see "<validator> vs.
027: * <field-Validator> syntax" below).</p>
028: *
029: * <p>There are two places where the differences between the two validator flavors
030: * are important to keep in mind:</p>
031: *
032: * <ol>
033: * <li> when choosing the xml syntax used for declaring a validator
034: * (either <validator> or <field-validator>)</li>
035: * <li> when using the short-circuit capability</li>
036: * </ol>
037: *
038: * <p><b>NOTE:</b>Note that you do not declare what "flavor" of validator you are
039: * using in your -validation.xml file, you just declare the name of the validator
040: * to use and WebWork will know whether it's a "plain Validator" or a "FieldValidator"
041: * by looking at the validation class that the validator's programmer chose
042: * to implement.</p>
043: * <!-- END SNIPPET: validatorFlavours -->
044: *
045: *
046: *
047: *
048: * <!-- START SNIPPET: validationRules -->
049: * <p>To define validation rules for an Action, create a file named ActionName-validation.xml
050: * in the same package as the Action. You may also create alias-specific validation rules which
051: * add to the default validation rules defined in ActionName-validation.xml by creating
052: * another file in the same directory named ActionName-aliasName-validation.xml. In both
053: * cases, ActionName is the name of the Action class, and aliasName is the name of the
054: * Action alias defined in the xwork.xml configuration for the Action.</p>
055: *
056: * <p>The framework will also search up the inheritance tree of the Action to
057: * find validation rules for directly implemented interfaces and parent classes of the Action.
058: * This is particularly powerful when combined with ModelDriven Actions and the VisitorFieldValidator.
059: * Here's an example of how validation rules are discovered. Given the following class structure:</p>
060: *
061: * <ul>
062: * <li>interface Animal;</li>
063: * <li>interface Quadraped extends Animal;</li>
064: * <li>class AnimalImpl implements Animal;</li>
065: * <li>class QuadrapedImpl extends AnimalImpl implements Quadraped;</li>
066: * <li>class Dog extends QuadrapedImpl;</li>
067: * </ul>
068: *
069: * <p>The framework method will look for the following config files if Dog is to be validated:</p>
070: *
071: * <ul>
072: * <li>Animal</li>
073: * <li>Animal-aliasname</li>
074: * <li>AnimalImpl</li>
075: * <li>AnimalImpl-aliasname</li>
076: * <li>Quadraped</li>
077: * <li>Quadraped-aliasname</li>
078: * <li>QuadrapedImpl</li>
079: * <li>QuadrapedImpl-aliasname</li>
080: * <li>Dog</li>
081: * <li>Dog-aliasname</li>
082: * </ul>
083: *
084: * <p>While this process is similar to what the XW:Localization framework does
085: * when finding messages, there are some subtle differences. The most important
086: * difference is that validation rules are discovered from the parent downwards.
087: * </p>
088: *
089: * <p><b>NOTE:</b>Child's *-validation.xml will override parent's *-validation.xml
090: * according to the class hierarchi defined above.</p>
091: * <!-- END SNIPPET: validationRules -->
092: *
093: *
094: * <!-- START SNIPPET: validatorVsFieldValidators1 -->
095: * <p>There are two ways you can define validators in your -validation.xml file:</p>
096: * <ol>
097: * <li> <validator> </li>
098: * <li> <field-validator> </li>
099: * </ol>
100: * <p>Keep the following in mind when using either syntax:</p>
101: *
102: * <p><b>Non-Field-Validator</b>
103: * The <validator> element allows you to declare both types of validators
104: * (either a plain Validator a field-specific FieldValidator).</p>
105: * <!-- END SNIPPET: validatorVsFieldValidators1 -->
106: *
107: *<pre>
108: * <!-- START SNIPPET: nonFieldValidatorUsingValidatorSyntax -->
109: * <!-- Declaring a plain Validator using the <validator> syntax: -->
110: *
111: * <validator type="expression>
112: * <param name="expression">foo gt bar</param>
113: * <message>foo must be great than bar.</message>
114: * </validator>
115: * <!-- END SNIPPET: nonFieldValidatorUsingValidatorSyntax -->
116: * </pre>
117: *
118: * <pre>
119: * <!-- START SNIPPET: fieldValidatorUsingValidatorSyntax -->
120: * <!-- Declaring a field validator using the <validator> syntax; -->
121: *
122: * <validator type="required">
123: * <param name="fieldName">bar</param>
124: * <message>You must enter a value for bar.</message>
125: * </validator>
126: * <!-- END SNIPPET: fieldValidatorUsingValidatorSyntax -->
127: * </pre>
128: *
129: *
130: * <!-- START SNIPPET: validatorVsFieldValidators2 -->
131: * <p><b>field-validator</b>
132: * The <field-validator> elements are basically the same as the <validator> elements
133: * except that they inherit the fieldName attribute from the enclosing <field> element.
134: * FieldValidators defined within a <field-validator> element will have their fieldName
135: * automatically filled with the value of the parent <field> element's fieldName
136: * attribute. The reason for this structure is to conveniently group the validators
137: * for a particular field under one element, otherwise the fieldName attribute
138: * would have to be repeated, over and over, for each individual <validator>.</p>
139: *
140: * <p><b>HINT:</b>
141: * It is always better to defined field-validator inside a <field> tag instead of
142: * using a <validator> tag and supplying fieldName as its param as the xml code itself
143: * is clearer (grouping of field is clearer)</p>
144: *
145: * <p><b>NOTE:</b>
146: * Note that you should only use FieldValidators (not plain Validators) within a
147: * <field-validator> block. A plain Validator inside a <field> will not be
148: * allowed and would generate error when parsing the xml, as it is not allowed in
149: * the defined dtd (xwork-validator-1.0.2.dtd)</p>
150: * <!-- END SNIPPET: validatorVsFieldValidators2 -->
151: *
152: * <pre>
153: * <!-- START SNIPPET: fieldValidatorUsingFieldValidatorSyntax -->
154: * Declaring a FieldValidator using the <field-validator> syntax:
155: *
156: * <field name="email_address">
157: * <field-validator type="required">
158: * <message>You cannot leave the email address field empty.</message>
159: * </field-validator>
160: * <field-validator type="email">
161: * <message>The email address you entered is not valid.</message>
162: * </field-validator>
163: * </field>
164: * <!-- END SNIPPET: fieldValidatorUsingFieldValidatorSyntax -->
165: * </pre>
166: *
167: *
168: * <!-- START SNIPPET: validatorVsFieldValidators3 -->
169: * <p>The choice is yours. It's perfectly legal to only use <validator> elements
170: * without the <field> elements and set the fieldName attribute for each of them.
171: * The following are effectively equal:</P>
172: * <!-- END SNIPPET: validatorVsFieldValidators3 -->
173: *
174: * <pre>
175: * <!-- START-SNIPPET: similarVaidatorDeclaredInDiffSyntax -->
176: * <field name="email_address">
177: * <field-validator type="required">
178: * <message>You cannot leave the email address field empty.</message>
179: * </field-validator>
180: * <field-validator type="email">
181: * <message>The email address you entered is not valid.</message>
182: * </field-validator>
183: * </field>
184: *
185: *
186: * <validator type="required">
187: * <param name="fieldName">email_address</param>
188: * <message>You cannot leave the email address field empty.</message>
189: * </validator>
190: * <validator type="email">
191: * <param name="fieldName">email_address</param>
192: * <message>The email address you entered is not valid.</message>
193: * </validator>
194: * <!-- END SNIPPET: similarVaidatorDeclaredInDiffSyntax -->
195: * </pre>
196: *
197: *
198: * <!-- START SNIPPET: shortCircuitingValidators1 -->
199: * <p>Beginning with XWork 1.0.1 (bundled with WebWork 2.1), it is possible
200: * to short-circuit a stack of validators. Here is another sample config file
201: * containing validation rules from the Xwork test cases: Notice that some of the
202: * <field-validator> and <validator> elements have the short-circuit
203: * attribute set to true.</p>
204: * <!-- END SNIPPET : shortCircuitingValidators1 -->
205: *
206: *<pre>
207: * <!-- START SNIPPET: exShortCircuitingValidators -->
208: * <!DOCTYPE validators PUBLIC
209: * "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
210: * "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
211: * <validators>
212: * <!-- Field Validators for email field -->
213: * <field name="email">
214: * <field-validator type="required" short-circuit="true">
215: * <message>You must enter a value for email.</message>
216: * </field-validator>
217: * <field-validator type="email" short-circuit="true">
218: * <message>Not a valid e-mail.</message>
219: * </field-validator>
220: * </field>
221: * <!-- Field Validators for email2 field -->
222: * <field name="email2">
223: * <field-validator type="required">
224: * <message>You must enter a value for email2.</message>
225: * </field-validator>
226: * <field-validator type="email">
227: * <message>Not a valid e-mail2.</message>
228: * </field-validator>
229: * </field>
230: * <!-- Plain Validator 1 -->
231: * <validator type="expression">
232: * <param name="expression">email.equals(email2)</param>
233: * <message>Email not the same as email2</message>
234: * </validator>
235: * <!-- Plain Validator 2 -->
236: * <validator type="expression" short-circuit="true">
237: * <param name="expression">email.startsWith('mark')</param>
238: * <message>Email does not start with mark</message>
239: * </validator>
240: * </validators>
241: * <!-- END SNIPPET: exShortCircuitingValidators -->
242: *</pre>
243: *
244: * <!-- START SNIPPET:shortCircuitingValidators2 -->
245: * <p><b>short-circuiting and Validator flavors</b></p>
246: * <p>Plain validator takes precedence over field-validator. They get validated
247: * first in the order they are defined and then the field-validator in the order
248: * they are defined. Failure of a particular validator marked as short-circuit
249: * will prevent the evaluation of subsequent validators and an error (action
250: * error or field error depending on the type of validator) will be added to
251: * the ValidationContext of the object being validated.</p>
252: *
253: * <p>In the example above, the actual execution of validator would be as follows:</p>
254: *
255: * <ol>
256: * <li> Plain Validator 1</li>
257: * <li> Plain Validator 2</li>
258: * <li> Field Validators for email field</li>
259: * <li> Field Validators for email2 field</li>
260: * </ol>
261: *
262: * <p>Since Field Validator 2 is short-circuited, if its validation failed,
263: * it will causes Field validators for email field and Field validators for email2
264: * field to not be validated as well.</p>
265: *
266: * <p><b>Usefull Information:</b>
267: * More complecated validation should probably be done in the validate()
268: * method on the action itself (assuming the action implements Validatable
269: * interface which ActionSupport already does).</p>
270: *
271: * <p>
272: * A plain Validator (non FieldValidator) that gets short-circuited will
273: * completely break out of the validation stack – no other validators will be
274: * evaluated and plain validator takes precedence over field validator meaning
275: * that they get evaluated in the order they are defined before field validator
276: * gets a chance to be evaludated again according to their order defined.
277: * </p>
278: * <!-- END SNIPPET: shortCircuitingValidators2 -->
279: *
280: *
281: * <!-- START SNIPPET: scAndValidatorFlavours1 -->
282: * <p><b>Short cuircuiting and validator flavours</b></p>
283: * <p>A FieldValidator that gets short-circuited will only prevent other
284: * FieldValidators for the same field from being evaluated. Note that this
285: * "same field" behavior applies regardless of whether the <validator> or
286: * <field-validator> syntax was used to declare the validation rule.
287: * By way of example, given this -validation.xml file:</p>
288: * <!-- END SNIPPET: scAndValidatorFlavours1 -->
289: *
290: * <pre>
291: * <!-- START SNIPPET: exScAndValidatorFlavours -->
292: * <validator type="required" short-circuit="true">
293: * <param name="fieldName">bar</param>
294: * <message>You must enter a value for bar.</message>
295: * </validator>
296: *
297: * <validator type="expression">
298: * <param name="expression">foo gt bar</param>
299: * <message>foo must be great than bar.</message>
300: * </validator>
301: * <!-- END SNIPPET: exScAndValidatorFlavours -->
302: * </pre>
303: *
304: * <!-- START SNIPPET: scAndValidatorFlavours2 -->
305: * <p>both validators will be run, even if the "required" validator short-circuits.
306: * "required" validators are FieldValidator's and will not short-circuit the plain
307: * ExpressionValidator because FieldValidators only short-circuit other checks on
308: * that same field. Since the plain Validator is not field specific, it is
309: * not short-circuited.</p>
310: * <!-- END SNIPPET: scAndValidatorFlavours2 -->
311: *
312: *
313: * <!-- START SNIPPET: howXworkFindsValidatorForAction -->
314: * <p>As mentioned above, the framework will also search up the inheritance tree
315: * of the action to find default validations for interfaces and parent classes of
316: * the Action. If you are using the short-circuit attribute and relying on
317: * default validators higher up in the inheritance tree, make sure you don't
318: * accidentally short-circuit things higher in the tree that you really want!</p>
319: * <p>
320: * The effect of having common validators on both
321: * </p>
322: * <ul>
323: * <li><actionClass>-validation.xml</li>
324: * <li><actionClass>-<actionAlias>-validation.xml</li>
325: * </ul>
326: * <p>
327: * It should be noted that the nett effect will be validation on both the validators available
328: * in both validation configuration file. For example if we have 'requiredstring' validators defined
329: * in both validation xml file for field named 'address', we will see 2 validation error indicating that
330: * the the address cannot be empty (assuming validation failed). This is due to WebWork
331: * will merge validators found in both validation configuration files.
332: * </p>
333: * <p>
334: * The logic behind this design decision is such that we could have common validators in
335: * <actionClass>-validation.xml and more context specific validators to be located
336: * in <actionClass>-<actionAlias>-validation.xml
337: * </p>
338: * <!-- END SNIPPET: howXworkFindsValidatorForAction -->
339: *
340: * @author Jason Carreira
341: * @author tmjee
342: *
343: * @Version $Date: 2007-06-06 19:41:31 +0200 (Wed, 06 Jun 2007) $ $Id: Validator.java 1534 2007-06-06 17:41:31Z tm_jee $
344: */
345: public interface Validator {
346:
347: void setDefaultMessage(String message);
348:
349: String getDefaultMessage();
350:
351: String getMessage(Object object);
352:
353: void setMessageKey(String key);
354:
355: String getMessageKey();
356:
357: /**
358: * This method will be called before validate with a non-null ValidatorContext.
359: *
360: * @param validatorContext
361: */
362: void setValidatorContext(ValidatorContext validatorContext);
363:
364: ValidatorContext getValidatorContext();
365:
366: /**
367: * The validation implementation must guarantee that setValidatorContext will
368: * be called with a non-null ValidatorContext before validate is called.
369: *
370: * @param object
371: * @throws ValidationException
372: */
373: void validate(Object object) throws ValidationException;
374:
375: void setValidatorType(String type);
376:
377: String getValidatorType();
378: }
|