Coverage Report - org.apache.tapestry.valid.IValidationDelegate
 
Classes in this File Line Coverage Branch Coverage Complexity
IValidationDelegate
N/A
N/A
1
 
 1  
 // Copyright 2004, 2005 The Apache Software Foundation
 2  
 //
 3  
 // Licensed under the Apache License, Version 2.0 (the "License");
 4  
 // you may not use this file except in compliance with the License.
 5  
 // You may obtain a copy of the License at
 6  
 //
 7  
 //     http://www.apache.org/licenses/LICENSE-2.0
 8  
 //
 9  
 // Unless required by applicable law or agreed to in writing, software
 10  
 // distributed under the License is distributed on an "AS IS" BASIS,
 11  
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
 // See the License for the specific language governing permissions and
 13  
 // limitations under the License.
 14  
 
 15  
 package org.apache.tapestry.valid;
 16  
 
 17  
 import org.apache.tapestry.IMarkupWriter;
 18  
 import org.apache.tapestry.IRender;
 19  
 import org.apache.tapestry.IRequestCycle;
 20  
 import org.apache.tapestry.form.IFormComponent;
 21  
 import org.apache.tapestry.form.TextField;
 22  
 
 23  
 import java.io.Serializable;
 24  
 import java.util.List;
 25  
 
 26  
 /**
 27  
  * Interface used to track validation errors in forms and
 28  
  * {@link IFormComponent form element component}s (including
 29  
  * {@link TextField} and its subclasses).
 30  
  * <p>
 31  
  * In addition, controls how fields that are in error are presented (they can be
 32  
  * <em>decorated</em> in various ways by the delegate; the default
 33  
  * implementation adds two red asterisks to the right of the field).
 34  
  * <p>
 35  
  * Each {@link org.apache.tapestry.form.Form}&nbsp;must have its own validation
 36  
  * delegate instance.
 37  
  * <p>
 38  
  * Starting with release 1.0.8, this interface was extensively revised (in a
 39  
  * non-backwards compatible way) to move the tracking of errors and invalid
 40  
  * values (during a request cycle) to the delegate. It has evolved from a
 41  
  * largely stateless conduit for error messages into a very stateful tracker of
 42  
  * field state.
 43  
  * <p>
 44  
  * Starting with release 1.0.9, this interface was <em>again</em> reworked, to
 45  
  * allow tracking of errors in {@link IFormComponent form components}, and to
 46  
  * allow unassociated errors to be tracked. Unassociated errors are "global",
 47  
  * they don't apply to any particular field.
 48  
  * <p>
 49  
  * <b>Fields vs. Form Element Components </b> <br>
 50  
  * For most simple forms, these terms are pretty much synonymous. Your form will
 51  
  * render normally, and each form element component will render only once. Some
 52  
  * of your form components will be {@link ValidField}&nbsp;components and
 53  
  * handle most of their validation internally (with the help of
 54  
  * {@link IValidator}&nbsp;objects). In addition, your form listener may do
 55  
  * additional validation and notify the validation delegate of additional
 56  
  * errors, some of which are associated with a particular field, some of which
 57  
  * are unassociated with any particular field.
 58  
  * <p>
 59  
  * But what happens if you use a {@link org.apache.tapestry.components.ForBean}&nbsp;or
 60  
  * {@link org.apache.tapestry.form.ListEdit}&nbsp;inside your form? Some of
 61  
  * your components will render multiple times. In this case you will have
 62  
  * multiple <em>fields</em>. Each field will have a unique field name (the
 63  
  * {@link org.apache.tapestry.form.FormSupport#getElementId(IFormComponent) element id},
 64  
  * which you can see this in the generated HTML). It is this field name that the
 65  
  * delegate keys off of, which means that some fields generated by a component
 66  
  * may have errors and some may not, it all works fine (with one exception).
 67  
  * <p>
 68  
  * <b>The Exception </b> <br>
 69  
  * The problem is that a component doesn't know its field name until its
 70  
  * <code>render()</code> method is invoked (at which point, it allocates a
 71  
  * unique field name from the
 72  
  * {@link org.apache.tapestry.IForm#getElementId(org.apache.tapestry.form.IFormComponent)}.
 73  
  * This is not a problem for the field or its {@link IValidator}, but screws
 74  
  * things up for the {@link FieldLabel}.
 75  
  * <p>
 76  
  * Typically, the label is rendered <em>before</em> the corresponding form
 77  
  * component. Form components leave their last assigned field name in their
 78  
  * {@link IFormComponent#getName() name property}. So if the form component is
 79  
  * in any kind of loop, the {@link FieldLabel}will key its name,
 80  
  * {@link IFormComponent#getDisplayName() display name} and error status off of
 81  
  * its last renderred value. So the moral of the story is don't use
 82  
  * {@link FieldLabel}in this situation.
 83  
  * 
 84  
  * @author Howard Lewis Ship
 85  
  */
 86  
 
 87  
 public interface IValidationDelegate extends Serializable
 88  
 {
 89  
 
 90  
     /**
 91  
      * Invoked before other methods to configure the delegate for the given form
 92  
      * component. Sets the current field based on the
 93  
      * {@link IFormComponent#getName() name} of the form component.
 94  
      * <p>
 95  
      * The caller should invoke this with a parameter of null to record
 96  
      * unassociated global errors (errors not associated with any particular
 97  
      * field).
 98  
      * 
 99  
      * @since 1.0.8
 100  
      */
 101  
 
 102  
     void setFormComponent(IFormComponent component);
 103  
 
 104  
     /**
 105  
      * Returns true if the current field is in error (that is, had bad input
 106  
      * submitted by the end user).
 107  
      * 
 108  
      * @since 1.0.8
 109  
      */
 110  
 
 111  
     boolean isInError();
 112  
 
 113  
     /**
 114  
      * Returns the string submitted by the client as the value for the current
 115  
      * field.
 116  
      * 
 117  
      * @since 1.0.8
 118  
      */
 119  
 
 120  
     String getFieldInputValue();
 121  
 
 122  
     /**
 123  
      * Returns a {@link List} of {@link IFieldTracking}, in default order (the
 124  
      * order in which fields are renderred). A caller should not change the
 125  
      * values (the List is immutable). May return null if no fields are in
 126  
      * error.
 127  
      * 
 128  
      * @since 1.0.8
 129  
      */
 130  
 
 131  
     List getFieldTracking();
 132  
 
 133  
     /**
 134  
      * Resets any tracking information for the current field. This will clear
 135  
      * the field's inError flag, and set its error message and invalid input
 136  
      * value to null.
 137  
      * 
 138  
      * @since 1.0.8
 139  
      */
 140  
 
 141  
     void reset();
 142  
 
 143  
     /**
 144  
      * Clears all tracking information.
 145  
      * 
 146  
      * @since 1.0.10
 147  
      */
 148  
 
 149  
     void clear();
 150  
 
 151  
     /**
 152  
      * Clears all errors, but maintains user input. This is useful when a form
 153  
      * has been submitted for a semantic other than "process this data". A
 154  
      * common example of this is a dependent drop down list; selecting an option
 155  
      * in one drop down list forces a refresh submit of the form, to repopulate
 156  
      * the options in a second, dependent drop down list.
 157  
      * <p>
 158  
      * In these cases, the user input provided in the request is maintained, but
 159  
      * any errors should be cleared out (to prevent unwanted error messages and
 160  
      * decorations).
 161  
      * 
 162  
      * @since 3.0.1
 163  
      */
 164  
 
 165  
     void clearErrors();
 166  
 
 167  
     /**
 168  
      * Records the user's input for the current form component. Input should be
 169  
      * recorded even if there isn't an explicit error, since later form-wide
 170  
      * validations may discover an error in the field.
 171  
      * 
 172  
      * @since 3.0
 173  
      */
 174  
 
 175  
     void recordFieldInputValue(String input);
 176  
 
 177  
     /**
 178  
      * The error notification method, invoked during the rewind phase (that is,
 179  
      * while HTTP parameters are being extracted from the request and assigned
 180  
      * to various object properties).
 181  
      * <p>
 182  
      * Typically, the delegate simply invokes
 183  
      * {@link #record(String, ValidationConstraint)}or
 184  
      * {@link #record(IRender, ValidationConstraint)}, but special delegates
 185  
      * may override this behavior to provide (in some cases) different error
 186  
      * messages or more complicated error renderers.
 187  
      */
 188  
 
 189  
     void record(ValidatorException ex);
 190  
 
 191  
     /**
 192  
      * Records an error in the current field, or an unassociated error if there
 193  
      * is no current field.
 194  
      * 
 195  
      * @param message
 196  
      *            message to display (@see RenderString}
 197  
      * @param constraint
 198  
      *            the constraint that was violated, or null if not known
 199  
      * @since 1.0.9
 200  
      */
 201  
 
 202  
     void record(String message, ValidationConstraint constraint);
 203  
 
 204  
     /**
 205  
      * Convienience for recording a standard string messages against a field.
 206  
      * 
 207  
      * @param field
 208  
      *            the field to record the error message against, or null to
 209  
      *            record an unassociated error
 210  
      * @param message
 211  
      *            the error message to record
 212  
      * @since 4.0
 213  
      */
 214  
 
 215  
     void record(IFormComponent field, String message);
 216  
 
 217  
     /**
 218  
      * Records an error in the current component, or an unassociated error. The
 219  
      * maximum flexibility recorder.
 220  
      * 
 221  
      * @param errorRenderer
 222  
      *            object that will render the error message (@see RenderString}
 223  
      * @param constraint
 224  
      *            the constraint that was violated, or null if not known
 225  
      */
 226  
 
 227  
     void record(IRender errorRenderer, ValidationConstraint constraint);
 228  
 
 229  
     /**
 230  
      * Invoked before the field is rendered. If the field is in error, the
 231  
      * delegate may decorate the field in some way (to highlight its error
 232  
      * state).
 233  
      * 
 234  
      * @param writer
 235  
      *            the writer to which output should be sent
 236  
      * @param cycle
 237  
      *            the active request cycle
 238  
      * @param component
 239  
      *            the component being decorated
 240  
      * @param validator
 241  
      *            the validator for the component, or null if the component does
 242  
      *            have (or doesn't support) a validator
 243  
      */
 244  
 
 245  
     void writePrefix(IMarkupWriter writer, IRequestCycle cycle,
 246  
             IFormComponent component, IValidator validator);
 247  
 
 248  
     /**
 249  
      * Invoked just before the &lt;input&gt; element is closed. The delegate can
 250  
      * write additional attributes. This is often used to set the CSS class of
 251  
      * the field so that it can be displayed differently, if in error (or
 252  
      * required). *
 253  
      * 
 254  
      * @param writer
 255  
      *            the writer to which output should be sent
 256  
      * @param cycle
 257  
      *            the active request cycle
 258  
      * @param component
 259  
      *            the component being decorated
 260  
      * @param validator
 261  
      *            the validator for the component, or null if the component does
 262  
      *            have (or doesn't support) a validator
 263  
      * @since 1.0.5
 264  
      */
 265  
 
 266  
     void writeAttributes(IMarkupWriter writer, IRequestCycle cycle,
 267  
             IFormComponent component, IValidator validator);
 268  
 
 269  
     /**
 270  
      * Invoked after the form component is rendered, so that the delegate may
 271  
      * decorate the form component (if it is in error). *
 272  
      * 
 273  
      * @param writer
 274  
      *            the writer to which output should be sent
 275  
      * @param cycle
 276  
      *            the active request cycle
 277  
      * @param component
 278  
      *            the component being decorated
 279  
      * @param validator
 280  
      *            the validator for the component, or null if the component does
 281  
      *            have (or doesn't support) a validator
 282  
      */
 283  
 
 284  
     void writeSuffix(IMarkupWriter writer, IRequestCycle cycle,
 285  
             IFormComponent component, IValidator validator);
 286  
 
 287  
     /**
 288  
      * Invoked by a {@link FieldLabel} just before writing the name of the form
 289  
      * component.
 290  
      */
 291  
 
 292  
     void writeLabelPrefix(IFormComponent component,
 293  
             IMarkupWriter writer, IRequestCycle cycle);
 294  
     
 295  
     /**
 296  
      * Invoked just before the &lt;label&gt; element is closed. The delegate can
 297  
      * write additional attributes. This is often used to set the CSS class of
 298  
      * the label so that it can be displayed differently, if in error (or
 299  
      * required). Any attributes written here will be overriden by any informal
 300  
      * parameters specified in the {@link FieldLabel} implementation.
 301  
      * 
 302  
      * @param writer
 303  
      *            the writer to which output should be sent
 304  
      * @param cycle
 305  
      *            the active request cycle
 306  
      * @param component
 307  
      *            the component field that label decorates
 308  
      * @since 4.0.1
 309  
      */
 310  
 
 311  
     void writeLabelAttributes(IMarkupWriter writer, IRequestCycle cycle,
 312  
             IFormComponent component);
 313  
     
 314  
     /**
 315  
      * Invoked just before the actual field label text is written, right after all attributes and 
 316  
      * informal parameters are done being printed on the <code>&lt;label&gt;</code> tag. 
 317  
      * 
 318  
      * <p>
 319  
      *  Example, writing content would go here:
 320  
      * </p>
 321  
      * <p>
 322  
      *  &lt;label class="error"&gt &gt;&gt;here&lt;&lt; LABEL TEXT &lt;/label&gt;
 323  
      * </p>
 324  
      * 
 325  
      * @param writer
 326  
      *          The writer to use.
 327  
      * @param cycle
 328  
      *          Current request cycle.
 329  
      * @param component
 330  
      *          Field label is bound to.
 331  
      */
 332  
     void beforeLabelText(IMarkupWriter writer, IRequestCycle cycle, IFormComponent component);
 333  
     
 334  
     /**
 335  
      * Invoked just before the closing <code>&lt;/label&gt;</code> tag is written.
 336  
      * 
 337  
      * <p>
 338  
      *  Example, writing content would go here:
 339  
      * </p>
 340  
      * <p>
 341  
      *  &lt;label class="error"&gt LABEL TEXT  &gt;&gt;here&lt;&lt;  &lt;/label&gt;
 342  
      * </p>
 343  
      * 
 344  
      * @param writer
 345  
      *          The writer to use.
 346  
      * @param cycle
 347  
      *          Current request cycle.
 348  
      * @param component
 349  
      *          Field label is bound to.
 350  
      */
 351  
     void afterLabelText(IMarkupWriter writer, IRequestCycle cycle, IFormComponent component);
 352  
     
 353  
     /**
 354  
      * Invoked by a {@link FieldLabel} just after writing the name of the form
 355  
      * component.
 356  
      */
 357  
 
 358  
     void writeLabelSuffix(IFormComponent component, IMarkupWriter writer, IRequestCycle cycle);
 359  
 
 360  
     /**
 361  
      * Returns true if any form component has errors.
 362  
      */
 363  
 
 364  
     boolean getHasErrors();
 365  
 
 366  
     /**
 367  
      * Returns the {@link IFieldTracking}&nbsp;for the current component, if
 368  
      * any. Useful when displaying error messages for individual fields.
 369  
      * 
 370  
      * @since 3.0.2
 371  
      */
 372  
     IFieldTracking getCurrentFieldTracking();
 373  
 
 374  
     /**
 375  
      * Returns a list of {@link org.apache.tapestry.IRender} objects, each of
 376  
      * which will render an error message for a field tracked by the delegate,
 377  
      * plus any unassociated errors (for which no specific field is identified).
 378  
      * These objects can be rendered or converted to a string (via toString()).
 379  
      * 
 380  
      * @return non-empty List of {@link org.apache.tapestry.IRender}.
 381  
      */
 382  
 
 383  
     List getErrorRenderers();
 384  
 
 385  
     /**
 386  
      * Registers a field for automatic focus. The goal is for the first field
 387  
      * that is in error to get focus; failing that, the first required field;
 388  
      * failing that, any field.
 389  
      * 
 390  
      * @param field
 391  
      *            the field requesting focus
 392  
      * @param priority
 393  
      *            a priority level used to determine whether the registered
 394  
      *            field becomes the focus field. Constants for this purpose are
 395  
      *            defined in {@link ValidationConstants}.
 396  
      * @since 4.0
 397  
      */
 398  
 
 399  
     void registerForFocus(IFormComponent field, int priority);
 400  
 
 401  
     /**
 402  
      * Returns the field to focus upon, based on prior calls to
 403  
      * {@link #registerForFocus(IFormComponent, int)}.
 404  
      * 
 405  
      * @return the field name, or null if no field should receive focus.
 406  
      * @since 4.0
 407  
      */
 408  
     String getFocusField();
 409  
 
 410  
 }