jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject svn commit: r191499 [1/3] - in /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: ./ jndi/ lock/ nodetype/ observation/ query/lucene/ state/ state/obj/ state/xml/ version/ virtual/ xml/
Date Mon, 20 Jun 2005 15:58:58 GMT
Author: stefan
Date: Mon Jun 20 08:58:57 2005
New Revision: 191499

URL: http://svn.apache.org/viewcvs?rev=191499&view=rev
Log:
JCR-131: simplifying internal data model (NodeState) by limiting a node to *one* parent


Added:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java   (with props)
Modified:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/BatchedItemOperations.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/CachingHierarchyManager.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManager.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/BindableRepositoryFactory.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ChangeLogBasedHierarchyMgr.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/query/lucene/FileSystemDirectory.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/query/lucene/NodeIndexer.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/query/lucene/VolatileIndex.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ChangeLog.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/obj/ObjectPersistenceManager.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNodeImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/NodeStateEx.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/AbstractVISProvider.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/BatchedItemOperations.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/BatchedItemOperations.java?rev=191499&r1=191498&r2=191499&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/BatchedItemOperations.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/BatchedItemOperations.java Mon Jun 20 08:58:57 2005
@@ -52,7 +52,6 @@
 import java.util.Calendar;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Set;
 
 /**
@@ -420,7 +419,6 @@
 
         // 3. do move operation (modify and store affected states)
 
-
         boolean renameOnly = srcParent.getUUID().equals(destParent.getUUID());
 
         int srcNameIndex = srcName.getIndex();
@@ -428,16 +426,17 @@
             srcNameIndex = 1;
         }
 
-        // remove from old parent
         if (renameOnly) {
+            // change child node entry
             destParent.renameChildNodeEntry(srcName.getName(), srcNameIndex,
                     destName.getName());
         } else {
-            target.removeParentUUID(srcParent.getUUID());
-            target.addParentUUID(destParent.getUUID());
-
-            destParent.addChildNodeEntry(destName.getName(), target.getUUID());
+            // remove child node entry from old parent
             srcParent.removeChildNodeEntry(srcName.getName(), srcNameIndex);
+            // re-parent target node
+            target.setParentUUID(destParent.getUUID());
+            // add child node entry to new parent
+            destParent.addChildNodeEntry(destName.getName(), target.getUUID());
         }
 
         // change definition (id) of target node
@@ -487,7 +486,6 @@
 
         NodeState target = getNodeState(nodePath);
         NodeId parentId = new NodeId(target.getParentUUID());
-        NodeState parent = getNodeState(parentId);
 
         // 2. check if target state can be removed from parent
 
@@ -495,21 +493,9 @@
                 CHECK_ACCESS | CHECK_LOCK | CHECK_VERSIONING
                 | CHECK_CONSTRAINTS | CHECK_REFERENCES);
 
-        // 3. do remove operation (modify and store affected states)
+        // 3. do remove operation
 
-        // unlink node state from its parent
-        unlinkNodeState(target, target.getParentUUID());
-        // remove child node entries
-        // use temp array to avoid ConcurrentModificationException
-        ArrayList tmp =
-                new ArrayList(parent.getChildNodeEntries(target.getUUID()));
-        // remove from tail to avoid problems with same-name siblings
-        for (int i = tmp.size() - 1; i >= 0; i--) {
-            NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) tmp.get(i);
-            parent.removeChildNodeEntry(entry.getName(), entry.getIndex());
-        }
-        // store parent
-        stateMgr.store(parent);
+        removeNodeState(target);
     }
 
     //--------------------------------------< misc. high-level helper methods >
@@ -634,8 +620,7 @@
     }
 
     /**
-     * Checks if removing the given target node entirely (i.e. unlinking from
-     * all its parents) is allowed in the current context.
+     * Checks if removing the given target node is allowed in the current context.
      *
      * @param targetState
      * @param options     bit-wise OR'ed flags specifying the checks that should be
@@ -665,12 +650,8 @@
             throws ConstraintViolationException, AccessDeniedException,
             VersionException, LockException, ItemNotFoundException,
             ReferentialIntegrityException, RepositoryException {
-        List parentUUIDs = targetState.getParentUUIDs();
-        Iterator iter = parentUUIDs.iterator();
-        while (iter.hasNext()) {
-            NodeId parentId = new NodeId((String) iter.next());
-            checkRemoveNode(targetState, parentId, options);
-        }
+        NodeId parentId = new NodeId(targetState.getParentUUID());
+        checkRemoveNode(targetState, parentId, options);
     }
 
     /**
@@ -1204,40 +1185,36 @@
     }
 
     /**
-     * Unlinks the specified node state from all its parents and recursively
+     * Unlinks the specified node state from its parent and recursively
      * removes it including its properties and child nodes.
      * <p/>
-     * Note that access rights are <b><i>not</i></b> enforced!
+     * Note that no checks (access rights etc.) are performed on the specified
+     * target node state. Those checks have to be performed beforehand by the
+     * caller. However, the (recursive) removal of target node's child nodes are
+     * subject to the following checks: access rights, locking, versioning.
      *
-     * @param targetState
+     * @param target
      * @throws RepositoryException if an error occurs
      */
-    public void removeNodeState(NodeState targetState)
+    public void removeNodeState(NodeState target)
             throws RepositoryException {
 
-        // copy list to avoid ConcurrentModificationException
-        ArrayList parentUUIDs = new ArrayList(targetState.getParentUUIDs());
-        Iterator iter = parentUUIDs.iterator();
-        while (iter.hasNext()) {
-            String parentUUID = (String) iter.next();
-            NodeId parentId = new NodeId(parentUUID);
+        String parentUUID = target.getParentUUID();
+        if (parentUUID == null) {
+            String msg = "root node cannot be removed";
+            log.debug(msg);
+            throw new RepositoryException(msg);
+        }
+        NodeId parentId = new NodeId(parentUUID);
 
-            // unlink node state from this parent
-            unlinkNodeState(targetState, parentUUID);
+        NodeState parent = getNodeState(parentId);
+        // remove child node entry from parent
+        parent.removeChildNodeEntry(target.getUUID());
+        // store parent
+        stateMgr.store(parent);
 
-            // remove child node entries
-            NodeState parent = getNodeState(parentId);
-            // use temp array to avoid ConcurrentModificationException
-            ArrayList tmp =
-                    new ArrayList(parent.getChildNodeEntries(targetState.getUUID()));
-            // remove from tail to avoid problems with same-name siblings
-            for (int i = tmp.size() - 1; i >= 0; i--) {
-                NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) tmp.get(i);
-                parent.removeChildNodeEntry(entry.getName(), entry.getIndex());
-            }
-            // store parent
-            stateMgr.store(parent);
-        }
+        // remove target
+        recursiveRemoveNodeState(target);
     }
 
     /**
@@ -1503,88 +1480,79 @@
     }
 
     /**
-     * Unlinks the given node state from the specified parent i.e. removes
-     * <code>parentUUID</code> from its list of parents. If as a result
-     * the given node state would be orphaned it will be recursively removed
-     * including its properties and child nodes.
+     * Recursively removes the given node state including its properties and
+     * child nodes.
+     * <p/>
+     * The removal of child nodes is subject to the following checks:
+     * access rights, locking & versioning status. Referential integrity
+     * (references) is checked on commit.
      * <p/>
      * Note that the child node entry refering to <code>targetState</code> is
      * <b><i>not</i></b> automatically removed from <code>targetState</code>'s
-     * parent denoted by <code>parentUUID</code>.
+     * parent.
      *
      * @param targetState
-     * @param parentUUID
      * @throws RepositoryException if an error occurs
      */
