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");
+       }
+}

Reply via email to