You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by sv...@apache.org on 2016/06/29 19:01:18 UTC

wicket git commit: LambdaModel trick to get the object class

Repository: wicket
Updated Branches:
  refs/heads/lambdas-objectclass [created] ab7134388


LambdaModel trick to get the object class


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

Branch: refs/heads/lambdas-objectclass
Commit: ab7134388cf80ffd96f3c930afa9f228e736d9ff
Parents: 739bab4
Author: Sven Meier <sv...@apache.org>
Authored: Wed Jun 29 20:02:57 2016 +0200
Committer: Sven Meier <sv...@apache.org>
Committed: Wed Jun 29 21:00:48 2016 +0200

----------------------------------------------------------------------
 .../org/apache/wicket/model/LambdaModel.java    | 53 +++++++++++++++++++-
 .../apache/wicket/model/LambdaModelTest.java    |  2 +
 2 files changed, 54 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/ab713438/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
index 3266992..7b7eef2 100644
--- a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
+++ b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
@@ -16,6 +16,9 @@
  */
 package org.apache.wicket.model;
 
+import java.lang.invoke.SerializedLambda;
+import java.lang.reflect.Method;
+import java.util.Arrays;
 import java.util.Objects;
 
 import org.apache.wicket.lambda.WicketBiConsumer;
@@ -33,7 +36,7 @@ import org.apache.wicket.util.lang.Args;
  *
  * @param <T> The type of the Model Object
  */
-public class LambdaModel<T> implements IModel<T>
+public class LambdaModel<T> implements IObjectClassAwareModel<T>
 {
 	private static final long serialVersionUID = 1L;
 
@@ -66,6 +69,12 @@ public class LambdaModel<T> implements IModel<T>
 	}
 
 	@Override
+	public Class<T> getObjectClass()
+	{
+		return getReturnType(getter);
+	}
+
+	@Override
 	public int hashCode()
 	{
 		return org.apache.wicket.util.lang.Objects.hashCode(getter, setter);
@@ -151,6 +160,12 @@ public class LambdaModel<T> implements IModel<T>
 			private static final long serialVersionUID = 1L;
 
 			@Override
+			public Class<T> getObjectClass()
+			{
+				return getReturnType(getter);
+			}
+
+			@Override
 			public void detach() {
 				target.detach();
 			}
@@ -202,9 +217,45 @@ public class LambdaModel<T> implements IModel<T>
 			private static final long serialVersionUID = 1L;
 
 			@Override
+			public Class<T> getObjectClass()
+			{
+				return getReturnType(getter);
+			}
+
+			@Override
 			public void detach() {
 				target.detach();
 			}
 		};
 	}
+
+	/**
+	 * Get the return type of a {@link WicketSupplier} or {@link WicketFunction}.
+	 *
+	 * @param lambda
+	 * @return return type or {@code null}
+	 *
+	 * @see http://benjiweber.co.uk/blog/2015/08/04/lambda-type-references/
+	 */
+	@SuppressWarnings("unchecked")
+	static <T> Class<T> getReturnType(Object lambda)
+	{
+		try
+		{
+			Method replaceMethod = lambda.getClass().getDeclaredMethod("writeReplace");
+			replaceMethod.setAccessible(true);
+
+			SerializedLambda serialized = (SerializedLambda)replaceMethod.invoke(lambda);
+
+			Class<?> implClass = Class.forName(serialized.getImplClass().replaceAll("/", "."));
+
+			return (Class<T>)Arrays.asList(implClass.getDeclaredMethods()).stream()
+				.filter(method -> Objects.equals(method.getName(), serialized.getImplMethodName()))
+				.findFirst().get().getReturnType();
+		}
+		catch (Exception e)
+		{
+			return null;
+		}
+	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/ab713438/wicket-core/src/test/java/org/apache/wicket/model/LambdaModelTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/model/LambdaModelTest.java b/wicket-core/src/test/java/org/apache/wicket/model/LambdaModelTest.java
index 8bb31ff..576f4b6 100644
--- a/wicket-core/src/test/java/org/apache/wicket/model/LambdaModelTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/model/LambdaModelTest.java
@@ -111,6 +111,8 @@ public class LambdaModelTest
 		personNameModel.setObject(personName);
 		assertThat(personNameModel.getObject(), is(personName));
 
+		assertEquals(String.class, ((IObjectClassAwareModel<?>)personNameModel).getObjectClass());
+
 		serialize(personNameModel, personName);
 	}
 


Fwd: wicket git commit: LambdaModel trick to get the object class

Posted by Sven Meier <sv...@meiers.net>.
Hi all,

after reading 
http://benjiweber.co.uk/blog/2015/08/04/lambda-type-references/ I went 
ahead and let LambdaModel implement IObjectClassAwareModel.

