Author: ivaynberg Date: Fri Apr 27 15:40:46 2007 New Revision: 533245 URL: http://svn.apache.org/viewvc?view=rev&rev=533245 Log: changed form processing workflow to use postorder traverasals. this should be a noop for normal formcomponents, but for compound formcomponents that extend formcomponentpanel life should get a lot better - by the time their workflow methods are called all their children should be processed and thus there is no need to cascade these calls onto children manually like there is with preorder traversal.
Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java?view=diff&rev=533245&r1=533244&r2=533245 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java (original) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java Fri Apr 27 15:40:46 2007 @@ -832,7 +832,7 @@ { return visitChildren(null, visitor); } - + /** * @param component * Component being added 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=533245&r1=533244&r2=533245 ============================================================================== --- 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 Fri Apr 27 15:40:46 2007 @@ -95,8 +95,8 @@ * Form for handling (file) uploads with multipart requests is supported by * callign setMultiPart(true) ( although wicket will try to automatically detect * this for you ). Use this with - * [EMAIL PROTECTED] org.apache.wicket.markup.html.form.upload.FileUploadField} components. You can - * attach mutliple FileUploadField components for muliple file uploads. + * [EMAIL PROTECTED] org.apache.wicket.markup.html.form.upload.FileUploadField} components. + * You can attach mutliple FileUploadField components for muliple file uploads. * <p> * In case of an upload error two resource keys are available to specify error * messages: uploadTooLarge and uploadFailed @@ -305,7 +305,7 @@ */ public final void loadPersistentFormComponentValues() { - visitFormComponents(new FormComponent.AbstractVisitor() + visitFormComponentsPostOrder(new FormComponent.AbstractVisitor() { public void onFormComponent(final FormComponent formComponent) { @@ -406,7 +406,7 @@ { super.internalOnDetach(); setFlag(FLAG_SUBMITTED, false); - + super.onDetach(); } @@ -427,7 +427,7 @@ final IValuePersister persister = getValuePersister(); // Search for FormComponents like TextField etc. - visitFormComponents(new FormComponent.AbstractVisitor() + visitFormComponentsPostOrder(new FormComponent.AbstractVisitor() { public void onFormComponent(final FormComponent formComponent) { @@ -529,6 +529,41 @@ /** * 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) + { + FormComponent.visitFormComponentsPostOrder(this, visitor); + + /** + * TODO Post 1.2 General: Maybe we should re-think how Borders are + * implemented, because there are just too many exceptions in the code + * base because of borders. This time it is to solve the problem tested + * in BoxBorderTestPage_3 where the Form is defined in the box border + * and the FormComponents are in the "body". Thus, the formComponents + * are not childs of the form. They are rather childs of the border, as + * the Form itself. + */ + if (getParent() instanceof Border) + { + MarkupContainer border = getParent(); + Iterator iter = border.iterator(); + while (iter.hasNext()) + { + Component child = (Component)iter.next(); + if (child instanceof FormComponent) + { + visitor.formComponent((FormComponent)child); + } + } + } + } + + /** + * Convenient and typesafe way to visit all the form components on a form * * @param visitor * The visitor interface to call @@ -717,7 +752,7 @@ protected void internalOnModelChanged() { // Visit all the form components and validate each - visitFormComponents(new FormComponent.AbstractVisitor() + visitFormComponentsPostOrder(new FormComponent.AbstractVisitor() { public void onFormComponent(final FormComponent formComponent) { @@ -736,7 +771,7 @@ protected final void markFormComponentsInvalid() { // call invalidate methods of all nested form components - visitFormComponents(new FormComponent.AbstractVisitor() + visitFormComponentsPostOrder(new FormComponent.AbstractVisitor() { public void onFormComponent(final FormComponent formComponent) { @@ -754,7 +789,7 @@ protected final void markFormComponentsValid() { // call invalidate methods of all nested form components - visitFormComponents(new FormComponent.AbstractVisitor() + visitFormComponentsPostOrder(new FormComponent.AbstractVisitor() { public void onFormComponent(final FormComponent formComponent) { @@ -974,7 +1009,7 @@ */ protected final void updateFormComponentModels() { - visitFormComponents(new ValidationVisitor() + visitFormComponentsPostOrder(new ValidationVisitor() { public void validate(FormComponent formComponent) { @@ -992,7 +1027,7 @@ public final void clearInput() { // Visit all the (visible) form components and clear the input on each. - visitFormComponents(new FormComponent.AbstractVisitor() + visitFormComponentsPostOrder(new FormComponent.AbstractVisitor() { public void onFormComponent(final FormComponent formComponent) { @@ -1030,7 +1065,7 @@ */ protected final void validateRequired() { - visitFormComponents(new ValidationVisitor() + visitFormComponentsPostOrder(new ValidationVisitor() { public void validate(final FormComponent formComponent) { @@ -1044,7 +1079,7 @@ */ protected final void validateConversion() { - visitFormComponents(new ValidationVisitor() + visitFormComponentsPostOrder(new ValidationVisitor() { public void validate(final FormComponent formComponent) { @@ -1058,7 +1093,7 @@ */ protected final void validateValidators() { - visitFormComponents(new ValidationVisitor() + visitFormComponentsPostOrder(new ValidationVisitor() { public void validate(final FormComponent formComponent) { @@ -1228,7 +1263,7 @@ final IValuePersister persister = getValuePersister(); // Search for FormComponent children. Ignore all other - visitFormComponents(new FormComponent.AbstractVisitor() + visitFormComponentsPostOrder(new FormComponent.AbstractVisitor() { public void onFormComponent(final FormComponent formComponent) { @@ -1254,8 +1289,8 @@ /** * 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 + * 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. @@ -1289,7 +1324,7 @@ */ private void inputChanged() { - visitFormComponents(new FormComponent.AbstractVisitor() + visitFormComponentsPostOrder(new FormComponent.AbstractVisitor() { public void onFormComponent(final FormComponent formComponent) { Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java?view=diff&rev=533245&r1=533244&r2=533245 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java (original) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java Fri Apr 27 15:40:46 2007 @@ -21,12 +21,14 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.wicket.Component; import org.apache.wicket.Localizer; +import org.apache.wicket.MarkupContainer; import org.apache.wicket.Page; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.markup.ComponentTag; @@ -569,7 +571,22 @@ */ public final boolean isValid() { - return !hasErrorMessage(); + final boolean valid[] = { true }; + visitFormComponentsPostOrder(this, new IVisitor() + { + public Object formComponent(IFormProcessingListener formComponent) + { + final FormComponent fc = (FormComponent)formComponent; + if (fc.hasErrorMessage()) + { + valid[0] = false; + return Component.IVisitor.STOP_TRAVERSAL; + } + return Component.IVisitor.CONTINUE_TRAVERSAL; + } + }); + + return valid[0]; } /** @@ -1316,4 +1333,65 @@ { return true; } + + /** + * Visits any form components inside component if it is a container, or + * component itself if it is itself a form component + * + * @param component + * starting point of the traversal + * + * @param visitor + * The visitor to call + */ + public static final void visitFormComponentsPostOrder(Component component, + final FormComponent.IVisitor visitor) + { + if (visitor == null) + { + throw new IllegalArgumentException("Argument `visitor` cannot be null"); + } + + + visitFormComponentsPostOrderHelper(component, visitor); + } + + private static final Object visitFormComponentsPostOrderHelper(Component component, + final FormComponent.IVisitor visitor) + { + if (component instanceof MarkupContainer) + { + final MarkupContainer container = (MarkupContainer)component; + if (container.size() > 0) + { + boolean visitChildren = true; + if (container instanceof IFormProcessingListener) + { + visitChildren = ((IFormProcessingListener)container).processChildren(); + } + if (visitChildren) + { + final Iterator children = container.iterator(); + while (children.hasNext()) + { + final Component child = (Component)children.next(); + Object value = visitFormComponentsPostOrderHelper(child, visitor); + if (value == Component.IVisitor.STOP_TRAVERSAL) + { + return value; + } + } + } + } + } + + if (component instanceof FormComponent) + { + final FormComponent fc = (FormComponent)component; + return visitor.formComponent(fc); + } + + return null; + } + }