CheckArg.isNotNull(srcNode, "srcNode");
final Path sourcePath = srcNode.getPath(this);
WorkspaceCache workspaceCache = workspaceCache();
// Create a path cache so that we don't recompute the path for the same node more than once ...
AllPathsCache allPathsCache = new AllPathsCache(this, workspaceCache, context()) {
@Override
protected Set<NodeKey> getAdditionalParentKeys( CachedNode node,
NodeCache cache ) {
Set<NodeKey> keys = super.getAdditionalParentKeys(node, cache);
if (node instanceof SessionNode) {
SessionNode sessionNode = (SessionNode)node;
// Per the JCR TCK, we have to consider the nodes that *used to be* shared nodes before this
// session removed them, so we need to include the keys of the additional parents that were removed ...
ChangedAdditionalParents changed = sessionNode.additionalParents();
if (changed != null) {
keys = new HashSet<NodeKey>(keys);
keys.addAll(sessionNode.additionalParents().getRemovals());
}
}
return keys;
}
};
Lock readLock = this.lock.readLock();
Set<NodeKey> result = new HashSet<NodeKey>();
try {
readLock.lock();
for (Map.Entry<NodeKey, SessionNode> entry : changedNodes.entrySet()) {
SessionNode changedNodeThisSession = entry.getValue();
NodeKey changedNodeKey = entry.getKey();
CachedNode changedNode = null;
if (changedNodeThisSession == REMOVED) {
CachedNode persistentRemovedNode = workspaceCache.getNode(changedNodeKey);
if (persistentRemovedNode == null) {
// the node has been removed without having been persisted previously, so we'll take it into account
result.add(changedNodeKey);
continue;
}
changedNode = persistentRemovedNode;
} else {
changedNode = changedNodeThisSession;
}
// Compute all of the valid paths by which this node can be accessed. If *any* of these paths
// are below the source path, then the node should be included in the result ...
for (Path validPath : allPathsCache.getPaths(changedNode)) {
if (validPath.isAtOrBelow(sourcePath)) {
// The changed node is directly below the source node ...
result.add(changedNodeKey);
break;
}