This is an automated email from the ASF dual-hosted git repository.

adelbene pushed a commit to branch wicket-9.x
in repository https://gitbox.apache.org/repos/asf/wicket.git

commit 74bea4555695d3f64e30abba077149c451ea0749
Author: Andreas Svanberg <andreas.svanb...@mensa.se>
AuthorDate: Thu Oct 19 19:00:32 2023 +0200

    Easier to work with polymorphic values inside IModel
---
 .../main/java/org/apache/wicket/model/IModel.java  | 13 ++++++++
 .../java/org/apache/wicket/model/IModelTest.java   | 38 ++++++++++++++++++++++
 2 files changed, 51 insertions(+)

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 c9db790548..e9799682ea 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
@@ -370,6 +370,19 @@ public interface IModel<T> extends IDetachable
                };
        }
 
+       /**
+        * Returns an IModel, returning the object typed as {@code R} if it is 
an instance of that type,
+        * otherwise {@code null}.
+        *
+        * @param <R> the type the object should be an instance of
+        * @param clazz the {@code Class} the current model object should be an 
instance of
+        * @return a new IModel
+        */
+       default <R extends T> IModel<R> poly(Class<R> clazz) {
+               Args.notNull(clazz, "clazz");
+               return filter(clazz::isInstance).map(clazz::cast);
+       }
+
        /**
         * Suppresses generics warning when casting model types.
         *
diff --git a/wicket-core/src/test/java/org/apache/wicket/model/IModelTest.java 
b/wicket-core/src/test/java/org/apache/wicket/model/IModelTest.java
index e0cf82dcc6..09d1a1dc40 100644
--- a/wicket-core/src/test/java/org/apache/wicket/model/IModelTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/model/IModelTest.java
@@ -234,4 +234,42 @@ class IModelTest
                assertNotNull(clone);
                assertEquals("Some Name", clone.getObject());
        }
+
+       sealed interface TextMatchingStatus
+       {
+               record NotSubmitted() implements TextMatchingStatus {}
+               record Queued() implements TextMatchingStatus {}
+               record Analysed(int matchingInPercent) implements 
TextMatchingStatus {}
+               record Error(int errorCode, String humanReadableMessage) 
implements TextMatchingStatus {}
+       }
+
+       @Test
+       void polymorphicModelWrongClass()
+       {
+               IModel<TextMatchingStatus> statusModel = 
LoadableDetachableModel.of(() ->
+                               new TextMatchingStatus.Error(3, "File too 
big"));
+               IModel<TextMatchingStatus.Queued> poly = 
statusModel.poly(TextMatchingStatus.Queued.class);
+
+               assertNull(poly.getObject());
+       }
+
+       @Test
+       void polymorphicModelCorrectClass()
+       {
+               IModel<TextMatchingStatus> statusModel = 
LoadableDetachableModel.of(() ->
+                               new TextMatchingStatus.Analysed(14));
+               IModel<TextMatchingStatus.Analysed> poly = 
statusModel.poly(TextMatchingStatus.Analysed.class);
+
+               assertNotNull(poly.getObject());
+               assertEquals(new TextMatchingStatus.Analysed(14), 
poly.getObject());
+       }
+
+       @Test
+       void nullPoly()
+       {
+               assertThrows(IllegalArgumentException.class, () -> {
+                       
LoadableDetachableModel.of(TextMatchingStatus.NotSubmitted::new).poly(null);
+               });
+       }
+
 }

Reply via email to