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);
}
Show replies by date