[dna-commits] DNA SVN: r832 - trunk/dna-jcr/src/main/java/org/jboss/dna/jcr.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Thu Apr 16 10:53:11 EDT 2009


Author: rhauch
Date: 2009-04-16 10:53:11 -0400 (Thu, 16 Apr 2009)
New Revision: 832

Modified:
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
Log:
DNA-359 Session.refresh and Node.refresh Methods Not Supported

Applied the patch that implements the Session.refresh and Node.refresh by adding two SessionCache.refresh methods (one to refresh all contents, the other to refresh only those items below a branch).  

There is one case that the patch doesn't handle (well), and that is when a node is removed from a branch, refreshing that branch will not refresh the removed node.  This needs to be addressed, and will be described in the issue.

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java	2009-04-16 14:11:21 UTC (rev 831)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java	2009-04-16 14:53:11 UTC (rev 832)
@@ -1597,11 +1597,10 @@
     /**
      * {@inheritDoc}
      * 
-     * @throws UnsupportedOperationException always
      * @see javax.jcr.Item#refresh(boolean)
      */
-    public void refresh( boolean keepChanges ) {
-        throw new UnsupportedOperationException();
+    public void refresh( boolean keepChanges ) throws RepositoryException {
+        this.cache.refresh(this.nodeUuid, keepChanges);
     }
 
     /**

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java	2009-04-16 14:11:21 UTC (rev 831)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java	2009-04-16 14:53:11 UTC (rev 832)
@@ -665,6 +665,7 @@
      * @see javax.jcr.Session#refresh(boolean)
      */
     public void refresh( boolean keepChanges ) {
+        this.cache.refresh(keepChanges);
     }
 
     /**

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java	2009-04-16 14:11:21 UTC (rev 831)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java	2009-04-16 14:53:11 UTC (rev 832)
@@ -34,6 +34,7 @@
 import java.util.Map;
 import java.util.Queue;
 import java.util.Set;
+import java.util.Stack;
 import java.util.UUID;
 import javax.jcr.InvalidItemStateException;
 import javax.jcr.Item;
@@ -228,6 +229,103 @@
     }
 
     /**
+     * Refreshes (removes the cached state) for all cached nodes.
+     * <p>
+     * If {@code keepChanges == true}, modified nodes will not have their state refreshed.
+     * </p>
+     * 
+     * @param keepChanges indicates whether changed nodes should be kept or refreshed from the repository.
+     */
+    public void refresh( boolean keepChanges ) {
+        if (keepChanges) {
+            // Keep the pending operations
+            Set<UUID> retainedSet = new HashSet<UUID>(this.changedNodes.size() + this.deletedNodes.size());
+            retainedSet.addAll(this.changedNodes.keySet());
+            retainedSet.addAll(this.deletedNodes.keySet());
+
+            // Removed any cached nodes not already in the changed or deleted set
+            this.cachedNodes.keySet().retainAll(retainedSet);
+        } else {
+            // Throw out the old pending operations
+            this.requests.clear();
+            this.changedNodes.clear();
+            this.cachedNodes.clear();
+            this.deletedNodes.clear();
+        }
+
+    }
+
+    /**
+     * Refreshes (removes the cached state) for the node with the given UUID and any of its descendants.
+     * <p>
+     * If {@code keepChanges == true}, modified nodes will not have their state refreshed.
+     * </p>
+     * 
+     * @param nodeUuid the UUID of the node that is to be saved; may not be null
+     * @param keepChanges indicates whether changed nodes should be kept or refreshed from the repository.
+     * @throws RepositoryException if any error resulting while saving the changes to the repository
+     */
+    public void refresh( UUID nodeUuid,
+                         boolean keepChanges ) throws RepositoryException {
+        // Find the path of the given node ...
+        Path path = getPathFor(nodeUuid);
+
+        // Build the set of affected node UUIDs
+        Set<UUID> nodesUnderBranch = new HashSet<UUID>();
+        Stack<UUID> nodesToVisit = new Stack<UUID>();
+
+        nodesToVisit.add(nodeUuid);
+        while (!nodesToVisit.isEmpty()) {
+            UUID uuid = nodesToVisit.pop();
+            nodesUnderBranch.add(uuid);
+
+            NodeInfo nodeInfo = cachedNodes.get(uuid);
+            // Newly added nodes will be changedNodes but not cachedNodes
+            if (nodeInfo == null) nodeInfo = changedNodes.get(uuid);
+
+            if (nodeInfo != null) {
+                for (ChildNode childNode : nodeInfo.getChildren()) {
+                    nodesToVisit.add(childNode.getUuid());
+                }
+            }
+        }
+
+        if (keepChanges) {
+            // Keep the pending operations
+            for (UUID uuid : nodesUnderBranch) {
+                // getPathFor can (and will) add entries to cachedNodes - hence the existence of nodesToCheck
+                if (getPathFor(uuid).isDecendantOf(path)) {
+                    if (!this.changedNodes.containsKey(uuid) && !this.deletedNodes.containsKey(uuid)) {
+                        this.cachedNodes.remove(uuid);
+                    }
+                }
+            }
+        } else {
+            this.cachedNodes.keySet().removeAll(nodesUnderBranch);
+            this.changedNodes.keySet().removeAll(nodesUnderBranch);
+            this.deletedNodes.keySet().removeAll(nodesUnderBranch);
+
+            // Throw out the old pending operations
+            if (operations.isExecuteRequired()) {
+
+                // Make sure the builder has finished all the requests ...
+                this.requestBuilder.finishPendingRequest();
+
+                // Remove all of the enqueued requests for this branch ...
+                for (Iterator<Request> iter = this.requests.iterator(); iter.hasNext();) {
+                    Request request = iter.next();
+                    assert request instanceof ChangeRequest;
+                    ChangeRequest change = (ChangeRequest)request;
+                    if (change.changes(workspaceName, path)) {
+                        iter.remove();
+                    }
+                }
+            }
+        }
+
+    }
+
+    /**
      * Save any changes that have been accumulated by this session.
      * 
      * @throws RepositoryException if any error resulting while saving the changes to the repository
@@ -263,7 +361,7 @@
     }
 
     /**
-     * Save any changes to the identified node or its decendants. The supplied node may not have been deleted or created in this
+     * Save any changes to the identified node or its descendants. The supplied node may not have been deleted or created in this
      * session since the last save operation.
      * 
      * @param nodeUuid the UUID of the node that is to be saved; may not be null
@@ -313,6 +411,22 @@
                 return;
             }
 
+            /*
+             * branchUuids contains all the roots of the changes, but there may be further changes under the roots (e.g., a
+             * newly created node will have it's parent's UUID in branchUuids, but not the new node's uuid. 
+             */
+            Set<UUID> uuidsUnderBranch = new HashSet<UUID>();
+            for (UUID branchUuid : branchUuids) {
+                uuidsUnderBranch.add(branchUuid);
+                ChangedNodeInfo changedNode = changedNodes.get(branchUuid);
+                if (changedNode != null) {
+                    for (ChildNode childNode : changedNode.getChildren()) {
+                        uuidsUnderBranch.add(childNode.getUuid());
+                    }
+                }
+
+            }
+
             // Now execute the branch ...
             Graph.Batch branchBatch = store.batch(new BatchRequestBuilder(branchRequests));
             try {
@@ -324,11 +438,9 @@
                 this.operations = store.batch(this.requestBuilder);
 
                 // Remove all the cached, changed or deleted items that were just saved ...
-                for (UUID changedUuid : branchUuids) {
-                    cachedNodes.remove(changedUuid);
-                    changedNodes.remove(changedUuid);
-                    deletedNodes.remove(changedUuid);
-                }
+                cachedNodes.keySet().removeAll(uuidsUnderBranch);
+                changedNodes.keySet().removeAll(uuidsUnderBranch);
+                deletedNodes.keySet().removeAll(uuidsUnderBranch);
             } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
                 throw new PathNotFoundException(e.getLocalizedMessage(), e);
             } catch (RuntimeException e) {
@@ -402,7 +514,7 @@
         if (info == null) return null; // no such property on this node
 
         if (DnaLexicon.NODE_DEFINITON.equals(info.getPropertyName())) return null;
-        
+
         // Now create the appropriate JCR Property object ...
         return createAndCacheJcrPropertyFor(info);
     }




More information about the dna-commits mailing list