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

ahuber pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/causeway.git


The following commit(s) were added to refs/heads/main by this push:
     new 165953a7f6e CAUSEWAY-3859: Java record refactoring (part 41)
165953a7f6e is described below

commit 165953a7f6e27ae6f7a7565ca5cb9f39e7c1e446
Author: Andi Huber <[email protected]>
AuthorDate: Tue Feb 25 16:46:23 2025 +0100

    CAUSEWAY-3859: Java record refactoring (part 41)
---
 .../choices/ChoiceProviderForReferencesTest.java   |   4 +-
 .../choices/ChoiceProviderForValuesTest.java       |   4 +-
 viewers/wicket/ui/src/main/java/module-info.java   |   1 -
 .../choices/AttributePanelWithSelect.java          |  12 +-
 .../choices/ObjectChoicesAttributePanel.java       |   4 +-
 .../choices/ValueChoicesAttributePanel.java        |   3 +-
 .../widgets/select2/ChoiceProviderRecord.java      | 235 +++++++++++++++++++++
 .../ui/components/widgets/select2/Select2.java     |   8 +-
 .../widgets/select2/Select2ChoiceExt.java          |   7 +-
 .../widgets/select2/Select2MultiChoiceExt.java     |   7 +-
 .../select2/providers/ChoiceProviderAbstract.java  | 138 ------------
 .../ChoiceProviderAbstractForAttributeModel.java   |  69 ------
 .../select2/providers/ChoiceProviderDefault.java   |  90 --------
 13 files changed, 254 insertions(+), 328 deletions(-)

diff --git 
a/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForReferencesTest.java
 
b/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForReferencesTest.java
index 7de4114da4b..1ca28ceddf3 100644
--- 
a/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForReferencesTest.java
+++ 
b/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForReferencesTest.java
@@ -28,7 +28,7 @@
 import org.apache.causeway.core.metamodel._testing._TestDummies;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.objectmanager.memento.ObjectMemento;
