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 2026/05/18 04:48:42 UTC
(causeway) branch main updated: CAUSEWAY-3997: ListingUtil: allow for more advanced line adapters
This is an automated email from the ASF dual-hosted git repository.
andi-huber 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 03c17f0d837 CAUSEWAY-3997: ListingUtil: allow for more advanced line adapters
03c17f0d837 is described below
commit 03c17f0d837c28b0a7c76e829830c358ace004b8
Author: andi-huber <ah...@apache.org>
AuthorDate: Mon May 18 06:48:32 2026 +0200
CAUSEWAY-3997: ListingUtil: allow for more advanced line adapters
---
.../columnorder/Object_patchColumnOrder.java | 5 +-
.../org/apache/causeway/applib/util/Listing.java | 71 +++++++++++++++-------
.../apache/causeway/applib/util/ListingTest.java | 15 +++--
3 files changed, 58 insertions(+), 33 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/causeway/applib/services/columnorder/Object_patchColumnOrder.java b/api/applib/src/main/java/org/apache/causeway/applib/services/columnorder/Object_patchColumnOrder.java
index 118dcdb5949..bf6fc9c53bc 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/services/columnorder/Object_patchColumnOrder.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/services/columnorder/Object_patchColumnOrder.java
@@ -45,7 +45,6 @@
import org.apache.causeway.applib.services.metamodel.MetaModelService;
import org.apache.causeway.applib.services.metamodel.MetaModelService.AssociationsLookup;
import org.apache.causeway.applib.util.Listing;
-import org.apache.causeway.applib.util.Listing.ListingHandler;
import org.apache.causeway.applib.util.Listing.MergePolicy;
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.internal.exceptions._Exceptions;
@@ -157,8 +156,8 @@ private Listing<String> listing(final Stream<Identifier> availableIds, final Str
return enabled.merge(MergePolicy.ADD_NEW_AS_DISABLED, available);
}
- private final static ListingHandler<String> listingHandler() {
- return new ListingHandler<>(String.class, UnaryOperator.identity(), UnaryOperator.identity(), UnaryOperator.identity());
+ private final static Listing.LineAdapter<String> listingHandler() {
+ return Listing.lineAdapter(String.class, UnaryOperator.identity(), UnaryOperator.identity(), UnaryOperator.identity());
}
}
diff --git a/api/applib/src/main/java/org/apache/causeway/applib/util/Listing.java b/api/applib/src/main/java/org/apache/causeway/applib/util/Listing.java
index cb3b5d0ca2e..73a8ef836db 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/util/Listing.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/util/Listing.java
@@ -50,36 +50,37 @@
*/
@Programmatic
public record Listing<T>(
- @NonNull ListingHandler<T> handler,
+ @NonNull LineAdapter<T> lineAdapter,
@NonNull Can<Line> lines) {
- public record ListingHandler<T> (
- @NonNull Class<T> objectType,
- @NonNull Function<T, String> stringifier,
- @NonNull Function<String, T> destringifier,
- @NonNull Function<T, ?> keyExtractor) {
+ public interface LineAdapter<T> {
+ Class<T> objectType();
+ String stringify(T t);
+ T destringify(String literal);
+ Object extractKey(T t);
// -- LISTING FACTORIES
- public Listing<T> emptyListing() {
+ default Listing<T> emptyListing() {
return createListing(Can.empty());
}
- public Listing<T> createListing(@Nullable final Iterable<T> enabledElements) {
+ default Listing<T> createListing(@Nullable final Iterable<T> enabledElements) {
return createListing(_NullSafe.stream(enabledElements));
}
- public Listing<T> createListing(@Nullable final Stream<T> enabledElementStream) {
- if(enabledElementStream==null) return emptyListing();
+ default Listing<T> createListing(@Nullable final Stream<T> enabledElementStream) {
+ if(enabledElementStream==null)
+ return emptyListing();
return new Listing<>(this, enabledElementStream
- .map(t->new LineEnabled<>(t, stringifier().apply(t)))
+ .map(t->new LineEnabled<>(t, stringify(t)))
.collect(Can.toCan()));
}
- public Listing<T> parseListing(@Nullable final String wholeText) {
+ default Listing<T> parseListing(@Nullable final String wholeText) {
if(wholeText==null) return emptyListing();
return parseListing(TextUtils.readLines(wholeText));
}
- public Listing<T> parseListing(@Nullable final Can<String> textLines) {
+ default Listing<T> parseListing(@Nullable final Can<String> textLines) {
if(textLines==null) return emptyListing();
return new Listing<>(this, textLines.map(this::parseLine));
}
@@ -92,7 +93,7 @@ public Listing<T> parseListing(@Nullable final Can<String> textLines) {
* <p>If a line is not a comment, but can also not be mapped to {@code T},
* then it is commented out.
*/
- public Line parseLine(final String wholeLine) {
+ default Line parseLine(final String wholeLine) {
final var line = wholeLine.trim();
if(line.isBlank())
return new LineComment(line);
@@ -120,9 +121,35 @@ line, objectType().getSimpleName(), e)))
// -- HELPER
private Try<T> asT(final String stringified) {
- return Try.call(()->destringifier().apply(stringified));
+ return Try.call(()->destringify(stringified));
}
+ }
+
+ // -- ADAPTERS
+
+ public static <T> LineAdapter<T> lineAdapter(
+ @NonNull final Class<T> objectType,
+ @NonNull final Function<T, String> stringifier,
+ @NonNull final Function<String, T> destringifier,
+ @NonNull final Function<T, ?> keyExtractor) {
+ return new SimpleLineAdapter<>(objectType, stringifier, destringifier, keyExtractor);
+ }
+
+ private record SimpleLineAdapter<T> (
+ @NonNull Class<T> objectType,
+ @NonNull Function<T, String> stringifier,
+ @NonNull Function<String, T> destringifier,
+ @NonNull Function<T, ?> keyExtractor) implements LineAdapter<T> {
+ @Override public String stringify(final T t) {
+ return stringifier.apply(t);
+ }
+ @Override public T destringify(final String literal) {
+ return destringifier.apply(literal);
+ }
+ @Override public Object extractKey(final T t) {
+ return keyExtractor.apply(t);
+ }
}
public sealed interface Line
@@ -249,11 +276,11 @@ public enum MergePolicy {
public <K> Listing<T> merge(@NonNull final MergePolicy policy, @Nullable final Listing<T> newerVersion) {
if(newerVersion==null) return this;
final Map<Object, LineEnabled<T>> incomingByKey = newerVersion.streamEnabledLines()
- .collect(Collectors.toMap(
- line->handler().keyExtractor().apply(line.object()),
- UnaryOperator.identity(),
- (a, b)->a,
- LinkedHashMap::new));
+ .collect(Collectors.toMap(
+ line->lineAdapter().extractKey(line.object()),
+ UnaryOperator.identity(),
+ (a, b)->a,
+ LinkedHashMap::new));
if(incomingByKey.isEmpty()) return this;
var mergedLines = new ArrayList<Line>();
@@ -265,7 +292,7 @@ public <K> Listing<T> merge(@NonNull final MergePolicy policy, @Nullable final L
.forEach((final Line line)->{
@SuppressWarnings("unchecked")
var key = (line instanceof MappedLine mappedLine)
- ? handler().keyExtractor().apply((T) mappedLine.object())
+ ? lineAdapter().extractKey((T) mappedLine.object())
: null;
final boolean incomingContainsKey = key!=null
? incomingByKey.remove(key)!=null
@@ -309,7 +336,7 @@ public <K> Listing<T> merge(@NonNull final MergePolicy policy, @Nullable final L
}
}
- return new Listing<>(handler, Can.ofCollection(mergedLines));
+ return new Listing<>(lineAdapter, Can.ofCollection(mergedLines));
}
}
diff --git a/api/applib/src/test/java/org/apache/causeway/applib/util/ListingTest.java b/api/applib/src/test/java/org/apache/causeway/applib/util/ListingTest.java
index 459cfd8c588..f16bb0b9357 100644
--- a/api/applib/src/test/java/org/apache/causeway/applib/util/ListingTest.java
+++ b/api/applib/src/test/java/org/apache/causeway/applib/util/ListingTest.java
@@ -25,7 +25,7 @@
import org.springframework.util.StringUtils;
-import org.apache.causeway.applib.util.Listing.ListingHandler;
+import org.apache.causeway.applib.util.Listing.LineAdapter;
import org.apache.causeway.applib.util.Listing.MergePolicy;
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.io.TextUtils;
@@ -60,10 +60,9 @@ static Customer destringify(final String input) {
}
}
- private final ListingHandler<Customer> listingHandler =
- new ListingHandler<>(Customer.class, Customer::stringify, Customer::destringify, Customer::id);
- private final Listing<Customer> listing =
- sampleListing(listingHandler);
+ private final LineAdapter<Customer> lineAdapter = Listing
+ .lineAdapter(Customer.class, Customer::stringify, Customer::destringify, Customer::id);
+ private final Listing<Customer> listing = sampleListing(lineAdapter);
@Test
void parsing() {
@@ -106,7 +105,7 @@ void merging() {
[c] Henry
[d] Martha
""";
- var updateListing = listingHandler.parseListing(upd);
+ var updateListing = lineAdapter.parseListing(upd);
var merged = listing.merge(MergePolicy.ADD_NEW_AS_DISABLED, updateListing);
String expectedOutputAfterMerge = """
# this is a regular comment
@@ -129,7 +128,7 @@ void merging() {
// -- HELPER
- private Listing<Customer> sampleListing(final ListingHandler<Customer> listingHandler) {
+ private Listing<Customer> sampleListing(final LineAdapter<Customer> lineAdapter) {
String input = """
# this is a regular comment
[a] Jeff
@@ -140,7 +139,7 @@ private Listing<Customer> sampleListing(final ListingHandler<Customer> listingHa
[b] Jane
""";
- return listingHandler.parseListing(input);
+ return lineAdapter.parseListing(input);
}
private static void assertTextLinesMatch(final String a, final String b) {