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 60fac61ae2 CAUSEWAY-3711: adds and registers TreePathValueSemantics
60fac61ae2 is described below
commit 60fac61ae2b800e1e2653b3960a5ee971f89478d
Author: andi-huber <[email protected]>
AuthorDate: Sat Mar 30 10:37:16 2024 +0100
CAUSEWAY-3711: adds and registers TreePathValueSemantics
---
.../causeway/applib/graph/tree/TreeAdapter.java | 4 +-
.../causeway/applib/graph/tree/TreePath.java | 139 +++++++++++++++---
.../applib/graph/tree/TreePath_Default.java | 157 ---------------------
.../metamodel/CausewayModuleCoreMetamodel.java | 2 +
.../_testing/MetaModelContext_forTesting.java | 2 +
.../valuesemantics/TreePathValueSemantics.java | 137 ++++++++++++++++++
.../model/valuetypes/ValueTypeExample.java | 2 -
.../ui/components/tree/_TreeModelTreeAdapter.java | 34 ++---
8 files changed, 273 insertions(+), 204 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 f6feafa67a..0233dcad21 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
@@ -37,7 +37,9 @@ public interface TreeAdapter<T> {
* @return number of child tree-nodes of the specified {@code value}
tree-node (pojo)
*/
@Domain.Exclude
- int childCountOf(T value);
+ default int childCountOf(T value) {
+ return Math.toIntExact(childrenOf(value).count());
+ }
/**
* @param value - tree-node (pojo)
diff --git
a/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreePath.java
b/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreePath.java
index ed2803b93c..e56376d8cb 100644
---
a/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreePath.java
+++
b/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreePath.java
@@ -19,7 +19,9 @@
package org.apache.causeway.applib.graph.tree;
import java.io.Serializable;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.OptionalInt;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -27,12 +29,16 @@ import java.util.stream.Stream;
import org.springframework.lang.Nullable;
+import org.apache.causeway.applib.annotation.Value;
import org.apache.causeway.commons.functional.IndexedConsumer;
import org.apache.causeway.commons.internal.assertions._Assert;
+import org.apache.causeway.commons.internal.base._Refs;
import org.apache.causeway.commons.internal.base._Strings;
import org.apache.causeway.commons.internal.exceptions._Exceptions;
import org.apache.causeway.commons.internal.primitives._Ints;
+import lombok.val;
+
/**
* Provides an unambiguous way to address nodes by position within a
tree-structure. Examples:
* <ul>
@@ -42,19 +48,52 @@ import
org.apache.causeway.commons.internal.primitives._Ints;
* </ul>
* @since 2.0 {@index}
*/
-public interface TreePath extends Serializable {
+@Value
+public class TreePath implements Serializable {
+
+ // -- FACTORIES
+
+ public static TreePath of(final int ... canonicalPath) {
+ return new TreePath(canonicalPath);
+ }
+
+ public static TreePath root() {
+ return of(0);
+ }
+
+ // -- CONSTRUCTION
+
+ private static final long serialVersionUID = 530511373409525896L;
+ private final int[] canonicalPath;
+ private final int hashCode;
+
+ public TreePath(final int[] canonicalPath) {
+ Objects.requireNonNull(canonicalPath, "canonicalPath is required");
+ if(canonicalPath.length<1) {
+ throw new IllegalArgumentException("canonicalPath must not be
empty");
+ }
+ this.canonicalPath = canonicalPath;
+ this.hashCode = Arrays.hashCode(canonicalPath);
+ }
/**
* Number of path-elements.
* @apiNote Root has size = 1.
*/
- public int size();
+ public int size() {
+ return canonicalPath.length;
+ }
/**
* @param indexWithinSiblings
* @return a new TreePath instance composed of this with one canonical
path entry added
*/
- public TreePath append(int indexWithinSiblings);
+ public TreePath append(int indexWithinSiblings) {
+ final int[] newCanonicalPath = new int[canonicalPath.length+1];
+ System.arraycopy(canonicalPath, 0, newCanonicalPath, 0,
canonicalPath.length);
+ newCanonicalPath[canonicalPath.length] = indexWithinSiblings;
+ return new TreePath(newCanonicalPath);
+ }
/**
* Returns a sub-path containing all the path-elements of this path,
skipping
@@ -62,40 +101,80 @@ public interface TreePath extends Serializable {
* @apiNote The first element of the resulting path indicates the sibling
index
* of the tree-node the subPath corresponds to.
*/
- public TreePath subPath(int startIndex);
+ public TreePath subPath(int startIndex) {
+ if(startIndex<=0) return this;
+ if(startIndex>=size()) throw new IndexOutOfBoundsException(startIndex);
+ final int newSize = size() - startIndex;
+ final int[] newCanonicalPath = new int[newSize];
+ System.arraycopy(canonicalPath, startIndex, newCanonicalPath, 0,
newSize);
+ return new TreePath(newCanonicalPath);
+
+ }
/**
* Returns a TreePath instance that represents the parent path of this
TreePath,
* if this is not the root.
*/
- public @Nullable TreePath getParentIfAny();
+ public @Nullable TreePath getParentIfAny() {
+ if(isRoot()) {
+ return null;
+ }
+ final int[] newCanonicalPath = new int[canonicalPath.length-1];
+ System.arraycopy(canonicalPath, 0, newCanonicalPath, 0,
canonicalPath.length-1);
+ return new TreePath(newCanonicalPath);
+
+ }
+
+ public boolean isRoot() {
+ return canonicalPath.length==1;
+ }
- public boolean isRoot();
- public boolean startsWith(TreePath other);
+ public boolean startsWith(TreePath other) {
+ if(other.size()>this.size()) return false;
+ // optimization, not strictly required
+ if(other instanceof TreePath) {
+ final int lastIndexToCheck = other.size() - 1;
+ return Arrays.equals(
+ this.canonicalPath, 0, lastIndexToCheck,
+ ((TreePath)other).canonicalPath, 0, lastIndexToCheck);
+ }
+ return this.stringify("/").startsWith(other.stringify("/"));
+ }
- public IntStream streamPathElements();
+ public IntStream streamPathElements() {
+ return IntStream.of(canonicalPath);
+ }
/**
* Optionally the 2nd path-element's value, based on presence.
* It corresponds to the sibling index of the child node this tree-path
* (either directly references or) includes.
*/
- public OptionalInt childIndex();
-
- public String stringify(String delimiter);
-
- public Stream<TreePath> streamUpTheHierarchyStartingAtSelf();
-
- // -- CONSTRUCTION
+ public OptionalInt childIndex() {
+ return size()>=2
+ ? OptionalInt.of(canonicalPath[1])
+ : OptionalInt.empty();
+ }
- public static TreePath of(final int ... canonicalPath) {
- return new TreePath_Default(canonicalPath);
+ public String stringify(String delimiter) {
+ _Assert.assertTrue(_Strings.isNotEmpty(delimiter), ()->"non-empty
delimiter required");
+ return delimiter + streamPathElements()
+ .mapToObj(i->""+i)
+ .collect(Collectors.joining(delimiter));
}
- public static TreePath root() {
- return of(0);
+ public Stream<TreePath> streamUpTheHierarchyStartingAtSelf() {
+ val hasMore = _Refs.booleanRef(true);
+ return Stream.iterate((TreePath)this, __->hasMore.isTrue(),
TreePath::getParentIfAny)
+ .filter(x->{
+ if(x.isRoot()) {
+ hasMore.setValue(false); // stop the stream only after
we have included the root
+ }
+ return true;
+ });
}
+
/**
* Parses stringified tree path of format {@code
<delimiter>0<delimiter>3<delimiter>1} ...,
* as returned by {@link TreePath#stringify(String)}.
@@ -127,4 +206,26 @@ public interface TreePath extends Serializable {
return of(canonicalPath);
}
+ // -- OBJECT CONTRACTS
+
+ @Override
+ public boolean equals(final Object obj) {
+ if(obj instanceof TreePath) {
+ final TreePath other = (TreePath) obj;
+ return Arrays.equals(canonicalPath, other.canonicalPath);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ @Override
+ public String toString() {
+ return stringify("/");
+ }
+
+
}
diff --git
a/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreePath_Default.java
b/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreePath_Default.java
deleted file mode 100644
index df37ea3cda..0000000000
---
a/api/applib/src/main/java/org/apache/causeway/applib/graph/tree/TreePath_Default.java
+++ /dev/null
@@ -1,157 +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.applib.graph.tree;
-
-import java.util.Arrays;
-import java.util.Objects;
-import java.util.OptionalInt;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
-
-import org.apache.causeway.commons.internal.assertions._Assert;
-import org.apache.causeway.commons.internal.base._Refs;
-import org.apache.causeway.commons.internal.base._Strings;
-
-import lombok.NonNull;
-import lombok.val;
-
-/**
- * Package private mixin for TreePath.
- */
-class TreePath_Default implements TreePath {
-
- private static final long serialVersionUID = 530511373409525896L;
- private final int[] canonicalPath;
- private final int hashCode;
-
- TreePath_Default(final int[] canonicalPath) {
- Objects.requireNonNull(canonicalPath, "canonicalPath is required");
- if(canonicalPath.length<1) {
- throw new IllegalArgumentException("canonicalPath must not be
empty");
- }
- this.canonicalPath = canonicalPath;
- this.hashCode = Arrays.hashCode(canonicalPath);
- }
-
- @Override
- public int size() {
- return canonicalPath.length;
- }
-
- @Override
- public TreePath append(final int indexWithinSiblings) {
- final int[] newCanonicalPath = new int[canonicalPath.length+1];
- System.arraycopy(canonicalPath, 0, newCanonicalPath, 0,
canonicalPath.length);
- newCanonicalPath[canonicalPath.length] = indexWithinSiblings;
- return new TreePath_Default(newCanonicalPath);
- }
-
- @Override
- public TreePath getParentIfAny() {
- if(isRoot()) {
- return null;
- }
- final int[] newCanonicalPath = new int[canonicalPath.length-1];
- System.arraycopy(canonicalPath, 0, newCanonicalPath, 0,
canonicalPath.length-1);
- return new TreePath_Default(newCanonicalPath);
- }
-
- @Override
- public boolean isRoot() {
- return canonicalPath.length==1;
- }
-
- @Override
- public boolean startsWith(TreePath other) {
- if(other.size()>this.size()) return false;
- // optimization, not strictly required
- if(other instanceof TreePath_Default) {
- final int lastIndexToCheck = other.size() - 1;
- return Arrays.equals(
- this.canonicalPath, 0, lastIndexToCheck,
- ((TreePath_Default)other).canonicalPath, 0,
lastIndexToCheck);
- }
- return this.stringify("/").startsWith(other.stringify("/"));
- }
-
- @Override
- public OptionalInt childIndex() {
- return size()>=2
- ? OptionalInt.of(canonicalPath[1])
- : OptionalInt.empty();
- }
-
- @Override
- public TreePath subPath(int startIndex) {
- if(startIndex<=0) return this;
- if(startIndex>=size()) throw new IndexOutOfBoundsException(startIndex);
- final int newSize = size() - startIndex;
- final int[] newCanonicalPath = new int[newSize];
- System.arraycopy(canonicalPath, startIndex, newCanonicalPath, 0,
newSize);
- return new TreePath_Default(newCanonicalPath);
- }
-
- @Override
- public String stringify(@NonNull final String delimiter) {
- _Assert.assertTrue(_Strings.isNotEmpty(delimiter), ()->"non-empty
delimiter required");
- return delimiter + streamPathElements()
- .mapToObj(i->""+i)
- .collect(Collectors.joining(delimiter));
- }
-
- @Override
- public IntStream streamPathElements() {
- return IntStream.of(canonicalPath);
- }
-
- @Override
- public Stream<TreePath> streamUpTheHierarchyStartingAtSelf() {
- val hasMore = _Refs.booleanRef(true);
- return Stream.iterate((TreePath)this, __->hasMore.isTrue(),
TreePath::getParentIfAny)
- .filter(x->{
- if(x.isRoot()) {
- hasMore.setValue(false); // stop the stream only after
we have included the root
- }
- return true;
- });
- }
-
- // -- OBJECT CONTRACTS
-
- @Override
- public boolean equals(final Object obj) {
- if(obj instanceof TreePath_Default) {
- final TreePath_Default other = (TreePath_Default) obj;
- return Arrays.equals(canonicalPath, other.canonicalPath);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return hashCode;
- }
-
- @Override
- public String toString() {
- return stringify("/");
- }
-
-}
diff --git
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/CausewayModuleCoreMetamodel.java
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/CausewayModuleCoreMetamodel.java
index 8c9c9f251b..9d95c92868 100644
---
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/CausewayModuleCoreMetamodel.java
+++
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/CausewayModuleCoreMetamodel.java
@@ -97,6 +97,7 @@ import
org.apache.causeway.core.metamodel.valuesemantics.PasswordValueSemantics;
import org.apache.causeway.core.metamodel.valuesemantics.ShortValueSemantics;
import org.apache.causeway.core.metamodel.valuesemantics.StringValueSemantics;
import
org.apache.causeway.core.metamodel.valuesemantics.TreeNodeValueSemantics;
+import
org.apache.causeway.core.metamodel.valuesemantics.TreePathValueSemantics;
import org.apache.causeway.core.metamodel.valuesemantics.URLValueSemantics;
import org.apache.causeway.core.metamodel.valuesemantics.UUIDValueSemantics;
import
org.apache.causeway.core.metamodel.valuesemantics.temporal.LocalDateTimeValueSemantics;
@@ -156,6 +157,7 @@ import lombok.NonNull;
OidDtoValueSemantics.class,
UUIDValueSemantics.class,
LocaleValueSemantics.class,
+ TreePathValueSemantics.class,
TreeNodeValueSemantics.class,
ChangesDtoValueSemantics.class,
CommandDtoValueSemantics.class,
diff --git
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java
index 2f2aaa0b00..4174afa7ea 100644
---
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java
+++
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java
@@ -99,6 +99,7 @@ import
org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
import
org.apache.causeway.core.metamodel.specloader.SpecificationLoaderDefault;
import
org.apache.causeway.core.metamodel.valuesemantics.BigDecimalValueSemantics;
+import
org.apache.causeway.core.metamodel.valuesemantics.TreePathValueSemantics;
import org.apache.causeway.core.metamodel.valuesemantics.URLValueSemantics;
import org.apache.causeway.core.metamodel.valuesemantics.UUIDValueSemantics;
import
org.apache.causeway.core.metamodel.valuetypes.ValueSemanticsResolverDefault;
@@ -253,6 +254,7 @@ extends MetaModelContext {
new BigDecimalValueSemantics(),
new URLValueSemantics(),
new UUIDValueSemantics(),
+ new TreePathValueSemantics(),
this);
return Stream.concat(
diff --git
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/TreePathValueSemantics.java
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/TreePathValueSemantics.java
new file mode 100644
index 0000000000..a9ae584914
--- /dev/null
+++
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/TreePathValueSemantics.java
@@ -0,0 +1,137 @@
+/*
+ * 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.core.metamodel.valuesemantics;
+
+import javax.annotation.Priority;
+import javax.inject.Named;
+
+import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Component;
+
+import org.apache.causeway.applib.annotation.PriorityPrecedence;
+import org.apache.causeway.applib.graph.tree.TreePath;
+import org.apache.causeway.applib.services.bookmark.IdStringifier;
+import org.apache.causeway.applib.value.semantics.Parser;
+import org.apache.causeway.applib.value.semantics.Renderer;
+import org.apache.causeway.applib.value.semantics.ValueDecomposition;
+import org.apache.causeway.applib.value.semantics.ValueSemanticsAbstract;
+import org.apache.causeway.applib.value.semantics.ValueSemanticsProvider;
+import org.apache.causeway.commons.collections.Can;
+import org.apache.causeway.commons.internal.base._Strings;
+import org.apache.causeway.schema.common.v2.ValueType;
+
+import lombok.NonNull;
+import lombok.val;
+
+@Component
+@Named("causeway.metamodel.value.TreePathValueSemantics")
+@Priority(PriorityPrecedence.LATE)
+public class TreePathValueSemantics
+extends ValueSemanticsAbstract<TreePath>
+implements
+ Parser<TreePath>,
+ Renderer<TreePath>,
+ IdStringifier.EntityAgnostic<TreePath> {
+
+ @Override
+ public Class<TreePath> getCorrespondingClass() {
+ return TreePath.class;
+ }
+
+ @Override
+ public ValueType getSchemaValueType() {
+ return ValueType.STRING; // this type can be easily converted to
string and back
+ }
+
+ // -- COMPOSER
+
+ @Override
+ public ValueDecomposition decompose(final TreePath value) {
+ return decomposeAsString(value,
TreePathValueSemantics::canonicalStringify, ()->null);
+ }
+
+ @Override
+ public TreePath compose(final ValueDecomposition decomposition) {
+ return composeFromString(decomposition,
TreePathValueSemantics::canonicalDestringify, ()->null);
+ }
+
+ // -- ID STRINGIFIER
+
+ @Override
+ public String enstring(final @NonNull TreePath value) {
+ return canonicalStringify(value);
+ }
+
+ @Override
+ public TreePath destring(final @NonNull String stringified) {
+ return canonicalDestringify(stringified);
+ }
+
+ // -- RENDERER
+
+ @Override
+ public String titlePresentation(final ValueSemanticsProvider.Context
context, final TreePath value) {
+ return value == null ? "" : canonicalStringify(value);
+ }
+
+ // -- PARSER
+
+ @Override
+ public String parseableTextRepresentation(final
ValueSemanticsProvider.Context context, final TreePath value) {
+ return canonicalStringify(value);
+ }
+
+ @Override
+ public TreePath parseTextRepresentation(final
ValueSemanticsProvider.Context context, final String text) {
+ val input = _Strings.blankToNullOrTrim(text);
+ return canonicalDestringify(input);
+ }
+
+ @Override
+ public int typicalLength() {
+ return 40;
+ }
+
+ @Override
+ public int maxLength() {
+ return 1024;
+ }
+
+ @Override
+ public Can<TreePath> getExamples() {
+ return Can.of(
+ TreePath.root(),
+ TreePath.of(0, 1, 2, 3));
+ }
+
+ // -- HELPER
+
+ private static String canonicalStringify(@Nullable TreePath treePath) {
+ return treePath!=null
+ ? treePath.stringify("/")
+ : null;
+ }
+
+ private static TreePath canonicalDestringify(@Nullable String input) {
+ return input!=null
+ ? TreePath.parse(input, "/")
+ : null;
+ }
+
+}
diff --git
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/valuetypes/ValueTypeExample.java
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/valuetypes/ValueTypeExample.java
index 39d2d35402..5570d7dc9c 100644
---
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/valuetypes/ValueTypeExample.java
+++
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/valuetypes/ValueTypeExample.java
@@ -768,8 +768,6 @@ public abstract class ValueTypeExample<T> {
"anotherRoot", TreeAdapterString.class,
TreeState.rootCollapsed());
private static class TreeAdapterString implements TreeAdapter<String> {
- @Override public int childCountOf(final String value) {
- return 0; }
@Override public Stream<String> childrenOf(final String value) {
return Stream.empty(); }
}
diff --git
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/tree/_TreeModelTreeAdapter.java
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/tree/_TreeModelTreeAdapter.java
index e27d9b5246..6743e98edd 100644
---
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/tree/_TreeModelTreeAdapter.java
+++
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/tree/_TreeModelTreeAdapter.java
@@ -19,7 +19,6 @@
package org.apache.causeway.viewer.wicket.ui.components.tree;
import java.io.Serializable;
-import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Stream;
@@ -55,24 +54,8 @@ implements
this.treeAdapterClass = treeAdapterClass;
}
-// @Override
-// public Optional<_TreeNodeMemento> parentOf(final _TreeNodeMemento
treeModel) {
-// if(treeModel==null) {
-// return Optional.empty();
-// }
-// val pojoNode = demementify(treeModel);
-// if(pojoNode==null) {
-// return Optional.empty();
-// }
-// return wrappedTreeAdapter().parentOf(pojoNode)
-// .map(pojo->mementify(pojo,
treeModel.getTreePath().getParentIfAny()));
-// }
-
@Override
- public int childCountOf(final _TreeNodeMemento treeModel) {
- if(treeModel==null) {
- return 0;
- }
+ public int childCountOf(final @Nullable _TreeNodeMemento treeModel) {
val pojoNode = demementify(treeModel);
if(pojoNode==null) {
return 0;
@@ -81,10 +64,7 @@ implements
}
@Override
- public Stream<_TreeNodeMemento> childrenOf(final _TreeNodeMemento
treeModel) {
- if(treeModel==null) {
- return Stream.empty();
- }
+ public Stream<_TreeNodeMemento> childrenOf(final @Nullable
_TreeNodeMemento treeModel) {
val pojoNode = demementify(treeModel);
if(pojoNode==null) {
return Stream.empty();
@@ -93,14 +73,18 @@ implements
.map(newPojoToTreeModelMapper(treeModel));
}
+ // -- HELPER
+
_TreeNodeMemento mementify(final @NonNull Object pojo, final @NonNull
TreePath treePath) {
return new _TreeNodeMemento(
treePath,
ManagedObject.adaptSingular(getSpecificationLoader(),
pojo).getBookmark().orElseThrow());
}
- private @Nullable Object demementify(final _TreeNodeMemento model) {
- Objects.requireNonNull(model);
- return model.getPojo();
+
+ private @Nullable Object demementify(final @Nullable _TreeNodeMemento
model) {
+ return model!=null
+ ? model.getPojo()
+ : null;
}
private Function<Object, _TreeNodeMemento> newPojoToTreeModelMapper(final
_TreeNodeMemento parent) {