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 01fce3b7ad CAUSEWAY-3711: TreeAdapter: adds node resolving for given 
path
01fce3b7ad is described below

commit 01fce3b7ad34114764422098e96f87acedf4b698
Author: Andi Huber <[email protected]>
AuthorDate: Thu Apr 11 17:28:55 2024 +0200

    CAUSEWAY-3711: TreeAdapter: adds node resolving for given path
---
 .../causeway/applib/graph/tree/TreeAdapter.java    | 29 +++++++++++++++++++++-
 .../graph/tree/TreeAdapterWithConverter.java       | 23 ++++++++++++-----
 2 files changed, 45 insertions(+), 7 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreeAdapter.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreeAdapter.java
index 0233dcad21..ecfb94985a 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreeAdapter.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreeAdapter.java
@@ -18,8 +18,11 @@
  */
 package org.apache.causeway.applib.graph.tree;
 
+import java.util.Optional;
 import java.util.stream.Stream;
 
+import org.springframework.lang.Nullable;
+
 import org.apache.causeway.applib.annotation.Domain;
 
 /**
@@ -37,7 +40,7 @@ public interface TreeAdapter<T> {
      * @return number of child tree-nodes of the specified {@code value} 
tree-node (pojo)
      */
     @Domain.Exclude
-    default int childCountOf(T value) {
+    default int childCountOf(final T value) {
         return Math.toIntExact(childrenOf(value).count());
     }
 
@@ -48,4 +51,28 @@ public interface TreeAdapter<T> {
     @Domain.Exclude
     Stream<T> childrenOf(T value);
 
+
+    /**
+     * Resolves given {@link TreePath} to its corresponding sub-node relative 
to given node if possible.
+     * <p>
+     * E.g. starting from root, '/0' will return the root;<br>
+     * starting from root, '/0/2' will return the 3rd child of root;<br>
+     * starting from sub-node '/0/2', '/2/9' will resolve the 10th child 
('/0/2/9') of this sub-node
+     */
+    default Optional<T> resolveRelative(final @Nullable T node, final 
@Nullable TreePath relativePath) {
+        if(node==null
+                || relativePath==null
+                || relativePath.size()<1) {
+            return Optional.empty();
+        }
+        if(relativePath.size()==1) return Optional.of(node);
+        final int childIndex = relativePath.childIndex().orElse(-1);
+        if(childIndex<0) return Optional.empty();
+        final Optional<T> childNode = 
childrenOf(node).skip(childIndex).findFirst();
+        if(!childNode.isPresent()) return Optional.empty();
+        return relativePath.size()>2
+                ? resolveRelative(childNode.get(), relativePath.subPath(1))
+                : childNode;
+    }
+
 }
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreeAdapterWithConverter.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreeAdapterWithConverter.java
index 48f02d28ad..3b8e931378 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreeAdapterWithConverter.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreeAdapterWithConverter.java
@@ -18,6 +18,7 @@
  */
 package org.apache.causeway.applib.graph.tree;
 
+import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
@@ -29,12 +30,12 @@ import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 @RequiredArgsConstructor
-public abstract class TreeAdapterWithConverter<U, T> 
+public abstract class TreeAdapterWithConverter<U, T>
 implements TreeAdapter<T>{
-    
+
     protected abstract TreeAdapter<U> underlyingAdapter();
     protected abstract TreeConverter<U, T> converter();
-    
+
     @Override
     public final int childCountOf(final @Nullable T t) {
         if(t==null) return 0;
@@ -53,12 +54,22 @@ implements TreeAdapter<T>{
                         .map(childFactoryForParentNode(t))
                 : Stream.empty();
     }
-    
+
+    @Override
+    public final Optional<T> resolveRelative(final @Nullable T t, final 
@Nullable TreePath relativePath) {
+        if(t==null) return Optional.empty();
+        val underlyingNode = converter().toUnderlyingNode(t);
+        return underlyingNode!=null
+                ? underlyingAdapter().resolveRelative(underlyingNode, 
relativePath)
+                        .map(childFactoryForParentNode(t))
+                : Optional.empty();
+    }
+
     // -- HELPER
-    
+
     private Function<U, T> childFactoryForParentNode(final T parentNode) {
         return IndexedFunction.zeroBased((indexWithinSiblings, pojo)->
             converter().fromUnderlyingNode(pojo, parentNode, 
indexWithinSiblings));
     }
-    
+
 }

Reply via email to