Author: ehillenius
Date: Tue Jun  5 08:25:47 2007
New Revision: 544517

URL: http://svn.apache.org/viewvc?view=rev&rev=544517
Log:
formatted members

Modified:
    
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java

Modified: 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java?view=diff&rev=544517&r1=544516&r2=544517
==============================================================================
--- 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java
 (original)
+++ 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java
 Tue Jun  5 08:25:47 2007
@@ -138,16 +138,6 @@
 public class Form extends WebMarkupContainer implements IFormSubmitListener
 {
        /**
-        * Constant for specifying how a form is submitted, in this case using 
post.
-        */
-       public static final String METHOD_POST = "post";
-
-       /**
-        * Constant for specifying how a form is submitted, in this case using 
get.
-        */
-       public static final String METHOD_GET = "get";
-
-       /**
         * Visitor used for validation
         * 
         * @author Igor Vaynberg (ivaynberg)
@@ -186,28 +176,117 @@
                public abstract void validate(FormComponent formComponent);
        }
 
-       private static final String UPLOAD_TOO_LARGE_RESOURCE_KEY = 
"uploadTooLarge";
+       /**
+        * 
+        */
+       class FormDispatchRequest extends Request
+       {
+               private final ValueMap params = new ValueMap();
 
-       private static final String UPLOAD_FAILED_RESOURCE_KEY = "uploadFailed";
+               private final Request realRequest;
+
+               private final String url;
+
+               /**
+                * Construct.
+                * 
+                * @param realRequest
+                * @param url
+                */
+               public FormDispatchRequest(final Request realRequest, final 
String url)
+               {
+                       this.realRequest = realRequest;
+                       this.url = realRequest.decodeURL(url);
+
+                       String queryString = 
this.url.substring(this.url.indexOf("?") + 1);
+                       RequestUtils.decodeParameters(queryString, params);
+               }
+
+               /**
+                * @see org.apache.wicket.Request#getLocale()
+                */
+               public Locale getLocale()
+               {
+                       return realRequest.getLocale();
+               }
+
+               /**
+                * @see org.apache.wicket.Request#getParameter(java.lang.String)
+                */
+               public String getParameter(String key)
+               {
+                       return (String)params.get(key);
+               }
+
+               /**
+                * @see org.apache.wicket.Request#getParameterMap()
+                */
+               public Map getParameterMap()
+               {
+                       return params;
+               }
+
+               /**
+                * @see 
org.apache.wicket.Request#getParameters(java.lang.String)
+                */
+               public String[] getParameters(String key)
+               {
+                       String param = (String)params.get(key);
+                       if (param != null)
+                       {
+                               return new String[] { param };
+                       }
+                       return new String[0];
+               }
+
+               /**
+                * @see org.apache.wicket.Request#getPath()
+                */
+               public String getPath()
+               {
+                       return realRequest.getPath();
+               }
+
+               public String getRelativePathPrefixToContextRoot()
+               {
+                       return realRequest.getRelativePathPrefixToContextRoot();
+               }
+
+               public String getRelativePathPrefixToWicketHandler()
+               {
+                       return 
realRequest.getRelativePathPrefixToWicketHandler();
+               }
+
+               /**
+                * @see org.apache.wicket.Request#getURL()
+                */
+               public String getURL()
+               {
+                       return url;
+               }
+       }
+
+       /**
+        * Constant for specifying how a form is submitted, in this case using 
get.
+        */
+       public static final String METHOD_GET = "get";
+
+       /**
+        * Constant for specifying how a form is submitted, in this case using 
post.
+        */
+       public static final String METHOD_POST = "post";
 
        /** Flag that indicates this form has been submitted during this 
request */
        private static final short FLAG_SUBMITTED = FLAG_RESERVED1;
 
-       private static final long serialVersionUID = 1L;
-
        /** Log. */
        private static final Logger log = LoggerFactory.getLogger(Form.class);
 
-       /** Maximum size of an upload in bytes */
-       private Bytes maxSize = Bytes.MAX;
-
-       /** True if the form has enctype of multipart/form-data */
-       private boolean multiPart = false;
+       private static final long serialVersionUID = 1L;
 
-       private String javascriptId;
+       private static final String UPLOAD_FAILED_RESOURCE_KEY = "uploadFailed";
 
-       /** multi-validators assigned to this form */
-       private Object formValidators = null;
+       private static final String UPLOAD_TOO_LARGE_RESOURCE_KEY = 
"uploadTooLarge";
 
        /**
         * Any default button. If set, a hidden submit button will be rendered 
right
@@ -222,6 +301,17 @@
         */
        private Button defaultButton;
 
+       /** multi-validators assigned to this form */
+       private Object formValidators = null;
+
+       private String javascriptId;
+
+       /** Maximum size of an upload in bytes */
+       private Bytes maxSize = Bytes.MAX;
+
+       /** True if the form has enctype of multipart/form-data */
+       private boolean multiPart = false;
+
        /**
         * Constructs a form with no validation.
         * 
@@ -246,19 +336,101 @@
        }
 
        /**
-        * Gets the method used to submit the form. Defaults to 'post'. Override
-        * this if you have a requirement to alter this behavior.
+        * Adds a form validator to the form.
         * 
-        * @return the method used to submit the form.
+        * @param validator
+        *            validator
+        * @throws IllegalArgumentException
+        *             if validator is null
+        * @see IFormValidator
+        * @see IValidatorAddListener
         */
-       protected String getMethod()
+       public void add(IFormValidator validator)
        {
-               return METHOD_POST;
+               if (validator == null)
+               {
+                       throw new IllegalArgumentException("validator argument 
cannot be null");
+               }
+
+               // add the validator
+               formValidators_add(validator);
+
+               // see whether the validator listens for add events
+               if (validator instanceof IValidatorAddListener)
+               {
+                       ((IValidatorAddListener)validator).onAdded(this);
+               }
        }
 
-       protected boolean getStatelessHint()
+       /**
+        * Clears the input from the form's nested children of type
+        * [EMAIL PROTECTED] FormComponent}. This method is typically called 
when a form needs
+        * to be reset.
+        */
+       public final void clearInput()
        {
-               return false;
+               // Visit all the (visible) form components and clear the input 
on each.
+               visitFormComponentsPostOrder(new FormComponent.AbstractVisitor()
+               {
+                       public void onFormComponent(final FormComponent 
formComponent)
+                       {
+                               if (formComponent.isVisibleInHierarchy())
+                               {
+                                       // Clear input from form component
+                                       formComponent.clearInput();
+                               }
+                       }
+               });
+       }
+
+       /**
+        * /** Registers an error feedback message for this component
+        * 
+        * @param error
+        *            error message
+        * @param args
+        *            argument replacement map for ${key} variables
+        */
+       public final void error(String error, Map args)
+       {
+               error(new MapVariableInterpolator(error, args).toString());
+       }
+
+       /**
+        * Gets the button which submitted this form.
+        * 
+        * @return The button which submitted this form or null if the 
processing
+        *         was not trigger by a registered button component
+        */
+       public final IFormSubmittingComponent findSubmittingButton()
+       {
+               IFormSubmittingComponent submittingButton = 
(IFormSubmittingComponent)getPage()
+                               .visitChildren(IFormSubmittingComponent.class, 
new IVisitor()
+                               {
+                                       public Object component(final Component 
component)
+                                       {
+                                               // Get button
+                                               final IFormSubmittingComponent 
submit = (IFormSubmittingComponent)component;
+
+                                               // Check for button-name or 
button-name.x request string
+                                               if (submit.getForm() != null
+                                                               && 
submit.getForm().getRootForm() == Form.this
+                                                               && 
(getRequest().getParameter(submit.getInputName()) != null || getRequest()
+                                                                               
.getParameter(submit.getInputName() + ".x") != null))
+                                               {
+                                                       if 
(!component.isVisible())
+                                                       {
+                                                               throw new 
WicketRuntimeException("Submit Button "
+                                                                               
+ submit.getInputName() + " (path="
+                                                                               
+ component.getPageRelativePath() + ") is not visible");
+                                                       }
+                                                       return submit;
+                                               }
+                                               return CONTINUE_TRAVERSAL;
+                                       }
+                               });
+
+               return submittingButton;
        }
 
        /**
@@ -291,6 +463,26 @@
        }
 
        /**
+        * This generates a piece of javascript code that sets the url in the
+        * special hidden field and submits the form.
+        * 
+        * Warning: This code should only be called in the rendering phase for 
form
+        * components inside the form because it uses the css/javascript id of 
the
+        * form which can be stored in the markup.
+        * 
+        * @param url
+        *            The interface url that has to be stored in the hidden 
field
+        *            and submitted
+        * @return The javascript code that submits the form.
+        */
+       public final CharSequence getJsForInterfaceUrl(CharSequence url)
+       {
+               return new 
AppendingStringBuffer("document.getElementById('").append(getHiddenFieldId())
+                               
.append("').value='").append(url).append("';document.getElementById('").append(
+                                               
getJavascriptId()).append("').submit();");
+       }
+
+       /**
         * @return the maxSize of uploaded files
         */
        public Bytes getMaxSize()
@@ -299,12 +491,107 @@
        }
 
        /**
-        * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
-        * <p>
-        * Retrieves FormComponent values related to the page using the 
persister
-        * and assign the values to the FormComponent. Thus initializing them.
-        */
-       public final void loadPersistentFormComponentValues()
+        * Returns the root form or this, if this is the root form.
+        * 
+        * @return root form or this form
+        */
+       public Form getRootForm()
+       {
+               Form form;
+               Form parent = this;
+               do
+               {
+                       form = parent;
+                       parent = (Form)form.findParent(Form.class);
+               }
+               while (parent != null);
+
+               return form;
+       }
+
+       /**
+        * Returns the prefix used when building validator keys. This allows a 
form
+        * to use a separate "set" of keys. For example if prefix "short" is
+        * returned, validator key short.Required will be tried instead of 
Required
+        * key.
+        * <p>
+        * This can be useful when different designs are used for a form. In a 
form
+        * where error messages are displayed next to their respective form
+        * components as opposed to at the top of the form, the ${label} 
attribute
+        * is of little use and only causes redundant information to appear in 
the
+        * message. Forms like these can return the "short" (or any other 
string)
+        * validator prefix and declare key: short.Required=required to 
override the
+        * longer message which is usually declared like this: 
Required=${label} is
+        * a required field
+        * <p>
+        * Returned prefix will be used for all form components. The prefix can 
also
+        * be overridden on form component level by overriding
+        * [EMAIL PROTECTED] FormComponent#getValidatorKeyPrefix()}
+        * 
+        * @return prefix prepended to validator keys
+        */
+       public String getValidatorKeyPrefix()
+       {
+               return null;
+       }
+
+       /**
+        * Gets whether the current form has any error registered.
+        * 
+        * @return True if this form has at least one error.
+        */
+       public final boolean hasError()
+       {
+               // if this form itself has an error message
+               if (hasErrorMessage())
+               {
+                       return true;
+               }
+
+               // the form doesn't have any errors, now check any nested form
+               // components
+               return anyFormComponentError();
+       }
+
+       /**
+        * Returns whether the form is a root form, which means that there's no
+        * other form in it's parent hierarchy.
+        * 
+        * @return true if form is a root form, false otherwise
+        */
+       public boolean isRootForm()
+       {
+               return findParent(Form.class) == null;
+       }
+
+       /**
+        * Checks if this form has been submitted during the current request
+        * 
+        * @return true if the form has been submitted during this request, 
false
+        *         otherwise
+        */
+       public final boolean isSubmitted()
+       {
+               return getFlag(FLAG_SUBMITTED);
+       }
+
+       /**
+        * Method made final because we want to ensure users call setVersioned.
+        * 
+        * @see org.apache.wicket.Component#isVersioned()
+        */
+       public boolean isVersioned()
+       {
+               return super.isVersioned();
+       }
+
+       /**
+        * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
+        * <p>
+        * Retrieves FormComponent values related to the page using the 
persister
+        * and assign the values to the FormComponent. Thus initializing them.
+        */
+       public final void loadPersistentFormComponentValues()
        {
                visitFormComponentsPostOrder(new FormComponent.AbstractVisitor()
                {
@@ -390,25 +677,48 @@
        }
 
        /**
-        * Checks if this form has been submitted during the current request
+        * Process the form. Though you can override this method to provide your
+        * whole own algorithm, it is not recommended to do so.
+        * <p>
+        * See the class documentation for further details on the form 
processing
+        * </p>
         * 
-        * @return true if the form has been submitted during this request, 
false
-        *         otherwise
+        * @return False if the form had an error
         */
-       public final boolean isSubmitted()
+       public boolean process()
        {
-               return getFlag(FLAG_SUBMITTED);
-       }
+               // run validation
+               validate();
 
-       /**
-        * @see org.apache.wicket.Component#onDetach()
-        */
-       protected void onDetach()
-       {
-               super.internalOnDetach();
-               setFlag(FLAG_SUBMITTED, false);
+               // If a validation error occurred
+               if (hasError())
+               {
+                       // mark all children as invalid
+                       markFormComponentsInvalid();
 
-               super.onDetach();
+                       // let subclass handle error
+                       onError();
+
+                       // Form has an error
+                       return false;
+               }
+               else
+               {
+                       // mark all childeren as valid
+                       markFormComponentsValid();
+
+                       // before updating, call the interception method for 
clients
+                       beforeUpdateFormComponentModels();
+
+                       // Update model using form data
+                       updateFormComponentModels();
+
+                       // Persist FormComponents if requested
+                       persistFormComponentData();
+
+                       // Form has no error
+                       return true;
+               }
        }
 
        /**
@@ -519,25 +829,21 @@
        }
 
        /**
-        * Method made final because we want to ensure users call setVersioned.
-        * 
-        * @see org.apache.wicket.Component#isVersioned()
-        */
-       public boolean isVersioned()
-       {
-               return super.isVersioned();
-       }
-
-       /**
         * Convenient and typesafe way to visit all the form components on a 
form
-        * postorder (deepest first)
         * 
         * @param visitor
         *            The visitor interface to call
         */
-       public final void visitFormComponentsPostOrder(final 
FormComponent.IVisitor visitor)
+       public final void visitFormComponents(final FormComponent.IVisitor 
visitor)
        {
-               FormComponent.visitFormComponentsPostOrder(this, visitor);
+               visitChildren(FormComponent.class, new IVisitor()
+               {
+                       public Object component(final Component component)
+                       {
+                               visitor.formComponent((FormComponent)component);
+                               return CONTINUE_TRAVERSAL;
+                       }
+               });
 
                /**
                 * TODO Post 1.2 General: Maybe we should re-think how Borders 
are
@@ -565,20 +871,14 @@
 
        /**
         * Convenient and typesafe way to visit all the form components on a 
form
+        * postorder (deepest first)
         * 
         * @param visitor
         *            The visitor interface to call
         */
-       public final void visitFormComponents(final FormComponent.IVisitor 
visitor)
+       public final void visitFormComponentsPostOrder(final 
FormComponent.IVisitor visitor)
        {
-               visitChildren(FormComponent.class, new IVisitor()
-               {
-                       public Object component(final Component component)
-                       {
-                               visitor.formComponent((FormComponent)component);
-                               return CONTINUE_TRAVERSAL;
-                       }
-               });
+               FormComponent.visitFormComponentsPostOrder(this, visitor);
 
                /**
                 * TODO Post 1.2 General: Maybe we should re-think how Borders 
are
@@ -605,264 +905,452 @@
        }
 
        /**
-        * If a default button was set on this form, this method will be called 
to
-        * render an extra field with an invisible style so that pressing enter 
in
-        * one of the textfields will do a form submit using this button. This
-        * method is overridable as what we do is best effort only, and may not 
what
-        * you want in specific situations. So if you have specific usability
-        * concerns, or want to follow another strategy, you may override this
-        * method.
+        * Find out whether there is any registered error for a form component.
         * 
-        * @param markupStream
-        *            The markup stream
-        * @param openTag
-        *            The open tag for the body
+        * @return whether there is any registered error for a form component
         */
-       protected void appendDefaultButtonField(final MarkupStream markupStream,
-                       final ComponentTag openTag)
+       private boolean anyFormComponentError()
        {
-               String nameAndId = getHiddenFieldId();
-               AppendingStringBuffer buffer = new AppendingStringBuffer();
-               // get the value, first seeing whether the value attribute is 
set
-               // by a model
-               String value = defaultButton.getModelObjectAsString();
-               if (value == null || "".equals(value))
+               final Object value = visitChildren(new IVisitor()
                {
-                       // nope it isn't; try to read from the attributes
-                       // note that we're only trying lower case here
-                       value = 
defaultButton.getMarkupAttributes().getString("value");
-               }
+                       public Object component(final Component component)
+                       {
+                               if (component.hasErrorMessage())
+                               {
+                                       return STOP_TRAVERSAL;
+                               }
 
-               // append the button
-               buffer.append("<input type=\"submit\" 
value=\"").append(value).append("\" name=\"").append(
-                               defaultButton.getInputName()).append("\"");
-               buffer.append("style=\"width: 0px; height: 0px; position: 
absolute; left:-100px;\"");
-               buffer.append(" />");
-               getResponse().write(buffer);
-       }
+                               // Traverse all children
+                               return CONTINUE_TRAVERSAL;
+                       }
+               });
 
-       /**
-        * Template method to allow clients to do any processing (like 
recording the
-        * current model so that, in case onSubmit does further validation, the
-        * model can be rolled back) before the actual updating of form 
component
-        * models is done.
-        */
-       protected void beforeUpdateFormComponentModels()
-       {
+               return value == IVisitor.STOP_TRAVERSAL ? true : false;
        }
 
        /**
-        * Called (by the default implementation of 'process') when all fields
-        * validated, the form was updated and it's data was allowed to be
-        * persisted. It is meant for delegating further processing to clients.
-        * <p>
-        * This implementation first finds out whether the form processing was
-        * triggered by a nested button of this form. If that is the case, that
-        * button's onSubmit is called first.
-        * </p>
-        * <p>
-        * Regardless of whether a submitting button was found, the form's 
onSubmit
-        * method is called next.
-        * </p>
+        * Method for dispatching/calling a interface on a page from the given 
url.
+        * Used by [EMAIL PROTECTED] 
org.apache.wicket.markup.html.form.Form#onFormSubmitted()}
+        * for dispatching events
         * 
-        * @param submittingButton
-        *            the button that triggered this form processing, or null 
if the
-        *            processing was triggered by something else (like a 
non-Wicket
-        *            submit button or a javascript execution)
-        */
-       protected void delegateSubmit(IFormSubmittingComponent submittingButton)
-       {
-               // when the given button is not null, it means that it was the
-               // submitting button
-               if (submittingButton != null)
+        * @param page
+        *            The page where the event should be called on.
+        * @param url
+        *            The url which describes the component path and the 
interface
+        *            to be called.
+        */
+       private void dispatchEvent(final Page page, final String url)
+       {
+               RequestCycle rc = RequestCycle.get();
+               IRequestCycleProcessor processor = rc.getProcessor();
+               final RequestParameters requestParameters = 
processor.getRequestCodingStrategy().decode(
+                               new FormDispatchRequest(rc.getRequest(), url));
+               IRequestTarget rt = processor.resolve(rc, requestParameters);
+               if (rt instanceof ListenerInterfaceRequestTarget)
                {
-                       submittingButton.onSubmit();
+                       ListenerInterfaceRequestTarget interfaceTarget = 
((ListenerInterfaceRequestTarget)rt);
+                       
interfaceTarget.getRequestListenerInterface().invoke(page, 
interfaceTarget.getTarget());
+               }
+               else
+               {
+                       throw new WicketRuntimeException(
+                                       "Attempt to access unknown request 
listener interface "
+                                                       + 
requestParameters.getInterfaceName());
                }
-
-               // Model was successfully updated with valid data
-               onSubmit();
        }
 
        /**
-        * Gets the button which submitted this form.
-        * 
-        * @return The button which submitted this form or null if the 
processing
-        *         was not trigger by a registered button component
+        * @param validator
+        *            The form validator to add to the formValidators Object 
(which
+        *            may be an array of IFormValidators or a single instance, 
for
+        *            efficiency)
         */
-       public final IFormSubmittingComponent findSubmittingButton()
+       private void formValidators_add(final IFormValidator validator)
        {
-               IFormSubmittingComponent submittingButton = 
(IFormSubmittingComponent)getPage()
-                               .visitChildren(IFormSubmittingComponent.class, 
new IVisitor()
-                               {
-                                       public Object component(final Component 
component)
-                                       {
-                                               // Get button
-                                               final IFormSubmittingComponent 
submit = (IFormSubmittingComponent)component;
+               if (this.formValidators == null)
+               {
+                       this.formValidators = validator;
+               }
+               else
+               {
+                       // Get current list size
+                       final int size = formValidators_size();
 
-                                               // Check for button-name or 
button-name.x request string
-                                               if (submit.getForm() != null
-                                                               && 
submit.getForm().getRootForm() == Form.this
-                                                               && 
(getRequest().getParameter(submit.getInputName()) != null || getRequest()
-                                                                               
.getParameter(submit.getInputName() + ".x") != null))
-                                               {
-                                                       if 
(!component.isVisible())
-                                                       {
-                                                               throw new 
WicketRuntimeException("Submit Button "
-                                                                               
+ submit.getInputName() + " (path="
-                                                                               
+ component.getPageRelativePath() + ") is not visible");
-                                                       }
-                                                       return submit;
-                                               }
-                                               return CONTINUE_TRAVERSAL;
-                                       }
-                               });
+                       // Create array that holds size + 1 elements
+                       final IFormValidator[] validators = new 
IFormValidator[size + 1];
 
-               return submittingButton;
-       }
+                       // Loop through existing validators copying them
+                       for (int i = 0; i < size; i++)
+                       {
+                               validators[i] = formValidators_get(i);
+                       }
 
-       /**
-        * Gets the form component persistence manager; it is lazy loaded.
-        * 
-        * @return The form component value persister
-        */
-       protected IValuePersister getValuePersister()
-       {
-               return new CookieValuePersister();
+                       // Add new validator to the end
+                       validators[size] = validator;
+
+                       // Save new validator list
+                       this.formValidators = validators;
+               }
        }
 
        /**
-        * Gets whether the current form has any error registered.
+        * Gets form validator from formValidators Object (which may be an 
array of
+        * IFormValidators or a single instance, for efficiency) at the given 
index
         * 
-        * @return True if this form has at least one error.
+        * @param index
+        *            The index of the validator to get
+        * @return The form validator
         */
-       public final boolean hasError()
+       private IFormValidator formValidators_get(int index)
        {
-               // if this form itself has an error message
-               if (hasErrorMessage())
+               if (this.formValidators == null)
                {
-                       return true;
+                       throw new IndexOutOfBoundsException();
                }
-
-               // the form doesn't have any errors, now check any nested form
-               // components
-               return anyFormComponentError();
+               if (this.formValidators instanceof IFormValidator[])
+               {
+                       return ((IFormValidator[])formValidators)[index];
+               }
+               return (IFormValidator)formValidators;
        }
 
        /**
-        * @see org.apache.wicket.Component#internalOnModelChanged()
+        * @return The number of form validators in the formValidators Object 
(which
+        *         may be an array of IFormValidators or a single instance, for
+        *         efficiency)
         */
-       protected void internalOnModelChanged()
+       private int formValidators_size()
        {
-               // Visit all the form components and validate each
-               visitFormComponentsPostOrder(new FormComponent.AbstractVisitor()
+               if (this.formValidators == null)
                {
-                       public void onFormComponent(final FormComponent 
formComponent)
-                       {
-                               // If form component is using form model
-                               if (formComponent.sameInnermostModel(Form.this))
-                               {
-                                       formComponent.modelChanged();
-                               }
-                       }
-               });
+                       return 0;
+               }
+               if (this.formValidators instanceof IFormValidator[])
+               {
+                       return ((IFormValidator[])formValidators).length;
+               }
+               return 1;
        }
 
        /**
-        * Mark each form component on this form invalid.
+        * Visits the form's children FormComponents and inform them that a new 
user
+        * input is available in the Request
         */
-       protected final void markFormComponentsInvalid()
+       private void inputChanged()
        {
-               // call invalidate methods of all nested form components
                visitFormComponentsPostOrder(new FormComponent.AbstractVisitor()
                {
                        public void onFormComponent(final FormComponent 
formComponent)
                        {
                                if (formComponent.isVisibleInHierarchy())
                                {
-                                       formComponent.invalid();
+                                       formComponent.inputChanged();
                                }
                        }
                });
        }
 
        /**
-        * Mark each form component on this form valid.
+        * Persist (e.g. Cookie) FormComponent data to be reloaded and 
re-assigned
+        * to the FormComponent automatically when the page is visited by the 
user
+        * next time.
+        * 
+        * @see org.apache.wicket.markup.html.form.FormComponent#updateModel()
         */
-       protected final void markFormComponentsValid()
+       private void persistFormComponentData()
        {
-               // call invalidate methods of all nested form components
-               visitFormComponentsPostOrder(new FormComponent.AbstractVisitor()
+               // Cannot add cookies to request cycle unless it accepts them
+               // We could conceivably be HTML over some other protocol!
+               if (getRequestCycle() instanceof WebRequestCycle)
                {
-                       public void onFormComponent(final FormComponent 
formComponent)
+                       // The persistence manager responsible to persist and 
retrieve
+                       // FormComponent data
+                       final IValuePersister persister = getValuePersister();
+
+                       // Search for FormComponent children. Ignore all other
+                       visitFormComponentsPostOrder(new 
FormComponent.AbstractVisitor()
                        {
-                               if (formComponent.isVisibleInHierarchy())
+                               public void onFormComponent(final FormComponent 
formComponent)
                                {
-                                       formComponent.valid();
+                                       if 
(formComponent.isVisibleInHierarchy())
+                                       {
+                                               // If peristence is switched on 
for that FormComponent
+                                               // ...
+                                               if 
(formComponent.isPersistent())
+                                               {
+                                                       // Save component's 
data (e.g. in a cookie)
+                                                       
persister.save(formComponent);
+                                               }
+                                               else
+                                               {
+                                                       // Remove component's 
data (e.g. cookie)
+                                                       
persister.clear(formComponent);
+                                               }
+                                       }
                                }
-                       }
-               });
-       }
-
-       /**
-        * Returns the HiddenFieldId which will be used as the name and id 
property
-        * of the hiddenfield that is generated for event dispatches.
-        * 
-        * @return The name and id of the hidden field.
-        */
-       protected final String getHiddenFieldId()
-       {
-               return getJavascriptId() + "_hf_0";
-       }
-
-       /**
-        * Returns the javascript/css id of this form that will be used to 
generated
-        * the id="xxx" attribute. it will be generated if not set already in 
the
-        * onComponentTag. Where it will be tried to load from the markup first
-        * before it is generated.
-        * 
-        * @return The javascript/css id of this form.
-        */
-       protected final String getJavascriptId()
-       {
-               if (Strings.isEmpty(javascriptId))
-               {
-                       javascriptId = getMarkupId();
+                       });
                }
-               return javascriptId;
        }
 
        /**
-        * Append an additional hidden input tag to support anchor tags that can
-        * submit a form.
+        * If a default button was set on this form, this method will be called 
to
+        * render an extra field with an invisible style so that pressing enter 
in
+        * one of the textfields will do a form submit using this button. This
+        * method is overridable as what we do is best effort only, and may not 
what
+        * you want in specific situations. So if you have specific usability
+        * concerns, or want to follow another strategy, you may override this
+        * method.
         * 
         * @param markupStream
         *            The markup stream
         * @param openTag
         *            The open tag for the body
         */
-       protected void onComponentTagBody(final MarkupStream markupStream, 
final ComponentTag openTag)
+       protected void appendDefaultButtonField(final MarkupStream markupStream,
+                       final ComponentTag openTag)
        {
-               if (isRootForm())
+               String nameAndId = getHiddenFieldId();
+               AppendingStringBuffer buffer = new AppendingStringBuffer();
+               // get the value, first seeing whether the value attribute is 
set
+               // by a model
+               String value = defaultButton.getModelObjectAsString();
+               if (value == null || "".equals(value))
                {
-                       // get the hidden field id
-                       String nameAndId = getHiddenFieldId();
-
-                       // render the hidden field
-                       AppendingStringBuffer buffer = new 
AppendingStringBuffer(
-                                       "<div style=\"display:none\"><input 
type=\"hidden\" name=\"").append(nameAndId)
-                                       .append("\" 
id=\"").append(nameAndId).append("\" /></div>");
-                       getResponse().write(buffer);
-
-                       // if a default button was set, handle the rendering of 
that
-                       if (defaultButton != null && 
defaultButton.isVisibleInHierarchy()
-                                       && defaultButton.isEnabled())
-                       {
-                               appendDefaultButtonField(markupStream, openTag);
-                       }
+                       // nope it isn't; try to read from the attributes
+                       // note that we're only trying lower case here
+                       value = 
defaultButton.getMarkupAttributes().getString("value");
                }
 
-               // do the rest of the processing
-               super.onComponentTagBody(markupStream, openTag);
+               // append the button
+               buffer.append("<input type=\"submit\" 
value=\"").append(value).append("\" name=\"").append(
+                               defaultButton.getInputName()).append("\"");
+               buffer.append("style=\"width: 0px; height: 0px; position: 
absolute; left:-100px;\"");
+               buffer.append(" />");
+               getResponse().write(buffer);
+       }
+
+       /**
+        * Template method to allow clients to do any processing (like 
recording the
+        * current model so that, in case onSubmit does further validation, the
+        * model can be rolled back) before the actual updating of form 
component
+        * models is done.
+        */
+       protected void beforeUpdateFormComponentModels()
+       {
+       }
+
+       /**
+        * Called (by the default implementation of 'process') when all fields
+        * validated, the form was updated and it's data was allowed to be
+        * persisted. It is meant for delegating further processing to clients.
+        * <p>
+        * This implementation first finds out whether the form processing was
+        * triggered by a nested button of this form. If that is the case, that
+        * button's onSubmit is called first.
+        * </p>
+        * <p>
+        * Regardless of whether a submitting button was found, the form's 
onSubmit
+        * method is called next.
+        * </p>
+        * 
+        * @param submittingButton
+        *            the button that triggered this form processing, or null 
if the
+        *            processing was triggered by something else (like a 
non-Wicket
+        *            submit button or a javascript execution)
+        */
+       protected void delegateSubmit(IFormSubmittingComponent submittingButton)
+       {
+               // when the given button is not null, it means that it was the
+               // submitting button
+               if (submittingButton != null)
+               {
+                       submittingButton.onSubmit();
+               }
+
+               // Model was successfully updated with valid data
+               onSubmit();
+       }
+
+       /**
+        * Returns the HiddenFieldId which will be used as the name and id 
property
+        * of the hiddenfield that is generated for event dispatches.
+        * 
+        * @return The name and id of the hidden field.
+        */
+       protected final String getHiddenFieldId()
+       {
+               return getJavascriptId() + "_hf_0";
+       }
+
+       /**
+        * Returns the javascript/css id of this form that will be used to 
generated
+        * the id="xxx" attribute. it will be generated if not set already in 
the
+        * onComponentTag. Where it will be tried to load from the markup first
+        * before it is generated.
+        * 
+        * @return The javascript/css id of this form.
+        */
+       protected final String getJavascriptId()
+       {
+               if (Strings.isEmpty(javascriptId))
+               {
+                       javascriptId = getMarkupId();
+               }
+               return javascriptId;
+       }
+
+
+       /**
+        * Gets the method used to submit the form. Defaults to 'post'. Override
+        * this if you have a requirement to alter this behavior.
+        * 
+        * @return the method used to submit the form.
+        */
+       protected String getMethod()
+       {
+               return METHOD_POST;
+       }
+
+       protected boolean getStatelessHint()
+       {
+               return false;
+       }
+
+       /**
+        * Gets the form component persistence manager; it is lazy loaded.
+        * 
+        * @return The form component value persister
+        */
+       protected IValuePersister getValuePersister()
+       {
+               return new CookieValuePersister();
+       }
+
+       /**
+        * Handles multi-part processing of the submitted data.
+        * 
+        * WARNING
+        * 
+        * If this method is overridden it can break [EMAIL PROTECTED] 
FileUploadField}s on
+        * this form
+        * 
+        * @return false if form is multipart and upload failed
+        */
+       protected boolean handleMultiPart()
+       {
+               if (multiPart)
+               {
+                       // Change the request to a multipart web request so 
parameters are
+                       // parsed out correctly
+                       try
+                       {
+                               final WebRequest multipartWebRequest = 
((WebRequest)getRequest())
+                                               
.newMultipartWebRequest(this.maxSize);
+                               
getRequestCycle().setRequest(multipartWebRequest);
+                       }
+                       catch (WicketRuntimeException wre)
+                       {
+                               if (wre.getCause() == null || !(wre.getCause() 
instanceof FileUploadException))
+                               {
+                                       throw wre;
+                               }
+
+                               FileUploadException e = 
(FileUploadException)wre.getCause();
+                               // Create model with exception and maximum size 
values
+                               final Map model = new HashMap();
+                               model.put("exception", e);
+                               model.put("maxSize", maxSize);
+
+                               if (e instanceof SizeLimitExceededException)
+                               {
+                                       // Resource key should be 
<form-id>.uploadTooLarge to
+                                       // override default message
+                                       final String defaultValue = "Upload 
must be less than " + maxSize;
+                                       String msg = getString(getId() + "." + 
UPLOAD_TOO_LARGE_RESOURCE_KEY, Model
+                                                       .valueOf(model), 
defaultValue);
+                                       error(msg);
+
+                                       if (log.isDebugEnabled())
+                                       {
+                                               log.error(msg, e);
+                                       }
+                                       else
+                                       {
+                                               log.error(msg);
+                                       }
+                               }
+                               else
+                               {
+                                       // Resource key should be 
<form-id>.uploadFailed to override
+                                       // default message
+                                       final String defaultValue = "Upload 
failed: " + e.getLocalizedMessage();
+                                       String msg = getString(getId() + "." + 
UPLOAD_FAILED_RESOURCE_KEY, Model
+                                                       .valueOf(model), 
defaultValue);
+                                       error(msg);
+
+                                       log.error(msg, e);
+                               }
+
+                               // don't process the form if there is a 
FileUploadException
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       /**
+        * @see org.apache.wicket.Component#internalOnModelChanged()
+        */
+       protected void internalOnModelChanged()
+       {
+               // Visit all the form components and validate each
+               visitFormComponentsPostOrder(new FormComponent.AbstractVisitor()
+               {
+                       public void onFormComponent(final FormComponent 
formComponent)
+                       {
+                               // If form component is using form model
+                               if (formComponent.sameInnermostModel(Form.this))
+                               {
+                                       formComponent.modelChanged();
+                               }
+                       }
+               });
+       }
+
+       /**
+        * Mark each form component on this form invalid.
+        */
+       protected final void markFormComponentsInvalid()
+       {
+               // call invalidate methods of all nested form components
+               visitFormComponentsPostOrder(new FormComponent.AbstractVisitor()
+               {
+                       public void onFormComponent(final FormComponent 
formComponent)
+                       {
+                               if (formComponent.isVisibleInHierarchy())
+                               {
+                                       formComponent.invalid();
+                               }
+                       }
+               });
+       }
+
+       /**
+        * Mark each form component on this form valid.
+        */
+       protected final void markFormComponentsValid()
+       {
+               // call invalidate methods of all nested form components
+               visitFormComponentsPostOrder(new FormComponent.AbstractVisitor()
+               {
+                       public void onFormComponent(final FormComponent 
formComponent)
+                       {
+                               if (formComponent.isVisibleInHierarchy())
+                               {
+                                       formComponent.valid();
+                               }
+                       }
+               });
        }
 
        /**
@@ -924,83 +1412,83 @@
        }
 
        /**
-        * Method to override if you want to do something special when an error
-        * occurs (other than simply displaying validation errors).
-        */
-       protected void onError()
-       {
-       }
-
-       /**
-        * @see org.apache.wicket.Component#onRender(MarkupStream)
+        * Append an additional hidden input tag to support anchor tags that can
+        * submit a form.
+        * 
+        * @param markupStream
+        *            The markup stream
+        * @param openTag
+        *            The open tag for the body
         */
-       protected void onRender(final MarkupStream markupStream)
+       protected void onComponentTagBody(final MarkupStream markupStream, 
final ComponentTag openTag)
        {
-               // Force multi-part on if any child form component is multi-part
-               visitFormComponents(new FormComponent.AbstractVisitor()
+               if (isRootForm())
                {
-                       public void onFormComponent(FormComponent formComponent)
-                       {
-                               if (formComponent.isVisible() && 
formComponent.isMultiPart())
-                               {
-                                       setMultiPart(true);
-                               }
+                       // get the hidden field id
+                       String nameAndId = getHiddenFieldId();
+
+                       // render the hidden field
+                       AppendingStringBuffer buffer = new 
AppendingStringBuffer(
+                                       "<div style=\"display:none\"><input 
type=\"hidden\" name=\"").append(nameAndId)
+                                       .append("\" 
id=\"").append(nameAndId).append("\" /></div>");
+                       getResponse().write(buffer);
+
+                       // if a default button was set, handle the rendering of 
that
+                       if (defaultButton != null && 
defaultButton.isVisibleInHierarchy()
+                                       && defaultButton.isEnabled())
+                       {
+                               appendDefaultButtonField(markupStream, openTag);
                        }
-               });
+               }
 
-               super.onRender(markupStream);
+               // do the rest of the processing
+               super.onComponentTagBody(markupStream, openTag);
        }
 
        /**
-        * Implemented by subclasses to deal with form submits.
+        * @see org.apache.wicket.Component#onDetach()
         */
-       protected void onSubmit()
+       protected void onDetach()
        {
+               super.internalOnDetach();
+               setFlag(FLAG_SUBMITTED, false);
+
+               super.onDetach();
        }
 
        /**
-        * Process the form. Though you can override this method to provide your
-        * whole own algorithm, it is not recommended to do so.
-        * <p>
-        * See the class documentation for further details on the form 
processing
-        * </p>
-        * 
-        * @return False if the form had an error
+        * Method to override if you want to do something special when an error
+        * occurs (other than simply displaying validation errors).
         */
-       public boolean process()
+       protected void onError()
        {
-               // run validation
-               validate();
-
-               // If a validation error occurred
-               if (hasError())
-               {
-                       // mark all children as invalid
-                       markFormComponentsInvalid();
-
-                       // let subclass handle error
-                       onError();
+       }
 
-                       // Form has an error
-                       return false;
-               }
-               else
+       /**
+        * @see org.apache.wicket.Component#onRender(MarkupStream)
+        */
+       protected void onRender(final MarkupStream markupStream)
+       {
+               // Force multi-part on if any child form component is multi-part
+               visitFormComponents(new FormComponent.AbstractVisitor()
                {
-                       // mark all childeren as valid
-                       markFormComponentsValid();
-
-                       // before updating, call the interception method for 
clients
-                       beforeUpdateFormComponentModels();
-
-                       // Update model using form data
-                       updateFormComponentModels();
+                       public void onFormComponent(FormComponent formComponent)
+                       {
+                               if (formComponent.isVisible() && 
formComponent.isMultiPart())
+                               {
+                                       setMultiPart(true);
+                               }
+                       }
+               });
 
-                       // Persist FormComponents if requested
-                       persistFormComponentData();
+               super.onRender(markupStream);
+       }
 
-                       // Form has no error
-                       return true;
-               }
+       /**
+        * Implemented by subclasses to deal with form submits.
+        */
+       protected void onSubmit()
+       {
        }
 
        /**
@@ -1022,27 +1510,6 @@
        }
 
        /**
-        * Clears the input from the form's nested children of type
-        * [EMAIL PROTECTED] FormComponent}. This method is typically called 
when a form needs
-        * to be reset.
-        */
-       public final void clearInput()
-       {
-               // Visit all the (visible) form components and clear the input 
on each.
-               visitFormComponentsPostOrder(new FormComponent.AbstractVisitor()
-               {
-                       public void onFormComponent(final FormComponent 
formComponent)
-                       {
-                               if (formComponent.isVisibleInHierarchy())
-                               {
-                                       // Clear input from form component
-                                       formComponent.clearInput();
-                               }
-                       }
-               });
-       }
-
-       /**
         * Validates the form by checking required fields, converting raw input 
and
         * running validators for every form component, and last running global 
form
         * validators. This method is typically called before updating any 
models.
@@ -1057,7 +1524,6 @@
                validateFormValidators();
        }
 
-
        /**
         * Triggers type conversion on form components
         */
@@ -1073,18 +1539,6 @@
        }
 
        /**
-        * Triggers any added [EMAIL PROTECTED] IFormValidator}s.
-        */
-       protected final void validateFormValidators()
-       {
-               final int count = formValidators_size();
-               for (int i = 0; i < count; i++)
-               {
-                       validateFormValidator(formValidators_get(i));
-               }
-       }
-
-       /**
         * Validates form with the given form validator
         * 
         * @param validator
@@ -1120,468 +1574,14 @@
        }
 
        /**
-        * Find out whether there is any registered error for a form component.
-        * 
-        * @return whether there is any registered error for a form component
-        */
-       private boolean anyFormComponentError()
-       {
-               final Object value = visitChildren(new IVisitor()
-               {
-                       public Object component(final Component component)
-                       {
-                               if (component.hasErrorMessage())
-                               {
-                                       return STOP_TRAVERSAL;
-                               }
-
-                               // Traverse all children
-                               return CONTINUE_TRAVERSAL;
-                       }
-               });
-
-               return value == IVisitor.STOP_TRAVERSAL ? true : false;
-       }
-
-       /**
-        * Handles multi-part processing of the submitted data.
-        * 
-        * WARNING
-        * 
-        * If this method is overridden it can break [EMAIL PROTECTED] 
FileUploadField}s on
-        * this form
-        * 
-        * @return false if form is multipart and upload failed
+        * Triggers any added [EMAIL PROTECTED] IFormValidator}s.
         */
-       protected boolean handleMultiPart()
+       protected final void validateFormValidators()
        {
-               if (multiPart)
+               final int count = formValidators_size();
+               for (int i = 0; i < count; i++)
                {
-                       // Change the request to a multipart web request so 
parameters are
-                       // parsed out correctly
-                       try
-                       {
-                               final WebRequest multipartWebRequest = 
((WebRequest)getRequest())
-                                               
.newMultipartWebRequest(this.maxSize);
-                               
getRequestCycle().setRequest(multipartWebRequest);
-                       }
-                       catch (WicketRuntimeException wre)
-                       {
-                               if (wre.getCause() == null || !(wre.getCause() 
instanceof FileUploadException))
-                               {
-                                       throw wre;
-                               }
-
-                               FileUploadException e = 
(FileUploadException)wre.getCause();
-                               // Create model with exception and maximum size 
values
-                               final Map model = new HashMap();
-                               model.put("exception", e);
-                               model.put("maxSize", maxSize);
-
-                               if (e instanceof SizeLimitExceededException)
-                               {
-                                       // Resource key should be 
<form-id>.uploadTooLarge to
-                                       // override default message
-                                       final String defaultValue = "Upload 
must be less than " + maxSize;
-                                       String msg = getString(getId() + "." + 
UPLOAD_TOO_LARGE_RESOURCE_KEY, Model
-                                                       .valueOf(model), 
defaultValue);
-                                       error(msg);
-
-                                       if (log.isDebugEnabled())
-                                       {
-                                               log.error(msg, e);
-                                       }
-                                       else
-                                       {
-                                               log.error(msg);
-                                       }
-                               }
-                               else
-                               {
-                                       // Resource key should be 
<form-id>.uploadFailed to override
-                                       // default message
-                                       final String defaultValue = "Upload 
failed: " + e.getLocalizedMessage();
-                                       String msg = getString(getId() + "." + 
UPLOAD_FAILED_RESOURCE_KEY, Model
-                                                       .valueOf(model), 
defaultValue);
-                                       error(msg);
-
-                                       log.error(msg, e);
-                               }
-
-                               // don't process the form if there is a 
FileUploadException
-                               return false;
-                       }
+                       validateFormValidator(formValidators_get(i));
                }
-               return true;
-       }
-
-       /**
-        * Persist (e.g. Cookie) FormComponent data to be reloaded and 
re-assigned
-        * to the FormComponent automatically when the page is visited by the 
user
-        * next time.
-        * 
-        * @see org.apache.wicket.markup.html.form.FormComponent#updateModel()
-        */
-       private void persistFormComponentData()
-       {
-               // Cannot add cookies to request cycle unless it accepts them
-               // We could conceivably be HTML over some other protocol!
-               if (getRequestCycle() instanceof WebRequestCycle)
-               {
-                       // The persistence manager responsible to persist and 
retrieve
-                       // FormComponent data
-                       final IValuePersister persister = getValuePersister();
-
-                       // Search for FormComponent children. Ignore all other
-                       visitFormComponentsPostOrder(new 
FormComponent.AbstractVisitor()
-                       {
-                               public void onFormComponent(final FormComponent 
formComponent)
-                               {
-                                       if 
(formComponent.isVisibleInHierarchy())
-                                       {
-                                               // If peristence is switched on 
for that FormComponent
-                                               // ...
-                                               if 
(formComponent.isPersistent())
-                                               {
-                                                       // Save component's 
data (e.g. in a cookie)
-                                                       
persister.save(formComponent);
-                                               }
-                                               else
-                                               {
-                                                       // Remove component's 
data (e.g. cookie)
-                                                       
persister.clear(formComponent);
-                                               }
-                                       }
-                               }
-                       });
-               }
-       }
-
-       /**
-        * Method for dispatching/calling a interface on a page from the given 
url.
-        * Used by [EMAIL PROTECTED] 
org.apache.wicket.markup.html.form.Form#onFormSubmitted()}
-        * for dispatching events
-        * 
-        * @param page
-        *            The page where the event should be called on.
-        * @param url
-        *            The url which describes the component path and the 
interface
-        *            to be called.
-        */
-       private void dispatchEvent(final Page page, final String url)
-       {
-               RequestCycle rc = RequestCycle.get();
-               IRequestCycleProcessor processor = rc.getProcessor();
-               final RequestParameters requestParameters = 
processor.getRequestCodingStrategy().decode(
-                               new FormDispatchRequest(rc.getRequest(), url));
-               IRequestTarget rt = processor.resolve(rc, requestParameters);
-               if (rt instanceof ListenerInterfaceRequestTarget)
-               {
-                       ListenerInterfaceRequestTarget interfaceTarget = 
((ListenerInterfaceRequestTarget)rt);
-                       
interfaceTarget.getRequestListenerInterface().invoke(page, 
interfaceTarget.getTarget());
-               }
-               else
-               {
-                       throw new WicketRuntimeException(
-                                       "Attempt to access unknown request 
listener interface "
-                                                       + 
requestParameters.getInterfaceName());
-               }
-       }
-
-       /**
-        * Visits the form's children FormComponents and inform them that a new 
user
-        * input is available in the Request
-        */
-       private void inputChanged()
-       {
-               visitFormComponentsPostOrder(new FormComponent.AbstractVisitor()
-               {
-                       public void onFormComponent(final FormComponent 
formComponent)
-                       {
-                               if (formComponent.isVisibleInHierarchy())
-                               {
-                                       formComponent.inputChanged();
-                               }
-                       }
-               });
-       }
-
-       /**
-        * This generates a piece of javascript code that sets the url in the
-        * special hidden field and submits the form.
-        * 
-        * Warning: This code should only be called in the rendering phase for 
form
-        * components inside the form because it uses the css/javascript id of 
the
-        * form which can be stored in the markup.
-        * 
-        * @param url
-        *            The interface url that has to be stored in the hidden 
field
-        *            and submitted
-        * @return The javascript code that submits the form.
-        */
-       public final CharSequence getJsForInterfaceUrl(CharSequence url)
-       {
-               return new 
AppendingStringBuffer("document.getElementById('").append(getHiddenFieldId())
-                               
.append("').value='").append(url).append("';document.getElementById('").append(
-                                               
getJavascriptId()).append("').submit();");
-       }
-
-       /**
-        * 
-        */
-       class FormDispatchRequest extends Request
-       {
-               private final Request realRequest;
-
-               private final String url;
-
-               private final ValueMap params = new ValueMap();
-
-               /**
-                * Construct.
-                * 
-                * @param realRequest
-                * @param url
-                */
-               public FormDispatchRequest(final Request realRequest, final 
String url)
-               {
-                       this.realRequest = realRequest;
-                       this.url = realRequest.decodeURL(url);
-
-                       String queryString = 
this.url.substring(this.url.indexOf("?") + 1);
-                       RequestUtils.decodeParameters(queryString, params);
-               }
-
-               /**
-                * @see org.apache.wicket.Request#getLocale()
-                */
-               public Locale getLocale()
-               {
-                       return realRequest.getLocale();
-               }
-
-               /**
-                * @see org.apache.wicket.Request#getParameter(java.lang.String)
-                */
-               public String getParameter(String key)
-               {
-                       return (String)params.get(key);
-               }
-
-               /**
-                * @see org.apache.wicket.Request#getParameterMap()
-                */
-               public Map getParameterMap()
-               {
-                       return params;
-               }
-
-               /**
-                * @see 
org.apache.wicket.Request#getParameters(java.lang.String)
-                */
-               public String[] getParameters(String key)
-               {
-                       String param = (String)params.get(key);
-                       if (param != null)
-                       {
-                               return new String[] { param };
-                       }
-                       return new String[0];
-               }
-
-               /**
-                * @see org.apache.wicket.Request#getPath()
-                */
-               public String getPath()
-               {
-                       return realRequest.getPath();
-               }
-
-               /**
-                * @see org.apache.wicket.Request#getURL()
-                */
-               public String getURL()
-               {
-                       return url;
-               }
-
-               public String getRelativePathPrefixToContextRoot()
-               {
-                       return realRequest.getRelativePathPrefixToContextRoot();
-               }
-
-               public String getRelativePathPrefixToWicketHandler()
-               {
-                       return 
realRequest.getRelativePathPrefixToWicketHandler();
-               }
-       }
-
-       /**
-        * Returns the prefix used when building validator keys. This allows a 
form
-        * to use a separate "set" of keys. For example if prefix "short" is
-        * returned, validator key short.Required will be tried instead of
-        * Required key.
-        * <p>
-        * This can be useful when different designs are used for a form. In a 
form
-        * where error messages are displayed next to their respective form
-        * components as opposed to at the top of the form, the ${label} 
attribute
-        * is of little use and only causes redundant information to appear in 
the
-        * message. Forms like these can return the "short" (or any other 
string)
-        * validator prefix and declare key: short.Required=required to
-        * override the longer message which is usually declared like this:
-        * Required=${label} is a required field
-        * <p>
-        * Returned prefix will be used for all form components. The prefix can 
also
-        * be overridden on form component level by overriding
-        * [EMAIL PROTECTED] FormComponent#getValidatorKeyPrefix()}
-        * 
-        * @return prefix prepended to validator keys
-        */
-       public String getValidatorKeyPrefix()
-       {
-               return null;
-       }
-
-       /**
-        * Adds a form validator to the form.
-        * 
-        * @param validator
-        *            validator
-        * @throws IllegalArgumentException
-        *             if validator is null
-        * @see IFormValidator
-        * @see IValidatorAddListener
-        */
-       public void add(IFormValidator validator)
-       {
-               if (validator == null)
-               {
-                       throw new IllegalArgumentException("validator argument 
cannot be null");
-               }
-
-               // add the validator
-               formValidators_add(validator);
-
-               // see whether the validator listens for add events
-               if (validator instanceof IValidatorAddListener)
-               {
-                       ((IValidatorAddListener)validator).onAdded(this);
-               }
-       }
-
-       /**
-        * @param validator
-        *            The form validator to add to the formValidators Object 
(which
-        *            may be an array of IFormValidators or a single instance, 
for
-        *            efficiency)
-        */
-       private void formValidators_add(final IFormValidator validator)
-       {
-               if (this.formValidators == null)
-               {
-                       this.formValidators = validator;
-               }
-               else
-               {
-                       // Get current list size
-                       final int size = formValidators_size();
-
-                       // Create array that holds size + 1 elements
-                       final IFormValidator[] validators = new 
IFormValidator[size + 1];
-
-                       // Loop through existing validators copying them
-                       for (int i = 0; i < size; i++)
-                       {
-                               validators[i] = formValidators_get(i);
-                       }
-
-                       // Add new validator to the end
-                       validators[size] = validator;
-
-                       // Save new validator list
-                       this.formValidators = validators;
-               }
-       }
-
-       /**
-        * Gets form validator from formValidators Object (which may be an 
array of
-        * IFormValidators or a single instance, for efficiency) at the given 
index
-        * 
-        * @param index
-        *            The index of the validator to get
-        * @return The form validator
-        */
-       private IFormValidator formValidators_get(int index)
-       {
-               if (this.formValidators == null)
-               {
-                       throw new IndexOutOfBoundsException();
-               }
-               if (this.formValidators instanceof IFormValidator[])
-               {
-                       return ((IFormValidator[])formValidators)[index];
-               }
-               return (IFormValidator)formValidators;
-       }
-
-       /**
-        * @return The number of form validators in the formValidators Object 
(which
-        *         may be an array of IFormValidators or a single instance, for
-        *         efficiency)
-        */
-       private int formValidators_size()
-       {
-               if (this.formValidators == null)
-               {
-                       return 0;
-               }
-               if (this.formValidators instanceof IFormValidator[])
-               {
-                       return ((IFormValidator[])formValidators).length;
-               }
-               return 1;
-       }
-
-       /**
-        * /** Registers an error feedback message for this component
-        * 
-        * @param error
-        *            error message
-        * @param args
-        *            argument replacement map for ${key} variables
-        */
-       public final void error(String error, Map args)
-       {
-               error(new MapVariableInterpolator(error, args).toString());
-       }
-
-       /**
-        * Returns whether the form is a root form, which means that there's no
-        * other form in it's parent hierarchy.
-        * 
-        * @return true if form is a root form, false otherwise
-        */
-       public boolean isRootForm()
-       {
-               return findParent(Form.class) == null;
-       }
-
-       /**
-        * Returns the root form or this, if this is the root form.
-        * 
-        * @return root form or this form
-        */
-       public Form getRootForm()
-       {
-               Form form;
-               Form parent = this;
-               do
-               {
-                       form = parent;
-                       parent = (Form)form.findParent(Form.class);
-               }
-               while (parent != null);
-
-               return form;
        }
 }


Reply via email to