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 bfe6ca992a CAUSEWAY-3404: adding TextUtils for GA (WIP)
bfe6ca992a is described below

commit bfe6ca992a40be8aca9fba1ee8af452ea08ed490
Author: Andi Huber <[email protected]>
AuthorDate: Tue May 9 07:04:27 2023 +0200

    CAUSEWAY-3404: adding TextUtils for GA (WIP)
---
 .../org/apache/causeway/applib/value/Markup.java   |   3 +-
 commons/src/main/java/module-info.java             |   3 +-
 .../commons/internal/base/_StringCutter.java       | 184 ----------------
 .../causeway/commons/internal/base/_Text.java      |  31 +--
 .../internal/debug/xray/graphics/_Graphics.java    |  13 +-
 .../commons/internal/exceptions/_Exceptions.java   |   4 +-
 .../apache/causeway/commons/util/TextUtils.java    | 242 +++++++++++++++++++++
 .../causeway/commons/internal/base/TextTest.java   |  29 +--
 .../{internal/base => util}/StringCutterTest.java  |   6 +-
 .../actions/action/invocation/IdentifierUtil.java  |   4 +-
 .../TableColumnOrderServiceUsingTxtFile.java       |   6 +-
 .../testdomain/value/ValueSemanticsTester.java     |   4 +-
 .../model/valuetypes/ValueTypeExample.java         |   4 +-
 .../fixturescripts/ExecutionParametersDefault.java |   4 +-
 .../integtestsupport/applib/ApprovalsOptions.java  |  19 +-
 .../apache/causeway/tooling/j2adoc/J2AdocUnit.java |   2 +-
 .../tooling/j2adoc/util}/ResourceCoordinates.java  |  10 +-
 .../tooling/j2adoc/convert/HtmlToAsciiDocTest.java |   4 +-
 .../tooling/model4adoc/AsciiDocFactory.java        |   5 +-
 .../causeway/tooling/model4adoc/NodeWriter.java    |  27 +--
 .../model4adoc/include/IncludeStatements.java      |   6 +-
 .../viewer/resources/ResourceAbstract.java         |   4 +-
 .../wicket/ui/util/LicensedTextTemplate.java       |   4 +-
 23 files changed, 329 insertions(+), 289 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/value/Markup.java 
b/api/applib/src/main/java/org/apache/causeway/applib/value/Markup.java
index abfd94979d..1ec9a30cc2 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/value/Markup.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/value/Markup.java
@@ -31,6 +31,7 @@ import org.apache.causeway.applib.CausewayModuleApplib;
 import org.apache.causeway.applib.annotation.Value;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.base._Text;
+import org.apache.causeway.commons.util.TextUtils;
 
 import lombok.EqualsAndHashCode;
 
