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 2016/04/24 17:14:25 UTC
wicket git commit: Add filter/map/flatMap/orElse/orElseGet methods to
IModel
Repository: wicket
Updated Branches:
refs/heads/monad-model [created] 484132a85
Add filter/map/flatMap/orElse/orElseGet methods to IModel
discussion-at: http://markmail.org/message/i34iulxttjc7umij
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/484132a8
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/484132a8
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/484132a8
Branch: refs/heads/monad-model
Commit: 484132a85c81fe96878d1c93e19940fb71d6f10f
Parents: f2f0ba0
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Sun Apr 24 17:11:53 2016 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Sun Apr 24 17:11:53 2016 +0200
----------------------------------------------------------------------
.../java/org/apache/wicket/model/IModel.java | 185 +++++++++++++++++++
.../apache/wicket/model/LambdaModelTest.java | 18 +-
.../org/apache/wicket/model/lambda/Person.java | 40 ++++
3 files changed, 242 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/484132a8/wicket-core/src/main/java/org/apache/wicket/model/IModel.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/model/IModel.java b/wicket-core/src/main/java/org/apache/wicket/model/IModel.java
index 53994ae..789d27a 100644
--- a/wicket-core/src/main/java/org/apache/wicket/model/IModel.java
+++ b/wicket-core/src/main/java/org/apache/wicket/model/IModel.java
@@ -17,6 +17,10 @@
package org.apache.wicket.model;
+import org.apache.wicket.lambda.WicketBiFunction;
+import org.apache.wicket.lambda.WicketFunction;
+import org.apache.wicket.lambda.WicketSupplier;
+
/**
* A IModel wraps the actual model Object used by a Component. IModel implementations are used as a
* facade for the real model so that users have control over the actual persistence strategy. Note
@@ -78,4 +82,185 @@ public interface IModel<T> extends IDetachable
@Override
default void detach() {}
+
+ /**
+ * Returns a IModel checking whether the predicate holds for the
+ * contained object, if it is not null. If the predicate doesn't evaluate
+ * to true, the contained object will be null.
+ *
+ * @param predicate a predicate to be used for testing the contained object
+ * @return a new IModel
+ */
+ default IModel<T> filter(WicketFunction<T, Boolean> predicate) {
+ return (IModel<T>) () -> {
+ T object = IModel.this.getObject();
+ if (object != null && predicate.apply(object)) {
+ return object;
+ }
+ else {
+ return null;
+ }
+ };
+ }
+
+ /**
+ * Returns a IModel applying the given mapper to
+ * the contained object, if it is not NULL.
+ *
+ * @param <R> the new type of the contained object
+ * @param mapper a mapper, to be applied to the contained object
+ * @return a new IModel
+ */
+ default <R> IModel<R> map(WicketFunction<T, R> mapper) {
+ return (IModel<R>) () -> {
+ T object = IModel.this.getObject();
+ if (object == null) {
+ return null;
+ }
+ else {
+ return mapper.apply(object);
+ }
+ };
+ }
+
+ /**
+ * Returns a IModel applying the given combining function to
+ * the contained object of this and the given other model, if they are not null.
+ *
+ * @param <R> the resulting type
+ * @param <U> the other models type
+ * @param combine a function combining this and the others object to
+ * a result.
+ * @param other another model to be combined with this one
+ * @return a new IModel
+ */
+ default <R, U> IModel<R> mapWith(WicketBiFunction<T, U, R> combine, IModel<U> other) {
+ return (IModel<R>) () -> {
+ T t = IModel.this.getObject();
+ U u = other.getObject();
+ if (t != null && u != null) {
+ return combine.apply(t, u);
+ }
+ else {
+ return null;
+ }
+ };
+ }
+
+ /**
+ * Returns a IModel applying the given mapper to the contained
+ * object, if it is not NULL.
+ *
+ * @param <R> the new type of the contained object
+ * @param mapper a mapper, to be applied to the contained object
+ * @return a new IModel
+ */
+ default <R> IModel<R> flatMap(WicketFunction<T, IModel<R>> mapper) {
+ return (IModel<R>) () -> {
+ T object = IModel.this.getObject();
+ if (object == null) {
+ return null;
+ }
+ else {
+ return mapper.apply(object).getObject();
+ }
+ };
+ }
+
+ /**
+ * Returns a IModel applying the {@link WicketFunction} contained
+ * inside the given model to the object contained inside this model.
+ *
+ * @param <R> the type of the new contained object
+ * @param mapper an {@link IModel} containing a function to be applied
+ * to the contained model object.
+ * @return a new IModel
+ */
+ default <R> IModel<R> apply(IModel<WicketFunction<T, R>> mapper) {
+ return (IModel<R>) () -> {
+ T object = IModel.this.getObject();
+ WicketFunction<T, R> f = mapper.getObject();
+ if (object == null || f == null) {
+ return null;
+ }
+ else {
+ return f.apply(object);
+ }
+ };
+ }
+
+ /**
+ * Returns a IModel, returning either the contained object
+ * or the given default value, depending on the nullness of the
+ * contained object.
+ *
+ * @param other a default value
+ * @return a new IModel
+ */
+ default IModel<T> orElse(T other) {
+ return (IModel<T>) () -> {
+ T object = IModel.this.getObject();
+ if (object == null) {
+ return other;
+ }
+ else {
+ return object;
+ }
+ };
+ }
+
+ /**
+ * Returns a IModel, returning either the contained object
+ * or invoking the given supplier to get a default value.
+ *
+ * @param other a supplier to be used as a default
+ * @return a new IModel
+ */
+ default IModel<T> orElseGet(WicketSupplier<T> other) {
+ return (IModel<T>) () -> {
+ T object = IModel.this.getObject();
+ if (object == null) {
+ return other.get();
+ }
+ else {
+ return object;
+ }
+ };
+ }
+
+ /**
+ * Returns a IModel lifting the given object into the
+ * Model.
+ *
+ * @param <T> the type of the given object
+ * @param object an object to be lifted into a IModel
+ * @return a new IModel
+ */
+ static <T> IModel<T> of(T object) {
+ return of((WicketSupplier<T>) () -> object);
+ }
+
+ /**
+ * Returns a IModel applying the given supplier to
+ * get the object.
+ *
+ * @param <T> the type of the given object
+ * @param supplier a supplier, to be used to get a value
+ * @return a new IModel
+ */
+ static <T> IModel<T> of(WicketSupplier<T> supplier) {
+ return (IModel<T>) () -> supplier.get();
+ }
+
+ /**
+ * Returns a IModel using the getObject() method
+ * of the given model.
+ *
+ * @param <T> the type of the contained object
+ * @param model a model,
+ * @return a new IModel
+ */
+ static <T> IModel<T> of(IModel<T> model) {
+ return (IModel<T>) () -> model.getObject();
+ }
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/484132a8/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..597ed16 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
@@ -38,8 +38,24 @@ public class LambdaModelTest
public void methodReference()
{
Person person = new Person();
+ person.setName("john");
+ Person.Address address = new Person.Address();
+ person.setAddress(address);
+// address.setStreet("Street");
+ address.setNumber(123);
+
IModel<String> personNameModel = new LambdaModel<>(person::getName, person::setName);
- check(personNameModel);
+// check(personNameModel);
+
+ IModel<Person.Address> addressModel = Model.<Person>of(Model.of(person))
+ .filter((p) -> p.getName().equals("john"))
+ .map(Person::getAddress);
+
+ System.err.println("addressModel= " + addressModel
+ .flatMap(address1 -> Model.loadableDetachable(() -> address1))
+ .map(Person.Address::getStreet)
+ .orElse("N/A")
+ .getObject());
}
@Test
http://git-wip-us.apache.org/repos/asf/wicket/blob/484132a8/wicket-core/src/test/java/org/apache/wicket/model/lambda/Person.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/model/lambda/Person.java b/wicket-core/src/test/java/org/apache/wicket/model/lambda/Person.java
index 4e4e74a..0134c46 100644
--- a/wicket-core/src/test/java/org/apache/wicket/model/lambda/Person.java
+++ b/wicket-core/src/test/java/org/apache/wicket/model/lambda/Person.java
@@ -25,6 +25,8 @@ public class Person implements Serializable
{
private String name;
+ private Address address;
+
public String getName()
{
return name;
@@ -34,4 +36,42 @@ public class Person implements Serializable
{
this.name = name;
}
+
+ public Address getAddress()
+ {
+ return address;
+ }
+
+ public void setAddress(Address address)
+ {
+ this.address = address;
+ }
+
+ public static class Address implements Serializable
+ {
+ private String street;
+
+ private int number;
+
+ public String getStreet()
+ {
+ return street;
+ }
+
+ public void setStreet(String street)
+ {
+ this.street = street;
+ }
+
+ public int getNumber()
+ {
+ return number;
+ }
+
+ public void setNumber(int number)
+ {
+ this.number = number;
+ }
+ }
+
}