Let this idea sink in and then we can discuss whether we want to have 
this 'hack' in core.

Have fun
Sven


-------- Forwarded Message --------
Subject: 	wicket git commit: LambdaModel trick to get the object class
Date: 	Wed, 29 Jun 2016 19:01:18 +0000 (UTC)
From: 	svenmeier@apache.org
Reply-To: 	dev@wicket.apache.org
To: 	commits@wicket.apache.org



Repository: wicket
Updated Branches:
   refs/heads/lambdas-objectclass [created] ab7134388


LambdaModel trick to get the object class


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

Branch: refs/heads/lambdas-objectclass
Commit: ab7134388cf80ffd96f3c930afa9f228e736d9ff
Parents: 739bab4
Author: Sven Meier <sv...@apache.org>
Authored: Wed Jun 29 20:02:57 2016 +0200
Committer: Sven Meier <sv...@apache.org>
Committed: Wed Jun 29 21:00:48 2016 +0200

----------------------------------------------------------------------
  .../org/apache/wicket/model/LambdaModel.java    | 53 +++++++++++++++++++-
  .../apache/wicket/model/LambdaModelTest.java    |  2 +
  2 files changed, 54 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/ab713438/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
index 3266992..7b7eef2 100644
--- a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
+++ b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
@@ -16,6 +16,9 @@
   */
  package org.apache.wicket.model;
  
+import java.lang.invoke.SerializedLambda;
+import java.lang.reflect.Method;
+import java.util.Arrays;
  import java.util.Objects;
  
  import org.apache.wicket.lambda.WicketBiConsumer;
@@ -33,7 +36,7 @@ import org.apache.wicket.util.lang.Args;
   *
   * @param <T> The type of the Model Object
   */
-public class LambdaModel<T> implements IModel<T>
+public class LambdaModel<T> implements IObjectClassAwareModel<T>
  {
  	private static final long serialVersionUID = 1L;
  
@@ -66,6 +69,12 @@ public class LambdaModel<T> implements IModel<T>
  	}
  
  	@Override
+	public Class<T> getObjectClass()
+	{
+		return getReturnType(getter);
+	}
+
+	@Override
  	public int hashCode()
  	{
  		return org.apache.wicket.util.lang.Objects.hashCode(getter, setter);
@@ -151,6 +160,12 @@ public class LambdaModel<T> implements IModel<T>
  			private static final long serialVersionUID = 1L;
  
  			@Override
+			public Class<T> getObjectClass()
+			{
+				return getReturnType(getter);
+			}
+
+			@Override
  			public void detach() {
  				target.detach();
  			}
@@ -202,9 +217,45 @@ public class LambdaModel<T> implements IModel<T>
  			private static final long serialVersionUID = 1L;
  
  			@Override
+			public Class<T> getObjectClass()
+			{
+				return getReturnType(getter);
+			}
+
+			@Override
  			public void detach() {
  				target.detach();
  			}
  		};
  	}
+
+	/**
+	 * Get the return type of a {@link WicketSupplier} or {@link WicketFunction}.
+	 *
+	 * @param lambda
+	 * @return return type or {@code null}
+	 *
+	 * @see http://benjiweber.co.uk/blog/2015/08/04/lambda-type-references/
+	 */
+	@SuppressWarnings("unchecked")
+	static <T> Class<T> getReturnType(Object lambda)
+	{
+		try
+		{
+			Method replaceMethod = lambda.getClass().getDeclaredMethod("writeReplace");
+			replaceMethod.setAccessible(true);
+
+			SerializedLambda serialized = (SerializedLambda)replaceMethod.invoke(lambda);
+
+			Class<?> implClass = Class.forName(serialized.getImplClass().replaceAll("/", "."));
+
+			return (Class<T>)Arrays.asList(implClass.getDeclaredMethods()).stream()
+				.filter(method -> Objects.equals(method.getName(), serialized.getImplMethodName()))
+				.findFirst().get().getReturnType();
+		}
+		catch (Exception e)
+		{
+			return null;
+		}
+	}
  }

http://git-wip-us.apache.org/repos/asf/wicket/blob/ab713438/wicket-core/src/test/java/org/apache/wicket/model/LambdaModelTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/model/LambdaModelTest.java b/wicket-core/src/test/java/org/apache/wicket/model/LambdaModelTest.java
index 8bb31ff..576f4b6 100644
--- a/wicket-core/src/test/java/org/apache/wicket/model/LambdaModelTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/model/LambdaModelTest.java
@@ -111,6 +111,8 @@ public class LambdaModelTest
  		personNameModel.setObject(personName);
  		assertThat(personNameModel.getObject(), is(personName));
  
+		assertEquals(String.class, ((IObjectClassAwareModel<?>)personNameModel).getObjectClass());
+
  		serialize(personNameModel, personName);
  	}