-import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderDefault;
+import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.ChoiceProviderRecord;
 
 class ChoiceProviderForReferencesTest extends ChoiceProviderTestAbstract {
 
@@ -50,7 +50,7 @@ void roundtrip() {
                 .map(mmc.getObjectManager()::adapt);
 
         var isRequired = true;
-        var choiceProvider = new 
ChoiceProviderDefault(mockAttributeModel(choices, isRequired));
+        var choiceProvider = new 
ChoiceProviderRecord(mockAttributeModel(choices, isRequired));
 
         var response = new Response<ObjectMemento>();
         choiceProvider.query(null, 0, response);
diff --git 
a/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForValuesTest.java
 
b/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForValuesTest.java
index 38a89226bd2..7c09b121e0a 100644
--- 
a/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForValuesTest.java
+++ 
b/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForValuesTest.java
@@ -30,7 +30,7 @@
 import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.objectmanager.memento.ObjectMemento;
-import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderDefault;
+import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.ChoiceProviderRecord;
 
 class ChoiceProviderForValuesTest
 extends ChoiceProviderTestAbstract {
@@ -53,7 +53,7 @@ void roundtrip() {
                 .map(mmc.getObjectManager()::adapt);
 
         var isRequired = true;
-        var choiceProvider = new 
ChoiceProviderDefault(mockAttributeModel(choices, isRequired));
+        var choiceProvider = new 
ChoiceProviderRecord(mockAttributeModel(choices, isRequired));
 
         var response = new Response<ObjectMemento>();
         choiceProvider.query(null, 0, response);
diff --git a/viewers/wicket/ui/src/main/java/module-info.java 
b/viewers/wicket/ui/src/main/java/module-info.java
index a9a14e20141..7ee6ef34476 100644
--- a/viewers/wicket/ui/src/main/java/module-info.java
+++ b/viewers/wicket/ui/src/main/java/module-info.java
@@ -82,7 +82,6 @@
     exports 
org.apache.causeway.viewer.wicket.ui.components.widgets.formcomponent;
     exports org.apache.causeway.viewer.wicket.ui.components.widgets.links;
     exports org.apache.causeway.viewer.wicket.ui.components.widgets.navbar;
-    exports 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.providers;
     exports org.apache.causeway.viewer.wicket.ui.components.widgets.select2;
     exports 
org.apache.causeway.viewer.wicket.ui.components.widgets.themepicker;
     exports org.apache.causeway.viewer.wicket.ui.components.widgets.zclip;
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/AttributePanelWithSelect.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/AttributePanelWithSelect.java
index 9bacf15d649..919041d1372 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/AttributePanelWithSelect.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/AttributePanelWithSelect.java
@@ -19,11 +19,10 @@
 package org.apache.causeway.viewer.wicket.ui.components.attributes.choices;
 
 import java.io.Serializable;
-import java.util.function.Function;
 
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.WebMarkupContainer;
-
+import org.jspecify.annotations.NonNull;
 import org.jspecify.annotations.Nullable;
 
 import org.apache.causeway.core.metamodel.object.ManagedObject;
@@ -32,13 +31,11 @@
 import org.apache.causeway.viewer.commons.model.components.UiString;
 import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
 import 
org.apache.causeway.viewer.wicket.ui.components.attributes.AttributePanelWithFormField;
+import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.ChoiceProviderRecord;
 import org.apache.causeway.viewer.wicket.ui.components.widgets.select2.Select2;
-import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderAbstract;
 import org.apache.causeway.viewer.wicket.ui.util.Wkt;
 import org.apache.causeway.viewer.wicket.ui.util.Wkt.EventTopic;
 
-import org.jspecify.annotations.NonNull;
-
 public abstract class AttributePanelWithSelect
 extends AttributePanelWithFormField<ManagedObject> {
 
@@ -59,11 +56,10 @@ protected AttributePanelWithSelect(
     }
 
     protected final Select2 createSelect2(
-            final String id,
-            final Function<UiAttributeWkt, ChoiceProviderAbstract> 
choiceProviderFactory) {
+            final String id) {
         var attributeModel = attributeModel();
         var select2 = Select2.createSelect2(id, attributeModel,
-                choiceProviderFactory.apply(attributeModel),
+                new ChoiceProviderRecord(attributeModel),
                 getAttributeModelChangeDispatcher());
         var settings = select2.getSettings();
         settings.setPlaceholder(attributeModel.getFriendlyName());
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ObjectChoicesAttributePanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ObjectChoicesAttributePanel.java
index 4317d0a3d91..1512b43248c 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ObjectChoicesAttributePanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ObjectChoicesAttributePanel.java
@@ -38,7 +38,6 @@
 import 
org.apache.causeway.viewer.wicket.ui.components.attributes.AttributeFragmentFactory.InputFragment;
 import 
org.apache.causeway.viewer.wicket.ui.components.attributes.choices.AttributePanelWithSelect.ChoiceTitleHandler;
 import 
org.apache.causeway.viewer.wicket.ui.components.widgets.objectsimplelink.ObjectLinkSimplePanel;
-import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderDefault;
 import org.apache.causeway.viewer.wicket.ui.util.Wkt;
 import org.apache.causeway.viewer.wicket.ui.util.WktComponents;
 
@@ -85,8 +84,7 @@ protected FormComponent<ManagedObject> 
createFormComponent(final String id, fina
         this.objectLink = new 
ChoiceFormComponent(UiComponentType.OBJECT_LINK.getId(), this);
         objectLink.setRequired(attributeModel.isRequired());
 
-        this.select2 = createSelect2(ID_AUTO_COMPLETE,
-                ChoiceProviderDefault::new);
+        this.select2 = createSelect2(ID_AUTO_COMPLETE);
 
         objectLink.addOrReplace(select2.asComponent());
         objectLink.setOutputMarkupId(true);
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ValueChoicesAttributePanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ValueChoicesAttributePanel.java
index 08635636343..6ceb9e06f2a 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ValueChoicesAttributePanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ValueChoicesAttributePanel.java
@@ -28,7 +28,6 @@
 import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
 import 
org.apache.causeway.viewer.wicket.ui.components.attributes.AttributeFragmentFactory.InputFragment;
 import 
org.apache.causeway.viewer.wicket.ui.components.attributes.choices.AttributePanelWithSelect.ChoiceTitleHandler;
-import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderDefault;
 import org.apache.causeway.viewer.wicket.ui.util.Wkt;
 import org.apache.causeway.viewer.wicket.ui.util.WktTooltips;
 
@@ -58,7 +57,7 @@ protected Component createComponentForOutput(final String id) 
{
     protected FormComponent<ManagedObject> createFormComponent(
             final String id, final UiAttributeWkt attributeModel) {
         if(select2 == null) {
-            this.select2 = createSelect2(id, ChoiceProviderDefault::new);
+            this.select2 = createSelect2(id);
         } else {
             select2.clearInput();
         }
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/ChoiceProviderRecord.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/ChoiceProviderRecord.java
new file mode 100644
index 00000000000..d29a610319e
--- /dev/null
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/ChoiceProviderRecord.java
@@ -0,0 +1,235 @@
+/*
+ *  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.causeway.viewer.wicket.ui.components.widgets.select2;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+import org.apache.wicket.util.string.Strings;
+import org.jspecify.annotations.Nullable;
+import org.wicketstuff.select2.ChoiceProvider;
+import org.wicketstuff.select2.Response;
+
+import org.apache.causeway.applib.services.i18n.TranslationContext;
+import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import org.apache.causeway.commons.collections.Can;
+import org.apache.causeway.commons.internal.base._NullSafe;
+import org.apache.causeway.core.metamodel.object.ManagedObject;
+import org.apache.causeway.core.metamodel.objectmanager.memento.ObjectMemento;
+import org.apache.causeway.core.metamodel.util.Facets;
+import org.apache.causeway.viewer.commons.model.attrib.UiAttribute;
+import org.apache.causeway.viewer.commons.model.attrib.UiParameter;
+import org.apache.causeway.viewer.wicket.model.models.HasCommonContext;
+import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
+
+public record ChoiceProviderRecord(
+    UiAttributeWkt attributeModel,
+    UiAttribute.ChoiceProviderSort choiceProviderSort)
+implements HasCommonContext, Serializable {
+
+    public ChoiceProviderRecord(
+            final UiAttributeWkt attributeModel) {
+        this(attributeModel, 
UiAttribute.ChoiceProviderSort.valueOf(attributeModel));
+    }
+    
+    /**
+     * Get the value for displaying to an end user.
+     */
+    public String getDisplayValue(final ObjectMemento choiceMemento) {
+        if (choiceMemento == null
+                || choiceMemento.isEmpty()) {
+            return 
getPlaceholderRenderService().asText(PlaceholderLiteral.NULL_REPRESENTATION);
+        }
+        return translate(choiceMemento.title());
+    }
+
+    /**
+     * This method is called to get the id value of an object (used as the 
value attribute of a
+     * choice element) The id can be extracted from the object like a primary 
key, or if the list is
+     * stable you could just return a toString of the index.
+     * <p>
+     * Note that the given index can be {@code -1} if the object in question 
is not contained in the
+     * available choices.
+     */
+    public String getIdValue(final ObjectMemento choiceMemento) {
+        if (choiceMemento == null) {
+            return ObjectMemento.NULL_ID;
+        }
+        return ObjectMemento.enstringToUrlBase64(choiceMemento);
+    }
+
+    /**
+     * Queries application for choices that match the search {@code term} and 
adds them to the
+     * {@code response}
+     */
+    public void query(
+            final String term,
+            final int page,
+            final org.wicketstuff.select2.Response<ObjectMemento> response) {
+
+        var mementosFiltered = query(term);
+
+        if(isRequired()) {
+            response.addAll(mementosFiltered.toList());
+            return;
+        }
+
+        // else, if not mandatory, prepend null
+        var mementosIncludingNull = mementosFiltered.toArrayList();
+        mementosIncludingNull.add(0, null);
+
+        response.addAll(mementosIncludingNull);
+    }
+
+    /**
+     * Converts a list of choice ids back into application's choice objects. 
When the choice
+     * provider is attached to a single-select component the {@code ids} 
collection will contain
+     * exactly one id, and a collection containing exactly one choice should 
be returned.
+     */
+    public Collection<ObjectMemento> toChoices(final Collection<String> ids) {
+        return _NullSafe.stream(ids)
+                .map(this::mementoFromIdWithNullHandling)
+                .collect(Collectors.toList());
+    }
+    
+    // -- UTIL
+    
+    /** adapter method */
+    ChoiceProvider<ObjectMemento> toSelect2ChoiceProvider() {
+        var delegate = this;
+        return new ChoiceProvider<ObjectMemento>() {
+            private static final long serialVersionUID = 1L;
+
+            @Override public Collection<ObjectMemento> 
toChoices(Collection<String> ids) {
+                return delegate.toChoices(ids);
+            }
+            @Override public void query(String term, int page, 
Response<ObjectMemento> response) {
+                delegate.query(term, page, response);
+            }
+            @Override public String getIdValue(ObjectMemento object) {
+                return delegate.getIdValue(object);
+            }
+            @Override public String getDisplayValue(ObjectMemento object) {
+                return delegate.getDisplayValue(object);
+            }
+        };
+    }
+    
+    // -- HELPER
+    
+    private Can<ObjectMemento> queryAll() {
+        return attributeModel().getChoices() // must not return detached 
entities
+                .map(ManagedObject::getMementoElseFail);
+    }
+
+    private Can<ObjectMemento> 
queryWithAutoCompleteUsingObjectSpecification(final String term) {
+        var autoCompleteAdapters = Facets
+                .autoCompleteExecute(attributeModel().getElementType(), term);
+        return autoCompleteAdapters
+                .map(ManagedObject::getMementoElseFail);
+    }
+
+    private Can<ObjectMemento> queryWithAutoComplete(final String term) {
+        var attributeModel = attributeModel();
+        var pendingArgs = attributeModel.isParameter()
+                ? 
((UiParameter)attributeModel).getParameterNegotiationModel().getParamValues()
+                : Can.<ManagedObject>empty();
+        var pendingArgMementos = pendingArgs
+                .map(ManagedObject::getMementoElseFail);
+
+        if(attributeModel.isParameter()) {
+            // recover any pendingArgs
+            var paramModel = (UiParameter)attributeModel;
+
+            paramModel
+                .getParameterNegotiationModel()
+                .setParamValues(
+                        reconstructPendingArgs(paramModel, 
pendingArgMementos));
+        }
+
+        return attributeModel
+                .getAutoComplete(term)
+                .map(ManagedObject::getMementoElseFail);
+    }
+
+    private Can<ManagedObject> reconstructPendingArgs(
+            final UiParameter parameterModel,
+            final Can<ObjectMemento> pendingArgMementos) {
+        var pendingArgsList = _NullSafe.stream(pendingArgMementos)
+            .map(getObjectManager()::demementify)
+            .collect(Can.toCan());
+
+       return pendingArgsList;
+    }
+    
+    private @Nullable ObjectMemento mementoFromIdWithNullHandling(final String 
id) {
+        if(ObjectMemento.NULL_ID.equals(id)) return null;
+        
+        return mementoFromId(id);
+    }
+    
+    /**
+     * Whether to not prepend <code>null</code> as choice candidate.
+     */
+    private boolean isRequired() {
+        return attributeModel().isRequired();
+    }
+
+    /**
+     * Get choice candidates with filtering (don't include <code>null</code>).
+     */
+    private Can<ObjectMemento> query(final String term) {
+        return switch(choiceProviderSort) {
+            case CHOICES->filter(term, queryAll());
+            case AUTO_COMPLETE->queryWithAutoComplete(term);
+            case 
OBJECT_AUTO_COMPLETE->queryWithAutoCompleteUsingObjectSpecification(term);
+            case NO_CHOICES->Can.empty();
+        };
+    }
+
+    /**
+     * Filters all choices against a term by using their
+     * {@link ManagedObject#getTitle() title string}
+     *
+     * @param term The term entered by the user
+     * @param choiceMementos The collections of choices to filter
+     * @return A list of all matching choices
+     */
+    private Can<ObjectMemento> filter(
+            final String term,
+            final Can<ObjectMemento> choiceMementos) {
+
+        if (Strings.isEmpty(term)) return choiceMementos;
+
+        var translationContext = TranslationContext.empty();
+        var translator = getTranslationService();
+        var termLower = term.toLowerCase();
+
+        return choiceMementos.filter((final ObjectMemento candidateMemento)->{
+            var title = translator.translate(translationContext, 
candidateMemento.title());
+            return title.toLowerCase().contains(termLower);
+        });
+    }
+
+    private @Nullable ObjectMemento mementoFromId(final @Nullable String id) {
+        return ObjectMemento.destringFromUrlBase64(id);
+    }
+
+}
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2.java
index f722355cfed..9047ce6d98c 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2.java
@@ -24,6 +24,7 @@
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.LambdaModel;
 import org.apache.wicket.model.Model;
+import org.jspecify.annotations.NonNull;
 import org.wicketstuff.select2.AbstractSelect2Choice;
 import org.wicketstuff.select2.Select2Choice;
 import org.wicketstuff.select2.Select2MultiChoice;
@@ -31,14 +32,11 @@
 import org.apache.causeway.commons.functional.Either;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.objectmanager.memento.ObjectMemento;
-import org.apache.causeway.viewer.wicket.model.models.HasCommonContext;
 import 
org.apache.causeway.viewer.wicket.model.models.AttributeModelWithMultiChoice;
 import 
org.apache.causeway.viewer.wicket.model.models.AttributeModelWithSingleChoice;
+import org.apache.causeway.viewer.wicket.model.models.HasCommonContext;
 import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
 import 
org.apache.causeway.viewer.wicket.ui.components.attributes.AttributeModelChangeDispatcher;
-import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderAbstract;
-
-import org.jspecify.annotations.NonNull;
 
 /**
  * Wrapper around either a {@link Select2Choice} or a {@link 
Select2MultiChoice}.
@@ -52,7 +50,7 @@ public record Select2(
     public static Select2 createSelect2(
             final String id,
             final UiAttributeWkt attributeModel,
-            final ChoiceProviderAbstract choiceProvider,
+            final ChoiceProviderRecord choiceProvider,
             final AttributeModelChangeDispatcher select2ChangeDispatcher) {
         var select2 = new Select2(attributeModel.isSingular()
                 ? Either.left(
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2ChoiceExt.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2ChoiceExt.java
index 73c637d24d8..598d155a53f 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2ChoiceExt.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2ChoiceExt.java
@@ -25,7 +25,6 @@
 import org.apache.causeway.applib.id.LogicalType;
 import org.apache.causeway.core.metamodel.objectmanager.memento.ObjectMemento;
 import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
-import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderAbstract;
 
 import lombok.Getter;
 import lombok.experimental.Accessors;
@@ -40,7 +39,7 @@ public static Select2ChoiceExt create(
             final String id,
             final IModel<ObjectMemento> modelObject,
             final UiAttributeWkt attributeModel,
-            final ChoiceProviderAbstract choiceProvider) {
+            final ChoiceProviderRecord choiceProvider) {
         return new Select2ChoiceExt(id, modelObject, attributeModel, 
choiceProvider);
     }
 
@@ -50,8 +49,8 @@ private Select2ChoiceExt(
             final String id,
             final IModel<ObjectMemento> model,
             final UiAttributeWkt attributeModel,
-            final ChoiceProviderAbstract choiceProvider) {
-        super(id, model, choiceProvider);
+            final ChoiceProviderRecord choiceProvider) {
+        super(id, model, choiceProvider.toSelect2ChoiceProvider());
 
         logicalType = attributeModel.getElementType().logicalType();
 
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2MultiChoiceExt.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2MultiChoiceExt.java
index fd17a0986f8..fd52d905d4c 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2MultiChoiceExt.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/Select2MultiChoiceExt.java
@@ -29,7 +29,6 @@
 import org.apache.causeway.commons.internal.base._Casts;
 import org.apache.causeway.core.metamodel.objectmanager.memento.ObjectMemento;
 import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
-import 
org.apache.causeway.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderAbstract;
 
 import lombok.Getter;
 import lombok.experimental.Accessors;
@@ -44,7 +43,7 @@ public static Select2MultiChoiceExt create(
             final String id,
             final IModel<ArrayList<ObjectMemento>> modelObject,
             final UiAttributeWkt attributeModel,
-            final ChoiceProviderAbstract choiceProvider) {
+            final ChoiceProviderRecord choiceProvider) {
 
         return new Select2MultiChoiceExt(id, 
_Casts.uncheckedCast(modelObject), attributeModel, choiceProvider);
     }
@@ -55,9 +54,9 @@ public static Select2MultiChoiceExt create(
             final String id,
             final IModel<Collection<ObjectMemento>> model,
             final UiAttributeWkt attributeModel,
-            final ChoiceProviderAbstract choiceProvider) {
+            final ChoiceProviderRecord choiceProvider) {
 
-        super(id, model, choiceProvider);
+        super(id, model, choiceProvider.toSelect2ChoiceProvider());
         logicalType = attributeModel.getElementType().logicalType();
 
         getSettings().setCloseOnSelect(true);
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/providers/ChoiceProviderAbstract.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/providers/ChoiceProviderAbstract.java
deleted file mode 100644
index a7b8be5dfa4..00000000000
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/providers/ChoiceProviderAbstract.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- *  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.causeway.viewer.wicket.ui.components.widgets.select2.providers;
-
-import java.util.Collection;
-import java.util.stream.Collectors;
-
-import org.apache.wicket.util.string.Strings;
-import org.wicketstuff.select2.ChoiceProvider;
-
-import org.jspecify.annotations.Nullable;
-
-import org.apache.causeway.applib.services.i18n.TranslationContext;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
-import org.apache.causeway.commons.collections.Can;
-import org.apache.causeway.commons.internal.base._NullSafe;
-import org.apache.causeway.core.metamodel.object.ManagedObject;
-import org.apache.causeway.core.metamodel.objectmanager.memento.ObjectMemento;
-import org.apache.causeway.viewer.wicket.model.models.HasCommonContext;
-
-public abstract class ChoiceProviderAbstract
-extends ChoiceProvider<ObjectMemento>
-implements HasCommonContext {
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Whether to not prepend <code>null</code> as choice candidate.
-     */
-    protected abstract boolean isRequired();
-
-    /**
-     * Get choice candidates with filtering (don't include <code>null</code>).
-     */
-    protected abstract Can<ObjectMemento> query(@Nullable String term);
-
-    @Override
-    public final String getDisplayValue(final ObjectMemento choiceMemento) {
-        if (choiceMemento == null
-                || choiceMemento.isEmpty()) {
-            return 
getPlaceholderRenderService().asText(PlaceholderLiteral.NULL_REPRESENTATION);
-        }
-        return translate(choiceMemento.title());
-    }
-
-    @Override
-    public final String getIdValue(final ObjectMemento choiceMemento) {
-        if (choiceMemento == null) {
-            return ObjectMemento.NULL_ID;
-        }
-        return ObjectMemento.enstringToUrlBase64(choiceMemento);
-    }
-
-    protected final @Nullable ObjectMemento mementoFromId(final @Nullable 
String id) {
-        return ObjectMemento.destringFromUrlBase64(id);
-    }
-
-    @Override
-    public final void query(
-            final String term,
-            final int page,
-            final org.wicketstuff.select2.Response<ObjectMemento> response) {
-
-        var mementosFiltered = query(term);
-
-        if(isRequired()) {
-            response.addAll(mementosFiltered.toList());
-            return;
-        }
-
-        // else, if not mandatory, prepend null
-        var mementosIncludingNull = mementosFiltered.toArrayList();
-        mementosIncludingNull.add(0, null);
-
-        response.addAll(mementosIncludingNull);
-    }
-
-    @Override
-    public final Collection<ObjectMemento> toChoices(final Collection<String> 
ids) {
-        return _NullSafe.stream(ids)
-                .map(this::mementoFromIdWithNullHandling)
-                .collect(Collectors.toList());
-    }
-
-    // -- UTILITY
-
-    /**
-     * Filters all choices against a term by using their
-     * {@link ManagedObject#getTitle() title string}
-     *
-     * @param term The term entered by the user
-     * @param choiceMementos The collections of choices to filter
-     * @return A list of all matching choices
-     */
-    protected final Can<ObjectMemento> filter(
-            final String term,
-            final Can<ObjectMemento> choiceMementos) {
-
-        if (Strings.isEmpty(term)) {
-            return choiceMementos;
-        }
-
-        var translationContext = TranslationContext.empty();
-        var translator = getTranslationService();
-        var termLower = term.toLowerCase();
-
-        return choiceMementos.filter((final ObjectMemento candidateMemento)->{
-            var title = translator.translate(translationContext, 
candidateMemento.title());
-            return title.toLowerCase().contains(termLower);
-        });
-
-    }
-
-    // -- HELPER
-
-    private @Nullable ObjectMemento mementoFromIdWithNullHandling(final String 
id) {
-        if(ObjectMemento.NULL_ID.equals(id)) {
-            return null;
-        }
-        return mementoFromId(id);
-    }
-
-}
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/providers/ChoiceProviderAbstractForAttributeModel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/providers/ChoiceProviderAbstractForAttributeModel.java
deleted file mode 100644
index 4a6d5a9a698..00000000000
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/providers/ChoiceProviderAbstractForAttributeModel.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  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.causeway.viewer.wicket.ui.components.widgets.select2.providers;
-
-import org.apache.causeway.commons.collections.Can;
-import org.apache.causeway.core.metamodel.objectmanager.memento.ObjectMemento;
-import org.apache.causeway.viewer.commons.model.attrib.UiAttribute;
-import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
-
-import lombok.Getter;
-import lombok.experimental.Accessors;
-
-public abstract class ChoiceProviderAbstractForAttributeModel
-extends ChoiceProviderAbstract {
-
-    private static final long serialVersionUID = 1L;
-
-    @Getter @Accessors(fluent = true)
-    private final UiAttributeWkt attributeModel;
-    private final UiAttribute.ChoiceProviderSort choiceProviderSort;
-
-    protected ChoiceProviderAbstractForAttributeModel(final UiAttributeWkt 
attributeModel) {
-        super();
-        this.attributeModel = attributeModel;
-        this.choiceProviderSort = 
UiAttribute.ChoiceProviderSort.valueOf(attributeModel);
-    }
-
-    @Override
-    protected final boolean isRequired() {
-        return attributeModel().isRequired();
-    }
-
-    @Override
-    protected final Can<ObjectMemento> query(final String term) {
-        switch(choiceProviderSort) {
-        case CHOICES:
-            return super.filter(term, queryAll());
-        case AUTO_COMPLETE:
-            return queryWithAutoComplete(term);
-        case OBJECT_AUTO_COMPLETE:
-            return queryWithAutoCompleteUsingObjectSpecification(term);
-        case NO_CHOICES:
-        default:
-            // fall through
-        }
-        return Can.empty();
-    }
-
-    protected abstract Can<ObjectMemento> queryAll();
-    protected abstract Can<ObjectMemento> queryWithAutoComplete(String term);
-    protected abstract Can<ObjectMemento> 
queryWithAutoCompleteUsingObjectSpecification(String term);
-
-}
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/providers/ChoiceProviderDefault.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/providers/ChoiceProviderDefault.java
deleted file mode 100644
index 5235f872705..00000000000
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/providers/ChoiceProviderDefault.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- *  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.causeway.viewer.wicket.ui.components.widgets.select2.providers;
-
-import org.apache.causeway.commons.collections.Can;
-import org.apache.causeway.commons.internal.base._NullSafe;
-import org.apache.causeway.core.metamodel.object.ManagedObject;
-import org.apache.causeway.core.metamodel.objectmanager.memento.ObjectMemento;
-import org.apache.causeway.core.metamodel.util.Facets;
-import org.apache.causeway.viewer.commons.model.attrib.UiParameter;
-import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
-
-public class ChoiceProviderDefault
-extends ChoiceProviderAbstractForAttributeModel {
-
-    private static final long serialVersionUID = 1L;
-
-    public ChoiceProviderDefault(
-            final UiAttributeWkt attributeModel) {
-        super(attributeModel);
-    }
-
-    @Override
-    protected Can<ObjectMemento> queryAll() {
-        return attributeModel().getChoices() // must not return detached 
entities
-                .map(ManagedObject::getMementoElseFail);
-    }
-
-    @Override
-    protected Can<ObjectMemento> 
queryWithAutoCompleteUsingObjectSpecification(final String term) {
-        var autoCompleteAdapters = Facets
-                .autoCompleteExecute(attributeModel().getElementType(), term);
-        return autoCompleteAdapters
-                .map(ManagedObject::getMementoElseFail);
-    }
-
-    @Override
-    protected Can<ObjectMemento> queryWithAutoComplete(final String term) {
-        var attributeModel = attributeModel();
-        var pendingArgs = attributeModel.isParameter()
-                ? 
((UiParameter)attributeModel).getParameterNegotiationModel().getParamValues()
-                : Can.<ManagedObject>empty();
-        var pendingArgMementos = pendingArgs
-                .map(ManagedObject::getMementoElseFail);
-
-        if(attributeModel.isParameter()) {
-            // recover any pendingArgs
-            var paramModel = (UiParameter)attributeModel;
-
-            paramModel
-                .getParameterNegotiationModel()
-                .setParamValues(
-                        reconstructPendingArgs(paramModel, 
pendingArgMementos));
-        }
-
-        return attributeModel
-                .getAutoComplete(term)
-                .map(ManagedObject::getMementoElseFail);
-    }
-
-    // -- HELPER
-
-    private Can<ManagedObject> reconstructPendingArgs(
-            final UiParameter parameterModel,
-            final Can<ObjectMemento> pendingArgMementos) {
-
-        var pendingArgsList = _NullSafe.stream(pendingArgMementos)
-            .map(getObjectManager()::demementify)
-            .collect(Can.toCan());
-
-       return pendingArgsList;
-    }
-
-}


Reply via email to