You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2024/06/16 07:29:01 UTC

(causeway) branch master updated: CAUSEWAY-3642: moves matching responsibility into Tokens (SPI polishing)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new d159f9c60c CAUSEWAY-3642: moves matching responsibility into Tokens (SPI polishing)
d159f9c60c is described below

commit d159f9c60c957a1fc8de25ab198bdc1f8a805462
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sun Jun 16 09:28:55 2024 +0200

    CAUSEWAY-3642: moves matching responsibility into Tokens (SPI polishing)
---
 .../services/search/CollectionSearchService.java   | 54 +++++++++++++++++-----
 .../tabular/interactive/_SearchUtils.java          |  5 ++
 2 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/causeway/applib/services/search/CollectionSearchService.java b/api/applib/src/main/java/org/apache/causeway/applib/services/search/CollectionSearchService.java
index 860c4c446f..3f5cf0c9c2 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/services/search/CollectionSearchService.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/services/search/CollectionSearchService.java
@@ -22,6 +22,8 @@ import java.io.Serializable;
 import java.util.function.BiPredicate;
 import java.util.function.Function;
 
+import org.springframework.lang.Nullable;
+
 import org.apache.causeway.applib.services.i18n.TranslatableString;
 import org.apache.causeway.applib.services.i18n.TranslationContext;
 import org.apache.causeway.commons.internal.base._Strings;
@@ -42,7 +44,12 @@ import lombok.NonNull;
 public interface CollectionSearchService {
 
     public static interface Tokens extends Serializable {
-
+        /**
+         * @apiNote for convenience, the searchArg can be pre-processed by
+         *      by the {@link CollectionSearchService#matcher(Class)};
+         *      The default implementation already handles the empty searchArg case.
+         */
+        boolean match(@Nullable String searchArg);
     }
 
     /**
@@ -51,32 +58,55 @@ public interface CollectionSearchService {
      */
     boolean handles(@NonNull Class<?> domainType);
 
-    // -- SEARCH ARGUMENT
+    // -- TOKENIZER
 
     /**
-     * For given {@code domainType} returns a {@link BiPredicate}
-     * that matches {@link Tokens} against a nullable searchString.
+     * Returns a function that for a given domainObject returns {@link Tokens} (words),
+     * that are then matchable by {@link #matcher(Class)}.
      * <p>
-     * For example, the searchString could be tokenized (parsed into tokens),
-     * and then matched against the {@link Tokens} using either OR or AND semantics.
+     * For example the domain object's title could be tokenized (parsed into tokens).
      *
      * @param domainType - entity or view-model type to be rendered as row in a table
      * @apiNote guarded by a call to {@link #handles(Class)}
      */
-    <T> BiPredicate<Tokens, String> matcher(
+    <T> Function<T, Tokens> tokenizer(
             @NonNull Class<T> domainType);
 
+    // -- MATCHER
+
     /**
-     * Returns a function that for a given domainObject returns {@link Tokens} (words),
-     * that are then matchable by {@link #matcher(Class)}.
+     * For given {@code domainType} returns a {@link BiPredicate}
+     * that matches {@link Tokens} against a nullable searchString.
      * <p>
-     * For example the domain object's title could be tokenized (parsed into tokens).
+     * For example, the searchString could be tokenized (parsed into tokens),
+     * and then matched against the {@link Tokens} using either OR or AND semantics.
+     * <p>
+     * The default implementation sanitizes the user input (searchArg)
+     * then strips any leading or trailing blanks and handles the empty searchArg case.
      *
      * @param domainType - entity or view-model type to be rendered as row in a table
      * @apiNote guarded by a call to {@link #handles(Class)}
      */
-    <T> Function<T, Tokens> tokenizer(
-            @NonNull Class<T> domainType);
+    default <T> BiPredicate<Tokens, String> matcher(
+            final @NonNull Class<T> domainType) {
+        return (tokens, searchArg) -> {
+            var sanitized = _Strings.blankToNullOrTrim(searchArg);
+            return _Strings.isNotEmpty(sanitized)
+                ? tokens.match(sanitized)
+                : true; // empty searchArg means 'unfiltered'
+        };
+    }
+
+    // -- SEARCH ARG SANITIZER
+
+    /**
+     * Pre-process user input before passing it to the matcher.
+     * <p>
+     * Default behavior is to strip leading or trailing blanks (if any).
+     */
+    default String sanitzeSearchArgument(final @Nullable String searchArg) {
+        return _Strings.blankToNullOrTrim(searchArg);
+    }
 
     // -- SEARCH PROMT
 
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/interactive/_SearchUtils.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/interactive/_SearchUtils.java
index 8b5b41ffbe..03b3a266de 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/interactive/_SearchUtils.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/interactive/_SearchUtils.java
@@ -43,6 +43,11 @@ class _SearchUtils {
         @NonNull final BiPredicate<Tokens, String> matcher;
         @NonNull final String searchPromptPlaceholderText;
 
+        /**
+         * @deprecated {@link Tokens} could be stored with the {@link DataRow}
+         *      on first request-cycle, such we don't need to re-hydrate pojos
+         *      on follow-up partial page updates
+         */
         @Deprecated
         @NonNull final BiPredicate<Object, String> searchPredicate() {
             return (pojo, searchArg) -> {