-    private void unlinkNodeState(NodeState targetState, String parentUUID)
+    private void recursiveRemoveNodeState(NodeState targetState)
             throws RepositoryException {
 
-        // check if this node state would be orphaned after unlinking it from parent
-        ArrayList parentUUIDs = new ArrayList(targetState.getParentUUIDs());
-        parentUUIDs.remove(parentUUID);
-        boolean orphaned = parentUUIDs.isEmpty();
-
-        if (orphaned) {
-            // remove child nodes
-            // use temp array to avoid ConcurrentModificationException
-            ArrayList tmp = new ArrayList(targetState.getChildNodeEntries());
-            // remove from tail to avoid problems with same-name siblings
-            for (int i = tmp.size() - 1; i >= 0; i--) {
-                NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) tmp.get(i);
-                NodeId nodeId = new NodeId(entry.getUUID());
-                try {
-                    NodeState nodeState = (NodeState) stateMgr.getItemState(nodeId);
-                    // check if child node can be removed
-                    // (access rights, locking & versioning status)
-                    checkRemoveNode(nodeState, (NodeId) targetState.getId(),
-                            CHECK_ACCESS | CHECK_LOCK | CHECK_VERSIONING);
-                    // unlink child node (recursive)
-                    unlinkNodeState(nodeState, targetState.getUUID());
-                } catch (ItemStateException ise) {
-                    String msg = "internal error: failed to retrieve state of "
-                            + nodeId;
-                    log.debug(msg);
-                    throw new RepositoryException(msg, ise);
-                }
-                // remove child node entry
-                targetState.removeChildNodeEntry(entry.getName(), entry.getIndex());
+        // remove child nodes
+        // use temp array to avoid ConcurrentModificationException
+        ArrayList tmp = new ArrayList(targetState.getChildNodeEntries());
+        // remove from tail to avoid problems with same-name siblings
+        for (int i = tmp.size() - 1; i >= 0; i--) {
+            NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) tmp.get(i);
+            NodeId nodeId = new NodeId(entry.getUUID());
+            try {
+                NodeState nodeState = (NodeState) stateMgr.getItemState(nodeId);
+                // check if child node can be removed
+                // (access rights, locking & versioning status);
+                // referential integrity (references) is checked
+                // on commit
+                checkRemoveNode(nodeState, (NodeId) targetState.getId(),
+                        CHECK_ACCESS
+                        | CHECK_LOCK
+                        | CHECK_VERSIONING);
+                // remove child node
+                recursiveRemoveNodeState(nodeState);
+            } catch (ItemStateException ise) {
+                String msg = "internal error: failed to retrieve state of "
+                        + nodeId;
+                log.debug(msg);
+                throw new RepositoryException(msg, ise);
             }
+            // remove child node entry
+            targetState.removeChildNodeEntry(entry.getName(), entry.getIndex());
+        }
 
-            // remove properties
-            // use temp array to avoid ConcurrentModificationException
-            tmp = new ArrayList(targetState.getPropertyEntries());
-            for (int i = 0; i < tmp.size(); i++) {
-                NodeState.PropertyEntry entry = (NodeState.PropertyEntry) tmp.get(i);
-                PropertyId propId =
-                        new PropertyId(targetState.getUUID(), entry.getName());
-                try {
-                    PropertyState propState =
-                            (PropertyState) stateMgr.getItemState(propId);
-                    // remove property entry
-                    targetState.removePropertyEntry(propId.getName());
-                    // destroy property state
-                    stateMgr.destroy(propState);
-                } catch (ItemStateException ise) {
-                    String msg = "internal error: failed to retrieve state of "
-                            + propId;
-                    log.debug(msg);
-                    throw new RepositoryException(msg, ise);
-                }
+        // remove properties
+        // use temp array to avoid ConcurrentModificationException
+        tmp = new ArrayList(targetState.getPropertyEntries());
+        for (int i = 0; i < tmp.size(); i++) {
+            NodeState.PropertyEntry entry = (NodeState.PropertyEntry) tmp.get(i);
+            PropertyId propId =
+                    new PropertyId(targetState.getUUID(), entry.getName());
+            try {
+                PropertyState propState =
+                        (PropertyState) stateMgr.getItemState(propId);
+                // remove property entry
+                targetState.removePropertyEntry(propId.getName());
+                // destroy property state
+                stateMgr.destroy(propState);
+            } catch (ItemStateException ise) {
+                String msg = "internal error: failed to retrieve state of "
+                        + propId;
+                log.debug(msg);
+                throw new RepositoryException(msg, ise);
             }
         }
 
-        // now actually do unlink target state from specified parent state
-        // (i.e. remove uuid of parent state from target state's parent list)
-        targetState.removeParentUUID(parentUUID);
-
-        if (orphaned) {
-            // destroy target state (pass overlayed state since target state
-            // might have been modified during unlinking)
-            stateMgr.destroy(targetState.getOverlayedState());
-        } else {
-            // store target state
-            stateMgr.store(targetState);
-        }
+        // now actually do unlink target state
+        targetState.setParentUUID(null);
+        // destroy target state (pass overlayed state since target state
+        // might have been modified during unlinking)
+        stateMgr.destroy(targetState.getOverlayedState());
     }
 
     /**
@@ -1672,9 +1640,13 @@
                         }
 
                         // check if existing can be removed
-                        checkRemoveNode(existingState, CHECK_ACCESS | CHECK_LOCK
-                                | CHECK_VERSIONING | CHECK_CONSTRAINTS);
-
+                        // (access rights, locking & versioning status,
+                        // node type constraints)
+                        checkRemoveNode(existingState,
+                                CHECK_ACCESS
+                                | CHECK_LOCK
+                                | CHECK_VERSIONING
+                                | CHECK_CONSTRAINTS);
                         // do remove existing
                         removeNodeState(existingState);
                     }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/CachingHierarchyManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/CachingHierarchyManager.java?rev=191499&r1=191498&r2=191499&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/CachingHierarchyManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/CachingHierarchyManager.java Mon Jun 20 08:58:57 2005
@@ -16,20 +16,20 @@
  */
 package org.apache.jackrabbit.core;
 
+import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.core.state.ItemState;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.ItemStateManager;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.NodeStateListener;
 import org.apache.log4j.Logger;
-import org.apache.commons.collections.map.ReferenceMap;
 
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
-import java.util.List;
-import java.util.Iterator;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -57,8 +57,7 @@
     /**
      * Mapping of item ids to <code>LRUEntry</code> in the path map
      */
-    private final ReferenceMap idCache = new ReferenceMap(
-            ReferenceMap.HARD, ReferenceMap.HARD);
+    private final ReferenceMap idCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.HARD);
 
     /**
      * Set of items that were moved
@@ -86,83 +85,23 @@
     private LRUEntry tail;
 
     /**
-     * Create a new instance of this class. This hierarchy manager will not
-     * check for item states that have been moved into attic space
-     * @param rootNodeUUID root node UUID
-     * @param provider item state manager
-     * @param nsResolver namespace resolver
-     */
-    public CachingHierarchyManager(String rootNodeUUID,
-                                   ItemStateManager provider,
-                                   NamespaceResolver nsResolver) {
-        this(rootNodeUUID, provider, nsResolver, null);
-    }
-
-    /**
      * Create a new instance of this class.
+     *
      * @param rootNodeUUID root node UUID
-     * @param provider item state manager
-     * @param nsResolver namespace resolver
-     * @param attic item state manager for states in the attic space
+     * @param provider     item state manager
+     * @param nsResolver   namespace resolver
      */
     public CachingHierarchyManager(String rootNodeUUID,
                                    ItemStateManager provider,
-                                   NamespaceResolver nsResolver,
-                                   ItemStateManager attic) {
-
-        super(rootNodeUUID, provider, nsResolver, attic);
-
-        this.upperLimit = DEFAULT_UPPER_LIMIT;
-    }
-
-    //-----------------------------------------------------< HierarchyManager >
-
-    /**
-     * {@inheritDoc}
-     *
-     * Check the item indicated inside our path cache first.
-     */
-    public NodeId[] listParents(ItemId id)
-            throws ItemNotFoundException, RepositoryException {
-
-        if (id.denotesNode()) {
-            PathMap.Element element = get(id);
-            if (element != null) {
-                PathMap.Element parent = element.getParent();
-                if (parent != null) {
-                    LRUEntry entry = (LRUEntry) element.get();
-                    if (entry != null) {
-                        return new NodeId[] { (NodeId) entry.getId() };
-                    }
-                }
-            }
-        }
-        return super.listParents(id);
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * Check the path indicated inside our cache first.
-     */
-    public ItemId resolvePath(Path path)
-            throws PathNotFoundException, RepositoryException {
-
-        PathMap.Element element = map(path);
-        if (element == null) {
-            return super.resolvePath(path);
-        }
-        LRUEntry entry = (LRUEntry) element.get();
-        if (element.hasPath(path)) {
-            entry.touch();
-            return entry.getId();
-        }
-        return super.resolvePath(path, entry.getId(), element.getDepth() + 1);
+                                   NamespaceResolver nsResolver) {
+        super(rootNodeUUID, provider, nsResolver);
+        upperLimit = DEFAULT_UPPER_LIMIT;
     }
 
+    //-------------------------------------------------< base class overrides >
     /**
      * {@inheritDoc}
-     *
+     * <p/>
      * Cache the intermediate item inside our cache.
      */
     protected ItemId resolvePath(Path path, ItemState state, int next)
@@ -186,37 +125,13 @@
 
     /**
      * {@inheritDoc}
-     *
-     * Overridden method simply checks whether we have an item matching the id
-     * and returns its path, otherwise calls base implementation.
-     */
-    public synchronized Path getPath(ItemId id)
-            throws ItemNotFoundException, RepositoryException {
-
-        if (id.denotesNode()) {
-            PathMap.Element element = get(id);
-            if (element != null) {
-                try {
-                    return element.getPath();
-                } catch (MalformedPathException mpe) {
-                    String msg = "Failed to build path of " + id;
-                    log.debug(msg);
-                    throw new RepositoryException(msg, mpe);
-                }
-            }
-        }
-        return super.getPath(id);
-    }
-
-    /**
-     * {@inheritDoc}
-     *
+     * <p/>
      * Overridden method tries to find a mapping for the intermediate item
      * <code>state</code> and add its path elements to the builder currently
      * being used. If no mapping is found, the item is cached instead after
      * the base implementation has been invoked.
      */
-    protected void getPath(Path.PathBuilder builder, ItemState state)
+    protected void buildPath(Path.PathBuilder builder, ItemState state)
             throws ItemStateException, RepositoryException {
 
         if (state.isNode()) {
@@ -236,7 +151,7 @@
             }
         }
 
-        super.getPath(builder, state);
+        super.buildPath(builder, state);
 
         if (state.isNode()) {
             try {
@@ -247,6 +162,51 @@
         }
     }
 
+    //-----------------------------------------------------< HierarchyManager >
+    /**
+     * {@inheritDoc}
+     * <p/>
+     * Check the path indicated inside our cache first.
+     */
+    public ItemId resolvePath(Path path)
+            throws PathNotFoundException, RepositoryException {
+
+        PathMap.Element element = map(path);
+        if (element == null) {
+            return super.resolvePath(path);
+        }
+        LRUEntry entry = (LRUEntry) element.get();
+        if (element.hasPath(path)) {
+            entry.touch();
+            return entry.getId();
+        }
+        return super.resolvePath(path, entry.getId(), element.getDepth() + 1);
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p/>
+     * Overridden method simply checks whether we have an item matching the id
+     * and returns its path, otherwise calls base implementation.
+     */
+    public synchronized Path getPath(ItemId id)
+            throws ItemNotFoundException, RepositoryException {
+
+        if (id.denotesNode()) {
+            PathMap.Element element = get(id);
+            if (element != null) {
+                try {
+                    return element.getPath();
+                } catch (MalformedPathException mpe) {
+                    String msg = "Failed to build path of " + id;
+                    log.debug(msg);
+                    throw new RepositoryException(msg, mpe);
+                }
+            }
+        }
+        return super.getPath(id);
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -295,18 +255,6 @@
         return super.isAncestor(nodeId, itemId);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public Path[] getAllPaths(ItemId id, boolean includeZombies)
-            throws ItemNotFoundException, RepositoryException {
-
-        if (!includeZombies) {
-            return new Path[] { getPath(id) };
-        }
-        return super.getAllPaths(id, includeZombies);
-    }
-
     //----------------------------------------------------< ItemStateListener >
 
     /**
@@ -357,8 +305,8 @@
      * state.
      *
      * @param overlayer the <code>ItemState</code> that overlaid another
-     *        item state. To get the overlaid state, invoke
-     *        {@link ItemState#getOverlayedState()}
+     *                  item state. To get the overlaid state, invoke
+     *                  {@link ItemState#getOverlayedState()}
      */
     public void stateUncovered(ItemState overlayer) {
         if (overlayer.isNode()) {
@@ -378,16 +326,16 @@
             log.warn("Added node does not have parent, ignoring event.");
         } catch (MalformedPathException e) {
             log.warn("Unable to create path of " + uuid, e);
-        } catch(ItemNotFoundException e) {
+        } catch (ItemNotFoundException e) {
             log.warn("Unable to get path of " + state.getId(), e);
-        } catch(RepositoryException e) {
+        } catch (RepositoryException e) {
             log.warn("Unable to get path of " + state.getId(), e);
         }
     }
 
     /**
      * {@inheritDoc}
-     *
+     * <p/>
      * Generate subsequent add and remove notifications for every replacement.
      */
     public void nodesReplaced(NodeState state) {
@@ -399,13 +347,9 @@
         Iterator iter = entries.iterator();
         while (iter.hasNext()) {
             NodeState.ChildNodeEntry now = (NodeState.ChildNodeEntry) iter.next();
-            NodeState.ChildNodeEntry old = null;
+            NodeState.ChildNodeEntry old =
+                    ((NodeState) state.getOverlayedState()).getChildNodeEntry(now.getUUID());;
 
-            List list = ((NodeState) state.getOverlayedState()).
-                    getChildNodeEntries(now.getUUID());
-            if (list.size() > 0) {
-                old = (NodeState.ChildNodeEntry) list.get(0);
-            }
             if (old == null) {
                 log.warn("Reordered child node not found in old list.");
                 continue;
@@ -427,17 +371,18 @@
             log.warn("Added node does not have parent, ignoring event.");
         } catch (MalformedPathException e) {
             log.warn("Unable to create path of " + uuid, e);
-        } catch(ItemNotFoundException e) {
+        } catch (ItemNotFoundException e) {
             log.warn("Unable to get path of " + state.getId(), e);
-        } catch(RepositoryException e) {
+        } catch (RepositoryException e) {
             log.warn("Unable to get path of " + state.getId(), e);
         }
     }
 
-    //-------------------------------------------------------< private methods >
+    //------------------------------------------------------< private methods >
 
     /**
      * Return a cached element in the path map, given its id
+     *
      * @param id node id
      * @return cached element, <code>null</code> if not found
      */
@@ -456,6 +401,7 @@
      * Return the nearest cached element in the path map, given a path.
      * The returned element is guaranteed to have an associated object that
      * is not <code>null</code>.
+     *
      * @param path path
      * @return cached element, <code>null</code> if not found
      */
@@ -477,8 +423,9 @@
     /**
      * Cache an item in the hierarchy given its id and path. Adds a listener
      * for this item state to get notified about changes.
+     *
      * @param state item state, may be <code>null</code>
-     * @param path path to item
+     * @param path  path to item
      */
     private void cache(ItemState state, Path path) {
         ItemId id = state.getId();
@@ -520,6 +467,7 @@
 
     /**
      * Return a flag indicating whether a certain element is cached.
+     *
      * @param id item id
      * @return <code>true</code> if the item is already cached;
      *         <code>false</code> otherwise
@@ -532,6 +480,7 @@
 
     /**
      * Evict item from cache. Evicts the associated <code>LRUEntry</code>
+     *
      * @param id item id
      */
     private void evict(ItemId id) {
@@ -545,7 +494,8 @@
 
     /**
      * Evict item from cache
-     * @param entry LRU entry
+     *
+     * @param entry               LRU entry
      * @param removeFromPathCache whether to remove from path cache
      */
     private void evict(LRUEntry entry, boolean removeFromPathCache) {
@@ -564,6 +514,7 @@
     /**
      * Evict path map element from cache. This will traverse all children
      * of this element and evict the objects associated with them
+     *
      * @param element path map element
      */
     private void evict(PathMap.Element element) {
@@ -579,8 +530,9 @@
     /**
      * Insert a node into the cache. This will automatically shift
      * all indexes of sibling nodes having index greater or equal.
+     *
      * @param path child path
-     * @param id node id
+     * @param id   node id
      */
     private void insert(Path path, ItemId id) throws PathNotFoundException {
         synchronized (cacheMonitor) {
@@ -608,8 +560,9 @@
     /**
      * Remove an item from the cache in order to shift the indexes
      * of items following this item.
+     *
      * @param path child path
-     * @param id node id
+     * @param id   node id
      */
     private void remove(Path path, ItemId id) throws PathNotFoundException {
         synchronized (cacheMonitor) {
@@ -654,6 +607,7 @@
 
         /**
          * Create a new instance of this class
+         *
          * @param id item id
          */
         public LRUEntry(ItemId id, PathMap.Element element) {
@@ -706,6 +660,7 @@
 
         /**
          * Return previous LRU entry
+         *
          * @return previous LRU entry
          */
         public LRUEntry getPrevious() {
@@ -714,6 +669,7 @@
 
         /**
          * Return next LRU entry
+         *
          * @return next LRU entry
          */
         public LRUEntry getNext() {
@@ -722,6 +678,7 @@
 
         /**
          * Return item ID
+         *
          * @return item ID
          */
         public ItemId getId() {
@@ -730,6 +687,7 @@
 
         /**
          * Return element in path map
+         *
          * @return element in path map
          */
         public PathMap.Element getElement() {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManager.java?rev=191499&r1=191498&r2=191499&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManager.java Mon Jun 20 08:58:57 2005
@@ -21,19 +21,22 @@
 import javax.jcr.RepositoryException;
 
 /**
- * <code>HierarchyManager</code> ...
+ * The <code>HierarchyManager</code> interface ...
  */
 public interface HierarchyManager {
 
     /**
+     * Resolves a path into an item id.
      * @param path
      * @return
      * @throws PathNotFoundException
      * @throws RepositoryException
      */
-    ItemId resolvePath(Path path) throws PathNotFoundException, RepositoryException;
+    ItemId resolvePath(Path path)
+            throws PathNotFoundException, RepositoryException;
 
     /**
+     * Returns the path to the given item.
      * @param id
      * @return
      * @throws ItemNotFoundException
@@ -42,7 +45,8 @@
     Path getPath(ItemId id) throws ItemNotFoundException, RepositoryException;
 
     /**
-     * @param id
+     * Returns the name of the specified item.
+     * @param id id of item whose name should be returned
      * @return
      * @throws ItemNotFoundException
      * @throws RepositoryException
@@ -79,46 +83,4 @@
      */
     boolean isAncestor(NodeId nodeId, ItemId itemId)
             throws ItemNotFoundException, RepositoryException;
-
-    /**
-     * @param id
-     * @return
-     * @throws ItemNotFoundException
-     * @throws RepositoryException
-     */
-    Path[] getAllPaths(ItemId id) throws ItemNotFoundException, RepositoryException;
-
-    /**
-     * @param id
-     * @param includeZombies
-     * @return
-     * @throws ItemNotFoundException
-     * @throws RepositoryException
-     */
-    Path[] getAllPaths(ItemId id, boolean includeZombies)
-            throws ItemNotFoundException, RepositoryException;
-
-    /**
-     * @param id
-     * @return
-     * @throws ItemNotFoundException
-     * @throws RepositoryException
-     */
-    NodeId[] listParents(ItemId id) throws ItemNotFoundException, RepositoryException;
-
-    /**
-     * @param id
-     * @return
-     * @throws ItemNotFoundException
-     * @throws RepositoryException
-     */
-    ItemId[] listChildren(NodeId id) throws ItemNotFoundException, RepositoryException;
-
-    /**
-     * @param id
-     * @return
-     * @throws ItemNotFoundException
-     * @throws RepositoryException
-     */
-    ItemId[] listZombieChildren(NodeId id) throws ItemNotFoundException, RepositoryException;
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java?rev=191499&r1=191498&r2=191499&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java Mon Jun 20 08:58:57 2005
@@ -27,11 +27,6 @@
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
 
 /**
  * <code>HierarchyManagerImpl</code> ...
@@ -40,28 +35,27 @@
 
     private static Logger log = Logger.getLogger(HierarchyManagerImpl.class);
 
-    private final NodeId rootNodeId;
-    private final ItemStateManager provider;
-    private final ItemStateManager attic;
+    protected final NodeId rootNodeId;
+    protected final ItemStateManager provider;
     // used for outputting user-friendly paths and names
-    private final NamespaceResolver nsResolver;
+    protected final NamespaceResolver nsResolver;
 
     public HierarchyManagerImpl(String rootNodeUUID,
                                 ItemStateManager provider,
                                 NamespaceResolver nsResolver) {
-        this(rootNodeUUID, provider, nsResolver, null);
-    }
-
-    public HierarchyManagerImpl(String rootNodeUUID,
-                                ItemStateManager provider,
-                                NamespaceResolver nsResolver,
-                                ItemStateManager attic) {
-        this.rootNodeId = new NodeId(rootNodeUUID);
+        rootNodeId = new NodeId(rootNodeUUID);
         this.provider = provider;
-        this.attic = attic;
         this.nsResolver = nsResolver;
     }
 
+    public NodeId getRootNodeId() {
+        return rootNodeId;
+    }
+
+    public NamespaceResolver getNamespaceResolver() {
+        return nsResolver;
+    }
+
     //-------------------------------------------------< misc. helper methods >
     /**
      * Failsafe conversion of internal <code>Path</code> to JCR path for use in
@@ -97,129 +91,33 @@
         }
     }
 
-    //-----------------------------------------------------< HierarchyManager >
-    /**
-     * {@inheritDoc}
-     */
-    public NodeId[] listParents(ItemId id)
-            throws ItemNotFoundException, RepositoryException {
-        ArrayList list = new ArrayList();
-        try {
-            if (id.denotesNode()) {
-                NodeState state = (NodeState) getItemState(id);
-                Iterator iter = state.getParentUUIDs().iterator();
-                while (iter.hasNext()) {
-                    list.add(new NodeId((String) iter.next()));
-                }
-            } else {
-                PropertyState state = (PropertyState) getItemState(id);
-                list.add(new NodeId(state.getParentUUID()));
-            }
-        } catch (NoSuchItemStateException e) {
-            String msg = "failed to retrieve state of item " + id;
-            log.debug(msg);
-            throw new ItemNotFoundException(msg, e);
-        } catch (ItemStateException e) {
-            String msg = "failed to retrieve state of item " + id;
-            log.debug(msg);
-            throw new RepositoryException(msg, e);
-        }
-        return (NodeId[]) list.toArray(new NodeId[list.size()]);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ItemId[] listChildren(NodeId id)
-            throws ItemNotFoundException, RepositoryException {
-        NodeState parentState;
-        try {
-            parentState = (NodeState) getItemState(id);
-        } catch (NoSuchItemStateException e) {
-            String msg = "failed to retrieve state of parent node " + id;
-            log.debug(msg);
-            throw new ItemNotFoundException(msg, e);
-        } catch (ItemStateException e) {
-            String msg = "failed to retrieve state of parent node " + id;
-            log.debug(msg);
-            throw new RepositoryException(msg, e);
-        }
-        ArrayList list = new ArrayList();
-        Iterator iter = parentState.getPropertyEntries().iterator();
-        while (iter.hasNext()) {
-            // properties
-            NodeState.PropertyEntry pe = (NodeState.PropertyEntry) iter.next();
-            list.add(new PropertyId(id.getUUID(), pe.getName()));
-        }
-        iter = parentState.getChildNodeEntries().iterator();
-        while (iter.hasNext()) {
-            // child nodes
-            NodeState.ChildNodeEntry cne = (NodeState.ChildNodeEntry) iter.next();
-            list.add(new NodeId(cne.getUUID()));
-        }
-        return (ItemId[]) list.toArray(new ItemId[list.size()]);
-    }
-
+    //---------------------------------------------------------< overridables >
     /**
-     * {@inheritDoc}
+     * @param id
+     * @return
+     * @throws NoSuchItemStateException
+     * @throws ItemStateException
      */
-    public ItemId[] listZombieChildren(NodeId id)
-            throws ItemNotFoundException, RepositoryException {
-        // FIXME messy code
-        NodeState parentState;
-        try {
-            parentState = (NodeState) getItemState(id, true);
-        } catch (NoSuchItemStateException nsise) {
-            String msg = "failed to retrieve state of parent node " + id;
-            log.debug(msg);
-            throw new ItemNotFoundException(msg, nsise);
-        } catch (ItemStateException ise) {
-            String msg = "failed to retrieve state of parent node " + id;
-            log.debug(msg);
-            throw new RepositoryException(msg, ise);
-        }
-
-        ArrayList list = new ArrayList();
-        Iterator iter = parentState.getRemovedPropertyEntries().iterator();
-        while (iter.hasNext()) {
-            // removed properties
-            NodeState.PropertyEntry pe = (NodeState.PropertyEntry) iter.next();
-            list.add(new PropertyId(id.getUUID(), pe.getName()));
-        }
-        iter = parentState.getRemovedChildNodeEntries().iterator();
-        while (iter.hasNext()) {
-            // removed child nodes
-            NodeState.ChildNodeEntry cne = (NodeState.ChildNodeEntry) iter.next();
-            list.add(new NodeId(cne.getUUID()));
-        }
-        return (ItemId[]) list.toArray(new ItemId[list.size()]);
+    protected ItemState getItemState(ItemId id)
+            throws NoSuchItemStateException, ItemStateException {
+        return provider.getItemState(id);
     }
 
     /**
-     * {@inheritDoc}
+     * @param id
+     * @return
      */
-    public synchronized ItemId resolvePath(Path path)
-            throws PathNotFoundException, RepositoryException {
-        // shortcut
-        if (path.denotesRoot()) {
-            return rootNodeId;
-        }
-
-        if (!path.isCanonical()) {
-            String msg = "path is not canonical";
-            log.debug(msg);
-            throw new RepositoryException(msg);
-        }
-
-        return resolvePath(path, rootNodeId, 1);
+    protected boolean hasItemState(ItemId id) {
+        return provider.hasItemState(id);
     }
 
     /**
-     * Resolve a path into an item ID. Recursively invoked method that may be
+     * Resolve a path into an item id. Recursively invoked method that may be
      * overridden by some subclass to either return cached responses or add
      * response to cache.
+     *
      * @param path full path of item to resolve
-     * @param id item id
+     * @param id   item id
      * @param next next path element index to resolve
      */
     protected ItemId resolvePath(Path path, ItemId id, int next)
@@ -239,12 +137,13 @@
     }
 
     /**
-     * Resolve a path into an item ID. Recursively invoked method that may be
+     * Resolve a path into an item id. Recursively invoked method that may be
      * overridden by some subclass to either return cached responses or add
      * response to cache.
-     * @param path full path of item to resolve
+     *
+     * @param path  full path of item to resolve
      * @param state intermediate state
-     * @param next next path element index to resolve
+     * @param next  next path element index to resolve
      */
     protected ItemId resolvePath(Path path, ItemState state, int next)
             throws PathNotFoundException, ItemStateException {
@@ -291,41 +190,15 @@
     }
 
     /**
-     * {@inheritDoc}
-     */
-    public synchronized Path getPath(ItemId id)
-            throws ItemNotFoundException, RepositoryException {
-
-        Path.PathBuilder builder = new Path.PathBuilder();
-
-        try {
-            getPath(builder, getItemState(id));
-            return builder.getPath();
-        } catch (NoSuchItemStateException nsise) {
-            String msg = "failed to build path of " + id;
-            log.debug(msg);
-            throw new ItemNotFoundException(msg, nsise);
-        } catch (ItemStateException ise) {
-            String msg = "failed to build path of " + id;
-            log.debug(msg);
-            throw new RepositoryException(msg, ise);
-        } catch (MalformedPathException mpe) {
-            String msg = "failed to build path of " + id;
-            log.debug(msg);
-            throw new RepositoryException(msg, mpe);
-        }
-    }
-
-    /**
-     * Adds the path element of an item ID to the path currently being built.
+     * Adds the path element of an item id to the path currently being built.
      * Recursively invoked method that may be overridden by some subclass to
      * either return cached responses or add response to cache. On exit,
      * <code>builder</code> contains the path of <code>state</code>.
      *
      * @param builder builder currently being used
-     * @param state item to find path of
+     * @param state   item to find path of
      */
-    protected void getPath(Path.PathBuilder builder, ItemState state)
+    protected void buildPath(Path.PathBuilder builder, ItemState state)
             throws ItemStateException, RepositoryException {
 
         String parentUUID = state.getParentUUID();
@@ -335,30 +208,26 @@
         }
 
         NodeState parent = (NodeState) getItemState(new NodeId(parentUUID));
-        getPath(builder, parent);
+        // recursively build path of parent
+        buildPath(builder, parent);
 
         if (state.isNode()) {
             NodeState nodeState = (NodeState) state;
             String uuid = nodeState.getUUID();
-            List entries = parent.getChildNodeEntries(uuid);
-            if (entries.isEmpty()) {
+            NodeState.ChildNodeEntry entry = parent.getChildNodeEntry(uuid);
+            if (entry == null) {
                 String msg = "failed to build path of " + state.getId() + ": "
                         + parent.getUUID() + " has no child entry for "
                         + uuid;
                 log.debug(msg);
                 throw new ItemNotFoundException(msg);
             }
-            // if the parent has more than one child node entries pointing
-            // to the same child node, always use the first one
-            NodeState.ChildNodeEntry entry =
-                    (NodeState.ChildNodeEntry) entries.get(0);
             // add to path
             if (entry.getIndex() == 1) {
                 builder.addLast(entry.getName());
             } else {
                 builder.addLast(entry.getName(), entry.getIndex());
             }
-
         } else {
             PropertyState propState = (PropertyState) state;
             QName name = propState.getName();
@@ -367,6 +236,56 @@
         }
     }
 
+    //-----------------------------------------------------< HierarchyManager >
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized ItemId resolvePath(Path path)
+            throws PathNotFoundException, RepositoryException {
+        // shortcut
+        if (path.denotesRoot()) {
+            return rootNodeId;
+        }
+
+        if (!path.isCanonical()) {
+            String msg = "path is not canonical";
+            log.debug(msg);
+            throw new RepositoryException(msg);
+        }
+
+        return resolvePath(path, rootNodeId, 1);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized Path getPath(ItemId id)
+            throws ItemNotFoundException, RepositoryException {
+        // shortcut
+        if (id.equals(rootNodeId)) {
+            return Path.ROOT;
+        }
+
+        Path.PathBuilder builder = new Path.PathBuilder();
+
+        try {
+            buildPath(builder, getItemState(id));
+            return builder.getPath();
+        } catch (NoSuchItemStateException nsise) {
+            String msg = "failed to build path of " + id;
+            log.debug(msg);
+            throw new ItemNotFoundException(msg, nsise);
+        } catch (ItemStateException ise) {
+            String msg = "failed to build path of " + id;
+            log.debug(msg);
+            throw new RepositoryException(msg, ise);
+        } catch (MalformedPathException mpe) {
+            String msg = "failed to build path of " + id;
+            log.debug(msg);
+            throw new RepositoryException(msg, mpe);
+        }
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -375,7 +294,7 @@
         if (itemId.denotesNode()) {
             NodeId nodeId = (NodeId) itemId;
             NodeState parentState;
-            if (!provider.hasItemState(nodeId)) {
+            if (!hasItemState(nodeId)) {
                 String msg = "failed to resolve name of " + nodeId;
                 log.debug(msg);
                 throw new ItemNotFoundException(nodeId.toString());
@@ -395,14 +314,13 @@
                 throw new RepositoryException(msg, ise);
             }
 
-            List entries = parentState.getChildNodeEntries(nodeId.getUUID());
-            if (entries.size() == 0) {
+            NodeState.ChildNodeEntry entry =
+                    parentState.getChildNodeEntry(nodeId.getUUID());
+            if (entry == null) {
                 String msg = "failed to resolve name of " + nodeId;
                 log.debug(msg);
                 throw new RepositoryException(msg);
             }
-            NodeState.ChildNodeEntry entry =
-                    (NodeState.ChildNodeEntry) entries.get(0);
             return entry.getName();
         } else {
             PropertyId propId = (PropertyId) itemId;
@@ -416,7 +334,7 @@
     public int getDepth(ItemId id)
             throws ItemNotFoundException, RepositoryException {
         try {
-            ItemState state = getItemState(id, false);
+            ItemState state = getItemState(id);
             String parentUUID = state.getParentUUID();
             if (parentUUID != null) {
                 return getDepth(new NodeId(parentUUID)) + 1;
@@ -439,7 +357,7 @@
     public boolean isAncestor(NodeId nodeId, ItemId itemId)
             throws ItemNotFoundException, RepositoryException {
         try {
-            ItemState state = getItemState(itemId, false);
+            ItemState state = getItemState(itemId);
             String parentUUID = state.getParentUUID();
             if (parentUUID != null) {
                 if (parentUUID.equals(nodeId.getUUID())) {
@@ -456,202 +374,6 @@
         } catch (ItemStateException ise) {
             String msg = "failed to determine degree of relationship of "
                     + nodeId + " and " + itemId;
-            log.debug(msg);
-            throw new RepositoryException(msg, ise);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public synchronized Path[] getAllPaths(ItemId id)
-            throws ItemNotFoundException, RepositoryException {
-        return getAllPaths(id, false);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public synchronized Path[] getAllPaths(ItemId id, boolean includeZombies)
-            throws ItemNotFoundException, RepositoryException {
-        Path.PathBuilder builder = new Path.PathBuilder();
-        ArrayList list = new ArrayList();
-        list.add(builder);
-
-        NodeId nodeId;
-        if (!id.denotesNode()) {
-            try {
-                PropertyState propState =
-                        (PropertyState) getItemState(id, includeZombies);
-                QName name = propState.getName();
-                // add to path
-                builder.addFirst(name);
-                nodeId = new NodeId(propState.getParentUUID());
-            } catch (NoSuchItemStateException nsise) {
-                String msg = "failed to build path of " + id;
-                log.debug(msg);
-                throw new ItemNotFoundException(msg, nsise);
-            } catch (ItemStateException ise) {
-                String msg = "failed to build path of " + id;
-                log.debug(msg);
-                throw new RepositoryException(msg, ise);
-            }
-        } else {
-            nodeId = (NodeId) id;
-        }
-
-        // recursively traverse parent nodes
-        recursiveBuildPaths(nodeId, builder, list, includeZombies);
-
-        Path[] paths = new Path[list.size()];
-        int i = 0;
-        Iterator iter = list.iterator();
-        while (iter.hasNext()) {
-            Path.PathBuilder pb = (Path.PathBuilder) iter.next();
-            try {
-                paths[i++] = pb.getPath();
-            } catch (MalformedPathException mpe) {
-                String msg = "failed to build all paths of " + id;
-                log.debug(msg);
-                throw new RepositoryException(msg, mpe);
-            }
-        }
-        return paths;
-    }
-
-    //------------------------------------------------------< private methods >
-    /**
-     * @param id
-     * @return
-     * @throws NoSuchItemStateException
-     * @throws ItemStateException
-     */
-    private ItemState getItemState(ItemId id)
-            throws NoSuchItemStateException, ItemStateException {
-
-        return provider.getItemState(id);
-    }
-
-    /**
-     * @param id
-     * @param includeZombies
-     * @return
-     * @throws NoSuchItemStateException
-     * @throws ItemStateException
-     */
-    private ItemState getItemState(ItemId id, boolean includeZombies)
-            throws NoSuchItemStateException, ItemStateException {
-        if (includeZombies && attic != null && attic.hasItemState(id)) {
-            // try attic first
-            return attic.getItemState(id);
-        }
-        // fallback: get transient/persistent state
-        return getItemState(id);
-    }
-
-    /**
-     * @param nodeId
-     * @param builder
-     * @param builders
-     * @param includeZombies
-     * @throws ItemNotFoundException
-     * @throws RepositoryException
-     */
-    private void recursiveBuildPaths(NodeId nodeId, Path.PathBuilder builder,
-                                     List builders, boolean includeZombies)
-            throws ItemNotFoundException, RepositoryException {
-        try {
-            NodeState nodeState = (NodeState) getItemState(nodeId, includeZombies);
-
-            String uuid = nodeState.getUUID();
-            /**
-             * the parent uuid list contains an entry for every parent-child
-             * link to the specified node. this list may contain duplicate
-             * entries if the same parent node has more than one child link to
-             * the same target node. because the following code expects unique
-             * entries in the parent uuid list, we put them into a set.
-             */
-            HashSet parentUUIDs = new HashSet(nodeState.getParentUUIDs());
-            if (includeZombies) {
-                parentUUIDs.addAll(nodeState.getRemovedParentUUIDs());
-            }
-            if (parentUUIDs.size() == 0) {
-                // nodeId denotes the root node
-                builder.addRoot();
-                return;
-            }
-
-            // if the specified node has n parents,
-            // we need to create n - 1 path builder clones
-            LinkedList queue = new LinkedList();
-            queue.add(builder);
-            int n = parentUUIDs.size() - 1;
-            while (n-- > 0) {
-                Path.PathBuilder clone = (Path.PathBuilder) builder.clone();
-                queue.addLast(clone);
-                // add to list of path builders
-                builders.add(clone);
-            }
-
-            Iterator iter = parentUUIDs.iterator();
-            while (iter.hasNext()) {
-                String parentUUID = (String) iter.next();
-                NodeState parent =
-                        (NodeState) getItemState(new NodeId(parentUUID), includeZombies);
-                ArrayList entries = new ArrayList(parent.getChildNodeEntries(uuid));
-                if (includeZombies) {
-                    Iterator riter = parent.getRemovedChildNodeEntries().iterator();
-                    while (riter.hasNext()) {
-                        NodeState.ChildNodeEntry entry =
-                                (NodeState.ChildNodeEntry) riter.next();
-                        if (entry.getUUID().equals(uuid)) {
-                            entries.add(entry);
-                        }
-                    }
-                }
-                if (entries.isEmpty()) {
-                    String msg = "failed to build path of " + nodeId
-                            + ": " + parent.getUUID()
-                            + " has no child entry for " + uuid;
-                    log.debug(msg);
-                    throw new ItemNotFoundException(msg);
-                }
-                n = entries.size() - 1;
-                while (n-- > 0) {
-                    // the same parent has multiple child references to
-                    // this node, more path builder clones are needed
-
-                    // since we are consuming the queue of path builders
-                    // starting at the tail, we can safely clone 'builder'
-                    // because it will be consumed as the very last queue entry
-                    Path.PathBuilder clone = (Path.PathBuilder) builder.clone();
-                    queue.add(clone);
-                    // add to list of path builders
-                    builders.add(clone);
-                }
-                for (int i = 0; i < entries.size(); i++) {
-                    NodeState.ChildNodeEntry entry =
-                            (NodeState.ChildNodeEntry) entries.get(i);
-
-                    // get a path builder clone from the tail of the queue
-                    Path.PathBuilder pb = (Path.PathBuilder) queue.removeLast();
-                    // add entry to path
-                    if (entry.getIndex() == 1) {
-                        pb.addFirst(entry.getName());
-                    } else {
-                        pb.addFirst(entry.getName(), entry.getIndex());
-                    }
-
-                    // recurse
-                    recursiveBuildPaths(new NodeId(parentUUID), pb, builders, includeZombies);
-                }
-            }
-        } catch (NoSuchItemStateException nsise) {
-            String msg = "failed to build path of " + nodeId;
-            log.debug(msg);
-            throw new ItemNotFoundException(msg, nsise);
-        } catch (ItemStateException ise) {
-            String msg = "failed to build path of " + nodeId;
             log.debug(msg);
             throw new RepositoryException(msg, ise);
         }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java?rev=191499&r1=191498&r2=191499&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java Mon Jun 20 08:58:57 2005
@@ -16,10 +16,10 @@
  */
 package org.apache.jackrabbit.core;
 
-import org.apache.commons.collections.ReferenceMap;
+import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.commons.collections.iterators.IteratorChain;
-import org.apache.jackrabbit.core.nodetype.NodeDef;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
+import org.apache.jackrabbit.core.nodetype.NodeDef;
 import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.nodetype.PropDef;
 import org.apache.jackrabbit.core.nodetype.PropertyDefinitionImpl;
@@ -39,6 +39,7 @@
 import javax.jcr.AccessDeniedException;
 import javax.jcr.InvalidItemStateException;
 import javax.jcr.Item;
+import javax.jcr.ItemExistsException;
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.ItemVisitor;
 import javax.jcr.Node;
@@ -47,13 +48,12 @@
 import javax.jcr.ReferentialIntegrityException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.jcr.ItemExistsException;
 import javax.jcr.lock.LockException;
 import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
 import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.PropertyDefinition;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
 import javax.jcr.version.VersionException;
 import javax.jcr.version.VersionHistory;
 import java.util.ArrayList;
@@ -153,7 +153,7 @@
 
         // check status of this item for read operation
         if (status == STATUS_DESTROYED || status == STATUS_INVALIDATED) {
-                throw new InvalidItemStateException(id + ": the item does not exist anymore");
+            throw new InvalidItemStateException(id + ": the item does not exist anymore");
         }
     }
 
@@ -327,21 +327,24 @@
 
                 case ItemState.STATUS_NEW:
                     {
-                        String msg = safeGetJCRPath() + ": cannot save a new item.";
+                        String msg = safeGetJCRPath()
+                                + ": cannot save a new item.";
                         log.debug(msg);
                         throw new RepositoryException(msg);
                     }
 
                 case ItemState.STATUS_STALE_MODIFIED:
                     {
-                        String msg = safeGetJCRPath() + ": the item cannot be saved because it has been modified externally.";
+                        String msg = safeGetJCRPath()
+                                + ": the item cannot be saved because it has been modified externally.";
                         log.debug(msg);
                         throw new InvalidItemStateException(msg);
                     }
 
                 case ItemState.STATUS_STALE_DESTROYED:
                     {
-                        String msg = safeGetJCRPath() + ": the item cannot be saved because it has been deleted externally.";
+                        String msg = safeGetJCRPath()
+                                + ": the item cannot be saved because it has been deleted externally.";
                         log.debug(msg);
                         throw new InvalidItemStateException(msg);
                     }
@@ -368,7 +371,7 @@
                     case ItemState.STATUS_STALE_MODIFIED:
                         {
                             String msg = transientState.getId()
-                                + ": the item cannot be saved because it has been modified externally.";
+                                    + ": the item cannot be saved because it has been modified externally.";
                             log.debug(msg);
                             throw new InvalidItemStateException(msg);
                         }
@@ -376,7 +379,7 @@
                     case ItemState.STATUS_STALE_DESTROYED:
                         {
                             String msg = transientState.getId()
-                                + ": the item cannot be saved because it has been deleted externally.";
+                                    + ": the item cannot be saved because it has been deleted externally.";
                             log.debug(msg);
                             throw new InvalidItemStateException(msg);
                         }
@@ -411,13 +414,14 @@
                 transientState = (ItemState) iter.next();
                 // check if stale
                 if (transientState.getStatus() == ItemState.STATUS_STALE_MODIFIED) {
-                    String msg = transientState.getId() + ": the item cannot be removed because it has been modified externally.";
+                    String msg = transientState.getId()
+                            + ": the item cannot be removed because it has been modified externally.";
                     log.debug(msg);
                     throw new InvalidItemStateException(msg);
                 }
                 if (transientState.getStatus() == ItemState.STATUS_STALE_DESTROYED) {
                     String msg = transientState.getId()
-                        + ": the item cannot be removed because it has already been deleted externally.";
+                            + ": the item cannot be removed because it has already been deleted externally.";
                     log.debug(msg);
                     throw new InvalidItemStateException(msg);
                 }
@@ -630,6 +634,7 @@
 
     /**
      * Get or create a node references object for a given target id.
+     *
      * @param id target id
      * @return node references object
      * @throws ItemStateException if an error occurs
@@ -1158,181 +1163,186 @@
 
         // synchronize on this session
         synchronized (session) {
-            try {
-                /**
-                 * turn on temporary path caching for better performance
-                 * (assuming that the paths won't change during this save() call)
-                 */
-                stateMgr.enablePathCaching(true);
-
-                /**
-                 * build list of transient (i.e. new & modified) states that
-                 * should be persisted
-                 */
-                Collection dirty = getTransientStates();
-                if (dirty.size() == 0) {
-                    // no transient items, nothing to do here
-                    return;
-                }
-
-                /**
-                 * build list of transient descendents in the attic
-                 * (i.e. those marked as 'removed')
-                 */
-                Collection removed = getRemovedStates();
+            /**
+             * build list of transient (i.e. new & modified) states that
+             * should be persisted
+             */
+            Collection dirty = getTransientStates();
+            if (dirty.size() == 0) {
+                // no transient items, nothing to do here
+                return;
+            }
 
-                /**
-                 * build set of item id's who are within the scope of
-                 * (i.e. affected by) this save operation
-                 */
-                Set affectedIds = new HashSet(dirty.size() + removed.size());
-                for (Iterator it =
-                        new IteratorChain(dirty.iterator(), removed.iterator());
-                     it.hasNext();) {
-                    affectedIds.add(((ItemState) it.next()).getId());
-                }
+            /**
+             * build list of transient descendents in the attic
+             * (i.e. those marked as 'removed')
+             */
+            Collection removed = getRemovedStates();
 
-                /**
-                 * make sure that this save operation is totally 'self-contained'
-                 * and independant; items within the scope of this save operation
-                 * must not have 'external' dependencies;
-                 * (e.g. adding/removing a parent/child link requires that both
-                 * parent and child are saved)
-                 */
-                for (Iterator it =
-                        new IteratorChain(dirty.iterator(), removed.iterator());
-                     it.hasNext();) {
-                    ItemState transientState = (ItemState) it.next();
-                    if (transientState.isNode()) {
-                        NodeState nodeState = (NodeState) transientState;
-                        Set dependentUUIDs = new HashSet();
-                        // removed parents
-                        dependentUUIDs.addAll(nodeState.getRemovedParentUUIDs());
-                        // added parents
-                        dependentUUIDs.addAll(nodeState.getAddedParentUUIDs());
-                        // removed child node entries
-                        for (Iterator cneIt =
-                                nodeState.getRemovedChildNodeEntries().iterator();
-                             cneIt.hasNext();) {
-                            NodeState.ChildNodeEntry cne =
-                                    (NodeState.ChildNodeEntry) cneIt.next();
-                            dependentUUIDs.add(cne.getUUID());
-                        }
-                        // added child node entries
-                        for (Iterator cneIt =
-                                nodeState.getAddedChildNodeEntries().iterator();
-                             cneIt.hasNext();) {
-                            NodeState.ChildNodeEntry cne =
-                                    (NodeState.ChildNodeEntry) cneIt.next();
-                            dependentUUIDs.add(cne.getUUID());
-                        }
+            /**
+             * build set of item id's who are within the scope of
+             * (i.e. affected by) this save operation
+             */
+            Set affectedIds = new HashSet(dirty.size() + removed.size());
+            for (Iterator it =
+                    new IteratorChain(dirty.iterator(), removed.iterator());
+                 it.hasNext();) {
+                affectedIds.add(((ItemState) it.next()).getId());
+            }
 
-                        // now walk through dependencies and check whether they
-                        // are within the scope of this save operation
-                        Iterator depIt = dependentUUIDs.iterator();
-                        while (depIt.hasNext()) {
-                            NodeId id = new NodeId((String) depIt.next());
-                            if (!affectedIds.contains(id)) {
-                                // need to save the parent as well
-                                String msg = itemMgr.safeGetJCRPath(id)
-                                        + " needs to be saved as well.";
-                                log.debug(msg);
-                                throw new ConstraintViolationException(msg);
+            /**
+             * make sure that this save operation is totally 'self-contained'
+             * and independant; items within the scope of this save operation
+             * must not have 'external' dependencies;
+             * (e.g. moving a node requires that the target node including both
+             * old and new parents are saved)
+             */
+            for (Iterator it =
+                    new IteratorChain(dirty.iterator(), removed.iterator());
+                 it.hasNext();) {
+                ItemState transientState = (ItemState) it.next();
+                if (transientState.isNode()) {
+                    NodeState nodeState = (NodeState) transientState;
+                    Set dependentUUIDs = new HashSet();
+                    if (nodeState.hasOverlayedState()) {
+                        String oldParentUUID =
+                                nodeState.getOverlayedState().getParentUUID();
+                        String newParentUUID = nodeState.getParentUUID();
+                        if (oldParentUUID != null) {
+                            if (newParentUUID == null) {
+                                // node has been removed, add old parent
+                                // to dependencies
+                                dependentUUIDs.add(oldParentUUID);
+                            } else {
+                                if (oldParentUUID != null &&
+                                        !oldParentUUID.equals(newParentUUID)) {
+                                    // node has been moved, add old and new parent
+                                    // to dependencies
+                                    dependentUUIDs.add(oldParentUUID);
+                                    dependentUUIDs.add(newParentUUID);
+                                }
                             }
                         }
                     }
-                }
-
-                /**
-                 * validate access and node type constraints
-                 * (this will also validate child removals)
-                 */
-                validateTransientItems(dirty.iterator(), removed.iterator());
-
-                /**
-                 * referential integrity checks:
-                 * make sure that a referenced node cannot be removed and
-                 * that all references are updated and persisted
-                 */
-                Collection dirtyRefs =
-                        checkReferences(dirty.iterator(), removed.iterator());
-
+                    // removed child node entries
+                    for (Iterator cneIt =
+                            nodeState.getRemovedChildNodeEntries().iterator();
+                         cneIt.hasNext();) {
+                        NodeState.ChildNodeEntry cne =
+                                (NodeState.ChildNodeEntry) cneIt.next();
+                        dependentUUIDs.add(cne.getUUID());
+                    }
+                    // added child node entries
+                    for (Iterator cneIt =
+                            nodeState.getAddedChildNodeEntries().iterator();
+                         cneIt.hasNext();) {
+                        NodeState.ChildNodeEntry cne =
+                                (NodeState.ChildNodeEntry) cneIt.next();
+                        dependentUUIDs.add(cne.getUUID());
+                    }
 
-                // start the update operation
-                try {
-                    stateMgr.edit();
-                } catch (IllegalStateException e) {
-                    String msg = "Unable to start edit operation";
-                    log.debug(msg);
-                    throw new RepositoryException(msg, e);
+                    // now walk through dependencies and check whether they
+                    // are within the scope of this save operation
+                    Iterator depIt = dependentUUIDs.iterator();
+                    while (depIt.hasNext()) {
+                        NodeId id = new NodeId((String) depIt.next());
+                        if (!affectedIds.contains(id)) {
+                            // need to save the parent as well
+                            String msg = itemMgr.safeGetJCRPath(id)
+                                    + " needs to be saved as well.";
+                            log.debug(msg);
+                            throw new ConstraintViolationException(msg);
+                        }
+                    }
                 }
+            }
 
-                boolean succeeded = false;
+            /**
+             * validate access and node type constraints
+             * (this will also validate child removals)
+             */
+            validateTransientItems(dirty.iterator(), removed.iterator());
 
-                try {
+            /**
+             * referential integrity checks:
+             * make sure that a referenced node cannot be removed and
+             * that all references are updated and persisted
+             */
+            Collection dirtyRefs =
+                    checkReferences(dirty.iterator(), removed.iterator());
 
-                    // process transient items marked as 'removed'
-                    removeTransientItems(removed.iterator());
 
-                    // initialize version histories for new nodes (might generate new transient state)
-                    if (initVersionHistories(dirty.iterator())) {
-                        // re-build the list of transient states because the previous call
-                        // generated new transient state
-                        dirty = getTransientStates();
+            // start the update operation
+            try {
+                stateMgr.edit();
+            } catch (IllegalStateException e) {
+                String msg = "Unable to start edit operation";
+                log.debug(msg);
+                throw new RepositoryException(msg, e);
+            }
 
-                        // and the references as well
-                        dirtyRefs = checkReferences(dirty.iterator(), removed.iterator());
-                    }
+            boolean succeeded = false;
 
-                    // process 'new' or 'modified' transient states
-                    persistTransientItems(dirty.iterator());
+            try {
 
-                    // dispose the transient states marked 'new' or 'modified'
-                    // at this point item state data is pushed down one level,
-                    // node instances are disconnected from the transient
-                    // item state and connected to the 'overlayed' item state.
-                    // transient item states must be removed now. otherwise
-                    // the session item state provider will return an orphaned
-                    // item state which is not referenced by any node instance.
-                    for (Iterator it = dirty.iterator(); it.hasNext();) {
-                        ItemState transientState = (ItemState) it.next();
-                        // dispose the transient state, it is no longer used
-                        stateMgr.disposeTransientItemState(transientState);
-                    }
+                // process transient items marked as 'removed'
+                removeTransientItems(removed.iterator());
 
-                    // store the references calculated above
-                    for (Iterator it = dirtyRefs.iterator(); it.hasNext();) {
-                        stateMgr.store((NodeReferences) it.next());
-                    }
+                // initialize version histories for new nodes (might generate new transient state)
+                if (initVersionHistories(dirty.iterator())) {
+                    // re-build the list of transient states because the previous call
+                    // generated new transient state
+                    dirty = getTransientStates();
 
-                    // end update operation
-                    stateMgr.update();
-                    // update operation succeeded
-                    succeeded = true;
-                } catch (ItemStateException e) {
-                    String msg = safeGetJCRPath() + ": unable to update item.";
-                    log.debug(msg);
-                    throw new RepositoryException(msg, e);
-                } finally {
-                    if (!succeeded) {
-                        // update operation failed, cancel all modifications
-                        stateMgr.cancel();
-                    }
+                    // and the references as well
+                    dirtyRefs = checkReferences(dirty.iterator(), removed.iterator());
                 }
 
-                // now it is safe to dispose the transient states:
-                // dispose the transient states marked 'removed'.
-                // item states in attic are removed after store, because
-                // the observation mechanism needs to build paths of removed
-                // items in store().
-                for (Iterator it = removed.iterator(); it.hasNext();) {
+                // process 'new' or 'modified' transient states
+                persistTransientItems(dirty.iterator());
+
+                // dispose the transient states marked 'new' or 'modified'
+                // at this point item state data is pushed down one level,
+                // node instances are disconnected from the transient
+                // item state and connected to the 'overlayed' item state.
+                // transient item states must be removed now. otherwise
+                // the session item state provider will return an orphaned
+                // item state which is not referenced by any node instance.
+                for (Iterator it = dirty.iterator(); it.hasNext();) {
                     ItemState transientState = (ItemState) it.next();
                     // dispose the transient state, it is no longer used
-                    stateMgr.disposeTransientItemStateInAttic(transientState);
+                    stateMgr.disposeTransientItemState(transientState);
+                }
+
+                // store the references calculated above
+                for (Iterator it = dirtyRefs.iterator(); it.hasNext();) {
+                    stateMgr.store((NodeReferences) it.next());
                 }
+
+                // end update operation
+                stateMgr.update();
+                // update operation succeeded
+                succeeded = true;
+            } catch (ItemStateException e) {
+                String msg = safeGetJCRPath() + ": unable to update item.";
+                log.debug(msg);
+                throw new RepositoryException(msg, e);
             } finally {
-                // turn off temporary path caching
-                stateMgr.enablePathCaching(false);
+                if (!succeeded) {
+                    // update operation failed, cancel all modifications
+                    stateMgr.cancel();
+                }
+            }
+
+            // now it is safe to dispose the transient states:
+            // dispose the transient states marked 'removed'.
+            // item states in attic are removed after store, because
+            // the observation mechanism needs to build paths of removed
+            // items in store().
+            for (Iterator it = removed.iterator(); it.hasNext();) {
+                ItemState transientState = (ItemState) it.next();
+                // dispose the transient state, it is no longer used
+                stateMgr.disposeTransientItemStateInAttic(transientState);
             }
         }
     }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java?rev=191499&r1=191498&r2=191499&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java Mon Jun 20 08:58:57 2005
@@ -16,7 +16,7 @@
  */
 package org.apache.jackrabbit.core;
 
-import org.apache.commons.collections.ReferenceMap;
+import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.core.nodetype.NodeDefId;
 import org.apache.jackrabbit.core.nodetype.NodeDefinitionImpl;
 import org.apache.jackrabbit.core.nodetype.PropDefId;
@@ -186,7 +186,8 @@
             NodeId parentId = new NodeId(state.getParentUUID());
             NodeImpl parent = (NodeImpl) getItem(parentId);
             NodeState parentState = (NodeState) parent.getItemState();
-            NodeState.ChildNodeEntry cne = (NodeState.ChildNodeEntry) parentState.getChildNodeEntries(state.getUUID()).get(0);
+            NodeState.ChildNodeEntry cne =
+                    (NodeState.ChildNodeEntry) parentState.getChildNodeEntry(state.getUUID());
             def = parent.getApplicableChildNodeDefinition(cne.getName(), state.getNodeTypeName());
             state.setDefinitionId(def.unwrap().getId());
         }



Mime
View raw message