diff --git a/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormVisitTest.java b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormVisitTest.java new file mode 100644 index 0000000000..4e2f039624 --- /dev/null +++ b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormVisitTest.java @@ -0,0 +1,557 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.wicket.markup.html.form; + +import org.apache.wicket.MarkupContainer; +import org.apache.wicket.markup.IMarkupResourceStreamProvider; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.form.validation.IFormValidator; +import org.apache.wicket.model.Model; +import org.apache.wicket.util.resource.IResourceStream; +import org.apache.wicket.util.resource.StringResourceStream; +import org.apache.wicket.util.tester.WicketTestCase; +import org.apache.wicket.validation.INullAcceptingValidator; +import org.apache.wicket.validation.IValidatable; +import org.apache.wicket.validation.IValidator; +import org.apache.wicket.validation.ValidationError; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * WICKET-3899 + * + * @author Pedro Santos + */ +public class FormVisitTest extends WicketTestCase +{ + TestFormPage page; + FormValidator formValidator = new FormValidator(); + AlwaysFail alwaysFail = new AlwaysFail(); + static int sequence; + + @BeforeEach + public void initialize() + { + page = new TestFormPage(); + tester.startPage(page); + } + + @Test + public void processForms() + { + page.outerForm.add(formValidator); + tester.newFormTester("outerForm").submit(); + + assertTrue(page.outerForm.onValidateCalled); + assertTrue(page.outerForm.onSubmitCalled); + assertTrue(page.outerForm.isSubmittedFlagged); + assertTrue(page.outerForm.onValidateModelObjectsCalled); + assertTrue(page.outerField.onValidCalled); + assertTrue(page.outerField.updateModelCalled); + assertTrue(formValidator.validatedCalled); + assertTrue(page.innerForm.onValidateCalled); + assertTrue(page.innerForm.onSubmitCalled); + assertTrue(page.innerForm.isSubmittedFlagged); + assertTrue(page.innerForm.onValidateModelObjectsCalled); + assertTrue(page.innerField.onValidCalled); + assertTrue(page.innerField.updateModelCalled); + } + + @Test + public void processOuterFormOnly() + { + page.outerForm.add(formValidator); + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + + assertTrue(page.outerForm.onValidateCalled); + assertTrue(page.outerForm.onSubmitCalled); + assertTrue(page.outerForm.isSubmittedFlagged); + assertTrue(page.outerForm.onValidateModelObjectsCalled); + assertTrue(page.outerField.onValidCalled); + assertTrue(page.outerField.updateModelCalled); + assertTrue(formValidator.validatedCalled); + assertFalse(page.innerForm.onValidateCalled); + assertFalse(page.innerForm.onSubmitCalled); + assertFalse(page.innerForm.isSubmittedFlagged); + assertFalse(page.innerForm.onValidateModelObjectsCalled); + assertFalse(page.innerField.onValidCalled); + assertFalse(page.innerField.updateModelCalled); + } + + @Test + public void processInnerFormOnly() + { + page.outerForm.add(formValidator); + tester.newFormTester("outerForm:outerContainer:innerForm").submit("innerContainer:innerFormSubmitButton"); + + assertFalse(page.outerForm.onValidateCalled); + assertFalse(page.outerForm.onSubmitCalled); + assertFalse(page.outerForm.isSubmittedFlagged); + assertFalse(page.outerForm.onValidateModelObjectsCalled); + assertFalse(page.outerField.onValidCalled); + assertFalse(page.outerField.updateModelCalled); + assertFalse(formValidator.validatedCalled); + assertTrue(page.innerForm.onValidateCalled); + assertTrue(page.innerForm.onSubmitCalled); + assertTrue(page.innerForm.isSubmittedFlagged); + assertTrue(page.innerForm.onValidateModelObjectsCalled); + assertTrue(page.innerField.onValidCalled); + assertTrue(page.innerField.updateModelCalled); + } + + @Test + public void validateInnerForm() + { + tester.newFormTester("outerForm").submit(); + + assertTrue(page.innerForm.onValidateCalled); + } + + @Test + public void dontValidateInnerForm() + { + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + assertFalse(page.innerForm.onValidateCalled); + } + + @Test + public void callInnerFormOnError() + { + page.innerField.add(alwaysFail); + tester.newFormTester("outerForm").submit(); + + assertTrue(page.innerForm.onErrorCalled); + } + + @Test + public void dontCallInnerFormOnErrorIfNotProcessChildren() + { + page.innerField.add(alwaysFail); + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + + assertFalse(page.innerForm.onErrorCalled); + } + + @Test + public void dontCallInnerFormOnErrorIfNotEnabled() + { + page.innerField.add(alwaysFail); + page.innerForm.setEnabled(false); + tester.newFormTester("outerForm").submit(); + + assertFalse(page.innerForm.onErrorCalled); + } + + @Test + public void dontCallOuterFormOnErrorTwice() + { + page.outerField.add(alwaysFail); + tester.newFormTester("outerForm").submit(); + + assertEquals(1, page.outerForm.numberOfOnErrorCalls); + } + + @Test + public void submitInnerForm() + { + tester.newFormTester("outerForm").submit(); + + assertTrue(page.innerForm.onSubmitCalled); + } + + @Test + public void dontSubmitInnerForm() + { + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + + assertFalse(page.innerForm.onSubmitCalled); + } + + @Test + public void setInnerFormSubmittedFlag() + { + tester.newFormTester("outerForm").submit(); + + assertTrue(page.innerForm.isSubmittedFlagged); + } + + @Test + public void dontSetInnerFormSubmittedFlag() + { + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + + assertFalse(page.innerForm.isSubmittedFlagged); + } + + @Test + public void validateInnerFormField() + { + page.innerField.add(alwaysFail); + tester.newFormTester("outerForm").submit(); + + assertTrue(alwaysFail.validatedCalled); + } + + @Test + public void dontValidateInnerFormFieldIfNotProcessChildren() + { + page.innerField.add(alwaysFail); + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + + assertFalse(alwaysFail.validatedCalled); + } + + @Test + public void dontValidateInnerFormFieldIfNotEnabled() + { + page.innerField.add(alwaysFail); + page.innerForm.setEnabled(false); + tester.newFormTester("outerForm").submit(); + + assertFalse(alwaysFail.validatedCalled); + } + + @Test + public void validateFormValidator() + { + page.innerForm.add(formValidator); + tester.newFormTester("outerForm").submit(); + + assertTrue(formValidator.validatedCalled); + } + + @Test + public void dontValidateFormValidatorIfFormNotEnabled() + { + page.innerForm.add(formValidator); + page.innerForm.setEnabled(false); + tester.newFormTester("outerForm").submit(); + + assertFalse(formValidator.validatedCalled); + } + + @Test + public void dontValidateFormValidatorIfFormNotProcessed() + { + page.innerForm.add(formValidator); + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + + assertFalse(formValidator.validatedCalled); + } + + @Test + public void dontValidateFormValidatorIfDependentNotEnabled() + { + page.innerForm.add(formValidator.setDependency(page.innerField)); + page.innerContainer.setEnabled(false); + tester.newFormTester("outerForm").submit(); + + assertFalse(formValidator.validatedCalled); + } + + @Test + public void dontValidateFormValidatorIfDependentNotProcessed() + { + page.outerForm.add(formValidator.setDependency(page.innerField)); + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + + assertFalse(formValidator.validatedCalled); + } + + @Test + public void validateFormValidatorIfDependentIsParticipant() + { + page.outerForm.add(formValidator.setDependency(page.innerField)); + // currently this flag affects just how form components are + // visited inside their form, the test just reflects this expectation + page.outerContainer.processChildren = false; + tester.newFormTester("outerForm").submit(); + + assertTrue(formValidator.validatedCalled); + } + + @Test + public void dontValidateFormValidatorIfDependentNorParticipant() + { + page.outerForm.add(formValidator.setDependency(page.innerField)); + page.innerContainer.processChildren = false; + tester.newFormTester("outerForm").submit(); + + assertFalse(formValidator.validatedCalled); + } + + @Test + public void validateInnerFormComponent() + { + tester.newFormTester("outerForm").submit(); + + assertTrue(page.innerField.onValidCalled); + } + + @Test + public void dontValidateInnerFormComponent() + { + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + + assertFalse(page.innerField.onValidCalled); + } + + @Test + public void validateFormComponentsInPostorder() + { + tester.newFormTester("outerForm").submit(); + + assertTrue(page.innerField.onValidCallOrder < page.outerField.onValidCallOrder); + } + + @Test + public void updateInnerFormComponentModel() + { + tester.newFormTester("outerForm").submit(); + + assertTrue(page.innerField.updateModelCalled); + } + + @Test + public void dontUpdateInnerFormComponentModel() + { + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + + assertFalse(page.innerField.updateModelCalled); + } + + @Test + public void updateFormComponentModelsInPostorder() + { + tester.newFormTester("outerForm").submit(); + + assertTrue(page.innerField.updateModelOrder < page.outerField.updateModelOrder); + } + + @Test + public void callInnerFormOnValidateModelObjects() + { + tester.newFormTester("outerForm").submit(); + + assertTrue(page.innerForm.onValidateModelObjectsCalled); + } + + @Test + public void dontCallInnerFormOnValidateModelObjects() + { + page.innerForm.wantSubmitOnParentFormSubmit = false; + tester.newFormTester("outerForm").submit(); + + assertFalse(page.innerForm.onValidateModelObjectsCalled); + } + + @Test + public void callFormOnValidateModelObjectsInPostorder() + { + tester.newFormTester("outerForm").submit(); + + assertTrue( + page.innerForm.onValidateModelObjectsCallOrder < page.outerForm.onValidateModelObjectsCallOrder); + } + + public static class TestFormPage extends WebPage implements IMarkupResourceStreamProvider + { + TestForm outerForm; + TestForm innerForm; + TestField outerField; + TestField innerField; + Button innerFormSubmitButton; + Container outerContainer; + Container innerContainer; + + public TestFormPage() + { + add(outerForm = new TestForm("outerForm")); + outerForm.add(outerContainer = new Container("outerContainer")); + outerContainer.add(outerField = new TestField("outerField")); + outerContainer.add(innerForm = new TestForm("innerForm")); + innerForm.add(innerContainer = new Container("innerContainer")); + innerContainer.add(innerField = new TestField("innerField")); + innerContainer.add(innerFormSubmitButton = new Button("innerFormSubmitButton")); + } + + public IResourceStream getMarkupResourceStream(MarkupContainer container, + Class containerClass) + { + return new StringResourceStream("" // + + "" // + + "
" // + + "
" // + + " " // + + " " // + + "
" // + + " " // + + "
" // + + " "// + + ""); + } + } + + static class TestForm extends Form + { + boolean wantSubmitOnParentFormSubmit = true; + boolean onValidateCalled; + boolean onErrorCalled; + boolean onSubmitCalled; + boolean isSubmittedFlagged; + boolean onValidateModelObjectsCalled; + int onValidateModelObjectsCallOrder; + int numberOfOnErrorCalls; + + public TestForm(String id) + { + super(id); + } + + @Override + protected void onSubmit() + { + onSubmitCalled = true; + } + + @Override + protected void onConfigure() + { + super.onConfigure(); + isSubmittedFlagged = isSubmitted(); + } + + @Override + protected boolean wantSubmitOnParentFormSubmit() + { + return wantSubmitOnParentFormSubmit; + } + + @Override + protected void onValidate() + { + onValidateCalled = true; + } + + @Override + protected void onValidateModelObjects() + { + onValidateModelObjectsCalled = true; + onValidateModelObjectsCallOrder = sequence++; + } + + @Override + protected void onError() + { + onErrorCalled = true; + numberOfOnErrorCalls++; + } + } + + static class Container extends WebMarkupContainer implements IFormVisitorParticipant + { + boolean processChildren = true; + + public Container(final String id) + { + super(id); + } + + @Override + public boolean processChildren() + { + return processChildren; + } + } + + static class TestField extends TextField implements IFormModelUpdateListener + { + + boolean onValidCalled; + boolean updateModelCalled; + int updateModelOrder; + int onValidCallOrder; + + public TestField(String id) + { + super(id, Model.of((String)null)); + } + + @Override + protected void onValid() + { + onValidCalled = true; + onValidCallOrder = sequence++; + } + + @Override + public void updateModel() + { + super.updateModel(); + updateModelCalled = true; + updateModelOrder = sequence++; + } + } + + static class FormValidator implements IFormValidator + { + FormComponent[] dependencies; + boolean validatedCalled; + + public FormComponent[] getDependentFormComponents() + { + return dependencies; + } + + public void validate(Form form) + { + validatedCalled = true; + } + + public FormValidator setDependency(FormComponent component) + { + this.dependencies = new FormComponent[] { component }; + return this; + } + } + + static class AlwaysFail implements IValidator, INullAcceptingValidator + { + boolean validatedCalled; + + @Override + public void validate(IValidatable validatable) + { + validatable.error(new ValidationError("foo")); + validatedCalled = true; + } + } + +} diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java index 8e80799c53..2c40d09a41 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java @@ -65,10 +65,7 @@ import org.apache.wicket.util.string.Strings; import org.apache.wicket.util.string.interpolator.MapVariableInterpolator; import org.apache.wicket.util.value.LongValue; -import org.apache.wicket.util.visit.ClassVisitFilter; -import org.apache.wicket.util.visit.IVisit; -import org.apache.wicket.util.visit.IVisitor; -import org.apache.wicket.util.visit.Visits; +import org.apache.wicket.util.visit.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -166,23 +163,10 @@ public abstract static class ValidationVisitor implements IVisitor formComponent, final IVisit visit) { - - Form form = formComponent.getForm(); - if (!form.isVisibleInHierarchy() || !form.isEnabledInHierarchy()) - { - // do not validate formComponent or any of formComponent's children - visit.dontGoDeeper(); - return; - } - if (formComponent.isVisibleInHierarchy() && formComponent.isEnabledInHierarchy()) { validate(formComponent); } - if (formComponent.processChildren() == false) - { - visit.dontGoDeeper(); - } } /** @@ -757,7 +741,7 @@ public final boolean isSubmitted() @Override public final void onRequest() { - onFormSubmitted(null); + onFormSubmitted(findSubmitter()); } /** @@ -1052,22 +1036,16 @@ protected void callOnError(IFormSubmitter submitter) } // invoke Form#onSubmit(..) going from innermost to outermost - Visits.visitPostOrder(processingForm, new IVisitor, Void>() - { - @Override - public void component(Form form, IVisit visit) + visitFormsPostOrder(processingForm, (form, visit) -> { + if (!form.isEnabledInHierarchy() || !form.isVisibleInHierarchy()) { - if (!form.isEnabledInHierarchy() || !form.isVisibleInHierarchy()) - { - visit.dontGoDeeper(); - return; - } - if (form.hasError()) - { - form.onError(); - } + return; + } + if (form.hasError()) + { + form.onError(); } - }, new ClassVisitFilter(Form.class)); + }); } @@ -1077,22 +1055,12 @@ public void component(Form form, IVisit visit) */ private void markFormsSubmitted(IFormSubmitter submitter) { - setFlag(FLAG_SUBMITTED, true); Form formToProcess = findFormToProcess(submitter); - visitChildren(Form.class, new IVisitor() - { - @Override - public void component(final Component component, final IVisit visit) + visitFormsPostOrder(formToProcess, (form, visit) -> { + if (form.isEnabledInHierarchy() && form.isVisibleInHierarchy()) { - Form form = (Form)component; - if ((form.wantSubmitOnParentFormSubmit() || form == formToProcess) - && form.isEnabledInHierarchy() && form.isVisibleInHierarchy()) - { - form.setFlag(FLAG_SUBMITTED, true); - return; - } - visit.dontGoDeeper(); + form.setFlag(FLAG_SUBMITTED, true); } }); } @@ -1210,6 +1178,38 @@ public final R visitFormComponentsPostOrder( return FormComponent.visitFormComponentsPostOrder(this, visitor); } + /** + * Visits forms from the @parameter form down in postorder, skipping any branch not flagged as + * form visitor participant + * + * @param formToProcess + * @param visitor + */ + private static void visitFormsPostOrder(Form formToProcess, IVisitor, Void> visitor) + { + Visits.visitPostOrder(formToProcess, visitor, new IVisitFilter() + { + @Override + public boolean visitObject(Object object) + { + if (object instanceof Form form) + { + return form == formToProcess || form.wantSubmitOnParentFormSubmit(); + } + return false; + } + @Override + public boolean visitChildren(Object object) + { + if (object instanceof Form form) + { + return form.wantSubmitOnParentFormSubmit(); + } + return true; + } + }); + } + /** * Find out whether there is any registered error for a form component. * @@ -1324,17 +1324,12 @@ protected void delegateSubmit(IFormSubmitter submittingComponent) // collect all forms innermost to outermost before any hierarchy is changed final List> forms = Generics.newArrayList(3); - Visits.visitPostOrder(processingForm, new IVisitor, Void>() - { - @Override - public void component(Form form, IVisit visit) + visitFormsPostOrder(processingForm, (form, visit) -> { + if (form.isSubmitted()) { - if (form.isSubmitted()) - { - forms.add(form); - } + forms.add(form); } - }, new ClassVisitFilter(Form.class)); + }); // process submitting component (if specified) if (submittingComponent != null) @@ -1563,8 +1558,8 @@ public void component(final FormComponent formComponent, IVisit visit) */ protected final void markFormComponentsValid() { - internalMarkFormComponentsValid(); markNestedFormComponentsValid(); + internalMarkFormComponentsValid(); } /** @@ -1572,19 +1567,14 @@ protected final void markFormComponentsValid() */ private void markNestedFormComponentsValid() { - visitChildren(Form.class, new IVisitor, Void>() - { - @Override - public void component(final Form form, final IVisit visit) + visitFormsPostOrder(this, (form, visit) -> { + if (form == Form.this) { - if (form.isSubmitted()) - { - form.internalMarkFormComponentsValid(); - } - else - { - visit.dontGoDeeper(); - } + return; + } + if (form.isSubmitted()) + { + form.internalMarkFormComponentsValid(); } }); } @@ -1890,8 +1880,8 @@ protected void onSubmit() */ protected final void updateFormComponentModels() { - internalUpdateFormComponentModels(); updateNestedFormComponentModels(); + internalUpdateFormComponentModels(); } /** @@ -1901,19 +1891,14 @@ protected final void updateFormComponentModels() */ private void updateNestedFormComponentModels() { - visitChildren(Form.class, new IVisitor, Void>() - { - @Override - public void component(final Form form, final IVisit visit) + visitFormsPostOrder(this, (form, visit) -> { + if (form == Form.this) { - if (form.isSubmitted()) - { - form.internalUpdateFormComponentModels(); - } - else - { - visit.dontGoDeeper(); - } + return; + } + if (form.isSubmitted()) + { + form.internalUpdateFormComponentModels(); } }); } @@ -1963,22 +1948,17 @@ protected void onValidate() */ private void internalOnValidateModelObjects() { - onValidateModelObjects(); - visitChildren(Form.class, new IVisitor, Void>() - { - @Override - public void component(Form form, IVisit visit) + visitFormsPostOrder(this, (form, visit) -> { + if (form == Form.this) { - if (form.isSubmitted()) - { - form.onValidateModelObjects(); - } - else - { - visit.dontGoDeeper(); - } + return; + } + if (form.isSubmitted()) + { + form.onValidateModelObjects(); } }); + onValidateModelObjects(); } /** @@ -2015,25 +1995,6 @@ public void validate(final FormComponent formComponent) }); } - /** - * Checks if the specified form component visible and is attached to a page - * - * @param fc - * form component - * - * @return true if the form component and all its parents are visible and there component is in - * page's hierarchy - */ - private boolean isFormComponentVisibleInPage(FormComponent fc) - { - if (fc == null) - { - throw new IllegalArgumentException("Argument `fc` cannot be null"); - } - return fc.isVisibleInHierarchy(); - } - - /** * Validates form with the given form validator * @@ -2059,13 +2020,13 @@ protected final void validateFormValidator(final IFormValidator validator) } // check if the dependent component is visible and is attached to // the page - else if (!isFormComponentVisibleInPage(dependent)) + else if (!dependent.isVisibleInHierarchy() || !dependent.isEnabledInHierarchy() || !dependent.isFormParticipant()) { if (log.isWarnEnabled()) { log.warn("IFormValidator in form `" + getPageRelativePath() + - "` depends on a component that has been removed from the page or is no longer visible. " + + "` depends on a component that has been removed from the page or is no longer visible/enabled. " + "Offending component id `" + dependent.getId() + "`."); } validate = false; @@ -2101,26 +2062,19 @@ protected final void validateFormValidators() */ private void validateNestedForms() { - Visits.visitPostOrder(this, new IVisitor, Void>() - { - @Override - public void component(final Form form, final IVisit visit) + visitFormsPostOrder(this, (form, visit) -> { + if (form == Form.this) { - if (form == Form.this) - { - // skip self, only process children - visit.stop(); - return; - } + return; + } - if (form.isSubmitted()) - { - form.validateComponents(); - form.validateFormValidators(); - form.onValidate(); - } + if (form.isSubmitted()) + { + form.validateComponents(); + form.validateFormValidators(); + form.onValidate(); } - }, new ClassVisitFilter(Form.class)); + }); } /** diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java index 6eddd4685c..28331766df 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java @@ -1602,6 +1602,35 @@ public final void updateAutoLabels(AjaxRequestTarget target) updateAutoLabels(target, false); } + /** + * @return if this form component is visited during the form processing + */ + public boolean isFormParticipant() + { + Component parent = getParent(); + boolean outsideParentForm = false; + while (parent != null) + { + if (parent instanceof IFormVisitorParticipant && !((IFormVisitorParticipant)parent).processChildren() && !outsideParentForm) + { + return false; + } + if (parent instanceof Form form) + { + if (!form.wantSubmitOnParentFormSubmit()) + { + return false; + } + if (form == this.getForm()) + { + outsideParentForm = true; + } + } + parent = parent.getParent(); + } + return true; + } + /** * Update the model of a {@link FormComponent} containing a {@link Collection}. *