You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2015/10/04 21:48:59 UTC

wicket git commit: WICKET-5992 Add support for lambdas in Ajax behaviors & components

Repository: wicket
Updated Branches:
  refs/heads/lambdas-ajax [created] 218a58e3e


WICKET-5992 Add support for lambdas in Ajax behaviors & components

Experiment with lambda support in AjaxEventBehavior.
Experiment with Component#on(event, listener) API.


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/218a58e3
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/218a58e3
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/218a58e3

Branch: refs/heads/lambdas-ajax
Commit: 218a58e3e359f08d1bb7f7d98249cfca51b28cb1
Parents: aa10baf
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Sun Oct 4 21:47:34 2015 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Sun Oct 4 21:47:34 2015 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/wicket/Component.java  | 42 ++++++++++++++++-
 .../apache/wicket/ajax/AjaxEventBehavior.java   | 27 ++++++++---
 ...AjaxFormChoiceComponentUpdatingBehavior.java | 12 +++--
 .../form/AjaxFormComponentUpdatingBehavior.java | 47 ++++++++++++++++----
 .../ajax/form/AjaxFormSubmitBehavior.java       |  2 +-
 .../wicket/model/lambda/AjaxListener.java       | 38 ++++++++++++++++
 .../java/org/apache/wicket/ComponentTest.java   | 43 +++++++++++++++++-
 .../wicket/ajax/AjaxEventBehaviorTest.java      | 32 +++++++++++++
 8 files changed, 219 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/218a58e3/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 2c22cee..ebd5b39 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Component.java
+++ b/wicket-core/src/main/java/org/apache/wicket/Component.java
@@ -24,7 +24,10 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.IAjaxRegionMarkupIdProvider;
+import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
 import org.apache.wicket.application.IComponentInstantiationListener;
 import org.apache.wicket.authorization.Action;
 import org.apache.wicket.authorization.AuthorizationException;
@@ -68,6 +71,7 @@ import org.apache.wicket.model.IComponentInheritedModel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.IModelComparator;
 import org.apache.wicket.model.IWrapModel;
+import org.apache.wicket.model.lambda.AjaxListener;
 import org.apache.wicket.protocol.http.WicketFilter;
 import org.apache.wicket.request.IRequestHandler;
 import org.apache.wicket.request.Request;
@@ -2875,7 +2879,7 @@ public abstract class Component
 		}
 
 		generatedMarkupId = -1;
-		setMetaData(MARKUP_ID_KEY, (String)markupId);
+		setMetaData(MARKUP_ID_KEY, (String) markupId);
 
 	}
 
