You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2007/02/13 10:31:53 UTC

svn commit: r506927 [1/8] - in /jackrabbit/trunk/contrib/spi: jcr2spi/ jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/ jcr2spi...

Author: angela
Date: Tue Feb 13 01:31:36 2007
New Revision: 506927

URL: http://svn.apache.org/viewvc?view=rev&rev=506927
Log:
Refactoring

- separate hierarchy from ItemStates
- remove ItemStateManager
- move all hierarchy related classes to a separate package ('hierarchy')
- allow loading of deep Item without loading ancestors
- consequently item definition is only built upon usage, since parent is needed.
- minor fixes with adding/removing mixin-nodetypes

Consequences for SPI interfaces:

- SPI impl must be able to deal with both proper itemID and path, since jcr2spi
  might not be aware of a uniqueID defined with a parent node.

- ItemInfo.getPath added, in order to be able to built the missing hierarchy
  entries if a deep Item identified by uniqueID (plus ev. path) is loaded

- LockInfo.getNodeId added, in order to be able to determine the lock-holding node.



Added:
    jackrabbit/trunk/contrib/spi/jcr2spi/TODO.txt   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntries.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/EntryFactory.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/EntryValidation.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEntry.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEntryImpl.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEventListener.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyManager.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyManagerImpl.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntry.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/PathResolver.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/PropertyEntry.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/PropertyEntryImpl.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/UniqueIdResolver.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/AbstractItemStateFactory.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/EmptyNodeReferences.java   (with props)
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/StateUtility.java   (with props)
Removed:
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/HierarchyManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/HierarchyManagerImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChildNodeEntries.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/entry/
Modified:
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManagerImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/LazyItemIterator.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ManagerProvider.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/PropertyImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractCopy.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractOperation.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddLabel.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddProperty.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Checkin.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Checkout.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Clone.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/LockOperation.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/LockRefresh.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/LockRelease.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Merge.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Move.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Operation.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Remove.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/RemoveLabel.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/RemoveVersion.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/ReorderNodes.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/ResolveMergeConflict.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Restore.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetMixin.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetPropertyValue.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Update.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/query/NodeIteratorImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/query/QueryImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/query/QueryManagerImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/query/QueryResultImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateFactory.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeReferences.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateFactory.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/UpdatableItemStateManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/LogUtil.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/DefaultVersionManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/SessionImporter.java
    jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/ItemInfo.java
    jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/LockInfo.java
    jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/LockInfoImpl.java
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NodeInfoImpl.java
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java

Added: jackrabbit/trunk/contrib/spi/jcr2spi/TODO.txt
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/TODO.txt?view=auto&rev=506927
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/TODO.txt (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/TODO.txt Tue Feb 13 01:31:36 2007
@@ -0,0 +1,21 @@
+- IMPROVE: Replace ItemState-duality by copy on write behaviour
+
+- BUG: NodeEntryImpl needs an attic for transiently moved and removed
+       child entries in order not to access those from the persistent
+       storage again.
+       In addition: having an attic allows to properly handle events
+       notifying external modifications for those moved/removed
+       NodeEntries, that are not identified by a uniqueID
+       
+- BUG: Node.hasProperty currently returns false, if prop-entry has
+       not been loaded yet -> should use same mechanism as Node.getProperty.
+       
+- IMPROVE: Refreshing and reloading states, that are transiently modified.
+
+- IMPROVE: review if ItemStateExceptions are really needed. currently
+           they are created from RepositoryExceptions and rethrown as
+           RepositoryExceptions
+           
+- IMPROVE: consistency of PathNotFoundException and ItemNotFoundException.
+
+

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/TODO.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/TODO.txt
------------------------------------------------------------------------------
    svn:keywords = author date id revision

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java?view=diff&rev=506927&r1=506926&r2=506927
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java Tue Feb 13 01:31:36 2007
@@ -23,10 +23,12 @@
 import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
 import org.apache.jackrabbit.jcr2spi.state.ItemStateLifeCycleListener;
 import org.apache.jackrabbit.jcr2spi.state.Status;
+import org.apache.jackrabbit.jcr2spi.state.NodeState;
 import org.apache.jackrabbit.jcr2spi.operation.Remove;
 import org.apache.jackrabbit.jcr2spi.operation.Operation;
 import org.apache.jackrabbit.jcr2spi.util.LogUtil;
 import org.apache.jackrabbit.jcr2spi.config.CacheBehaviour;
+import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
 import org.apache.jackrabbit.name.NoPrefixDeclaredException;
 import org.apache.jackrabbit.name.Path;
 import org.apache.jackrabbit.name.QName;
@@ -134,20 +136,32 @@
     }
 
     /**
-     * @see javax.jcr.Item#getParent()
+     * @see Item#getParent()
      */
-    public abstract Node getParent() throws ItemNotFoundException, AccessDeniedException, RepositoryException;
+    public Node getParent() throws ItemNotFoundException, AccessDeniedException, RepositoryException {
+        checkStatus();
+
+        // special treatment for root node
+        if (state.isNode() && ((NodeState)state).isRoot()) {
+            String msg = "Root node doesn't have a parent.";
+            log.debug(msg);
+            throw new ItemNotFoundException(msg);
+        }
+
+        NodeEntry parentEntry = getItemState().getHierarchyEntry().getParent();
+        return (Node) itemMgr.getItem(parentEntry);
+    }
 
     /**
      * @see javax.jcr.Item#getDepth()
      */
     public int getDepth() throws RepositoryException {
         checkStatus();
-        if (state.getParent() == null) {
+        if (state.isNode() && ((NodeState)state).isRoot()) {
             // shortcut
             return Path.ROOT_DEPTH;
         }
-        return session.getHierarchyManager().getDepth(state);
+        return session.getHierarchyManager().getDepth(state.getHierarchyEntry());
     }
 
     /**
@@ -245,7 +259,7 @@
         // check session status
         session.checkIsAlive();
         // check if item has been removed by this or another session
-        if (Status.isTerminal(state.getStatus())) {
+        if (Status.isTerminal(state.getStatus()) || Status.EXISTING_REMOVED == state.getStatus()) {
             throw new InvalidItemStateException("Item '" + this + "' doesn't exist anymore");
         }
 
@@ -258,7 +272,7 @@
                 // from the 'server'.
                 // Note, that with Observation-CacheBehaviour no manuel refresh
                 // is required. changes get pushed automatically.
-                state.reload(true);
+                state.getHierarchyEntry().reload(true, true);
             }
         } else {
             // check status of item state
@@ -282,7 +296,7 @@
                within this tree 'invalidated' in order to have them refreshed
                from the server upon the next access.*/
             if (session.getCacheBehaviour() != CacheBehaviour.OBSERVATION) {
-                state.invalidate(true);
+                state.getHierarchyEntry().invalidate(true);
             }
         }
     }
