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); + }); + } + }