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/isis.git

commit 9aa747ead77790658bcd591b697cc20fb170ad8d
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Fri May 4 16:38:24 2018 +0200

    ISIS-1943: introduces TreeModel that extends EntityModel
    
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1943
---
 .../java/org/apache/isis/applib/tree/TreePath.java |  10 ++
 .../apache/isis/applib/tree/TreePath_Default.java  |  32 +++++-
 .../components/tree/IsisToWicketTreeAdapter.java   | 125 +++++++++++++--------
 3 files changed, 119 insertions(+), 48 deletions(-)

diff --git 
a/core/applib/src/main/java/org/apache/isis/applib/tree/TreePath.java 
b/core/applib/src/main/java/org/apache/isis/applib/tree/TreePath.java
index 0e8c349..0ecda6c 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/tree/TreePath.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/tree/TreePath.java
@@ -20,6 +20,8 @@ package org.apache.isis.applib.tree;
 
 import java.io.Serializable;
 
+import javax.annotation.Nullable;
+
 /**
  * Provides an unambiguous way to address nodes by position within a 
tree-structure. Examples:
  * <ul>
@@ -37,6 +39,14 @@ public interface TreePath extends Serializable {
         */
        public TreePath append(int indexWithinSiblings);
        
+       /**
+        * 
+        * @return a new TreePath instance that represents the parent path of 
this
+        */
+       public @Nullable TreePath getParentIfAny();
+       
+       public boolean isRoot();
+       
        // -- CONSTRUCTION
        
        public static TreePath of(final int ... canonicalPath) {
diff --git 
a/core/applib/src/main/java/org/apache/isis/applib/tree/TreePath_Default.java 
b/core/applib/src/main/java/org/apache/isis/applib/tree/TreePath_Default.java
index ce30341..4851572 100644
--- 
a/core/applib/src/main/java/org/apache/isis/applib/tree/TreePath_Default.java
+++ 
b/core/applib/src/main/java/org/apache/isis/applib/tree/TreePath_Default.java
@@ -18,6 +18,7 @@
  */
 package org.apache.isis.applib.tree;
 
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -38,10 +39,39 @@ class TreePath_Default implements TreePath {
 
        @Override
        public TreePath append(int indexWithinSiblings) {
-               int[] newCanonicalPath = new int[canonicalPath.length+1];
+               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 boolean equals(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 canonicalPath.hashCode();
+       }
+
+       @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;
+       }
+       
 }
diff --git 
a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java
 
b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java
index 102a12a..164481d 100644
--- 
a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java
+++ 
b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java
@@ -5,6 +5,7 @@ import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.concurrent.atomic.LongAdder;
 import java.util.stream.Stream;
 
 import javax.resource.spi.IllegalStateException;
@@ -12,6 +13,7 @@ import javax.resource.spi.IllegalStateException;
 import org.apache.isis.applib.internal.collections._Lists;
 import org.apache.isis.applib.tree.TreeAdapter;
 import org.apache.isis.applib.tree.TreeNode;
+import org.apache.isis.applib.tree.TreePath;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.oid.RootOid;
 import org.apache.isis.core.runtime.system.context.IsisContext;
@@ -47,11 +49,11 @@ class IsisToWicketTreeAdapter {
        /**
         * Wicket's Tree Component implemented for Isis
         */
-       private static class EntityTree extends NestedTree<EntityModel> {
+       private static class EntityTree extends NestedTree<TreeModel> {
 
                private static final long serialVersionUID = 1L;
 
-               public EntityTree(String id, ITreeProvider<EntityModel> 
provider) {
+               public EntityTree(String id, ITreeProvider<TreeModel> provider) 
{
                        super(id, provider);
                        add(new WindowsTheme()); // TODO not required if Isis 
provides it's own css styles for tree-nodes
                }
@@ -60,9 +62,9 @@ class IsisToWicketTreeAdapter {
                 * To use a custom component for the representation of a node's 
content we override this method.
                 */
                @Override
-               protected Component newContentComponent(String id, 
IModel<EntityModel> node) {
-                       final EntityModel entityModel = node.getObject();
-                       final Component entityIconAndTitle = new 
EntityIconAndTitlePanel(id, entityModel);
+               protected Component newContentComponent(String id, 
IModel<TreeModel> node) {
+                       final TreeModel treeModel = node.getObject();
+                       final Component entityIconAndTitle = new 
EntityIconAndTitlePanel(id, treeModel);
                        return entityIconAndTitle;
                }
                
@@ -70,20 +72,20 @@ class IsisToWicketTreeAdapter {
                 * To hardcode Node's 
<pre>AjaxFallbackLink.isEnabledInHierarchy()->true</pre> we override this 
method.
                 */
                @Override
-               public Component newNodeComponent(String id, 
IModel<EntityModel> model) {
+               public Component newNodeComponent(String id, IModel<TreeModel> 
model) {
                        
-                       final Node<EntityModel> node =  new 
Node<EntityModel>(id, this, model) {
+                       final Node<TreeModel> node =  new Node<TreeModel>(id, 
this, model) {
                                private static final long serialVersionUID = 1L;
                                
                                @Override
-                               protected Component createContent(String id, 
IModel<EntityModel> model) {
+                               protected Component createContent(String id, 
IModel<TreeModel> model) {
                                        return 
EntityTree.this.newContentComponent(id, model);
                                }
                                
                                @Override
                                protected MarkupContainer 
createJunctionComponent(String id) {
                                        
-                                       final Node<EntityModel> node = this;
+                                       final Node<TreeModel> node = this;
                                        final Runnable toggleExpandCollapse = 
(Runnable & Serializable) this::toggle;
                                        
                                        return new AjaxFallbackLink<Void>(id) {
@@ -118,15 +120,34 @@ class IsisToWicketTreeAdapter {
        }
        
        // -- HELPER
+       
+       /**
+        * Extending the EntityModel to also provide a TreePath.
+        */
+       public static class TreeModel extends EntityModel {
+               private static final long serialVersionUID = 
8916044984628849300L;
+               
+               private final TreePath treePath;
+
+               public TreeModel(ObjectAdapter adapter, TreePath treePath) {
+                       super(adapter);
+                       this.treePath = treePath;
+               }
+               
+               public TreePath getTreePath() {
+                       return treePath;
+               }
+       }
+       
 
        @SuppressWarnings({"rawtypes", "unchecked"})
-       private static class EntityModelTreeAdapter implements 
TreeAdapter<EntityModel>, Serializable {
+       private static class TreeModelTreeAdapter implements 
TreeAdapter<TreeModel>, Serializable {
                private static final long serialVersionUID = 1L;
                
                private final Class<? extends TreeAdapter> treeAdapterClass;
                private transient TreeAdapter wrappedTreeAdapter;
                
-               private EntityModelTreeAdapter(Class<? extends TreeAdapter> 
treeAdapterClass) {
+               private TreeModelTreeAdapter(Class<? extends TreeAdapter> 
treeAdapterClass) {
                        this.treeAdapterClass = treeAdapterClass;
                }
                
@@ -142,37 +163,39 @@ class IsisToWicketTreeAdapter {
                }
 
                @Override
-               public Optional<EntityModel> parentOf(EntityModel entityModel) {
-                       if(entityModel==null) {
+               public Optional<TreeModel> parentOf(TreeModel treeModel) {
+                       if(treeModel==null) {
                                return Optional.empty();
                        }
-                       return 
wrappedTreeAdapter().parentOf(unwrap(entityModel))
-                                       .map(this::wrap);
+                       return wrappedTreeAdapter().parentOf(unwrap(treeModel))
+                                       .map(pojo->wrap(pojo, 
treeModel.getTreePath().getParentIfAny())); 
                }
 
                @Override
-               public int childCountOf(EntityModel entityModel) {
-                       if(entityModel==null) {
+               public int childCountOf(TreeModel treeModel) {
+                       if(treeModel==null) {
                                return 0;
                        }
-                       return 
wrappedTreeAdapter().childCountOf(unwrap(entityModel));
+                       return 
wrappedTreeAdapter().childCountOf(unwrap(treeModel));
                }
 
                @Override
-               public Stream<EntityModel> childrenOf(EntityModel entityModel) {
-                       if(entityModel==null) {
+               public Stream<TreeModel> childrenOf(TreeModel treeModel) {
+                       if(treeModel==null) {
                                return Stream.empty();
                        }
-                       return 
wrappedTreeAdapter().childrenOf(unwrap(entityModel))
-                                       .map(this::wrap);
+                       final LongAdder indexWithinSiblings = new LongAdder(); 
+                       return 
wrappedTreeAdapter().childrenOf(unwrap(treeModel))
+                                       .map(pojo->wrap(pojo, 
treeModel.getTreePath().append(indexWithinSiblings.intValue()) ))
+                                       
.peek(__->indexWithinSiblings.increment());
                }
                
-               private EntityModel wrap(Object pojo) {
+               private TreeModel wrap(Object pojo, TreePath treePath) {
                        Objects.requireNonNull(pojo);
-                       return new 
EntityModel(persistenceSession().getAdapterFor(pojo));
+                       return new 
TreeModel(persistenceSession().getAdapterFor(pojo), treePath);
                }
                
-               private Object unwrap(EntityModel model) {
+               private Object unwrap(TreeModel model) {
                        Objects.requireNonNull(model);
                        return model.getObject().getObject();
                }
@@ -186,14 +209,17 @@ class IsisToWicketTreeAdapter {
        /**
         * Wicket's ITreeProvider implemented for Isis
         */
-       private static class EntityModelTreeProvider implements 
ITreeProvider<EntityModel> {
+       private static class TreeModelTreeProvider implements 
ITreeProvider<TreeModel> {
 
                private static final long serialVersionUID = 1L;
                
-               private final EntityModel primaryValue;
-               private final EntityModelTreeAdapter treeAdapter;
+               /**
+                * tree's root
+                */
+               private final TreeModel primaryValue;
+               private final TreeModelTreeAdapter treeAdapter;
 
-               private EntityModelTreeProvider(EntityModel primaryValue, 
EntityModelTreeAdapter treeAdapter) {
+               private TreeModelTreeProvider(TreeModel primaryValue, 
TreeModelTreeAdapter treeAdapter) {
                        this.primaryValue = primaryValue;
                        this.treeAdapter = treeAdapter;
                }
@@ -203,23 +229,23 @@ class IsisToWicketTreeAdapter {
                }
 
                @Override
-               public Iterator<? extends EntityModel> getRoots() {
+               public Iterator<? extends TreeModel> getRoots() {
                        return _Lists.singleton(primaryValue).iterator();
                }
 
                @Override
-               public boolean hasChildren(EntityModel node) {
+               public boolean hasChildren(TreeModel node) {
                        return treeAdapter.childCountOf(node)>0;
                }
 
                @Override
-               public Iterator<? extends EntityModel> getChildren(EntityModel 
node) {
+               public Iterator<? extends TreeModel> getChildren(TreeModel 
node) {
                        return treeAdapter.childrenOf(node).iterator();
                }
 
                @Override
-               public IModel<EntityModel> model(final EntityModel entityModel) 
{
-                       return new LoadableDetachableEntityModel(entityModel);
+               public IModel<TreeModel> model(final TreeModel treeModel) {
+                       return new LoadableDetachableEntityModel(treeModel);
                }
                
        }
@@ -229,29 +255,34 @@ class IsisToWicketTreeAdapter {
         * @return Wicket's ITreeProvider
         */
        @SuppressWarnings({ "rawtypes", "unchecked" })
-       private static ITreeProvider<EntityModel> 
toITreeProvider(ModelAbstract<ObjectAdapter> model) {
-               
-               final TreeNode tree = (TreeNode) model.getObject().getObject();
-               final EntityModelTreeAdapter wrappingTreeAdapter = new 
EntityModelTreeAdapter(tree.getTreeAdapterClass());
+       private static ITreeProvider<TreeModel> 
toITreeProvider(ModelAbstract<ObjectAdapter> model) {
                
-               return new 
EntityModelTreeProvider(wrappingTreeAdapter.wrap(tree.getValue()), 
wrappingTreeAdapter);             
+               final TreeNode treeNode = (TreeNode) 
model.getObject().getObject();
+               final TreeModelTreeAdapter wrappingTreeAdapter = new 
TreeModelTreeAdapter(treeNode.getTreeAdapterClass());
+               return new TreeModelTreeProvider(
+                               wrappingTreeAdapter.wrap(treeNode.getValue(), 
treeNode.getPositionAsPath()), 
+                               wrappingTreeAdapter);           
        }
        
-       private static class LoadableDetachableEntityModel extends 
LoadableDetachableModel<EntityModel> {
+       private static class LoadableDetachableEntityModel extends 
LoadableDetachableModel<TreeModel> {
                private static final long serialVersionUID = 1L;
 
                private final RootOid id;
+               private final TreePath treePath;
+               private final int hashCode;
 
-               public LoadableDetachableEntityModel(EntityModel eModel) {
-                       super(eModel);
-                       id = (RootOid) eModel.getObject().getOid();
+               public LoadableDetachableEntityModel(TreeModel tModel) {
+                       super(tModel);
+                       this.id = (RootOid) tModel.getObject().getOid();
+                       this.treePath = tModel.getTreePath();
+                       this.hashCode = Objects.hash(id.hashCode(), 
treePath.hashCode());
                }
 
                /*
                 * loads EntityModel using Oid (id)
                 */
                @Override
-               protected EntityModel load() {
+               protected TreeModel load() {
                        
                        final PersistenceSession persistenceSession = 
IsisContext.getPersistenceSession()
                                        .orElseThrow(()->new 
RuntimeException(new IllegalStateException(
@@ -271,7 +302,7 @@ class IsisToWicketTreeAdapter {
                                                String.format("Tree creation: 
could not recreate Pojo from Oid: '%s'", id)); 
                        }
                        
-                       return new EntityModel(objAdapter);
+                       return new TreeModel(objAdapter, treePath);
                }
 
                /*
@@ -282,7 +313,7 @@ class IsisToWicketTreeAdapter {
                public boolean equals(Object obj) {
                        if (obj instanceof LoadableDetachableEntityModel) {
                                final LoadableDetachableEntityModel other = 
(LoadableDetachableEntityModel) obj;
-                               return id.equals(other.id);
+                               return treePath.equals(other.treePath) && 
id.equals(other.id);
                        }
                        return false;
                }
@@ -292,7 +323,7 @@ class IsisToWicketTreeAdapter {
                 */
                @Override
                public int hashCode() {
-                       return id.hashCode();
+                       return hashCode;
                }
        }
 

-- 
To stop receiving notification emails like this one, please contact
ahu...@apache.org.

Reply via email to