@@ -73,7 +74,7 @@ public final class Markup implements Serializable {
 
     public static String summarizeHtmlAsTitle(final String html) {
         return _Strings.ellipsifyAtEnd(
-                _Text.normalize(_Text.getLines(html)).stream()
+                _Text.normalize(TextUtils.readLines(html)).stream()
                 .collect(Collectors.joining(" ")),
                 255, "...");
     }
diff --git a/commons/src/main/java/module-info.java 
b/commons/src/main/java/module-info.java
index 4a5e235359..2692cbcd4b 100644
--- a/commons/src/main/java/module-info.java
+++ b/commons/src/main/java/module-info.java
@@ -23,8 +23,9 @@ module org.apache.causeway.commons {
     exports org.apache.causeway.commons.functional;
     exports org.apache.causeway.commons.handler;
     exports org.apache.causeway.commons.having;
-    exports org.apache.causeway.commons.resource;
     exports org.apache.causeway.commons.io;
+    exports org.apache.causeway.commons.util;
+    // internals exported as well
     exports org.apache.causeway.commons.internal;
     exports org.apache.causeway.commons.internal.assertions;
     exports org.apache.causeway.commons.internal.base;
diff --git 
a/commons/src/main/java/org/apache/causeway/commons/internal/base/_StringCutter.java
 
b/commons/src/main/java/org/apache/causeway/commons/internal/base/_StringCutter.java
deleted file mode 100644
index dc50cdd291..0000000000
--- 
a/commons/src/main/java/org/apache/causeway/commons/internal/base/_StringCutter.java
+++ /dev/null
@@ -1,184 +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.commons.internal.base;
-
-import java.util.function.UnaryOperator;
-
-import org.apache.causeway.commons.internal.assertions._Assert;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NonNull;
-
-/**
- * <h1>- internal use only -</h1>
- * <p>
- * String cutting utility.
- * </p>
- * <p>
- * <b>WARNING</b>: Do <b>NOT</b> use any of the classes provided by this 
package! <br/>
- * These may be changed or removed without notice!
- * </p>
- *
- * @since 2.0
- */
-@AllArgsConstructor(staticName = "of")
-public final class _StringCutter {
-
-    @Getter
-    private final @NonNull String value;
-
-    /**
-     * Returns a new {@link _StringCutter} holding a the string value as 
returned by given {@code mapper}.
-     */
-    public _StringCutter map(final @NonNull UnaryOperator<String> mapper) {
-        return _StringCutter.of(mapper.apply(value));
-    }
-
-    /**
-     * Whether the held string value contains the specified
-     * sequence of char values.
-     *
-     * @param s the sequence to search for
-     * @return true if the held string value contains {@code s}, false 
otherwise
-     */
-    public boolean contains(final CharSequence s) {
-        return value.contains(s);
-    }
-
-    /**
-     * Searches for first occurrence of given {@code str} within
-     * held string value and drops any characters that come before
-     * (the matching part).
-     * <p>
-     * If no match acts as identity operator.
-     */
-    public _StringCutter dropBefore(final @NonNull String str) {
-        _Assert.assertNotEmpty(str, ()->"can only matches against non-empty 
string");
-        final int index = value.indexOf(str);
-        if(index>-1) {
-            return _StringCutter.of(value.substring(index));
-        }
-        return this;
-    }
-
-    /**
-     * Searches for first occurrence of given {@code str} within
-     * held string value and drops any characters that come after
-     * (the matching part).
-     */
-    public _StringCutter dropAfter(final @NonNull String str) {
-        _Assert.assertNotEmpty(str, ()->"can only matches against non-empty 
string");
-        final int index = value.indexOf(str);
-        if(index>-1) {
-            return _StringCutter.of(value.substring(0, index + str.length()));
-        }
-        return this;
-    }
-
-    /**
-     * Searches for last occurrence of given {@code str} within
-     * held string value and drops any characters that come before
-     * (the matching part).
-     */
-    public _StringCutter dropBeforeLast(final @NonNull String str) {
-        _Assert.assertNotEmpty(str, ()->"can only matches against non-empty 
string");
-        final int index = value.lastIndexOf(str);
-        if(index>-1) {
-            return _StringCutter.of(value.substring(index));
-        }
-        return this;
-    }
-
-    /**
-     * Searches for last occurrence of given {@code str} within
-     * held string value and drops any characters that come after
-     * (the matching part).
-     */
-    public _StringCutter dropAfterLast(final @NonNull String str) {
-        _Assert.assertNotEmpty(str, ()->"can only matches against non-empty 
string");
-        final int index = value.lastIndexOf(str);
-        if(index>-1) {
-            return _StringCutter.of(value.substring(0, index + str.length()));
-        }
-        return this;
-    }
-
-    /**
-     * Searches for first occurrence of given {@code str} within
-     * held string value, keeps any characters that come before
-     * (the matching part) and drops the rest.
-     * <p>
-     * If no match acts as identity operator.
-     */
-    public _StringCutter keepBefore(final @NonNull String str) {
-        _Assert.assertNotEmpty(str, ()->"can only matches against non-empty 
string");
-        final int index = value.indexOf(str);
-        if(index>-1) {
-            return _StringCutter.of(value.substring(0, index));
-        }
-        return this;
-    }
-
-    /**
-     * Searches for first occurrence of given {@code str} within
-     * held string value, keeps any characters that come after
-     * (the matching part) and drops the rest.
-     */
-    public _StringCutter keepAfter(final @NonNull String str) {
-        _Assert.assertNotEmpty(str, ()->"can only matches against non-empty 
string");
-        final int index = value.indexOf(str);
-        if(index>-1) {
-            return _StringCutter.of(value.substring(index + str.length()));
-        }
-        return this;
-    }
-
-    /**
-     * Searches for last occurrence of given {@code str} within
-     * held string value, keeps any characters that come before
-     * (the matching part) and drops the rest.
-     * <p>
-     * If no match acts as identity operator.
-     */
-    public _StringCutter keepBeforeLast(final @NonNull String str) {
-        _Assert.assertNotEmpty(str, ()->"can only matches against non-empty 
string");
-        final int index = value.indexOf(str);
-        if(index>-1) {
-            return _StringCutter.of(value.substring(0, index));
-        }
-        return this;
-    }
-
-    /**
-     * Searches for last occurrence of given {@code str} within
-     * held string value, keeps any characters that come after
-     * (the matching part) and drops the rest.
-     */
-    public _StringCutter keepAfterLast(final @NonNull String str) {
-        _Assert.assertNotEmpty(str, ()->"can only matches against non-empty 
string");
-        final int index = value.indexOf(str);
-        if(index>-1) {
-            return _StringCutter.of(value.substring(index + str.length()));
-        }
-        return this;
-    }
-
-
-}
diff --git 
a/commons/src/main/java/org/apache/causeway/commons/internal/base/_Text.java 
b/commons/src/main/java/org/apache/causeway/commons/internal/base/_Text.java
index a86270a70d..194774ff6f 100644
--- a/commons/src/main/java/org/apache/causeway/commons/internal/base/_Text.java
+++ b/commons/src/main/java/org/apache/causeway/commons/internal/base/_Text.java
@@ -39,6 +39,7 @@ import org.springframework.lang.Nullable;
 import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.collections._Lists;
+import org.apache.causeway.commons.util.TextUtils;
 
 import lombok.Getter;
 import lombok.NonNull;
@@ -62,28 +63,6 @@ public final class _Text {
 
     private _Text() {}
 
-    /**
-     * Converts given {@code text} into a {@link Stream} of lines,
-     * removing new line characters {@code \n,\r} in the process.
-     * @param text - nullable
-     * @return non-null
-     * @apiNote Java 11+ provides {@code String.lines()}
-     */
-    public static Stream<String> streamLines(final @Nullable String text){
-        return _Strings.splitThenStream(text, "\n")
-                .map(s->s.replace("\r", ""));
-    }
-
-    /**
-     * Converts given {@code text} into a {@link Can} of lines,
-     * removing new line characters {@code \n,\r} in the process.
-     * @param text - nullable
-     * @return non-null
-     */
-    public static Can<String> getLines(final @Nullable String text){
-        return Can.ofStream(streamLines(text));
-    }
-
     public static Can<String> breakLines(final Can<String> lines, final int 
maxChars) {
         if(lines.isEmpty()) {
             return lines;
@@ -169,7 +148,7 @@ public final class _Text {
         if(text==null) {
             return "";
         }
-        return 
normalize(getLines(text)).stream().collect(Collectors.joining("\n"));
+        return 
normalize(TextUtils.readLines(text)).stream().collect(Collectors.joining("\n"));
     }
 
     /**
@@ -308,15 +287,15 @@ public final class _Text {
     // -- TESTING SUPPORT
 
     public static void assertTextEquals(final @Nullable String a, final 
@Nullable String b) {
-        assertTextEquals(getLines(a), getLines(b));
+        assertTextEquals(TextUtils.readLines(a), TextUtils.readLines(b));
     }
 
     public static void assertTextEquals(final @NonNull Can<String> a, final 
@Nullable String b) {
-        assertTextEquals(a, getLines(b));
+        assertTextEquals(a, TextUtils.readLines(b));
     }
 
     public static void assertTextEquals(final @Nullable String a, final 
@NonNull Can<String> b) {
-        assertTextEquals(getLines(a), b);
+        assertTextEquals(TextUtils.readLines(a), b);
     }
 
     public static void assertTextEquals(final @NonNull Can<String> a, final 
@NonNull Can<String> b) {
diff --git 
a/commons/src/main/java/org/apache/causeway/commons/internal/debug/xray/graphics/_Graphics.java
 
b/commons/src/main/java/org/apache/causeway/commons/internal/debug/xray/graphics/_Graphics.java
index 3678eb8028..4e42871b93 100644
--- 
a/commons/src/main/java/org/apache/causeway/commons/internal/debug/xray/graphics/_Graphics.java
+++ 
b/commons/src/main/java/org/apache/causeway/commons/internal/debug/xray/graphics/_Graphics.java
@@ -33,6 +33,7 @@ import java.util.Optional;
 import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.internal.base._Refs;
 import org.apache.causeway.commons.internal.base._Text;
+import org.apache.causeway.commons.util.TextUtils;
 
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
@@ -52,7 +53,7 @@ final class _Graphics {
             new float[] { 2f, 0f, 2f },
             2f);
 
-    static Optional<Font> lookupFont(String fontName, float size) {
+    static Optional<Font> lookupFont(final String fontName, final float size) {
         val ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
         for (Font font : ge.getAllFonts()) {
             if(font.getFontName().equals(fontName)) {
@@ -62,7 +63,7 @@ final class _Graphics {
         return Optional.empty();
     }
 
-    static void arrowHorizontal(Graphics2D g, int m0, int m1, int y) {
+    static void arrowHorizontal(final Graphics2D g, final int m0, final int 
m1, final int y) {
 
         g.drawLine(m0, y, m1, y);
 
@@ -79,7 +80,7 @@ final class _Graphics {
         g.setStroke(origStroke);
     }
 
-    static void enableTextAntialiasing(Graphics2D g) {
+    static void enableTextAntialiasing(final Graphics2D g) {
 
         g.setRenderingHint(
                 RenderingHints.KEY_TEXT_ANTIALIASING,
@@ -116,11 +117,11 @@ final class _Graphics {
         int lineDescent;
         int lineHeight;
 
-        Dimension layout(FontMetrics metrics, int hPadding, int vPadding, int 
lineGap, int maxCharsPerLine) {
+        Dimension layout(final FontMetrics metrics, final int hPadding, final 
int vPadding, final int lineGap, final int maxCharsPerLine) {
             this.hPadding = hPadding;
             this.vPadding = vPadding;
             this.lineGap = lineGap;
-            lines = _Text.breakLines(_Text.getLines(label), maxCharsPerLine);
+            lines = _Text.breakLines(TextUtils.readLines(label), 
maxCharsPerLine);
             if(lines.isEmpty()) {
                 return new Dimension(0, 0);
             }
@@ -137,7 +138,7 @@ final class _Graphics {
             return new Dimension(width, height);
         }
 
-        void render(Graphics2D g) {
+        void render(final Graphics2D g) {
             if(lines==null
                     || lines.isEmpty()) {
                 return;
diff --git 
a/commons/src/main/java/org/apache/causeway/commons/internal/exceptions/_Exceptions.java
 
b/commons/src/main/java/org/apache/causeway/commons/internal/exceptions/_Exceptions.java
index e8b70cac28..8bd89d02b1 100644
--- 
a/commons/src/main/java/org/apache/causeway/commons/internal/exceptions/_Exceptions.java
+++ 
b/commons/src/main/java/org/apache/causeway/commons/internal/exceptions/_Exceptions.java
@@ -33,9 +33,9 @@ import org.springframework.lang.Nullable;
 
 import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.internal.base._NullSafe;
-import org.apache.causeway.commons.internal.base._StringCutter;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.collections._Lists;
+import org.apache.causeway.commons.util.TextUtils;
 
 import lombok.NonNull;
 import lombok.val;
@@ -440,7 +440,7 @@ public final class _Exceptions {
                     val replacement = entry.getValue();
                     var s = str;
                     s = s.replace(entry.getKey() + ".", replacement.isEmpty() 
? "{" : replacement + ".");
-                    val cutter = _StringCutter.of(s);
+                    val cutter = TextUtils.cutter(s);
                     val left = cutter.keepBefore(".").getValue();
                     val right = cutter.keepAfter(".").getValue();
                     s = replacement.isEmpty()
diff --git 
a/commons/src/main/java/org/apache/causeway/commons/util/TextUtils.java 
b/commons/src/main/java/org/apache/causeway/commons/util/TextUtils.java
new file mode 100644
index 0000000000..4b06983509
--- /dev/null
+++ b/commons/src/main/java/org/apache/causeway/commons/util/TextUtils.java
@@ -0,0 +1,242 @@
+/*
+ *  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.commons.util;
+
+import java.util.function.UnaryOperator;
+import java.util.stream.Stream;
+
+import org.springframework.lang.Nullable;
+
+import org.apache.causeway.commons.collections.Can;
+import org.apache.causeway.commons.internal.assertions._Assert;
+import org.apache.causeway.commons.internal.base._Strings;
+
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.experimental.UtilityClass;
+
+/**
+ * Utilities for text processing.
+ *
+ * @since 2.0 {@index}
+ */
+@UtilityClass
+public class TextUtils {
+
+    // -- LINE READING
+
+    /**
+     * Converts given {@code text} into a {@link Stream} of lines,
+     * removing new line characters {@code \n,\r} in the process.
+     * @param text - nullable
+     * @return non-null
+     * @apiNote Java 11+ provides {@code String.lines()}
+     */
+    public static Stream<String> streamLines(final @Nullable String text){
+        return _Strings.splitThenStream(text, "\n")
+                .map(s->s.replace("\r", ""));
+    }
+
+    /**
+     * Converts given {@code text} into a {@link Can} of lines,
+     * removing new line characters {@code \n,\r} in the process.
+     * @param text - nullable
+     * @return non-null
+     */
+    public static Can<String> readLines(final @Nullable String text){
+        return Can.ofStream(streamLines(text));
+    }
+
+    // -- STRING CUTTER
+
+    public StringCutter cutter(final @NonNull String value) {
+        return StringCutter.of(value);
+    }
+
+    /**
+     * Holder of immutable {@link String} value, that provides
+     * dropping of characters before or after search and match for
+     * a specific character sequence.
+     */
+    @AllArgsConstructor(staticName = "of", access = AccessLevel.PRIVATE)
+    public final static class StringCutter {
+
+        @Getter
+        private final @NonNull String value;
+
+        /**
+         * Returns a new {@link StringCutter} holding a the string value as 
returned by given {@code mapper}.
+         */
+        public StringCutter map(final @NonNull UnaryOperator<String> mapper) {
+            return StringCutter.of(mapper.apply(value));
+        }
+
+        /**
+         * Whether the held string value contains the specified
+         * sequence of char values.
+         *
+         * @param str the sequence to search for
+         * @return true if the held string value contains {@code str},
+         *  false otherwise (as well as when null or empty)
+         */
+        public boolean contains(final @Nullable CharSequence str) {
+            return _Strings.isNullOrEmpty(str)
+                    ? false
+                    : value.contains(str);
+        }
+
+        /**
+         * Searches for first occurrence of given {@code str} within
+         * held string value and drops any characters that come before
+         * (the matching part).
+         * <p>
+         * If no match, then acts as identity operator.
+         */
+        public StringCutter dropBefore(final @NonNull String str) {
+            _Assert.assertNotEmpty(str, this::matcherNotEmptyMsg);
+            final int index = value.indexOf(str);
+            if(index>-1) {
+                return StringCutter.of(value.substring(index));
+            }
+            return this;
+        }
+
+        /**
+         * Searches for first occurrence of given {@code str} within
+         * held string value and drops any characters that come after
+         * (the matching part).
+         * <p>
+         * If no match, then acts as identity operator.
+         */
+        public StringCutter dropAfter(final @NonNull String str) {
+            _Assert.assertNotEmpty(str, this::matcherNotEmptyMsg);
+            final int index = value.indexOf(str);
+            if(index>-1) {
+                return StringCutter.of(value.substring(0, index + 
str.length()));
+            }
+            return this;
+        }
+
+        /**
+         * Searches for last occurrence of given {@code str} within
+         * held string value and drops any characters that come before
+         * (the matching part).
+         * <p>
+         * If no match, then acts as identity operator.
+         */
+        public StringCutter dropBeforeLast(final @NonNull String str) {
+            _Assert.assertNotEmpty(str, this::matcherNotEmptyMsg);
+            final int index = value.lastIndexOf(str);
+            if(index>-1) {
+                return StringCutter.of(value.substring(index));
+            }
+            return this;
+        }
+
+        /**
+         * Searches for last occurrence of given {@code str} within
+         * held string value and drops any characters that come after
+         * (the matching part).
+         * <p>
+         * If no match, then acts as identity operator.
+         */
+        public StringCutter dropAfterLast(final @NonNull String str) {
+            _Assert.assertNotEmpty(str, this::matcherNotEmptyMsg);
+            final int index = value.lastIndexOf(str);
+            if(index>-1) {
+                return StringCutter.of(value.substring(0, index + 
str.length()));
+            }
+            return this;
+        }
+
+        /**
+         * Searches for first occurrence of given {@code str} within
+         * held string value, keeps any characters that come before
+         * (the matching part) and drops the rest.
+         * <p>
+         * If no match, then acts as identity operator.
+         */
+        public StringCutter keepBefore(final @NonNull String str) {
+            _Assert.assertNotEmpty(str, this::matcherNotEmptyMsg);
+            final int index = value.indexOf(str);
+            if(index>-1) {
+                return StringCutter.of(value.substring(0, index));
+            }
+            return this;
+        }
+
+        /**
+         * Searches for first occurrence of given {@code str} within
+         * held string value, keeps any characters that come after
+         * (the matching part) and drops the rest.
+         * <p>
+         * If no match, then acts as identity operator.
+         */
+        public StringCutter keepAfter(final @NonNull String str) {
+            _Assert.assertNotEmpty(str, this::matcherNotEmptyMsg);
+            final int index = value.indexOf(str);
+            if(index>-1) {
+                return StringCutter.of(value.substring(index + str.length()));
+            }
+            return this;
+        }
+
+        /**
+         * Searches for last occurrence of given {@code str} within
+         * held string value, keeps any characters that come before
+         * (the matching part) and drops the rest.
+         * <p>
+         * If no match, then acts as identity operator.
+         */
+        public StringCutter keepBeforeLast(final @NonNull String str) {
+            _Assert.assertNotEmpty(str, this::matcherNotEmptyMsg);
+            final int index = value.indexOf(str);
+            if(index>-1) {
+                return StringCutter.of(value.substring(0, index));
+            }
+            return this;
+        }
+
+        /**
+         * Searches for last occurrence of given {@code str} within
+         * held string value, keeps any characters that come after
+         * (the matching part) and drops the rest.
+         * <p>
+         * If no match, then acts as identity operator.
+         */
+        public StringCutter keepAfterLast(final @NonNull String str) {
+            _Assert.assertNotEmpty(str, this::matcherNotEmptyMsg);
+            final int index = value.indexOf(str);
+            if(index>-1) {
+                return StringCutter.of(value.substring(index + str.length()));
+            }
+            return this;
+        }
+
+        // -- HELPER
+
+        private String matcherNotEmptyMsg() {
+            return "can only match search and match for non-empty string";
+        }
+
+    }
+
+}
diff --git 
a/commons/src/test/java/org/apache/causeway/commons/internal/base/TextTest.java 
b/commons/src/test/java/org/apache/causeway/commons/internal/base/TextTest.java
index c15d70aed1..93caef6c5d 100644
--- 
a/commons/src/test/java/org/apache/causeway/commons/internal/base/TextTest.java
+++ 
b/commons/src/test/java/org/apache/causeway/commons/internal/base/TextTest.java
@@ -23,53 +23,54 @@ import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import org.apache.causeway.commons.collections.Can;
+import org.apache.causeway.commons.util.TextUtils;
 
 class TextTest {
 
     @Test
     void lineParsingWin() {
-        assertEquals(Can.of("Hallo", "", "World"), 
_Text.getLines("Hallo\r\n\r\nWorld"));
+        assertEquals(Can.of("Hallo", "", "World"), 
TextUtils.readLines("Hallo\r\n\r\nWorld"));
     }
 
     @Test
     void lineParsingUx() {
-        assertEquals(Can.of("Hallo", "", "World"), 
_Text.getLines("Hallo\n\nWorld"));
+        assertEquals(Can.of("Hallo", "", "World"), 
TextUtils.readLines("Hallo\n\nWorld"));
     }
 
     @Test
     void repeatedEmptyLineRemoval() {
-        
+
         assertEquals(Can.of("Hallo", "", "World"), 
_Text.removeRepeatedEmptyLines(Can.of("Hallo", "", "World")));
         assertEquals(Can.of("Hallo", "", "World"), 
_Text.removeRepeatedEmptyLines(Can.of("Hallo", "", "", "World")));
         assertEquals(Can.of("Hallo", "", "World"), 
_Text.removeRepeatedEmptyLines(Can.of("Hallo", "", " \t ", "World")));
-        
+
         assertEquals(Can.of("", "Hallo", "", "World"), 
_Text.removeRepeatedEmptyLines(Can.of("", "Hallo", "", "World")));
         assertEquals(Can.of("", "Hallo", "", "World"), 
_Text.removeRepeatedEmptyLines(Can.of("", "", "Hallo", "", "World")));
-        
+
         assertEquals(Can.of("Hallo", "", "World", ""), 
_Text.removeRepeatedEmptyLines(Can.of("Hallo", "", "World", "")));
         assertEquals(Can.of("Hallo", "", "World", ""), 
_Text.removeRepeatedEmptyLines(Can.of("Hallo", "", "World", "", "")));
-        
+
     }
-    
+
     @Test
     void leadingEmptyLineRemoval() {
-        
+
         assertEquals(Can.<String>empty(), 
_Text.removeLeadingEmptyLines(Can.of("", "", "")));
-        
+
         assertEquals(Can.of("Hallo", "", "World"), 
_Text.removeLeadingEmptyLines(Can.of("Hallo", "", "World")));
         assertEquals(Can.of("Hallo", "", "World"), 
_Text.removeLeadingEmptyLines(Can.of("", "Hallo", "", "World")));
         assertEquals(Can.of("Hallo", "", "World"), 
_Text.removeLeadingEmptyLines(Can.of("", "", "Hallo", "", "World")));
-        
+
     }
-    
+
     @Test
     void trailingEmptyLineRemoval() {
-        
+
         assertEquals(Can.<String>empty(), 
_Text.removeTrailingEmptyLines(Can.of("", "", "")));
-        
+
         assertEquals(Can.of("Hallo", "", "World"), 
_Text.removeTrailingEmptyLines(Can.of("Hallo", "", "World")));
         assertEquals(Can.of("Hallo", "", "World"), 
_Text.removeTrailingEmptyLines(Can.of("Hallo", "", "World", "")));
         assertEquals(Can.of("Hallo", "", "World"), 
_Text.removeTrailingEmptyLines(Can.of("Hallo", "", "World", "", "")));
     }
-    
+
 }
diff --git 
a/commons/src/test/java/org/apache/causeway/commons/internal/base/StringCutterTest.java
 b/commons/src/test/java/org/apache/causeway/commons/util/StringCutterTest.java
similarity index 87%
rename from 
commons/src/test/java/org/apache/causeway/commons/internal/base/StringCutterTest.java
rename to 
commons/src/test/java/org/apache/causeway/commons/util/StringCutterTest.java
index 49e60c59e5..a7585ca0ec 100644
--- 
a/commons/src/test/java/org/apache/causeway/commons/internal/base/StringCutterTest.java
+++ 
b/commons/src/test/java/org/apache/causeway/commons/util/StringCutterTest.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.causeway.commons.internal.base;
+package org.apache.causeway.commons.util;
 
 import org.junit.jupiter.api.Test;
 
@@ -26,7 +26,7 @@ class StringCutterTest {
 
     @Test
     void dropBeforeAndAfter() {
-        assertEquals("(or)", _StringCutter.of("HalloW(or)ld!")
+        assertEquals("(or)", TextUtils.cutter("HalloW(or)ld!")
                 .dropBefore("(")
                 .dropAfter(")")
                 .getValue());
@@ -34,7 +34,7 @@ class StringCutterTest {
 
     @Test
     void keepBeforeAndAfter() {
-        assertEquals("or", _StringCutter.of("HalloW(or)ld!")
+        assertEquals("or", TextUtils.cutter("HalloW(or)ld!")
                 .keepAfter("(")
                 .keepBefore(")")
                 .getValue());
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/IdentifierUtil.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/IdentifierUtil.java
index 26c3fe0875..58b6014a74 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/IdentifierUtil.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/IdentifierUtil.java
@@ -23,8 +23,8 @@ import org.springframework.lang.Nullable;
 import org.apache.causeway.applib.Identifier;
 import org.apache.causeway.applib.id.LogicalType;
 import org.apache.causeway.applib.services.command.Command;
-import org.apache.causeway.commons.internal.base._StringCutter;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
+import org.apache.causeway.commons.util.TextUtils;
 import org.apache.causeway.core.metamodel.commons.StringExtensions;
 import org.apache.causeway.core.metamodel.interactions.InteractionHead;
 import 
org.apache.causeway.core.metamodel.interactions.managed.ActionInteractionHead;
@@ -59,7 +59,7 @@ public class IdentifierUtil {
             final @NonNull Identifier.Type identifierType,
             final @NonNull String logicalMemberIdentifier) {
 
-        val stringCutter = _StringCutter.of(logicalMemberIdentifier);
+        val stringCutter = TextUtils.cutter(logicalMemberIdentifier);
         val logicalTypeName = stringCutter
                 .keepBefore("#")
                 .getValue();
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile.java
index a4dd490200..6e425be989 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile.java
@@ -31,8 +31,8 @@ import org.springframework.stereotype.Service;
 import org.apache.causeway.applib.annotation.PriorityPrecedence;
 import org.apache.causeway.applib.annotation.PropertyLayout;
 import org.apache.causeway.applib.services.tablecol.TableColumnOrderService;
-import org.apache.causeway.commons.internal.base._Text;
 import org.apache.causeway.commons.internal.resources._Resources;
+import org.apache.causeway.commons.util.TextUtils;
 import org.apache.causeway.core.metamodel.CausewayModuleCoreMetamodel;
 
 import lombok.val;
@@ -92,7 +92,7 @@ public class TableColumnOrderServiceUsingTxtFile implements 
TableColumnOrderServ
             return null;
         }
         val s = contentsIfAny.get();
-        return _Text.getLines(s)
+        return TextUtils.readLines(s)
                 .filter(propertyIds::contains)
                 .toList();
     }
@@ -157,7 +157,7 @@ public class TableColumnOrderServiceUsingTxtFile implements 
TableColumnOrderServ
             return null;
         }
         val s = contentsIfAny.get();
-        return _Text.getLines(s)
+        return TextUtils.readLines(s)
                 .filter(propertyIds::contains)
                 .toList();
     }
diff --git 
a/regressiontests/stable-value/src/test/java/org/apache/causeway/testdomain/value/ValueSemanticsTester.java
 
b/regressiontests/stable-value/src/test/java/org/apache/causeway/testdomain/value/ValueSemanticsTester.java
index 4e8774ec1a..8a620366f6 100644
--- 
a/regressiontests/stable-value/src/test/java/org/apache/causeway/testdomain/value/ValueSemanticsTester.java
+++ 
b/regressiontests/stable-value/src/test/java/org/apache/causeway/testdomain/value/ValueSemanticsTester.java
@@ -36,9 +36,9 @@ import org.apache.causeway.applib.value.semantics.Renderer;
 import org.apache.causeway.applib.value.semantics.ValueSemanticsProvider;
 import org.apache.causeway.commons.functional.Try;
 import org.apache.causeway.commons.internal.base._Casts;
-import org.apache.causeway.commons.internal.base._StringCutter;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
 import org.apache.causeway.commons.io.JaxbUtils;
+import org.apache.causeway.commons.util.TextUtils;
 import org.apache.causeway.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.causeway.core.metamodel.interactions.managed.ManagedProperty;
 import 
org.apache.causeway.core.metamodel.interactions.managed.PropertyInteraction;
@@ -153,7 +153,7 @@ public class ValueSemanticsTester<T> {
                 .formattedOutput(true)))
         .getValue().orElseThrow();
 
-        return _StringCutter.of(rawXml)
+        return TextUtils.cutter(rawXml)
                 .dropBefore("<ValueWithTypeDto")
                 .keepBeforeLast("</ValueWithTypeDto>")
                 .getValue()
diff --git 
a/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/valuetypes/ValueTypeExample.java
 
b/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/valuetypes/ValueTypeExample.java
index 52d81fc471..02f32dd076 100644
--- 
a/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/valuetypes/ValueTypeExample.java
+++ 
b/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/valuetypes/ValueTypeExample.java
@@ -61,8 +61,8 @@ import 
org.apache.causeway.applib.value.NamedWithMimeType.CommonMimeType;
 import org.apache.causeway.applib.value.Password;
 import org.apache.causeway.applib.value.semantics.ValueSemanticsAbstract;
 import org.apache.causeway.commons.collections.Can;
-import org.apache.causeway.commons.internal.base._StringCutter;
 import org.apache.causeway.commons.internal.base._Temporals;
+import org.apache.causeway.commons.util.TextUtils;
 import 
org.apache.causeway.core.metamodel.valuesemantics.ApplicationFeatureIdValueSemantics;
 import org.apache.causeway.core.metamodel.valuesemantics.MarkupValueSemantics;
 import org.apache.causeway.extensions.fullcalendar.applib.value.CalendarEvent;
@@ -163,7 +163,7 @@ public abstract class ValueTypeExample<T> {
         if(!name.contains("_")) {
             return Optional.empty();
         }
-        return Optional.of(_StringCutter.of(name)
+        return Optional.of(TextUtils.cutter(name)
                 .keepBefore("_")
                 .getValue());
     }
diff --git 
a/testing/fixtures/applib/src/main/java/org/apache/causeway/testing/fixtures/applib/fixturescripts/ExecutionParametersDefault.java
 
b/testing/fixtures/applib/src/main/java/org/apache/causeway/testing/fixtures/applib/fixturescripts/ExecutionParametersDefault.java
index 985a0a12fe..c8844269de 100644
--- 
a/testing/fixtures/applib/src/main/java/org/apache/causeway/testing/fixtures/applib/fixturescripts/ExecutionParametersDefault.java
+++ 
b/testing/fixtures/applib/src/main/java/org/apache/causeway/testing/fixtures/applib/fixturescripts/ExecutionParametersDefault.java
@@ -32,8 +32,8 @@ import org.joda.time.format.ISODateTimeFormat;
 
 import org.apache.causeway.commons.internal.base._Casts;
 import org.apache.causeway.commons.internal.base._Strings;
-import org.apache.causeway.commons.internal.base._Text;
 import org.apache.causeway.commons.internal.collections._Maps;
+import org.apache.causeway.commons.util.TextUtils;
 
 /**
  * Responsible for parsing the string parameter passed when executing
@@ -61,7 +61,7 @@ public class ExecutionParametersDefault implements 
ExecutionParameters {
         final Map<String, String> keyValues = _Maps.newLinkedHashMap();
         if (parameters != null) {
             try {
-                _Text.streamLines(parameters)
+                TextUtils.streamLines(parameters)
                 .forEach(line->{
                     final Matcher matcher = 
keyEqualsValuePattern.matcher(line);
                     if (matcher.matches()) {
diff --git 
a/testing/integtestsupport/applib/src/main/java/org/apache/causeway/testing/integtestsupport/applib/ApprovalsOptions.java
 
b/testing/integtestsupport/applib/src/main/java/org/apache/causeway/testing/integtestsupport/applib/ApprovalsOptions.java
index 61da64c6ab..ec2c5be60f 100644
--- 
a/testing/integtestsupport/applib/src/main/java/org/apache/causeway/testing/integtestsupport/applib/ApprovalsOptions.java
+++ 
b/testing/integtestsupport/applib/src/main/java/org/apache/causeway/testing/integtestsupport/applib/ApprovalsOptions.java
@@ -18,20 +18,21 @@
  */
 package org.apache.causeway.testing.integtestsupport.applib;
 
-import lombok.SneakyThrows;
-import lombok.experimental.UtilityClass;
-import lombok.val;
-
 import java.util.stream.Collectors;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.approvaltests.core.Options;
+import org.approvaltests.core.Scrubber;
+
 import org.apache.causeway.commons.internal.base._Strings;
-import org.apache.causeway.commons.internal.base._Text;
 import org.apache.causeway.commons.internal.collections._Lists;
 import org.apache.causeway.commons.internal.collections._Maps;
-import org.approvaltests.core.Options;
-import org.approvaltests.core.Scrubber;
+import org.apache.causeway.commons.util.TextUtils;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.SneakyThrows;
+import lombok.val;
+import lombok.experimental.UtilityClass;
 
 @UtilityClass
 public class ApprovalsOptions {
@@ -44,7 +45,7 @@ public class ApprovalsOptions {
     }
 
     private String scrub(final String input) {
-        return _Text.streamLines(input)
+        return TextUtils.streamLines(input)
                 .map(ApprovalsOptions::scrubLine)
                 .filter(line->!_Strings.nullToEmpty(line).isBlank()) // ignore 
blank lines, just in case
                 .collect(Collectors.joining("\n")); // UNIX line ending 
convention
diff --git 
a/tooling/java2adoc/src/main/java/org/apache/causeway/tooling/j2adoc/J2AdocUnit.java
 
b/tooling/java2adoc/src/main/java/org/apache/causeway/tooling/j2adoc/J2AdocUnit.java
index 06a2f318a7..cd78022b7d 100644
--- 
a/tooling/java2adoc/src/main/java/org/apache/causeway/tooling/j2adoc/J2AdocUnit.java
+++ 
b/tooling/java2adoc/src/main/java/org/apache/causeway/tooling/j2adoc/J2AdocUnit.java
@@ -31,8 +31,8 @@ import org.asciidoctor.ast.Document;
 
 import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.internal.base._Strings;
-import org.apache.causeway.commons.resource.ResourceCoordinates;
 import org.apache.causeway.tooling.j2adoc.util.AsciiDocIncludeTagFilter;
+import org.apache.causeway.tooling.j2adoc.util.ResourceCoordinates;
 import org.apache.causeway.tooling.javamodel.ast.AnyTypeDeclaration;
 import org.apache.causeway.tooling.javamodel.ast.CompilationUnits;
 import org.apache.causeway.tooling.javamodel.ast.PackageDeclarations;
diff --git 
a/commons/src/main/java/org/apache/causeway/commons/resource/ResourceCoordinates.java
 
b/tooling/java2adoc/src/main/java/org/apache/causeway/tooling/j2adoc/util/ResourceCoordinates.java
similarity index 94%
rename from 
commons/src/main/java/org/apache/causeway/commons/resource/ResourceCoordinates.java
rename to 
tooling/java2adoc/src/main/java/org/apache/causeway/tooling/j2adoc/util/ResourceCoordinates.java
index 2bbd4a1fa3..69458f2fb8 100644
--- 
a/commons/src/main/java/org/apache/causeway/commons/resource/ResourceCoordinates.java
+++ 
b/tooling/java2adoc/src/main/java/org/apache/causeway/tooling/j2adoc/util/ResourceCoordinates.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.causeway.commons.resource;
+package org.apache.causeway.tooling.j2adoc.util;
 
 import java.io.File;
 import java.util.Comparator;
@@ -24,19 +24,15 @@ import java.util.Comparator;
 import org.springframework.lang.Nullable;
 
 import org.apache.causeway.commons.collections.Can;
-import org.apache.causeway.commons.internal.base._StringCutter;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.collections._Lists;
+import org.apache.causeway.commons.util.TextUtils;
 
 import lombok.Builder;
 import lombok.NonNull;
 import lombok.Value;
 import lombok.val;
 
-/**
- * @deprecated move to tooling
- */
-@Deprecated
 @Value @Builder
 public class ResourceCoordinates
 implements Comparable<ResourceCoordinates> {
@@ -51,7 +47,7 @@ implements Comparable<ResourceCoordinates> {
             next = next.getParentFile();
         }
 
-        val cutter = _StringCutter.of(file.getName());
+        val cutter = TextUtils.cutter(file.getName());
 
         //XXX lombok issue, cannot use val
         final String simpleName = cutter.keepBeforeLast(".").getValue();
diff --git 
a/tooling/java2adoc/src/test/java/org/apache/causeway/tooling/j2adoc/convert/HtmlToAsciiDocTest.java
 
b/tooling/java2adoc/src/test/java/org/apache/causeway/tooling/j2adoc/convert/HtmlToAsciiDocTest.java
index 9006dcce82..d0df5c6c7d 100644
--- 
a/tooling/java2adoc/src/test/java/org/apache/causeway/tooling/j2adoc/convert/HtmlToAsciiDocTest.java
+++ 
b/tooling/java2adoc/src/test/java/org/apache/causeway/tooling/j2adoc/convert/HtmlToAsciiDocTest.java
@@ -25,7 +25,7 @@ import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import org.apache.causeway.commons.collections.Can;
-import org.apache.causeway.commons.internal.base._Text;
+import org.apache.causeway.commons.util.TextUtils;
 import org.apache.causeway.tooling.model4adoc.AsciiDocFactory;
 import org.apache.causeway.tooling.model4adoc.AsciiDocWriter;
 
@@ -51,7 +51,7 @@ class HtmlToAsciiDocTest {
 
         // then we expect 3 paragraphs delimited by an empty line
         final String adocAsString = AsciiDocWriter.toString(doc);
-        val lines = _Text.getLines(adocAsString).map(String::trim);
+        val lines = TextUtils.readLines(adocAsString).map(String::trim);
 
         assertEquals(Can.of("Hello", "", "second paragraph", "", "third 
paragraph", ""), lines);
     }
diff --git 
a/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/AsciiDocFactory.java
 
b/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/AsciiDocFactory.java
index 3e79f1093e..18a41f5588 100644
--- 
a/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/AsciiDocFactory.java
+++ 
b/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/AsciiDocFactory.java
@@ -35,6 +35,7 @@ import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.internal.base._Refs;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.base._Text;
+import org.apache.causeway.commons.util.TextUtils;
 import org.apache.causeway.tooling.model4adoc.ast.SimpleBlock;
 import org.apache.causeway.tooling.model4adoc.ast.SimpleCell;
 import org.apache.causeway.tooling.model4adoc.ast.SimpleColumn;
@@ -318,7 +319,7 @@ public class AsciiDocFactory {
             val sourceBlock = AsciiDocFactory.sourceBlock(doc,
                     languageAndOptions,
 
-                    _Text.normalize(_Text.getLines(source))
+                    _Text.normalize(TextUtils.readLines(source))
                     .stream()
                     .collect(Collectors.joining("\n")));
 
@@ -383,7 +384,7 @@ public class AsciiDocFactory {
             val sourceBlock = AsciiDocFactory.diagramBlock(doc,
                     diagramType,
                     diagramOptions,
-                    _Text.normalize(_Text.getLines(source))
+                    _Text.normalize(TextUtils.readLines(source))
                     .stream()
                     .collect(Collectors.joining("\n")));
 
diff --git 
a/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/NodeWriter.java
 
b/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/NodeWriter.java
index 5a967335ad..139c1823b4 100644
--- 
a/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/NodeWriter.java
+++ 
b/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/NodeWriter.java
@@ -44,6 +44,7 @@ import org.apache.causeway.commons.internal.base._Text;
 import org.apache.causeway.commons.internal.collections._Arrays;
 import org.apache.causeway.commons.internal.collections._Lists;
 import org.apache.causeway.commons.internal.collections._Sets;
+import org.apache.causeway.commons.util.TextUtils;
 
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
@@ -61,7 +62,7 @@ final class NodeWriter implements StructuralNodeVisitor {
             "Notice");
 
     @Override
-    public boolean documentHead(Document doc, int depth) {
+    public boolean documentHead(final Document doc, final int depth) {
 
         _Strings.nonEmpty(doc.getTitle())
         .ifPresent(title->printChapterTitle(title, depth+1));
@@ -132,7 +133,7 @@ final class NodeWriter implements StructuralNodeVisitor {
         UNKNOWN(x->false)
         ;
         private final Predicate<String> matcher;
-        public static Style parse(StructuralNode node) {
+        public static Style parse(final StructuralNode node) {
             val styleAttribute = node.getStyle();
             return Stream.of(Style.values())
                     .filter(style->style.matcher.test(styleAttribute))
@@ -163,7 +164,7 @@ final class NodeWriter implements StructuralNodeVisitor {
     }
 
     @Override
-    public boolean blockHead(Block block, int depth) {
+    public boolean blockHead(final Block block, final int depth) {
 
         val style = Style.parse(block);
 
@@ -227,7 +228,7 @@ final class NodeWriter implements StructuralNodeVisitor {
     }
 
     @Override
-    public void blockTail(Block block, int depth) {
+    public void blockTail(final Block block, final int depth) {
 
         val style = Style.parse(block);
 
@@ -251,7 +252,7 @@ final class NodeWriter implements StructuralNodeVisitor {
     // -_ LIST
 
     @Override
-    public boolean listHead(org.asciidoctor.ast.List list, int depth) {
+    public boolean listHead(final org.asciidoctor.ast.List list, final int 
depth) {
         if(bulletCount==0) {
             if(newLineCount<=1) {
                 printNewLine();
@@ -266,12 +267,12 @@ final class NodeWriter implements StructuralNodeVisitor {
     }
 
     @Override
-    public void listTail(org.asciidoctor.ast.List list, int depth) {
+    public void listTail(final org.asciidoctor.ast.List list, final int depth) 
{
         bulletCount--;
     }
 
     @Override
-    public boolean listItemHead(ListItem listItem, int depth) {
+    public boolean listItemHead(final ListItem listItem, final int depth) {
 
         val isCalloutStyle = 
Style.parse((org.asciidoctor.ast.List)(listItem.getParent()))
                 .isCalloutList();
@@ -317,7 +318,7 @@ final class NodeWriter implements StructuralNodeVisitor {
     }
 
     @Override
-    public void listItemTail(ListItem listItem, int depth) {
+    public void listItemTail(final ListItem listItem, final int depth) {
     }
 
     // -- TABLE
@@ -335,7 +336,7 @@ final class NodeWriter implements StructuralNodeVisitor {
     //  |Cell in column 3, row 2
     //  |===
     @Override
-    public boolean tableHead(Table table, int depth) {
+    public boolean tableHead(final Table table, final int depth) {
 
         _Strings.nonEmpty(table.getTitle())
         .ifPresent(this::printBlockTitle);
@@ -382,7 +383,7 @@ final class NodeWriter implements StructuralNodeVisitor {
         printfln(".%s", title);
     }
 
-    private void printSingleLineMap(String mapFormat, Map<String, String> map, 
String entryFormat) {
+    private void printSingleLineMap(final String mapFormat, final Map<String, 
String> map, final String entryFormat) {
         if(map.isEmpty()) {
             return;
         }
@@ -395,7 +396,7 @@ final class NodeWriter implements StructuralNodeVisitor {
 
     // -- HELPER - LOW LEVEL
 
-    private static Map<String, String> formatedAttrMap(Table table) {
+    private static Map<String, String> formatedAttrMap(final Table table) {
         final Map<String, String> formatedAttrMap = new LinkedHashMap<>();
 
         if(table.hasAttribute("cols")) {
@@ -468,7 +469,7 @@ final class NodeWriter implements StructuralNodeVisitor {
     private void print(final @NonNull String line) {
 
         if(line.contains("\n")) {
-            val lineIter = _Text.normalize(_Text.getLines(line)).iterator();
+            val lineIter = 
_Text.normalize(TextUtils.readLines(line)).iterator();
             while(lineIter.hasNext()) {
                 val nextLine = lineIter.next();
                 currentWriter().append(nextLine);
@@ -508,7 +509,7 @@ final class NodeWriter implements StructuralNodeVisitor {
         printNewLine();
     }
 
-    private Object nullToEmpty(Object x) {
+    private Object nullToEmpty(final Object x) {
         if(x==null) {
             return "";
         }
diff --git 
a/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/include/IncludeStatements.java
 
b/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/include/IncludeStatements.java
index 138b49d846..63e8f67e60 100644
--- 
a/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/include/IncludeStatements.java
+++ 
b/tooling/model4adoc/src/main/java/org/apache/causeway/tooling/model4adoc/include/IncludeStatements.java
@@ -23,9 +23,9 @@ import java.util.function.BiConsumer;
 import java.util.function.UnaryOperator;
 
 import org.apache.causeway.commons.collections.Can;
-import org.apache.causeway.commons.internal.base._StringCutter;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.collections._Lists;
+import org.apache.causeway.commons.util.TextUtils;
 
 import lombok.NonNull;
 import lombok.val;
@@ -80,7 +80,7 @@ public final class IncludeStatements {
 
             if(line.startsWith("include::")) {
 
-                var cutter = _StringCutter.of(line)
+                var cutter = TextUtils.cutter(line)
                         .keepAfter("include::");
 
                 val incl = IncludeStatement.builder();
@@ -110,7 +110,7 @@ public final class IncludeStatements {
                     referencePath = cutter.getValue();
                 }
 
-                cutter = _StringCutter.of(referencePath);
+                cutter = TextUtils.cutter(referencePath);
 
                 val namespaceAsString = cutter.keepBeforeLast("/").getValue();
 
diff --git 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ResourceAbstract.java
 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ResourceAbstract.java
index 85776cfd24..c047973a65 100644
--- 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ResourceAbstract.java
+++ 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ResourceAbstract.java
@@ -35,9 +35,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 
 import org.apache.causeway.applib.annotation.Where;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
-import org.apache.causeway.commons.internal.base._StringCutter;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.codec._UrlDecoderUtil;
+import org.apache.causeway.commons.util.TextUtils;
 import org.apache.causeway.core.config.viewer.web.WebAppContextPath;
 import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.causeway.core.metamodel.context.HasMetaModelContext;
@@ -114,7 +114,7 @@ implements HasMetaModelContext {
         // eg. http://localhost:8080/
         val serverAbsoluteBase =
                 _Strings
-                .suffix(_StringCutter.of(restfulAbsoluteBase)
+                .suffix(TextUtils.cutter(restfulAbsoluteBase)
                         .keepAfterLast(restfulRelativeBase)
                         .getValue(),
                 "/");
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/LicensedTextTemplate.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/LicensedTextTemplate.java
index b1765d713e..1fd72c2a4d 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/LicensedTextTemplate.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/LicensedTextTemplate.java
@@ -22,7 +22,7 @@ import java.util.stream.Collectors;
 
 import org.apache.wicket.util.template.PackageTextTemplate;
 
-import org.apache.causeway.commons.internal.base._Text;
+import org.apache.causeway.commons.util.TextUtils;
 
 import lombok.val;
 
@@ -50,7 +50,7 @@ extends PackageTextTemplate {
             val raw = super.getString();
 
             // strip first n comment lines
-            this.scriptTemplate = _Text.streamLines(raw)
+            this.scriptTemplate = TextUtils.streamLines(raw)
             .skip(skipLicenseLines)
             .collect(Collectors.joining(" "));
         }

Reply via email to