@@ -425,7 +439,7 @@
         // check status of this item for read operation
         if (state.getStatus() == Status.INVALIDATED) {
             // refresh to get current status from persistent storage
-            state.reload(false);
+            state.getHierarchyEntry().reload(false, false);
         }
         // now check if valid
         if (!state.isValid()) {
@@ -487,6 +501,22 @@
     protected void checkIsWritable() throws UnsupportedRepositoryOperationException, ConstraintViolationException, RepositoryException {
         checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
         checkStatus();
+    }
+
+    /**
+     * Returns true if the repository supports level 2 (writing). Note, that
+     * this method does not perform any additional validation tests such as
+     * access restrictions, locking, checkin status or protection that affect
+     * the writing to nodes and properties.
+     *
+     * @throws UnsupportedRepositoryOperationException
+     * @throws RepositoryException if the sanity check on this item fails.
+     * See {@link ItemImpl#checkStatus()}. 
+     * @see ItemStateValidator
+     */
+    protected boolean isWritable() throws RepositoryException {
+        checkStatus();
+        return session.isSupportedOption(Repository.LEVEL_2_SUPPORTED);
     }
 
     //------------------------------------< Implementation specific methods >---

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManager.java?view=diff&rev=506927&r1=506926&r2=506927
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManager.java Tue Feb 13 01:31:36 2007
@@ -17,8 +17,8 @@
 package org.apache.jackrabbit.jcr2spi;
 
 import org.apache.jackrabbit.name.Path;
-import org.apache.jackrabbit.jcr2spi.state.ItemState;
-import org.apache.jackrabbit.jcr2spi.state.NodeState;
+import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry;
+import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
 
 import javax.jcr.PathNotFoundException;
 import javax.jcr.AccessDeniedException;
@@ -66,13 +66,12 @@
     public boolean itemExists(Path path);
 
     /**
-     * Checks if the item with the given id exists.
+     * Checks if the item for given HierarchyEntry exists.
      *
-     * @param itemState state of the item to be checked
+     * @param hierarchyEntry
      * @return true if the specified item exists
      */
-    public boolean itemExists(ItemState itemState);
-
+    public boolean itemExists(HierarchyEntry hierarchyEntry);
 
     /**
      *
@@ -87,56 +86,56 @@
 
     /**
      *
-     * @param itemState
+     * @param hierarchyEntry
      * @return
      * @throws ItemNotFoundException
      * @throws AccessDeniedException
      * @throws RepositoryException
      */
-    public Item getItem(ItemState itemState)
+    public Item getItem(HierarchyEntry hierarchyEntry)
         throws ItemNotFoundException, AccessDeniedException, RepositoryException;
 
     /**
      *
-     * @param parentState
+     * @param parentEntry
      * @return
      * @throws ItemNotFoundException
      * @throws AccessDeniedException
      * @throws RepositoryException
      */
-    public boolean hasChildNodes(NodeState parentState)
+    public boolean hasChildNodes(NodeEntry parentEntry)
         throws ItemNotFoundException, AccessDeniedException, RepositoryException;
 
     /**
      *
-     * @param parentState
+     * @param parentEntry
      * @return
      * @throws ItemNotFoundException
      * @throws AccessDeniedException
      * @throws RepositoryException
      */
-    public NodeIterator getChildNodes(NodeState parentState)
+    public NodeIterator getChildNodes(NodeEntry parentEntry)
         throws ItemNotFoundException, AccessDeniedException, RepositoryException;
 
     /**
      *
-     * @param parentState
+     * @param parentEntry
      * @return
      * @throws ItemNotFoundException
      * @throws AccessDeniedException
      * @throws RepositoryException
      */
-    public boolean hasChildProperties(NodeState parentState)
+    public boolean hasChildProperties(NodeEntry parentEntry)
             throws ItemNotFoundException, AccessDeniedException, RepositoryException;
 
     /**
      *
-     * @param parentState
+     * @param parentEntry
      * @return
      * @throws ItemNotFoundException
      * @throws AccessDeniedException
      * @throws RepositoryException
      */
-    public PropertyIterator getChildProperties(NodeState parentState)
+    public PropertyIterator getChildProperties(NodeEntry parentEntry)
             throws ItemNotFoundException, AccessDeniedException, RepositoryException;
 }

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManagerImpl.java?view=diff&rev=506927&r1=506926&r2=506927
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManagerImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManagerImpl.java Tue Feb 13 01:31:36 2007
@@ -16,20 +16,21 @@
  */
 package org.apache.jackrabbit.jcr2spi;
 
+import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
+import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry;
+import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
+import org.apache.jackrabbit.jcr2spi.hierarchy.PropertyEntry;
 import org.apache.jackrabbit.jcr2spi.state.ItemState;
 import org.apache.jackrabbit.jcr2spi.state.NodeState;
 import org.apache.jackrabbit.jcr2spi.state.PropertyState;
-import org.apache.jackrabbit.jcr2spi.state.entry.ChildNodeEntry;
-import org.apache.jackrabbit.jcr2spi.state.entry.ChildPropertyEntry;
 import org.apache.jackrabbit.jcr2spi.state.ItemStateException;
+import org.apache.jackrabbit.jcr2spi.state.NoSuchItemStateException;
 import org.apache.jackrabbit.jcr2spi.util.Dumpable;
 import org.apache.jackrabbit.jcr2spi.util.LogUtil;
 import org.apache.jackrabbit.jcr2spi.version.VersionHistoryImpl;
 import org.apache.jackrabbit.jcr2spi.version.VersionImpl;
 import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.name.Path;
-import org.apache.jackrabbit.spi.QNodeDefinition;
-import org.apache.jackrabbit.spi.QPropertyDefinition;
 import org.apache.commons.collections.map.ReferenceMap;
 import org.slf4j.LoggerFactory;
 import org.slf4j.Logger;
@@ -41,14 +42,9 @@
 import javax.jcr.PropertyIterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.Item;
-import javax.jcr.nodetype.NodeDefinition;
-import javax.jcr.nodetype.PropertyDefinition;
 import java.io.PrintStream;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.Collection;
