Repository: wicket Updated Branches: refs/heads/WICKET-5677 c3eb7e249 -> 0a8e964f1
WICKET-5677: add onAddToPage lifecycle event Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/40c42104 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/40c42104 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/40c42104 Branch: refs/heads/WICKET-5677 Commit: 40c42104f9882b938dd84e8469f2922efebd2ce3 Parents: f0eb015 Author: Carl-Eric Menzel <[email protected]> Authored: Mon Aug 18 10:42:33 2014 +0200 Committer: Carl-Eric Menzel <[email protected]> Committed: Mon Aug 18 10:42:33 2014 +0200 ---------------------------------------------------------------------- .../main/java/org/apache/wicket/Component.java | 18 +++ .../java/org/apache/wicket/MarkupContainer.java | 47 ++++++ .../test/java/org/apache/wicket/OnAddTest.java | 160 +++++++++++++++++++ 3 files changed, 225 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/40c42104/wicket-core/src/main/java/org/apache/wicket/Component.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/Component.java b/wicket-core/src/main/java/org/apache/wicket/Component.java index 7f115ae..932a954 100644 --- a/wicket-core/src/main/java/org/apache/wicket/Component.java +++ b/wicket-core/src/main/java/org/apache/wicket/Component.java @@ -447,6 +447,7 @@ public abstract class Component private static final short RFLAG_CONFIGURED = 0x10; private static final short RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED = 0x20; private static final short RFLAG_INITIALIZE_SUPER_CALL_VERIFIED = 0x40; + private static final short RFLAG_ONADD_SUPER_CALL_VERIFIED = 0x80; /** * Flags that only keep their value during the request. Useful for cache markers, etc. At the @@ -4486,4 +4487,21 @@ public abstract class Component return getBehaviors(null); } + final void internalOnAdd() + { + setRequestFlag(RFLAG_ONADD_SUPER_CALL_VERIFIED, false); + onAddToPage(); + if (!getRequestFlag(RFLAG_ONADD_SUPER_CALL_VERIFIED)) + { + throw new IllegalStateException(Component.class.getName() + + " has not been properly added. Something in the hierarchy of " + + getClass().getName() + + " has not called super.onAddToPage() in the override of onAddToPage() method"); + } + } + + protected void onAddToPage() + { + setRequestFlag(RFLAG_ONADD_SUPER_CALL_VERIFIED, true); + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/40c42104/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java index ab2db9e..cbb1d05 100644 --- a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java +++ b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java @@ -937,6 +937,17 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp { child.internalInitialize(); } + + } + // onAdd should only be triggered + // - after onInitialize + // - if we are not initialized ourselves yet, then we delay calling onAdd until onInitialize + // - if we are initialized already, we can just call onAdd now + // - AND if we already have a page. See #onAdd + // - if we don't have a page yet, our own onAdd will be called when we get added to the page component tree. + if (page != null && this.isInitialized()) + { + child.internalOnAdd(); } // if the PREPARED_FOR_RENDER flag is set, we have already called @@ -947,6 +958,37 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp } } + @Override protected void onAddToPage() + { + super.onAddToPage(); + Component[] children = copyChildren(); + try + { + for (final Component child : children) + { + // We need to check whether the child's wasn't removed from the + // component in the meanwhile (e.g. from another's child + // onAddToPage) + if (child.getParent() == this) + { + child.internalOnAdd(); + } + } + } + catch (RuntimeException ex) + { + if (ex instanceof WicketRuntimeException) + { + throw ex; + } + else + { + throw new WicketRuntimeException("Error adding this container: " + + this, ex); + } + } + } + /** * THIS METHOD IS NOT PART OF THE PUBLIC API, DO NOT CALL IT * @@ -1947,4 +1989,9 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp } } + @Override protected void onInitialize() + { + super.onInitialize(); + internalOnAdd(); + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/40c42104/wicket-core/src/test/java/org/apache/wicket/OnAddTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/OnAddTest.java b/wicket-core/src/test/java/org/apache/wicket/OnAddTest.java new file mode 100644 index 0000000..117b22d --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/OnAddTest.java @@ -0,0 +1,160 @@ +/* + * 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; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.util.tester.WicketTesterScope; +import org.junit.Rule; +import org.junit.Test; + +public class OnAddTest +{ + @Rule + public WicketTesterScope scope = new WicketTesterScope(); + + private boolean onAddCalled = false; + + private Component createProbe() + { + return new Label("foo") + { + @Override + protected void onAddToPage() + { + super.onAddToPage(); + onAddCalled = true; + } + }; + } + + @Test + public void onAddIsCalledIfParentIsInitialized() + { + Page page = createPage(); + page.internalInitialize(); + page.add(createProbe()); + assertTrue(onAddCalled); + } + + private WebPage createPage() + { + return new WebPage() + { + }; + } + + @Test + public void onAddIsNotCalledIfParentIsNotInitialized() + { + Page page = createPage(); + page.add(createProbe()); + assertFalse(onAddCalled); + } + + @Test + public void onAddIsCalledWhenParentIsInitialized() + { + Page page = createPage(); + page.add(createProbe()); + page.internalInitialize(); + assertTrue(onAddCalled); + } + + @Test + public void onAddIsNotCalledWhenParentIsNotConnectedToPage() + { + MarkupContainer container = createContainer(); + container.internalInitialize(); + container.add(createProbe()); + assertFalse(onAddCalled); + } + + @Test + public void onAddIsCalledWhenParentIsAddedToPage() + { + MarkupContainer container = createContainer(); + container.internalInitialize(); + container.add(createProbe()); + assertFalse(onAddCalled); + WebPage page = createPage(); + page.internalInitialize(); + page.add(container); + assertTrue(onAddCalled); + } + + @Test + public void onAddIsCalledAfterRemoveAndAdd() + { + Page page = createPage(); + page.internalInitialize(); + Component probe = createProbe(); + page.add(probe); + assertTrue(onAddCalled); + onAddCalled = false; + page.remove(probe); + assertFalse(onAddCalled); + page.add(probe); + assertTrue(onAddCalled); + } + + @Test + public void onAddRecursesToChildren() + { + Page page = createPage(); + page.internalInitialize(); + page.add(createNestedProbe()); + assertTrue(onAddCalled); + } + + @Test + public void onAddEnforcesSuperCall() + { + Page page = createPage(); + page.internalInitialize(); + try + { + page.add(new Label("foo") + { + @Override + protected void onAddToPage() + { + ; // I should call super, but since I don't, this should throw an exception + } + }); + fail("should have thrown exception"); + } catch (IllegalStateException e) + { + assertTrue(e.getMessage().contains("super.onAddToPage")); + } + } + + private Component createNestedProbe() + { + return createContainer().add(createProbe()); + } + + private MarkupContainer createContainer() + { + return new WebMarkupContainer("bar"); + } +}