@@ -3164,7 +3168,7 @@ public abstract class Component
 	 */
 	public final <C extends IRequestablePage> void setResponsePage(final Class<C> cls)
 	{
-		getRequestCycle().setResponsePage(cls, (PageParameters)null);
+		getRequestCycle().setResponsePage(cls, (PageParameters) null);
 	}
 
 	/**
@@ -4600,4 +4604,38 @@ public abstract class Component
 	{
 		setRequestFlag(RFLAG_ON_RE_ADD_SUPER_CALL_VERIFIED, true);
 	}
+
+	/**
+	 * jQuery-like API for registering Ajax listeners
+	 *
+	 * @param eventName
+	 *              The name of the JavaScript event, e.g. 'click'
+	 * @param listener
+	 *              The listener to execute
+	 */
+	public void on(String eventName, AjaxListener listener)
+	{
+		Args.notNull(eventName, eventName);
+		Args.notNull(listener, "listener");
+
+		final AjaxEventBehavior ajaxBehavior;
+		switch (eventName)
+		{
+			case "change":
+			case "blur":
+				ajaxBehavior = new AjaxFormComponentUpdatingBehavior(eventName, listener);
+				break;
+			default:
+				if (AjaxFormChoiceComponentUpdatingBehavior.appliesTo(this))
+				{
+					ajaxBehavior = new AjaxFormChoiceComponentUpdatingBehavior(listener);
+				}
+				else
+				{
+					ajaxBehavior = new AjaxEventBehavior(eventName, listener);
+				}
+		}
+
+		add(ajaxBehavior);
+	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/218a58e3/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxEventBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxEventBehavior.java b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxEventBehavior.java
index 6dde195..b57ac41 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxEventBehavior.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxEventBehavior.java
@@ -23,6 +23,7 @@ import org.apache.wicket.Component;
 import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.model.lambda.WicketConsumer;
 import org.apache.wicket.util.lang.Args;
 import org.apache.wicket.util.lang.Checks;
 import org.apache.wicket.util.string.Strings;
@@ -61,7 +62,7 @@ import org.slf4j.LoggerFactory;
  * @author Igor Vaynberg (ivaynberg)
  * @see #onEvent(AjaxRequestTarget)
  */
-public abstract class AjaxEventBehavior extends AbstractDefaultAjaxBehavior
+public class AjaxEventBehavior extends AbstractDefaultAjaxBehavior
 {
 	private static final Logger LOGGER = LoggerFactory.getLogger(AjaxEventBehavior.class);
 
@@ -69,6 +70,8 @@ public abstract class AjaxEventBehavior extends AbstractDefaultAjaxBehavior
 
 	private final String event;
 
+	private final WicketConsumer<AjaxRequestTarget> consumer;
+
 	/**
 	 * Construct.
 	 * 
@@ -77,11 +80,17 @@ public abstract class AjaxEventBehavior extends AbstractDefaultAjaxBehavior
 	 */
 	public AjaxEventBehavior(String event)
 	{
+		this(event, null);
+	}
+
+	public AjaxEventBehavior(String event, WicketConsumer<AjaxRequestTarget> consumer)
+	{
 		Args.notEmpty(event, "event");
 
 		onCheckEvent(event);
 
 		this.event = event;
+		this.consumer = consumer;
 	}
 
 	@Override
@@ -145,14 +154,17 @@ public abstract class AjaxEventBehavior extends AbstractDefaultAjaxBehavior
 		return Strings.join(" ", cleanedEvents);
 	}
 
-	/**
-	 * 
-	 * @see org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#respond(AjaxRequestTarget)
-	 */
 	@Override
 	protected final void respond(final AjaxRequestTarget target)
 	{
-		onEvent(target);
+		if (consumer != null)
+		{
+			consumer.accept(target);
+		}
+		else
+		{
+			onEvent(target);
+		}
 	}
 
 	/**
@@ -161,5 +173,6 @@ public abstract class AjaxEventBehavior extends AbstractDefaultAjaxBehavior
 	 * @param target
 	 *      the current request handler
 	 */
-	protected abstract void onEvent(final AjaxRequestTarget target);
+	protected void onEvent(final AjaxRequestTarget target)
+	{}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/218a58e3/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormChoiceComponentUpdatingBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormChoiceComponentUpdatingBehavior.java b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormChoiceComponentUpdatingBehavior.java
index feaa75c..7272e21 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormChoiceComponentUpdatingBehavior.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormChoiceComponentUpdatingBehavior.java
@@ -27,6 +27,7 @@ import org.apache.wicket.markup.html.form.CheckGroup;
 import org.apache.wicket.markup.html.form.FormComponent;
 import org.apache.wicket.markup.html.form.RadioChoice;
 import org.apache.wicket.markup.html.form.RadioGroup;
+import org.apache.wicket.model.lambda.AjaxListener;
 import org.apache.wicket.request.resource.JavaScriptResourceReference;
 import org.apache.wicket.request.resource.ResourceReference;
 
@@ -46,7 +47,7 @@ import org.apache.wicket.request.resource.ResourceReference;
  * @see RadioGroup
  * @see CheckGroup
  */
-public abstract class AjaxFormChoiceComponentUpdatingBehavior extends
+public class AjaxFormChoiceComponentUpdatingBehavior extends
 	AjaxFormComponentUpdatingBehavior
 {
 	private static final ResourceReference CHOICE_JS = new JavaScriptResourceReference(
@@ -59,7 +60,12 @@ public abstract class AjaxFormChoiceComponentUpdatingBehavior extends
 	 */
 	public AjaxFormChoiceComponentUpdatingBehavior()
 	{
-		super("click");
+		this(null);
+	}
+
+	public AjaxFormChoiceComponentUpdatingBehavior(AjaxListener listener)
+	{
+		super("click", listener);
 	}
 
 	@Override
@@ -122,7 +128,7 @@ public abstract class AjaxFormChoiceComponentUpdatingBehavior extends
 	 *            the component to check
 	 * @return if the component applies to the {@link AjaxFormChoiceComponentUpdatingBehavior}
 	 */
-	static boolean appliesTo(Component component)
+	public static boolean appliesTo(Component component)
 	{
 		return (component instanceof RadioChoice) ||
 			(component instanceof CheckBoxMultipleChoice) || (component instanceof RadioGroup) ||

http://git-wip-us.apache.org/repos/asf/wicket/blob/218a58e3/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormComponentUpdatingBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormComponentUpdatingBehavior.java b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormComponentUpdatingBehavior.java
index b4de626..a014ddf 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormComponentUpdatingBehavior.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormComponentUpdatingBehavior.java
@@ -25,6 +25,7 @@ import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
 import org.apache.wicket.markup.html.form.FormComponent;
 import org.apache.wicket.markup.html.form.validation.IFormValidator;
+import org.apache.wicket.model.lambda.AjaxListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,7 +47,7 @@ import org.slf4j.LoggerFactory;
  * @see #onUpdate(org.apache.wicket.ajax.AjaxRequestTarget)
  * @see #onError(org.apache.wicket.ajax.AjaxRequestTarget, RuntimeException)
  */
-public abstract class AjaxFormComponentUpdatingBehavior extends AjaxEventBehavior
+public class AjaxFormComponentUpdatingBehavior extends AjaxEventBehavior
 {
 	private static final Logger log = LoggerFactory
 		.getLogger(AjaxFormComponentUpdatingBehavior.class);
@@ -56,6 +57,8 @@ public abstract class AjaxFormComponentUpdatingBehavior extends AjaxEventBehavio
 	 */
 	private static final long serialVersionUID = 1L;
 
+	private final AjaxListener listener;
+
 	/**
 	 * Construct.
 	 * 
@@ -64,13 +67,16 @@ public abstract class AjaxFormComponentUpdatingBehavior extends AjaxEventBehavio
 	 */
 	public AjaxFormComponentUpdatingBehavior(final String event)
 	{
+		this(event, null);
+	}
+
+	public AjaxFormComponentUpdatingBehavior(final String event, AjaxListener listener)
+	{
 		super(event);
+
+		this.listener = listener;
 	}
 
-	/**
-	 * 
-	 * @see org.apache.wicket.behavior.AbstractAjaxBehavior#onBind()
-	 */
 	@Override
 	protected void onBind()
 	{
@@ -151,18 +157,39 @@ public abstract class AjaxFormComponentUpdatingBehavior extends AjaxEventBehavio
 					formComponent.updateModel();
 				}
 
-				onUpdate(target);
+				if (listener != null)
+				{
+					listener.accept(target);
+				}
+				else
+				{
+					onUpdate(target);
+				}
 			}
 			else
 			{
 				formComponent.invalid();
 
-				onError(target, null);
+				if (listener != null)
+				{
+					listener.onError(target, null);
+				}
+				else
+				{
+					onError(target, null);
+				}
 			}
 		}
 		catch (RuntimeException e)
 		{
-			onError(target, e);
+			if (listener != null)
+			{
+				listener.onError(target, e);
+			}
+			else
+			{
+				onError(target, null);
+			}
 		}
 		formComponent.updateAutoLabels(target);
 	}
@@ -197,7 +224,9 @@ public abstract class AjaxFormComponentUpdatingBehavior extends AjaxEventBehavio
 	 * @param target
 	 *            the current request handler
 	 */
-	protected abstract void onUpdate(AjaxRequestTarget target);
+	protected void onUpdate(AjaxRequestTarget target)
+	{
+	}
 
 	/**
 	 * Called to handle any error resulting from updating form component. Errors thrown from

http://git-wip-us.apache.org/repos/asf/wicket/blob/218a58e3/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormSubmitBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormSubmitBehavior.java b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormSubmitBehavior.java
index c734e9b..3e82b97 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormSubmitBehavior.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormSubmitBehavior.java
@@ -40,7 +40,7 @@ import org.apache.wicket.markup.html.form.IFormSubmittingComponent;
  * @see #onAfterSubmit(org.apache.wicket.ajax.AjaxRequestTarget)
  * @see #onError(org.apache.wicket.ajax.AjaxRequestTarget)
  */
-public abstract class AjaxFormSubmitBehavior extends AjaxEventBehavior
+public class AjaxFormSubmitBehavior extends AjaxEventBehavior
 {
 	private static final long serialVersionUID = 1L;
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/218a58e3/wicket-core/src/main/java/org/apache/wicket/model/lambda/AjaxListener.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/model/lambda/AjaxListener.java b/wicket-core/src/main/java/org/apache/wicket/model/lambda/AjaxListener.java
new file mode 100644
index 0000000..3537be1
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/model/lambda/AjaxListener.java
@@ -0,0 +1,38 @@
+/*
+ * 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.model.lambda;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+
+/**
+ *
+ */
+@FunctionalInterface
+public interface AjaxListener extends WicketConsumer<AjaxRequestTarget>
+{
+	void onEvent(AjaxRequestTarget target);
+
+	default void onError(AjaxRequestTarget target, RuntimeException error)
+	{
+	}
+
+	@Override
+	default void accept(AjaxRequestTarget target)
+	{
+		onEvent(target);
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/218a58e3/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java b/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java
index a44739d..9473979 100644
--- a/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java
@@ -20,11 +20,15 @@ import java.lang.reflect.Method;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.behavior.Behavior;
 import org.apache.wicket.markup.html.WebComponent;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.link.Link;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
-import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.model.lambda.AjaxListener;
 import org.apache.wicket.util.tester.WicketTestCase;
 import org.junit.Test;
 
@@ -244,6 +248,41 @@ public class ComponentTest extends WicketTestCase
 		assertTrue(component.getFlagReserved5());
 	}
 
+	@Test
+	public void onClick()
+	{
+		MockPageWithOneComponent page = new MockPageWithOneComponent();
+		WebMarkupContainer component = new WebMarkupContainer(MockPageWithOneComponent.COMPONENT_ID);
+		final String eventName = "click";
+		AtomicBoolean executed = new AtomicBoolean(false);
+
+		component.on(eventName, (target) -> executed.set(true));
+
+		// this is how AjaxFormComponentUpdatingBehavior could be used
+//		component.on("change", new AjaxListener()
+//		{
+//			@Override
+//			public void onEvent(AjaxRequestTarget target)
+//			{
+//				// use 'form' if you need with
+//				final Form<?> form = Form.findForm(component);
+//			}
+//
+//			@Override
+//			public void onError(AjaxRequestTarget target, RuntimeException error)
+//			{
+//
+//			}
+//		});
+
+		page.add(component);
+		tester.startPage(page);
+
+		assertFalse(executed.get());
+		tester.executeAjaxEvent(component, eventName);
+		assertTrue(executed.get());
+	}
+
 	/**
 	 * Component#FLAG_RESERVED5 (Page's STATELESS_HINT) must be initially set to true
 	 */
@@ -263,4 +302,4 @@ public class ComponentTest extends WicketTestCase
 		protected void onRender() {
 		}
 	}
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/218a58e3/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxEventBehaviorTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxEventBehaviorTest.java b/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxEventBehaviorTest.java
index 8aea84c..ab2142d 100644
--- a/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxEventBehaviorTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxEventBehaviorTest.java
@@ -112,6 +112,18 @@ public class AjaxEventBehaviorTest extends WicketTestCase
 		assertThat(behavior.getEvent(), is("event event2on event3on on"));
 	}
 
+	@Test
+	public void lambdaConsumer()
+	{
+		AtomicInteger counter = new AtomicInteger(0);
+		LambdaConsumerTestPage page = new LambdaConsumerTestPage(counter);
+		tester.startPage(page);
+
+		assertEquals(0 ,counter.get());
+		tester.executeAjaxEvent("comp", "eventName");
+		assertEquals(1 ,counter.get());
+	}
+
 	private static class EventNamesBehavior extends AjaxEventBehavior
 	{
 		/**
@@ -158,4 +170,24 @@ public class AjaxEventBehaviorTest extends WicketTestCase
 			return new StringResourceStream("<html><body><span wicket:id='comp'></span></body></html>");
 		}
 	}
+
+	/**
+	 * Test page for #lambdaConsumer()
+	 */
+	private static class LambdaConsumerTestPage extends WebPage implements IMarkupResourceStreamProvider
+	{
+		private LambdaConsumerTestPage(final AtomicInteger counter)
+		{
+			WebComponent comp = new WebComponent("comp");
+			add(comp);
+
+			comp.add(new AjaxEventBehavior("eventName", (target) -> counter.incrementAndGet()));
+		}
+
+		@Override
+		public IResourceStream getMarkupResourceStream(MarkupContainer container, Class<?> containerClass)
+		{
+			return new StringResourceStream("<html><body><span wicket:id='comp'></span></body></html>");
+		}
+	}
 }