-import java.util.ArrayList;
-import java.util.List;
 
 /**
  * <code>ItemManagerImpl</code> implements the <code>ItemManager</code> interface.
@@ -96,10 +92,7 @@
      */
     public boolean itemExists(Path path) {
         try {
-            // check sanity of session
-            session.checkIsAlive();
-            // permissions are checked upon itemExists(ItemState)
-
+            // session-sanity & permissions are checked upon itemExists(ItemState)
             ItemState itemState = hierMgr.getItemState(path);
             return itemExists(itemState);
         } catch (PathNotFoundException pnfe) {
@@ -112,17 +105,33 @@
     }
 
     /**
-     * @see ItemManager#itemExists(ItemState)
+     * @see ItemManager#itemExists(HierarchyEntry)
+     */
+    public boolean itemExists(HierarchyEntry hierarchyEntry) {
+        try {
+            // session-sanity & permissions are checked upon itemExists(ItemState)
+            ItemState state = hierarchyEntry.getItemState();
+            return itemExists(state);
+        } catch (NoSuchItemStateException e) {
+            return false;
+        } catch (ItemStateException e) {
+            return false;
+        }
+    }
+
+    /**
+     *
+     * @param itemState
+     * @return
      */
-    public boolean itemExists(ItemState itemState) {
+    private boolean itemExists(ItemState itemState) {
         itemState.checkIsSessionState();
         try {
             // check sanity of session
             session.checkIsAlive();
-
-            // always return true if access rights are granted, existence
-            // of the state has been asserted before
-            return true;
+            // return true, if ItemState is valid. Access rights are granted,
+            // otherwise the state would not have been retrieved.
+            return itemState.isValid();
         } catch (ItemNotFoundException infe) {
             return false;
         } catch (RepositoryException re) {
@@ -135,19 +144,42 @@
      */
     public synchronized Item getItem(Path path)
             throws PathNotFoundException, AccessDeniedException, RepositoryException {
-        ItemState itemState = hierMgr.getItemState(path);
+        HierarchyEntry itemEntry = hierMgr.getHierarchyEntry(path);
         try {
-            return getItem(itemState);
+            return getItem(itemEntry);
         } catch (ItemNotFoundException infe) {
             throw new PathNotFoundException(LogUtil.safeGetJCRPath(path, session.getNamespaceResolver()));
         }
     }
 
     /**
-     * @see ItemManager#getItem(ItemState)
+     * @see ItemManager#getItem(HierarchyEntry)
      */
-    public Item getItem(ItemState itemState) throws ItemNotFoundException, AccessDeniedException, RepositoryException {
+    public Item getItem(HierarchyEntry hierarchyEntry) throws ItemNotFoundException, AccessDeniedException, RepositoryException {
+        try {
+            ItemState itemState = hierarchyEntry.getItemState();
+            return getItem(itemState);
+        } catch (NoSuchItemStateException e) {
+            throw new ItemNotFoundException(e);
+        } catch (ItemStateException e) {
+            throw new RepositoryException(e);
+        }
+    }
+
+    /**
+     *
+     * @param itemState
+     * @return
+     * @throws ItemNotFoundException
+     * @throws AccessDeniedException
+     * @throws RepositoryException
+     */
+    private Item getItem(ItemState itemState) throws ItemNotFoundException, AccessDeniedException, RepositoryException {
+        session.checkIsAlive();
         itemState.checkIsSessionState();
+        if (!itemState.isValid()) {
+            throw new ItemNotFoundException();
+        }
 
         // first try to access item from cache
         Item item = retrieveItem(itemState);
@@ -164,22 +196,20 @@
     }
 
     /**
-     * @see ItemManager#hasChildNodes(NodeState)
+     * @see ItemManager#hasChildNodes(NodeEntry)
      */
-    public synchronized boolean hasChildNodes(NodeState parentState)
+    public synchronized boolean hasChildNodes(NodeEntry parentEntry)
             throws ItemNotFoundException, AccessDeniedException, RepositoryException {
         // check sanity of session
         session.checkIsAlive();
-        parentState.checkIsSessionState();
 
-        Iterator iter = parentState.getChildNodeEntries().iterator();
+        Iterator iter = parentEntry.getNodeEntries();
         while (iter.hasNext()) {
             try {
-                // check read access
-                ChildNodeEntry entry = (ChildNodeEntry) iter.next();
-                if (session.getAccessManager().canRead(entry.getNodeState())) {
-                    return true;
-                }
+                // check read access by accessing the nodeState (implicit validation check)
+                NodeEntry entry = (NodeEntry) iter.next();
+                entry.getNodeState();
+                return true;
             } catch (ItemStateException e) {
                 // should not occur. ignore
                 log.debug("Failed to access node state.", e);
@@ -189,44 +219,32 @@
     }
 
     /**
-     * @see ItemManager#getChildNodes(NodeState)
+     * @see ItemManager#getChildNodes(NodeEntry)
      */
-    public synchronized NodeIterator getChildNodes(NodeState parentState)
+    public synchronized NodeIterator getChildNodes(NodeEntry parentEntry)
             throws ItemNotFoundException, AccessDeniedException, RepositoryException {
         // check sanity of session
         session.checkIsAlive();
-        parentState.checkIsSessionState();
 
-        Collection nodeEntries = parentState.getChildNodeEntries();
-        List childStates = new ArrayList(nodeEntries.size());
-        for (Iterator it = nodeEntries.iterator(); it.hasNext();) {
-            try {
-                childStates.add(((ChildNodeEntry) it.next()).getNodeState());
-            } catch (ItemStateException e) {
-                // should not occur
-                throw new RepositoryException(e);
-            }
-        }
-        return new LazyItemIterator(this, childStates);
+        Iterator it = parentEntry.getNodeEntries();
+        return new LazyItemIterator(this, it);
     }
 
     /**
-     * @see ItemManager#hasChildProperties(NodeState)
+     * @see ItemManager#hasChildProperties(NodeEntry)
      */
-    public synchronized boolean hasChildProperties(NodeState parentState)
+    public synchronized boolean hasChildProperties(NodeEntry parentEntry)
             throws ItemNotFoundException, AccessDeniedException, RepositoryException {
         // check sanity of session
         session.checkIsAlive();
-        parentState.checkIsSessionState();
 
-        Iterator iter = parentState.getPropertyEntries().iterator();
+        Iterator iter = parentEntry.getPropertyEntries();
         while (iter.hasNext()) {
             try {
-                ChildPropertyEntry entry = (ChildPropertyEntry) iter.next();
-                // check read access
-                if (session.getAccessManager().canRead(entry.getPropertyState())) {
-                    return true;
-                }
+                PropertyEntry entry = (PropertyEntry) iter.next();
+                // check read access by accessing the propState (also implicit validation).
+                entry.getPropertyState();
+                return true;
             } catch (ItemStateException e) {
                 // should not occur. ignore
                 log.debug("Failed to access node state.", e);
@@ -236,25 +254,15 @@
     }
 
     /**
-     * @see ItemManager#getChildProperties(NodeState)
+     * @see ItemManager#getChildProperties(NodeEntry)
      */
-    public synchronized PropertyIterator getChildProperties(NodeState parentState)
+    public synchronized PropertyIterator getChildProperties(NodeEntry parentEntry)
             throws ItemNotFoundException, AccessDeniedException, RepositoryException {
         // check sanity of session
         session.checkIsAlive();
-        parentState.checkIsSessionState();
 
-        Collection propEntries = parentState.getPropertyEntries();
-        List childStates = new ArrayList(propEntries.size());
-        for (Iterator it = propEntries.iterator(); it.hasNext();) {
-            try {
-                childStates.add(((ChildPropertyEntry)it.next()).getPropertyState());
-            } catch (ItemStateException e) {
-                // should not occur
-                throw new RepositoryException(e);
-            }
-        }
-        return new LazyItemIterator(this, childStates);
+        Iterator propEntries = parentEntry.getPropertyEntries();
+        return new LazyItemIterator(this, propEntries);
     }
 
     //----------------------------------------------< ItemLifeCycleListener >---
@@ -341,11 +349,6 @@
      * @throws RepositoryException
      */
     private NodeImpl createNodeInstance(NodeState state) throws RepositoryException {
-        // 1. get definition of the specified node
-        QNodeDefinition qnd = state.getDefinition();
-        NodeDefinition def = session.getNodeTypeManager().getNodeDefinition(qnd);
-
-        // 2. create instance
         // we want to be informed on life cycle changes of the new node object
         // in order to maintain item cache consistency
         ItemLifeCycleListener[] listeners = new ItemLifeCycleListener[]{this};
@@ -354,13 +357,13 @@
         QName ntName = state.getNodeTypeName();
         if (QName.NT_VERSION.equals(ntName)) {
             // version
-            return new VersionImpl(this, session, state, def, listeners);
+            return new VersionImpl(this, session, state, listeners);
         } else if (QName.NT_VERSIONHISTORY.equals(ntName)) {
             // version-history
-            return new VersionHistoryImpl(this, session, state, def, listeners);
+            return new VersionHistoryImpl(this, session, state, listeners);
         } else {
             // create common node object
-            return new NodeImpl(this, session, state, def, listeners);
+            return new NodeImpl(this, session, state, listeners);
         }
     }
 
@@ -369,16 +372,11 @@
      * @return a new <code>Property</code> instance.
      */
     private PropertyImpl createPropertyInstance(PropertyState state) {
-        // 1. get definition for the specified property
-        QPropertyDefinition qpd = state.getDefinition();
-        PropertyDefinition def = session.getNodeTypeManager().getPropertyDefinition(qpd);
-
-        // 2. create instance
-                // we want to be informed on life cycle changes of the new property object
+        // we want to be informed on life cycle changes of the new property object
         // in order to maintain item cache consistency
         ItemLifeCycleListener[] listeners = new ItemLifeCycleListener[]{this};
         // create property object
-        PropertyImpl prop = new PropertyImpl(this, session, state, def, listeners);
+        PropertyImpl prop = new PropertyImpl(this, session, state, listeners);
         return prop;
     }
 

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/LazyItemIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/LazyItemIterator.java?view=diff&rev=506927&r1=506926&r2=506927
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/LazyItemIterator.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/LazyItemIterator.java Tue Feb 13 01:31:36 2007
@@ -16,25 +16,27 @@
  */
 package org.apache.jackrabbit.jcr2spi;
 
-import org.apache.jackrabbit.jcr2spi.state.ItemState;
-import org.slf4j.LoggerFactory;
 import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry;
+import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
+import org.apache.jackrabbit.spi.ItemId;
 
-import javax.jcr.Item;
-import javax.jcr.Node;
 import javax.jcr.NodeIterator;
-import javax.jcr.Property;
 import javax.jcr.PropertyIterator;
-import javax.jcr.RepositoryException;
+import javax.jcr.Item;
 import javax.jcr.ItemNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.Property;
 import javax.jcr.RangeIterator;
+import javax.jcr.PathNotFoundException;
 import javax.jcr.version.VersionIterator;
 import javax.jcr.version.Version;
-import java.util.List;
 import java.util.NoSuchElementException;
-import java.util.Collection;
-import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
 
 /**
  * <code>LazyItemIterator</code> is an id-based iterator that instantiates
@@ -56,8 +58,8 @@
     /** the item manager that is used to lazily fetch the items */
     private final ItemManager itemMgr;
 
-    /** the list of item states */
-    private final List stateList;
+    /** Iterator over HierarchyEntry elements */
+    private final Iterator iter;
 
     /** the position of the next item */
     private int pos;
@@ -69,14 +71,37 @@
      * Creates a new <code>LazyItemIterator</code> instance.
      *
      * @param itemMgr item manager
-     * @param itemStates Collection of item states
+     * @param hierarchyEntryIterator Iterator over HierarchyEntries
      */
-    public LazyItemIterator(ItemManager itemMgr, Collection itemStates) {
+    public LazyItemIterator(ItemManager itemMgr, Iterator hierarchyEntryIterator) {
+        this.itemMgr = itemMgr;
+        this.iter = hierarchyEntryIterator;
+        // prefetch first item
+        pos = 0;
+        next = prefetchNext();
+    }
+
+    /**
+     * Creates a new <code>LazyItemIterator</code> instance.
+     *
+     * @param itemMgr
+     * @param hierarchyMgr
+     * @param itemIds
+     */
+    public LazyItemIterator(ItemManager itemMgr, HierarchyManager hierarchyMgr,
+                            Iterator itemIds)
+        throws PathNotFoundException, RepositoryException {
         this.itemMgr = itemMgr;
-        this.stateList = new ArrayList(itemStates);
+        List entries = new ArrayList();
+        while (itemIds.hasNext()) {
+            ItemId id = (ItemId) itemIds.next();
+            entries.add(hierarchyMgr.getHierarchyEntry(id));
+        }
+        this.iter = entries.iterator();
+
         // prefetch first item
         pos = 0;
-        prefetchNext();
+        next = prefetchNext();
     }
 
     /**
@@ -85,25 +110,21 @@
      * {@link #next} is set to the next available item in this iterator or to
      * <code>null</code> in case there are no more items.
      */
-    private void prefetchNext() {
-        // reset
-        next = null;
-        while (next == null && pos < stateList.size()) {
-            ItemState state = (ItemState) stateList.get(pos);
+    private Item prefetchNext() {
+        Item nextItem = null;
+        while (nextItem == null && iter.hasNext()) {
+            HierarchyEntry entry = (HierarchyEntry) iter.next();
             try {
-                next = itemMgr.getItem(state);
+                nextItem = itemMgr.getItem(entry);
             } catch (ItemNotFoundException e) {
-                log.debug("ignoring nonexistent item " + state);
-                // remove invalid id
-                stateList.remove(pos);
-                // try next
+                log.debug("Ignoring nonexistent item " + entry);
+                // try the next
             } catch (RepositoryException e) {
-                log.error("failed to fetch item " + state + ", skipping...", e);
-                // remove invalid id
-                stateList.remove(pos);
-                // try next
+                log.error("failed to fetch item " + entry + ", skipping...", e);
+                // try the next
             }
         }
+        return nextItem;
     }
 
     //-------------------------------------------------------< NodeIterator >---
@@ -149,10 +170,10 @@
      * @see RangeIterator#getSize()
      */
     public long getSize() {
-        // Always returns -1, since the original list may contains items that
+        // Always returns -1, since the entry-iterator may contains items that
         // are not accessible due to access constraints. -1 seems preferable
         // to returning a size that is not correct.
-        return UNDEFINED_SIZE;
+        return LazyItemIterator.UNDEFINED_SIZE;
     }
 
     /**
@@ -170,33 +191,19 @@
             throw new NoSuchElementException();
         }
 
-        // reset
-        next = null;
         // skip the first (skipNum - 1) items without actually retrieving them
         while (--skipNum > 0) {
             pos++;
-            if (pos >= stateList.size()) {
-                // skipped past last item
-                throw new NoSuchElementException();
-            }
-            ItemState state = (ItemState) stateList.get(pos);
-            // eliminate invalid items from this iterator
-            while (!itemMgr.itemExists(state)) {
-                log.debug("ignoring nonexistent item " + state);
-                // remove invalid id
-                stateList.remove(pos);
-                if (pos >= stateList.size()) {
-                    // skipped past last item
-                    throw new NoSuchElementException();
-                }
-                state = (ItemState) stateList.get(pos);
-                // try next
-                continue;
+            HierarchyEntry entry = (HierarchyEntry) iter.next();
+            // check if item exists but don't build Item instance.
+            while (!itemMgr.itemExists(entry)) {
+                log.debug("Ignoring nonexistent item " + entry);
+                entry = (HierarchyEntry) iter.next();
             }
         }
         // prefetch final item (the one to be returned on next())
         pos++;
-        prefetchNext();
+        next = prefetchNext();
     }
 
     //-----------------------------------------------------------< Iterator >---
@@ -218,7 +225,7 @@
         }
         Item item = next;
         pos++;
-        prefetchNext();
+        next = prefetchNext();
         return item;
     }
 

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ManagerProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ManagerProvider.java?view=diff&rev=506927&r1=506926&r2=506927
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ManagerProvider.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ManagerProvider.java Tue Feb 13 01:31:36 2007
@@ -17,10 +17,10 @@
 package org.apache.jackrabbit.jcr2spi;
 
 import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
 import org.apache.jackrabbit.jcr2spi.security.AccessManager;
 import org.apache.jackrabbit.jcr2spi.lock.LockManager;
 import org.apache.jackrabbit.jcr2spi.version.VersionManager;
-import org.apache.jackrabbit.jcr2spi.state.ItemStateManager;
 
 /**
  * <code>ManagerProvider</code>...
@@ -30,8 +30,6 @@
     public NamespaceResolver getNamespaceResolver();
 
     public HierarchyManager getHierarchyManager();
-
-    public ItemStateManager getItemStateManager();
 
     public AccessManager getAccessManager();
 

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java?view=diff&rev=506927&r1=506926&r2=506927
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java Tue Feb 13 01:31:36 2007
@@ -30,11 +30,10 @@
 import org.apache.jackrabbit.jcr2spi.state.NodeState;
 import org.apache.jackrabbit.jcr2spi.state.ItemStateException;
 import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
-import org.apache.jackrabbit.jcr2spi.state.entry.ChildNodeEntry;
-import org.apache.jackrabbit.jcr2spi.state.PropertyState;
 import org.apache.jackrabbit.jcr2spi.state.NoSuchItemStateException;
-import org.apache.jackrabbit.jcr2spi.state.ItemState;
-import org.apache.jackrabbit.jcr2spi.state.ItemStateManager;
+import org.apache.jackrabbit.jcr2spi.state.NodeReferences;
+import org.apache.jackrabbit.jcr2spi.state.Status;
+import org.apache.jackrabbit.jcr2spi.state.PropertyState;
 import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeManagerImpl;
 import org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeType;
 import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeConflictException;
@@ -48,10 +47,13 @@
 import org.apache.jackrabbit.jcr2spi.lock.LockManager;
 import org.apache.jackrabbit.jcr2spi.version.VersionImpl;
 import org.apache.jackrabbit.jcr2spi.util.LogUtil;
+import org.apache.jackrabbit.jcr2spi.util.StateUtility;
+import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
+import org.apache.jackrabbit.jcr2spi.hierarchy.PropertyEntry;
+import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry;
 import org.apache.jackrabbit.spi.QPropertyDefinition;
 import org.apache.jackrabbit.spi.QNodeDefinition;
 import org.apache.jackrabbit.spi.IdIterator;
-import org.apache.jackrabbit.spi.ItemId;
 import org.apache.jackrabbit.spi.QValue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -71,7 +73,6 @@
 import javax.jcr.PropertyType;
 import javax.jcr.NodeIterator;
 import javax.jcr.PropertyIterator;
-import javax.jcr.Repository;
 import javax.jcr.InvalidItemStateException;
 import javax.jcr.NoSuchWorkspaceException;
 import javax.jcr.nodetype.ConstraintViolationException;
@@ -90,7 +91,6 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Arrays;
-import java.util.Collection;
 
 /**
  * <code>NodeImpl</code>...
@@ -100,13 +100,10 @@
     private static Logger log = LoggerFactory.getLogger(NodeImpl.class);
 
     private QName primaryTypeName;
-    private NodeDefinition definition;
 
     protected NodeImpl(ItemManager itemMgr, SessionImpl session,
-                       NodeState state, NodeDefinition definition,
-                       ItemLifeCycleListener[] listeners) {
+                       NodeState state, ItemLifeCycleListener[] listeners) {
         super(itemMgr, session, state, listeners);
-        this.definition = definition;
         QName nodeTypeName = state.getNodeTypeName();
         // make sure the nodetype name is valid
         if (session.getNodeTypeManager().hasNodeType(nodeTypeName)) {
@@ -137,23 +134,6 @@
     }
 
     /**
-     * @see Item#getParent()
-     */
-    public Node getParent() throws ItemNotFoundException, AccessDeniedException, RepositoryException {
-        checkStatus();
-
-        NodeState parentState = getItemState().getParent();
-        // special treatment for root node
-        if (parentState == null) {
-            String msg = "Root node doesn't have a parent.";
-            log.debug(msg);
-            throw new ItemNotFoundException(msg);
-        }
-
-        return (Node) itemMgr.getItem(parentState);
-    }
-
-    /**
      * Implementation of {@link Item#accept(javax.jcr.ItemVisitor)} for nodes.
      *
      * @param visitor
@@ -288,9 +268,8 @@
             prop.setValue(v);
         } else {
             if (value == null) {
-                // create and remove property is a nop.
-                // TODO: check if is correct to avoid any validation exception
-                prop = null;
+                // create and remove property is not valid // TODO: correct?
+                throw new ItemNotFoundException("Cannot remove a non-existing property.");
             } else {
                 // new property to be added
                 prop = createProperty(propQName, value, type);
@@ -328,8 +307,7 @@
         } else {
             if (values == null) {
                 // create and remove property is a nop.
-                // TODO: check if is correct to avoid any validation exception
-                prop = null;
+                throw new ItemNotFoundException("Cannot remove a non-existing property.");
             } else {
                 // new property to be added
                 prop = createProperty(propName, values, type);
@@ -442,11 +420,15 @@
      */
     public Node getNode(String relPath) throws PathNotFoundException, RepositoryException {
         checkStatus();
-        NodeState state = resolveRelativeNodePath(relPath);
-        if (state == null) {
+        NodeEntry nodeEntry = resolveRelativeNodePath(relPath);
+        if (nodeEntry == null) {
             throw new PathNotFoundException(relPath);
         }
-        return (Node) itemMgr.getItem(state);
+        try {
+            return (Node) itemMgr.getItem(nodeEntry);
+        } catch (ItemNotFoundException e) {
+            throw new PathNotFoundException(relPath, e);
+        }
     }
 
     /**
@@ -457,7 +439,7 @@
         // NOTE: Don't use a class derived from TraversingElementVisitor to traverse
         // the child nodes because this would lead to an infinite recursion.
         try {
-            return itemMgr.getChildNodes(getNodeState());
+            return itemMgr.getChildNodes(getNodeEntry());
         } catch (ItemNotFoundException infe) {
             String msg = "Failed to list the child nodes of " + safeGetJCRPath();
             log.debug(msg);
@@ -485,11 +467,17 @@
      */
     public Property getProperty(String relPath) throws PathNotFoundException, RepositoryException {
         checkStatus();
-        PropertyState state = resolveRelativePropertyPath(relPath);
-        if (state == null) {
+        PropertyEntry entry = resolveRelativePropertyPath(relPath);
+        if (entry == null) {
             throw new PathNotFoundException(relPath);
         }
-        return (Property) itemMgr.getItem(state);
+        try {
+            return (Property) itemMgr.getItem(entry);
+        } catch (AccessDeniedException e) {
+            throw new PathNotFoundException(relPath.toString());
+        } catch (ItemNotFoundException e) {
+            throw new PathNotFoundException(relPath.toString());
+        }
     }
 
     /**
@@ -498,7 +486,7 @@
     public PropertyIterator getProperties() throws RepositoryException {
         checkStatus();
         try {
-            return itemMgr.getChildProperties(getNodeState());
+            return itemMgr.getChildProperties(getNodeEntry());
         } catch (ItemNotFoundException infe) {
             String msg = "Failed to list the child properties of " + getPath();
             log.debug(msg);
@@ -557,7 +545,11 @@
      */
     public int getIndex() throws RepositoryException {
         checkStatus();
-        return getNodeState().getIndex();
+        int index = getNodeEntry().getIndex();
+        if (index == Path.INDEX_UNDEFINED) {
+            throw new RepositoryException("Error while retrieving index.");
+        }
+        return index;
     }
 
     /**
@@ -565,6 +557,14 @@
      */
     public PropertyIterator getReferences() throws RepositoryException {
         checkStatus();
+        NodeReferences refs = getNodeState().getNodeReferences();
+        if (refs.isEmpty()) {
+            // there are no references, return empty iterator
+            return IteratorHelper.EMPTY;
+        } else {
+            return new LazyItemIterator(itemMgr, session.getHierarchyManager(), refs.iterator());
+        }
+        /*
         try {
             ItemStateManager itemStateMgr = session.getItemStateManager();
             Collection refStates = itemStateMgr.getReferingStates(getNodeState());
@@ -579,6 +579,7 @@
             log.debug(msg);
             throw new RepositoryException(msg, e);
         }
+        */
     }
 
     /**
@@ -586,8 +587,8 @@
      */
     public boolean hasNode(String relPath) throws RepositoryException {
         checkStatus();
-        NodeState childState = resolveRelativeNodePath(relPath);
-        return (childState != null) ? itemMgr.itemExists(childState) : false;
+        NodeEntry nodeEntry = resolveRelativeNodePath(relPath);
+        return (nodeEntry != null) ? itemMgr.itemExists(nodeEntry) : false;
     }
 
     /**
@@ -595,8 +596,8 @@
      */
     public boolean hasProperty(String relPath) throws RepositoryException {
         checkStatus();
-        PropertyState childState = resolveRelativePropertyPath(relPath);
-        return (childState != null) ? itemMgr.itemExists(childState) : false;
+        PropertyEntry childEntry = resolveRelativePropertyPath(relPath);
+        return (childEntry != null) ? itemMgr.itemExists(childEntry) : false;
     }
 
     /**
@@ -607,7 +608,7 @@
      * @return
      */
     private boolean hasProperty(QName propertyName) {
-        return getNodeState().hasPropertyName(propertyName);
+        return getNodeEntry().hasPropertyEntry(propertyName);
     }
 
     /**
@@ -615,7 +616,7 @@
      */
     public boolean hasNodes() throws RepositoryException {
         checkStatus();
-        return itemMgr.hasChildNodes(getNodeState());
+        return itemMgr.hasChildNodes(getNodeEntry());
     }
 
     /**
@@ -623,7 +624,7 @@
      */
     public boolean hasProperties() throws RepositoryException {
         checkStatus();
-        return itemMgr.hasChildProperties(getNodeState());
+        return itemMgr.hasChildProperties(getNodeEntry());
     }
 
     /**
@@ -651,7 +652,7 @@
      * @see Node#isNodeType(String)
      */
     public boolean isNodeType(String nodeTypeName) throws RepositoryException {
-        checkStatus();        
+        checkStatus();
         // try shortcut first (avoids parsing of name)
         try {
             if (NameFormat.format(primaryTypeName, session.getNamespaceResolver()).equals(nodeTypeName)) {
@@ -672,22 +673,25 @@
         checkIsWritable();
         QName mixinQName = getQName(mixinName);
         try {
-            if (!isValidMixin(mixinQName)) {
+            if (!canAddMixin(mixinQName)) {
                 throw new ConstraintViolationException("Cannot add '" + mixinName + "' mixin type.");
             }
         } catch (NodeTypeConflictException e) {
             throw new ConstraintViolationException(e.getMessage());
         }
 
-        // merge existing mixins and new mixins to one Array without modifying
-        // the node state.
-        QName[] currentMixins = getNodeState().getMixinTypeNames();
-        QName[] allMixins = new QName[currentMixins.length + 1];
-        System.arraycopy(currentMixins, 0, allMixins, 0, currentMixins.length);
-        allMixins[currentMixins.length] = mixinQName;
-        // perform the operation
-        Operation op = SetMixin.create(getNodeState(), allMixins);
-        session.getSessionItemStateManager().execute(op);
+        // get mixin types present in the jcr:mixintypes property without
+        // modifying the NodeState.
+        List mixinValue = getMixinTypes();
+        if (mixinValue.contains(mixinQName)) {
+            log.warn("Mixin " + mixinName + " has already been transiently added -> Ignored.");
+            return;
+        } else {
+            mixinValue.add(mixinQName);
+            // perform the operation
+            Operation op = SetMixin.create(getNodeState(), (QName[]) mixinValue.toArray(new QName[mixinValue.size()]));
+            session.getSessionItemStateManager().execute(op);
+        }
     }
 
     /**
@@ -697,47 +701,76 @@
         VersionException, ConstraintViolationException, LockException, RepositoryException {
         checkIsWritable();
         QName ntName = getQName(mixinName);
-        List remainingMixins = new ArrayList(Arrays.asList(getNodeState().getMixinTypeNames()));
+        List mixinValue = getMixinTypes();
         // remove name of target mixin
-        if (!remainingMixins.remove(ntName)) {
+        if (!mixinValue.remove(ntName)) {
             throw new NoSuchNodeTypeException("Cannot remove mixin '" + mixinName + "': Nodetype is not present on this node.");
         }
 
-        // build effective node type of remaining mixin's & primary type
-        NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
-        EffectiveNodeType entRemaining;
-
-        // build effective node type representing primary type including remaining mixin's
-        QName[] allRemaining = (QName[]) remainingMixins.toArray(new QName[remainingMixins.size() + 1]);
-        allRemaining[remainingMixins.size()] = primaryTypeName;
-        try {
-            entRemaining = session.getValidator().getEffectiveNodeType(allRemaining);
-        } catch (NodeTypeConflictException e) {
-            throw new ConstraintViolationException(e);
-        }
-
         // mix:referenceable needs additional assertion: the mixin cannot be
         // removed, if any references are left to this node.
-        NodeTypeImpl mixin = ntMgr.getNodeType(ntName);
-        if (mixin.isNodeType(QName.MIX_REFERENCEABLE) && !entRemaining.includesNodeType(QName.MIX_REFERENCEABLE)) {
-            PropertyIterator iter = getReferences();
-            if (iter.hasNext()) {
-                throw new ConstraintViolationException("Mixin type " + mixinName + " can not be removed: the node is being referenced through at least one property of type REFERENCE");
+        NodeTypeImpl mixin = session.getNodeTypeManager().getNodeType(ntName);
+        if (mixin.isNodeType(QName.MIX_REFERENCEABLE)) {
+            // build effective node type of remaining mixin's & primary type
+            EffectiveNodeType entRemaining;
+            QName[] allRemaining = (QName[]) mixinValue.toArray(new QName[mixinValue.size() + 1]);
+            allRemaining[mixinValue.size()] = primaryTypeName;
+            try {
+                entRemaining = session.getValidator().getEffectiveNodeType(allRemaining);
+            } catch (NodeTypeConflictException e) {
+                throw new ConstraintViolationException(e);
+            }
+
+            if (!entRemaining.includesNodeType(QName.MIX_REFERENCEABLE)) {
+                PropertyIterator iter = getReferences();
+                if (iter.hasNext()) {
+                    throw new ConstraintViolationException("Mixin type " + mixinName + " can not be removed: the node is being referenced through at least one property of type REFERENCE");
+                }
             }
         }
 
         // delegate to operation
-        QName[] mixins = (QName[]) remainingMixins.toArray(new QName[remainingMixins.size()]);
+        QName[] mixins = (QName[]) mixinValue.toArray(new QName[mixinValue.size()]);
         Operation op = SetMixin.create(getNodeState(), mixins);
         session.getSessionItemStateManager().execute(op);
     }
 
     /**
+     * Retrieves all mixins currently present on this node including those,
+     * that have been transiently added and excluding those, that have been
+     * transiently removed.<br>
+     * NOTE, that the result of this method, does NOT represent the list of
+     * mixin-types that currently affect this node. Instead if represents the
+     * current value of the jcr:mixinTypes property.
+     *
+     * @return
+     */
+    private List getMixinTypes() {
+        QName[] mixinValue = new QName[0];
+        if (getNodeEntry().hasPropertyEntry(QName.JCR_MIXINTYPES)) {
+            if (getNodeState().getStatus() == Status.EXISTING) {
+                mixinValue = getNodeState().getMixinTypeNames();
+            } else {
+                // possibility that a mixin has been transient added
+                try {
+                    PropertyState ps = getNodeState().getPropertyState(QName.JCR_MIXINTYPES);
+                    mixinValue = StateUtility.getMixinNames(ps);
+                } catch (ItemStateException e) {
+                    // should never occur
+                    log.error("Internal error", e);
+                }
+            } // else: no mixins present
+        }
+        List l = new ArrayList();
+        l.addAll(Arrays.asList(mixinValue));
+        return l;
+    }
+
+    /**
      * @see Node#canAddMixin(String)
      */
     public boolean canAddMixin(String mixinName) throws RepositoryException {
-        checkStatus();
-        if (!isSupportedOption(Repository.LEVEL_2_SUPPORTED)) {
+        if (!isWritable()) {
             // shortcut: repository does not support writing anyway.
             return false;
         }
@@ -746,7 +779,7 @@
             // locks, versioning, acces restriction.
             session.getValidator().checkIsWritable(getNodeState(), ItemStateValidator.CHECK_ALL);
             // then make sure the new mixin would not conflict.
-            return isValidMixin(getQName(mixinName));
+            return canAddMixin(getQName(mixinName));
         } catch (NodeTypeConflictException e) {
             log.debug("Cannot add mixin '" + mixinName + "': " + e.getMessage());
             return false;
@@ -767,7 +800,8 @@
      */
     public NodeDefinition getDefinition() throws RepositoryException {
         checkStatus();
-        return definition;
+        QNodeDefinition qnd = getNodeState().getDefinition();
+        return session.getNodeTypeManager().getNodeDefinition(qnd);
     }
 
     /**
@@ -869,8 +903,14 @@
         if (session.getWorkspace().getName().equals(srcWorkspaceName)) {
             return;
         }
-        // make sure the specified workspace is visible for the current session.
-        session.checkAccessibleWorkspace(srcWorkspaceName);
+        // test if the corresponding node exists in the src-workspace which includes
+        // a check if the specified source workspace is accessible
+        try {
+            getCorrespondingNodePath(srcWorkspaceName);
+        } catch (ItemNotFoundException e) {
+            // no corresponding node exists -> method has not effect
+            return;
+        }
 
         Operation op = Update.create((NodeState) getNodeState().getWorkspaceState(), srcWorkspaceName);
         ((WorkspaceImpl)session.getWorkspace()).getUpdatableItemStateManager().execute(op);
@@ -894,27 +934,7 @@
         if (failedIds.getSize() == 0) {
             return IteratorHelper.EMPTY;
         } else {
-            List failedStates = new ArrayList();
-            while (failedIds.hasNext()) {
-                try {
-                    ItemId id = failedIds.nextId();
-                    ItemState state = session.getItemStateManager().getItemState(id);
-                    if (state.isNode()) {
-                        failedStates.add(state);
-                    } else {
-                        // should not occur
-                        throw new RepositoryException("Merge failed with internal error: NodeState expected.");
-                    }
-                } catch (ItemStateException e) {
-                    // should not occur
-                    throw new RepositoryException(e);
-                }
-            }
-            if (failedStates.isEmpty()) {
-                return IteratorHelper.EMPTY;
-            } else {
-                return new LazyItemIterator(itemMgr, failedStates);
-            }
+            return new LazyItemIterator(itemMgr, session.getHierarchyManager(), failedIds);
         }
     }
 
@@ -1199,6 +1219,12 @@
                 return true;
             }
         }
+        // NEW nodes with inherited-mixins -> mixin not yet active
+        if (getNodeState().getStatus() == Status.NEW &&
+            session.getNodeTypeManager().getNodeType(qName).isMixin()) {
+            return false;
+        }
+
         // check effective node type
         return getEffectiveNodeType().includesNodeType(qName);
     }
@@ -1208,7 +1234,7 @@
      * @see ItemImpl#getQName()
      */
     QName getQName() throws RepositoryException {
-        if (getNodeState().getParent() == null) {
+        if (getNodeState().isRoot()) {
             // shortcut. the given state represents the root or an orphaned node
             return QName.ROOT;
         }
@@ -1324,21 +1350,16 @@
         session.getSessionItemStateManager().execute(an);
 
         // retrieve id of state that has been created during execution of AddNode
-        NodeState childState;
-        try {
-            List cne = getNodeState().getChildNodeEntries(nodeName);
-            if (definition.allowsSameNameSiblings()) {
-                // TODO TOBEFIXED find proper solution. problem with SNSs
-                childState = ((ChildNodeEntry)cne.get(cne.size()-1)).getNodeState();
-            } else {
-                childState = ((ChildNodeEntry)cne.get(0)).getNodeState();
-            }
-        } catch (ItemStateException e) {
-            // should not occur
-            throw new RepositoryException(e);
+        NodeEntry entry;
+        List cne = getNodeEntry().getNodeEntries(nodeName);
+        if (definition.allowsSameNameSiblings()) {
+            // TODO TOBEFIXED find proper solution. problem with SNSs
+            entry = ((NodeEntry)cne.get(cne.size()-1));
+        } else {
+            entry = ((NodeEntry)cne.get(0));
         }
         // finally retrieve the new node
-        return (Node) itemMgr.getItem(childState);
+        return (Node) itemMgr.getItem(entry);
     }
 
     /**
@@ -1352,15 +1373,15 @@
     protected Property getProperty(QName qName) throws PathNotFoundException, RepositoryException {
         checkStatus();
         try {
-            PropertyState pState = getNodeState().getPropertyState(qName);
-            return (Property) itemMgr.getItem(pState);
-        } catch (AccessDeniedException ade) {
-            throw new ItemNotFoundException(qName.toString());
-        } catch (NoSuchItemStateException e) {
+            PropertyEntry pEntry = getNodeEntry().getPropertyEntry(qName);
+            if (pEntry == null) {
+                throw new PathNotFoundException(qName.toString());
+            }
+            return (Property) itemMgr.getItem(pEntry);
+        } catch (AccessDeniedException e) {
+            throw new PathNotFoundException(qName.toString());
+        } catch (ItemNotFoundException e) {
             throw new PathNotFoundException(qName.toString());
-        } catch (ItemStateException e) {
-            String msg = "Error while accessing property " + qName.toString();
-            throw new RepositoryException(msg, e);
         }
     }
 
@@ -1467,14 +1488,10 @@
         return qName;
     }
 
-    private boolean isValidMixin(QName mixinName) throws NoSuchNodeTypeException, NodeTypeConflictException {
+    private boolean canAddMixin(QName mixinName) throws NoSuchNodeTypeException,
+        NodeTypeConflictException {
         NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
 
-        // get list of existing nodetypes
-        QName[] existingNts = getNodeState().getNodeTypeNames();
-        // build effective node type representing primary type including existing mixin's
-        EffectiveNodeType entExisting = session.getValidator().getEffectiveNodeType(existingNts);
-
         // first check characteristics of each mixin
         NodeType mixin = ntMgr.getNodeType(mixinName);
         if (!mixin.isMixin()) {
@@ -1486,6 +1503,12 @@
             log.error(mixin.getName() + ": already contained in primary node type");
             return false;
         }
+
+        // get list of existing nodetypes
+        QName[] existingNts = getNodeState().getNodeTypeNames();
+        // build effective node type representing primary type including existing mixin's
+        EffectiveNodeType entExisting = session.getValidator().getEffectiveNodeType(existingNts);
+
         // check if adding new mixin conflicts with existing nodetypes
         if (entExisting.includesNodeType(mixinName)) {
             log.error(mixin.getName() + ": already contained in mixin types");
@@ -1511,6 +1534,13 @@
     }
 
     /**
+     * @return <code>NodeEntry</code> of this <code>Node</code>
+     */
+    private NodeEntry getNodeEntry() {
+        return (NodeEntry) getItemState().getHierarchyEntry();
+    }
+
+    /**
      *
      * @param relativePath
      * @return
@@ -1568,42 +1598,38 @@
     }
 
     /**
-     * Returns the id of the node at <code>relPath</code> or <code>null</code>
-     * if no node exists at <code>relPath</code>.
+     * Returns the <code>NodeEntry</code> at <code>relPath</code> or
+     * <code>null</code> if no node exists at <code>relPath</code>.
      * <p/>
      * Note that access rights are not checked.
      *
      * @param relPath relative path of a (possible) node.
-     * @return the state of the node at <code>relPath</code> or <code>null</code>
-     * if no node exists at <code>relPath</code>.
+     * @return the HierarchyEntry of the node at <code>relPath</code> or
+     * <code>null</code> if no node exists at <code>relPath</code>.
      * @throws RepositoryException if <code>relPath</code> is not a valid
      * relative path.
      */
-    private NodeState resolveRelativeNodePath(String relPath) throws RepositoryException {
-        NodeState targetState = null;
+    private NodeEntry resolveRelativeNodePath(String relPath) throws RepositoryException {
+        NodeEntry targetEntry = null;
         try {
             Path rp = PathFormat.parse(relPath, session.getNamespaceResolver());
             // shortcut
             if (rp.getLength() == 1) {
                 Path.PathElement pe = rp.getNameElement();
                 if (pe == Path.CURRENT_ELEMENT) {
-                    targetState = getNodeState();
+                    targetEntry = getNodeEntry();
                 } else if (pe == Path.PARENT_ELEMENT) {
-                    targetState = getNodeState().getParent();
-                } else if (pe.denotesName()) {
-                    // if relative path is just a 'name' -> retrieve the corresponding
-                    // child-node (if existing).
-                    int index = pe.getNormalizedIndex();
-                    ChildNodeEntry cne = getNodeState().getChildNodeEntry(pe.getName(), index);
-                    if (cne != null) {
-                        targetState = cne.getNodeState();
-                    } // else: there's no child node with that name
+                    targetEntry = getNodeEntry().getParent();
+                } else {
+                    targetEntry = getNodeEntry().getNodeEntry(pe.getName(), pe.getNormalizedIndex());
                 }
-            } else {
+            }
+            if (targetEntry == null) {
+                // rp length > 1 OR child entry has not yet been loaded.
                 Path p = getQPath(rp);
-                ItemState itemState = session.getHierarchyManager().getItemState(p.getCanonicalPath());
-                if (itemState.isNode()) {
-                    targetState = (NodeState) itemState;
+                HierarchyEntry entry = session.getHierarchyManager().getHierarchyEntry(p.getCanonicalPath());
+                if (entry.denotesNode()) {
+                    targetEntry = (NodeEntry) entry;
                 } // else:  not a node
             }
         } catch (PathNotFoundException e) {
@@ -1612,13 +1638,8 @@
             String msg = "Invalid relative path: " + relPath;
             log.debug(msg);
             throw new RepositoryException(msg, e);
-        } catch (ItemStateException e) {
-            // should not occure
-            String msg = "Invalid relative path: " + relPath;
-            log.debug(msg);
-            throw new RepositoryException(msg, e);
         }
-        return targetState;
+        return targetEntry;
     }
 
     /**
@@ -1628,13 +1649,13 @@
      * Note that access rights are not checked.
      *
      * @param relPath relative path of a (possible) property
-     * @return the state of the property at <code>relPath</code> or
+     * @return the PropertyEntry of the property at <code>relPath</code> or
      * <code>null</code> if no property exists at <code>relPath</code>
      * @throws RepositoryException if <code>relPath</code> is not a valid
      * relative path
      */
-    private PropertyState resolveRelativePropertyPath(String relPath) throws RepositoryException {
-        PropertyState targetState = null;
+    private PropertyEntry resolveRelativePropertyPath(String relPath) throws RepositoryException {
+        PropertyEntry targetEntry = null;
         try {
             Path rp = PathFormat.parse(relPath, session.getNamespaceResolver());
             if (rp.getLength() == 1) {
@@ -1643,22 +1664,17 @@
                 if (rp.getNameElement().denotesName()) {
                     QName propName = rp.getNameElement().getName();
                     // check if property entry exists
-                    if (getNodeState().hasPropertyName(propName)) {
-                        try {
-                            targetState = getNodeState().getPropertyState(propName);
-                        } catch (ItemStateException e) {
-                            // should not occur due, since existance has been checked
-                            throw new RepositoryException(e);
-                        } // else: there's no property with that name
-                    }
-                } // else: return null.
-            } else {
+                    targetEntry = getNodeEntry().getPropertyEntry(propName);
+                } // else: entry may not have been loaded yet -> try via H-Mgr
+            }
+
+            if (targetEntry == null) {
                 // build and resolve absolute path
                 Path p = getQPath(rp).getCanonicalPath();
                 try {
-                    ItemState itemState = session.getHierarchyManager().getItemState(p);
-                    if (!itemState.isNode()) {
-                        targetState = (PropertyState) itemState;
+                    HierarchyEntry entry = session.getHierarchyManager().getHierarchyEntry(p);
+                    if (!entry.denotesNode()) {
+                        targetEntry = (PropertyEntry) entry;
                     } // else: not a property
                 } catch (PathNotFoundException e) {
                     // ignore -> return null;
@@ -1669,7 +1685,7 @@
             log.debug(msg);
             throw new RepositoryException(msg, e);
         }
-        return targetState;
+        return targetEntry;
     }
 
     /**

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/PropertyImpl.java?view=diff&rev=506927&r1=506926&r2=506927
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/PropertyImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/PropertyImpl.java Tue Feb 13 01:31:36 2007
@@ -24,6 +24,7 @@
 import org.apache.jackrabbit.name.NameFormat;
 import org.apache.jackrabbit.name.NamespaceResolver;
 import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
 import org.apache.jackrabbit.value.ValueFormat;
 import org.apache.jackrabbit.value.ValueHelper;
 import org.slf4j.LoggerFactory;
@@ -37,8 +38,6 @@
 import javax.jcr.Item;
 import javax.jcr.RepositoryException;
 import javax.jcr.Node;
-import javax.jcr.AccessDeniedException;
-import javax.jcr.ItemNotFoundException;
 import javax.jcr.ItemVisitor;
 import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
@@ -55,13 +54,9 @@
 
     public static final int UNDEFINED_PROPERTY_LENGTH = -1;
 
-    private final PropertyDefinition definition;
-
     public PropertyImpl(ItemManagerImpl itemManager, SessionImpl session,
-                        PropertyState state, PropertyDefinition definition,
-                        ItemLifeCycleListener[] listeners) {
+                        PropertyState state, ItemLifeCycleListener[] listeners) {
         super(itemManager, session, state, listeners);
-        this.definition = definition;
         // value will be read (and converted from qualified value) on demand.
     }
 
@@ -83,14 +78,6 @@
     }
 
     /**
-     * @see Item#getParent()
-     */
-    public Node getParent() throws ItemNotFoundException, AccessDeniedException, RepositoryException {
-        checkStatus();
-        return (Node) itemMgr.getItem(getItemState().getParent());
-    }
-
-    /**
      * Implementation of {@link Item#accept(javax.jcr.ItemVisitor)} for property.
      *
      * @param visitor
@@ -145,7 +132,7 @@
             }
         }
 
-        int targetType = definition.getRequiredType();
+        int targetType = getDefinition().getRequiredType();
         if (targetType == PropertyType.UNDEFINED) {
             targetType = (valueType == PropertyType.UNDEFINED) ?  PropertyType.STRING : valueType;
         }
@@ -389,8 +376,9 @@
      * @see javax.jcr.Property#getDefinition()
      */
     public PropertyDefinition getDefinition() throws RepositoryException {
-	checkStatus();
-        return definition;
+        checkStatus();
+        QPropertyDefinition qpd = getPropertyState().getDefinition();
+        return session.getNodeTypeManager().getPropertyDefinition(qpd);
     }
 
     /**
@@ -424,7 +412,7 @@
         checkIsWritable();
 
         // property specific check
-        if (definition.isMultiple() != multiValues) {
+        if (isMultiple() != multiValues) {
             throw new ValueFormatException(getPath() + "Multivalue definition of " + safeGetJCRPath() + " does not match to given value(s).");
         }
     }
@@ -435,7 +423,7 @@
      * @return true if the definition indicates that this Property is multivalued.
      */
     private boolean isMultiple() {
-	return definition.isMultiple();
+	return getPropertyState().isMultiValued();
     }
 
     /**
@@ -443,9 +431,9 @@
      * @param defaultType
      * @return the required type for this property.
      */
-    private int getRequiredType(int defaultType) {
+    private int getRequiredType(int defaultType) throws RepositoryException {
         // check type according to definition of this property
-        int reqType = definition.getRequiredType();
+        int reqType = getDefinition().getRequiredType();
         if (reqType == PropertyType.UNDEFINED) {
             if (defaultType == PropertyType.UNDEFINED) {
                 reqType = PropertyType.STRING;

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java?view=diff&rev=506927&r1=506926&r2=506927
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java Tue Feb 13 01:31:36 2007
@@ -16,17 +16,18 @@
  */
 package org.apache.jackrabbit.jcr2spi;
 
+import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
+import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
+import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry;
 import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeManagerImpl;
 import org.apache.jackrabbit.jcr2spi.security.SecurityConstants;
 import org.apache.jackrabbit.jcr2spi.security.AccessManager;
 import org.apache.jackrabbit.jcr2spi.state.SessionItemStateManager;
-import org.apache.jackrabbit.jcr2spi.state.ItemStateManager;
 import org.apache.jackrabbit.jcr2spi.state.UpdatableItemStateManager;
 import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
 import org.apache.jackrabbit.jcr2spi.state.ItemState;
-import org.apache.jackrabbit.jcr2spi.state.NoSuchItemStateException;
-import org.apache.jackrabbit.jcr2spi.state.ItemStateException;
 import org.apache.jackrabbit.jcr2spi.state.NodeState;
+import org.apache.jackrabbit.jcr2spi.state.ItemStateFactory;
 import org.apache.jackrabbit.jcr2spi.xml.DocViewSAXEventGenerator;
 import org.apache.jackrabbit.jcr2spi.xml.SysViewSAXEventGenerator;
 import org.apache.jackrabbit.jcr2spi.xml.ImportHandler;
@@ -119,7 +120,6 @@
     private final NodeTypeManagerImpl ntManager;
 
     private final SessionItemStateManager itemStateManager;
-    private final HierarchyManager hierarchyManager;
     private final ItemManager itemManager;
     private final ItemStateValidator validator;
 
@@ -138,12 +138,10 @@
 
         // build nodetype manager
         ntManager = new NodeTypeManagerImpl(workspace.getNodeTypeRegistry(), getNamespaceResolver(), internalGetValueFactory(), getQValueFactory());
-
         validator = new ItemStateValidator(workspace.getNodeTypeRegistry(), this);
 
-        itemStateManager = createSessionItemStateManager(workspace.getUpdatableItemStateManager());
-        hierarchyManager = createHierarchyManager();
-        itemManager = createItemManager();
+        itemStateManager = createSessionItemStateManager(workspace.getUpdatableItemStateManager(), workspace.getItemStateFactory());
+        itemManager = createItemManager(getHierarchyManager());
     }
 
     //--------------------------------------------------< Session interface >---
@@ -222,14 +220,9 @@
      */
     public Node getRootNode() throws RepositoryException {
         checkIsAlive();
-        try {
-            ItemState state = getItemStateManager().getRootState();
-            return (Node) itemManager.getItem(state);
-        } catch (ItemStateException e) {
-            String msg = "Failed to retrieve root node.";
-            log.error(msg, e);
-            throw new RepositoryException(msg, e);
-        }
+
+        NodeEntry re = getHierarchyManager().getRootEntry();
+        return (Node) itemManager.getItem(re);
     }
 
     /**
@@ -269,22 +262,18 @@
         // check sanity of this session
         checkIsAlive();
         try {
-            ItemState state = getItemStateManager().getItemState(id);
-            Item item = getItemManager().getItem(state);
+            HierarchyEntry hierarchyEntry = getHierarchyManager().getHierarchyEntry(id);
+            Item item = getItemManager().getItem(hierarchyEntry);
             if (item.isNode()) {
                 return (Node) item;
             } else {
                 log.error("NodeId '" + id + " does not point to a Node");
                 throw new ItemNotFoundException(id.toString());
             }
-        } catch (AccessDeniedException ade) {
+        } catch (PathNotFoundException e) {
             throw new ItemNotFoundException(id.toString());
-        } catch (NoSuchItemStateException e) {
+        } catch (AccessDeniedException e) {
             throw new ItemNotFoundException(id.toString());
-        } catch (ItemStateException e) {
-            String msg = "Failed to retrieve item state of item " + id;
-            log.error(msg, e);
-            throw new RepositoryException(msg, e);
         }
     }
 
@@ -622,7 +611,7 @@
         try {
             getLockManager().removeLockToken(lt);
         } catch (RepositoryException e) {
-            log.warn("Unable to remove lock token '" +lt+ "' from this session.", e);
+            log.warn("Unable to remove lock token '" +lt+ "' from this session. (" + e.getMessage() + ")");
         }
     }
 
@@ -678,31 +667,32 @@
         return new WorkspaceImpl(sessionInfo.getWorkspaceName(), this, config, sessionInfo);
     }
 
-    protected SessionItemStateManager createSessionItemStateManager(UpdatableItemStateManager workspaceStateManager) throws RepositoryException {
-        return new SessionItemStateManager(workspaceStateManager, getIdFactory(), getValidator(), getQValueFactory());
-    }
-
-    protected HierarchyManager createHierarchyManager() {
-        return new HierarchyManagerImpl(getItemStateManager(), getNamespaceResolver());
+    protected SessionItemStateManager createSessionItemStateManager(UpdatableItemStateManager workspaceStateManager, ItemStateFactory isf) throws RepositoryException {
+        return new SessionItemStateManager(workspaceStateManager, getValidator(), getQValueFactory(), isf);
     }
-
-    protected ItemManager createItemManager() {
-        return new ItemManagerImpl(getHierarchyManager(), this);
+    
+    protected ItemManager createItemManager(HierarchyManager hierarchyManager) {
+        return new ItemManagerImpl(hierarchyManager, this);
     }
 
     //---------------------------------------------------< ManagerProvider > ---
+    /**
+     * @see ManagerProvider#getNamespaceResolver()
+     */
     public NamespaceResolver getNamespaceResolver() {
         return nsMappings;
     }
 
+    /**
+     * @see ManagerProvider#getHierarchyManager()
+     */
     public HierarchyManager getHierarchyManager() {
-        return hierarchyManager;
-    }
-
-    public ItemStateManager getItemStateManager() {
-        return itemStateManager;
+        return workspace.getHierarchyManager();
     }
 
+    /**
+     * @see ManagerProvider#getLockManager()
+     */
     public LockManager getLockManager() {
         return workspace.getLockManager();
     }
@@ -711,6 +701,7 @@
      * Returns the <code>AccessManager</code> associated with this session.
      *
      * @return the <code>AccessManager</code> associated with this session
+     * @see ManagerProvider#getAccessManager()
      */
     public AccessManager getAccessManager() {
         return workspace.getAccessManager();
@@ -720,6 +711,7 @@
      * Returns the <code>VersionManager</code> associated with this session.
      *
      * @return the <code>VersionManager</code> associated with this session
+     * @see ManagerProvider#getVersionManager()
      */
     public VersionManager getVersionManager() {
         return workspace.getVersionManager();