/*
 *  ====================================================================
 *  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();
}