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));
}
-
+
}