blob: d44e05382c5fd3656d1d48a3c6bc1096ff1ccd26 [file] [log] [blame]
/*
* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Tapestry" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Tapestry", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package net.sf.tapestry.valid;
import java.util.List;
import net.sf.tapestry.IMarkupWriter;
import net.sf.tapestry.IRender;
import net.sf.tapestry.IRequestCycle;
import net.sf.tapestry.RequestCycleException;
import net.sf.tapestry.form.IFormComponent;
/**
* Interface used to track validation errors in forms and
* {@link IFormComponent}s (including {@link IField}).
*
* <p>In addition,
* controls how fields that are in error are presented (they can be
* marked in various ways by the delegate; the default implementation
* adds two red asterisks to the right of the field).
*
* <p>The interface is designed so that a single instance is be shared
* with many instances of {@link IFormComponent}.
*
* <p>Starting with release 1.0.8, this interface was extensively revised
* (in a non-backwards compatible way) to move the tracking of errors and
* invalid values (during a request cycle) to the delegate. It has evolved from
* a largely stateless conduit for error messages into a very stateful tracker
* of field state.
*
* <p>Starting with release 1.0.9, this interface was <em>again</em>
* reworked, to allow tracking of errors in {@link IFormComponent form components}
* (not just {@link IField}s}, and to allow unassociated (with any field) errors
* to be tracked.
*
* <p><b>Fields vs. {@link IField} vs. Form Components</b><br>
* For most simple forms, these terms are pretty much synonymous.
* Your form will render normally, and each form component will render
* only once. Some of your form components will by {@link ValidField}
* components (which implement {@link IField}) and handle most of
* their validation internally (with the help of {@link IValidator} objects).
* In addition, your form listener may do additional validation and notify
* the validation delegate of additional errors, some of which
* are associated with a particular field, some of which are unassociated
* with any particular field.
*
* <p>
* But what happens if you use a {@link net.sf.tapestry.components.Foreach} or
* {@link net.sf.tapestry.form.ListEdit} inside your form?
* Some of your components will render multiple times. In this case you will have
* multiple <em>fields</em>. Each field will have a unique field name (you can see this
* in the generated HTML). It is this field name that the delegate keys off of, which
* means that some fields generated by a component may have errors and some may not, it
* all works fine (with one exception).
*
* <p><b>The Exception</b><br>
* The problem is that a component doesn't know its field name until its
* <code>render()</code> method is invoked (at which point, it allocates a unique field
* name from the {@link net.sf.tapestry.form.Form}. This is not a problem for the field or its
* {@link IValidator}, but screws things up for the {@link FieldLabel}.
*
* <p>Typically, the label is renderred <em>before</em> the corresponding form component.
* Form components leave their last assigned field name in their
* {@link IFormComponent#getName() name property}. So if the form component is in any kind of
* loop, the {@link FieldLabel} will key its name,
* {@link IFormComponent#getDisplayName() display name} and error status off of
* its last renderred value. So the moral of the story is don't use
* {@link FieldLabel} in this situation.
*
*
* @author Howard Lewis Ship
* @version $Id$
*
**/
public interface IValidationDelegate
{
/**
* Invoked before other methods to configure the delegate for the given
* form component.
*
* <p>The caller should invoke this with a parameter of null to record
* global errors (errors not associated with any particular field).
*
* @since 1.0.8
*
**/
public void setFormComponent(IFormComponent component);
/**
* Returns true if the current component is in error (that is, had bad input
* submitted by the end user).
*
* @since 1.0.8
*
**/
public boolean isInError();
/**
* Returns the invalid string submitted by the client.
*
* @since 1.0.8
*
**/
public String getInvalidInput();
/**
* Returns a {@link List} of {@link IFieldTracking}, in default order
* (the order in which fields are renderred). A caller should
* not change the values (the List is immutable).
* May return null if no fields are in error.
*
* @since 1.0.8
**/
public List getFieldTracking();
/**
* Resets any tracking information for the current field. This will
* clear the field's inError flag, and set its error message and invalid input value
* to null.
*
* @since 1.0.8
*
**/
public void reset();
/**
* Clears all tracking information.
*
* @since 1.0.10
*
**/
public void clear();
/**
* The error notification method, invoked during the rewind phase
* (that is, while HTTP parameters are being extracted from the request
* and assigned to various object properties).
*
* <p>Typically, the delegate simply invokes
* {@link #record(String, ValidationConstraint, String)}, but special
* delegates may override this behavior to provide (in some cases)
* different error messages or more complicated error renderers.
**/
public void record(ValidatorException ex);
/**
* Records an error in the current component, or an unassociated error.
*
* @param message message to display (@see RenderString}
* @param constraint the constraint that was violated
* @param invalidInput the input provided by the user
*
* @since 1.0.9
**/
public void record(
String message,
ValidationConstraint constraint,
String invalidInput);
/**
* Records an error in the current component, or an unassociated error..
* The maximum flexibility recorder.
*
* @param errorRenderer object that will render the error message (@see RenderString}
* @param constraint the constraint that was violated
* @param invalidInput the input provided by the user
*
**/
public void record(
IRender errorRenderer,
ValidationConstraint constraint,
String invalidInput);
/**
* Invoked before the field is rendered. If the field is in error,
* the delegate may decorate the field in some way (to highlight its
* error state).
*
**/
public void writePrefix(IMarkupWriter writer, IRequestCycle cycle)
throws RequestCycleException;
/**
* Invoked just before the &lt;input&gt; element is closed.
* The delegate can write additional attributes. This is often used
* to set the CSS class of the field so that it can be displayed
* differently, if in error (or required).
*
* @since 1.0.5
**/
public void writeAttributes(IMarkupWriter writer, IRequestCycle cycle)
throws RequestCycleException;
/**
* Invoked after the form component is rendered, so that the
* delegate may decorate the form component (if it is in error).
*
**/
public void writeSuffix(IMarkupWriter writer, IRequestCycle cycle)
throws RequestCycleException;
/**
* Invoked by a {@link FieldLabel} just before writing the name
* of the form component.
*
**/
public void writeLabelPrefix(
IFormComponent component,
IMarkupWriter writer,
IRequestCycle cycle)
throws RequestCycleException;
/**
* Invoked by a {@link FieldLabel} just after writing the name
* of the form component.
*
**/
public void writeLabelSuffix(
IFormComponent component,
IMarkupWriter writer,
IRequestCycle cycle)
throws RequestCycleException;
/**
* Returns true if any form component has errors.
*
**/
public boolean getHasErrors();
}