You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by cm...@apache.org on 2014/08/18 11:14:04 UTC

git commit: WICKET-5677: add onAddToPage lifecycle event

Repository: wicket
Updated Branches:
  refs/heads/WICKET-5677 [created] 9a6ba692a


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/9a6ba692
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/9a6ba692
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/9a6ba692

Branch: refs/heads/WICKET-5677
Commit: 9a6ba692a48b76c30ead6915d4bc43275a255b3c
Parents: 64c8567
Author: Carl-Eric Menzel <cm...@wicketbuch.de>
Authored: Mon Aug 18 10:42:33 2014 +0200
Committer: Carl-Eric Menzel <cm...@apache.org>
Committed: Mon Aug 18 11:07:45 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/9a6ba692/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/9a6ba692/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/9a6ba692/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");
+	}
+}