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 2006/11/09 10:09:25 UTC

svn commit: r472818 - /jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/

Author: angela
Date: Thu Nov  9 01:09:24 2006
New Revision: 472818

URL: http://svn.apache.org/viewvc?view=rev&rev=472818
Log:
work in progress.

- nodestates must always be connected to their cne upon creation
  TODO: add some sort of caching to avoid traffic overhead
- add TODO for refresh, that currently doesn't work properly
- ItemState.refresh only takes changelog and returns the ids of the
  processed states. cleanup of events is left to caller.
- move of NodeStates does not work
- PathResolver: force start to be an NodeState
- all MODIFIED status for SessionStates as well in order to make sure
  that listeners are informed about external changes even if the 
  state is EXISTING.

next TODO: make sure, that public getChildNodeEntry/ies and hasChildNodeEntry check for validity of the connected NodeState. don't return entries, where the nodestate is (transiently) removed or stale.

Modified:
    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/ItemState.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/NodeState.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/PropertyState.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/TransientItemStateManager.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/state/WorkspaceItemStateManager.java

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java Thu Nov  9 01:09:24 2006
@@ -188,34 +188,39 @@
      *         present in the cache.
      */
     protected ItemState lookup(ItemId id) {
-        ItemState state;
+        NodeState start;
         // resolve UUID
         if (id.getUUID() != null) {
-            state = cache.getNodeState(id.getUUID());
-            if (state == null) {
+            start = cache.getNodeState(id.getUUID());
+            if (start == null) {
                 // not cached
                 return null;
             }
         } else {
             // start from root
             try {
-                state = getRootState();
+                start = getRootState();
             } catch (ItemStateException e) {
-                log.warn("unable to get root node state:" + e.getMessage());
+                // should never occur
+                log.error("Error while retrieving root node state:" + e.getMessage());
                 return null;
             }
         }
 
-        // resolve relative path
-        if (id.getPath() != null) {
+        if (id.getPath() == null) {
+            // path is null -> id points to a state identified by uuid
+            return start;
+        } else {
+            // resolve path part
             try {
-                state = PathResolver.lookup(state, id.getPath());
+                return PathResolver.lookup(start, id.getPath());
+            } catch (NoSuchItemStateException e) {
+                log.debug("exception while looking up state with id: " + id);
+                return null;
             } catch (ItemStateException e) {
-                log.warn("exception while looking up state with id: " + id);
+                log.debug("exception while looking up state with id: " + id);
                 return null;
             }
         }
-
-        return state;
     }
 }

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChildNodeEntries.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChildNodeEntries.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChildNodeEntries.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChildNodeEntries.java Thu Nov  9 01:09:24 2006
@@ -112,14 +112,15 @@
 
     /**
      * Returns the <code>ChildNodeEntry</code> for the given
-     * <code>nodeState</code>.
+     * <code>nodeState</code>. Note, that this method does not check if the
+     * given childNodeEntry (and its attached NodeState) is still valid.
      *
-     * @param nodeState the node state.
+     * @param childState the child node state for which a entry is searched.
      * @return the <code>ChildNodeEntry</code> or <code>null</code> if there
-     *         is no <code>ChildNodeEntry</code> for <code>nodeState</code>.
+     * is no <code>ChildNodeEntry</code> for the given <code>NodeState</code>.
      */
-    ChildNodeEntry get(NodeState nodeState) {
-        Object o = nameMap.get(nodeState.getQName());
+    ChildNodeEntry get(NodeState childState) {
+        Object o = nameMap.get(childState.getQName());
         if (o == null) {
             // no matching child node entry
             return null;
@@ -131,7 +132,7 @@
                 ChildNodeEntry cne = n.getChildNodeEntry();
                 // only check available child node entries
                 try {
-                    if (cne.isAvailable() && cne.getNodeState() == nodeState) {
+                    if (cne.isAvailable() && cne.getNodeState() == childState) {
                         return cne;
                     }
                 } catch (ItemStateException e) {
@@ -142,7 +143,7 @@
             // single child node with this name
             ChildNodeEntry cne = ((LinkedEntries.LinkNode) o).getChildNodeEntry();
             try {
-                if (cne.isAvailable() && cne.getNodeState() == nodeState) {
+                if (cne.isAvailable() && cne.getNodeState() == childState) {
                     return cne;
                 }
             } catch (ItemStateException e) {
@@ -241,7 +242,7 @@
                     }
                 } else {
                     // then this child node entry has never been accessed
-                    // before and is assumed valid
+                    // before and is assumed valid // TODO: check if correct.
                     index--;
                 }
                 if (index == 0) {
@@ -268,9 +269,9 @@
         if (uuid == null) {
             throw new IllegalArgumentException();
         }
-        List l = get(nodeName);
-        for (Iterator it = l.iterator(); it.hasNext();) {
-            ChildNodeEntry cne = (ChildNodeEntry) it.next();
+        Iterator cneIter = (nodeName != null) ? get(nodeName).iterator() : iterator();
+        while (cneIter.hasNext()) {
+            ChildNodeEntry cne = (ChildNodeEntry) cneIter.next();
             if (uuid.equals(cne.getUUID())) {
                 return cne;
             }
@@ -309,9 +310,9 @@
      * Adds a <code>ChildNodeEntry</code> for a child node with the given
      * name and an optional <code>uuid</code>.
      *
-     * @param nodeName the name of the child node.
-     * @param uuid     the UUID of the child node if it can be identified
-     *                 with a UUID; otherwise <code>null</code>.
+     * @param nodeName The name of the child node.
+     * @param uuid The UUID of the child node if it can be identified with a UUID;
+     * otherwise <code>null</code>.
      * @return the created ChildNodeEntry.
      */
     private ChildNodeEntry add(QName nodeName, String uuid) {
@@ -455,8 +456,7 @@
      * <code>beforeNode</code> does not have a <code>ChildNodeEntry</code>
      * in this <code>ChildNodeEntries</code>.
      */
-    void reorder(NodeState insertNode, NodeState beforeNode)
-        throws NoSuchItemStateException {
+    void reorder(NodeState insertNode, NodeState beforeNode) throws NoSuchItemStateException {
         Object insertObj = nameMap.get(insertNode.getQName());
         // the link node to move
         LinkedEntries.LinkNode insertLN = getLinkNode(insertNode);
@@ -510,19 +510,23 @@
             ChildNodeEntry newCne = ChildNodeReference.create(childState, nodeState.isf, nodeState.idFactory);
             entries.replaceNode(ln, newCne);
         } catch (NoSuchItemStateException e) {
-            log.error("Internal error.", e);
+            // should never occur.
+            log.error("Internal Error: ", e);
         }
     }
 
     /**
      * Returns the matching <code>LinkNode</code> from a list or a single
-     * <code>LinkNode</code>.
+     * <code>LinkNode</code>. Note, that in contrast to {@link #getLinkNode(ChildNodeEntry)}
+     * this method will throw <code>NoSuchItemStateException</code> if none of the
+     * entries matches either due to missing entry for given state name or due
+     * to missing availability of the <code>ChildNodeEntry</code>.
      *
-     * @param nodeState      the <code>NodeState</code> which is the value
-     *                       of on of the <code>LinkNode</code>s.
+     * @param nodeState the <code>NodeState</code> that is compared to the
+     * resolution of any ChildNodeEntry that matches by name.
      * @return the matching <code>LinkNode</code>.
      * @throws NoSuchItemStateException if none of the <code>LinkNode</code>s
-     *                                  matches.
+     * matches.
      */
     private LinkedEntries.LinkNode getLinkNode(NodeState nodeState)
         throws NoSuchItemStateException {
@@ -531,7 +535,7 @@
             // no matching child node entry
             throw new NoSuchItemStateException(nodeState.getQName().toString());
         }
-        
+
         if (listOrLinkNode instanceof List) {
             // has same name sibling
             for (Iterator it = ((List) listOrLinkNode).iterator(); it.hasNext();) {
@@ -560,8 +564,10 @@
         throw new NoSuchItemStateException(nodeState.getQName().toString());
     }
 
-    //---------------------------------------< unmodifiable Collection view >---
-
+    //--------------------------------------------< unmodifiable Collection >---
+    /**
+     * @see Collection#contains(Object)
+     */
     public boolean contains(Object o) {
         if (o instanceof ChildNodeEntry) {
             // narrow down to same name sibling nodes and check list
@@ -571,6 +577,9 @@
         }
     }
 
+    /**
+     * @see Collection#containsAll(Collection)
+     */
     public boolean containsAll(Collection c) {
         Iterator iter = c.iterator();
         while (iter.hasNext()) {
@@ -581,23 +590,38 @@
         return true;
     }
 
+    /**
+     * @see Collection#isEmpty()
+     */
     public boolean isEmpty() {
         return entries.isEmpty();
     }
 
+    /**
+     * @see Collection#iterator()
+     */
     public Iterator iterator() {
         return UnmodifiableIterator.decorate(entries.iterator());
     }
 
+    /**
+     * @see Collection#size()
+     */
     public int size() {
         return entries.size();
     }
 
+    /**
+     * @see Collection#toArray()
+     */
     public Object[] toArray() {
         ChildNodeEntry[] array = new ChildNodeEntry[size()];
         return toArray(array);
     }
 
+    /**
+     * @see Collection#toArray(Object[])
+     */
     public Object[] toArray(Object[] a) {
         if (!a.getClass().getComponentType().isAssignableFrom(ChildNodeEntry.class)) {
             throw new ArrayStoreException();
@@ -616,31 +640,61 @@
         return a;
     }
 
+    /**
+     * Throws <code>UnsupportedOperationException</code>.
+     *
+     * @see Collection#add(Object)
+     */
     public boolean add(Object o) {
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * Throws <code>UnsupportedOperationException</code>.
+     *
+     * @see Collection#addAll(Collection)
+     */
     public boolean addAll(Collection c) {
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * Throws <code>UnsupportedOperationException</code>.
+     *
+     * @see Collection#clear()
+     */
     public void clear() {
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * Throws <code>UnsupportedOperationException</code>.
+     *
+     * @see Collection#remove(Object)
+     */
     public boolean remove(Object o) {
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * Throws <code>UnsupportedOperationException</code>.
+     *
+     * @see Collection#removeAll(Collection)
+     */
     public boolean removeAll(Collection c) {
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * Throws <code>UnsupportedOperationException</code>.
+     *
+     * @see Collection#retainAll(Collection)
+     */
     public boolean retainAll(Collection c) {
         throw new UnsupportedOperationException();
     }
 
-
+    //-------------------------------------------------< AbstractLinkedList >---
     /**
      * An implementation of a linked list which provides access to the internal
      * LinkNode which links the entries of the list.
@@ -698,6 +752,7 @@
          *
          * @param value a child node entry.
          * @return a wrapping {@link LinkedEntries.LinkNode}.
+         * @see AbstractLinkedList#createNode(Object)
          */
         protected Node createNode(Object value) {
             return new LinkNode(value);
@@ -705,6 +760,7 @@
 
         /**
          * @return a new <code>LinkNode</code>.
+         * @see AbstractLinkedList#createHeaderNode()
          */
         protected Node createHeaderNode() {
             return new LinkNode();
@@ -746,7 +802,7 @@
             };
         }
 
-        //-----------------------------------------------------------------------
+        //----------------------------------------------------------------------
 
         /**
          * Extends the <code>AbstractLinkedList.Node</code>.

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java Thu Nov  9 01:09:24 2006
@@ -341,6 +341,7 @@
                         synchronized (this) {
                             reset();
                         }
+                        setStatus(Status.MODIFIED);
                     } else if (status == Status.EXISTING_MODIFIED) {
                         setStatus(Status.STALE_MODIFIED);
                     }
@@ -445,11 +446,12 @@
      * Used on the target state of a save call AFTER the changelog has been
      * successfully submitted to the SPI..
      *
-     * @param events
      * @param changeLog
+     * @return a Set of <code>ItemId</code>s in order to allow the caller to
+     * remove those events that have already been processed.
      * @throws IllegalStateException if this state is a 'session' state.
      */
-    abstract void refresh(Collection events, ChangeLog changeLog) throws IllegalStateException;
+    abstract Set refresh(ChangeLog changeLog) throws IllegalStateException;
 
     /**
      * Copy all state information from overlayed state to this state
@@ -527,21 +529,6 @@
             default:
                 String msg = "Cannot mark item state with status " + status + " modified.";
                 throw new IllegalStateException(msg);
-        }
-    }
-
-    //--------------------------------------------------------------------------
-    /**
-     *
-     * @param events
-     * @param processedState
-     */
-    static void removeEvent(Collection events, ItemState processedState) {
-        for (Iterator it = events.iterator(); it.hasNext();) {
-            if (((Event)it.next()).getItemId().equals(processedState.getId())) {
-                it.remove();
-                break;
-            }
         }
     }
 }

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java Thu Nov  9 01:09:24 2006
@@ -87,10 +87,12 @@
     private void putToCache(ItemState state) {
         if (state.isNode() && (state.getStatus() == Status.EXISTING || state.getStatus() == Status.MODIFIED)) {
             NodeState nodeState = (NodeState) state;
+            // NOTE: uuid is retrieved from the state and not from the NodeId.
             String uuid = nodeState.getUUID();
             if (uuid != null) {
                 uuid2NodeState.put(uuid, nodeState);
             }
         }
+        // TODO: add caching for other items as well
     }
 }

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java Thu Nov  9 01:09:24 2006
@@ -123,7 +123,6 @@
         this.uuid = uuid;
         this.nodeTypeName = nodeTypeName;
         this.definition = definition;
-        assertAvailability();
     }
 
     /**
@@ -151,7 +150,6 @@
                 init(wspState.getMixinTypeNames(), wspState.getChildNodeEntries(), wspState.getPropertyNames(), wspState.getNodeReferences());
             }
         }
-        assertAvailability();
     }
 
     /**
@@ -185,17 +183,6 @@
         this.references = references;
     }
 
-    private void assertAvailability() {
-        // TODO: TOBEFIXED. duality of creating states via ISM or via factory may result in a cached state, that is not connected to its cne.
-        if (uuid != null && parent != null) {
-            // make sure this state is connected to its childNode-entry
-            ChildNodeEntry cne = parent.childNodeEntries.get(name, uuid);
-            if (cne != null && !cne.isAvailable()) {
-                parent.childNodeEntries.replaceEntry(this);
-            }
-        }
-    }
-
     //----------------------------------------------------------< ItemState >---
     /**
      * Determines if this item state represents a node.
@@ -360,17 +347,17 @@
     }
 
     /**
-     * Determines if there are any child node entries.
+     * Determines if there are any valid child node entries.
      *
      * @return <code>true</code> if there are child node entries,
-     *         <code>false</code> otherwise.
+     * <code>false</code> otherwise.
      */
     public boolean hasChildNodeEntries() {
         return containsValidChildNodeEntry(childNodeEntries);
     }
 
     /**
-     * Determines if there is a <code>ChildNodeEntry</code> with the
+     * Determines if there is a valid <code>ChildNodeEntry</code> with the
      * specified <code>name</code>.
      *
      * @param name <code>QName</code> object specifying a node name
@@ -388,7 +375,7 @@
      * @param name  <code>QName</code> object specifying a node name
      * @param index 1-based index if there are same-name child node entries
      * @return <code>true</code> if there is a <code>ChildNodeEntry</code> with
-     *         the specified <code>name</code> and <code>index</code>.
+     * the specified <code>name</code> and <code>index</code>.
      */
     public synchronized boolean hasChildNodeEntry(QName name, int index) {
         return childNodeEntries.get(name, index) != null;
@@ -409,13 +396,34 @@
 
     /**
      * Returns the <code>ChildNodeEntry</code> with the specified
+     * <code>NodeId</code> or <code>null</code> if there's no matching
+     * entry.
+     *
+     * @param nodeId the id of the child node state.
+     * @return the <code>ChildNodeEntry</code> with the specified
+     * <code>NodeId</code> or <code>null</code> if there's no matching entry.
+     */
+    public synchronized ChildNodeEntry getChildNodeEntry(NodeId nodeId) {
+        String uuid = nodeId.getUUID();
+        Path path = nodeId.getPath();
+        if (uuid != null && path == null) {
+            // retrieve child-entry by uuid
+            return childNodeEntries.get(null, uuid);
+        } else {
+           // retrieve child-entry by name and index
+            Path.PathElement nameElement = path.getNameElement();
+            return childNodeEntries.get(nameElement.getName(), nameElement.getIndex());
+        }
+    }
+
+    /**
+     * Returns the <code>ChildNodeEntry</code> with the specified
      * <code>NodeState</code> or <code>null</code> if there's no matching
      * entry.
      *
      * @param nodeState the child node state.
      * @return the <code>ChildNodeEntry</code> with the specified
-     *         <code>NodeState</code> or <code>null</code> if there's no
-     *         matching entry.
+     * <code>NodeState</code> or <code>null</code> if there's no matching entry.
      */
     private synchronized ChildNodeEntry getChildNodeEntry(NodeState nodeState) {
         return childNodeEntries.get(nodeState);
@@ -465,7 +473,7 @@
                 return false;
             }
         } else {
-            // then it must be valid
+            // then it must be valid // TODO check if this assumption is correct.
             return true;
         }
     }
@@ -525,39 +533,26 @@
     /*
      * Returns the property state with the given name.
      *
-     * @param propertyName the name of the property state to return.
-     * @throws NoSuchItemStateException if there is no property state with the
-     *                                  given name.
-     * @throws ItemStateException       if an error occurs while retrieving the
-     *                                  property state.
+     * @param propertyName The name of the property state to return.
+     * @throws NoSuchItemStateException If there is no (valid) property state
+     * with the given name.
+     * @throws ItemStateException If an error occurs while retrieving the
+     * property state.
      */
     public synchronized PropertyState getPropertyState(QName propertyName)
-            throws NoSuchItemStateException, ItemStateException {
-        PropertyState propState = getAnyPropertyState(propertyName);
-        if (propState.isValid()) {
-            return propState;
-        } else {
-            throw new NoSuchItemStateException(idFactory.createPropertyId(getNodeId(), propertyName).toString());
-        }
-    }
+        throws NoSuchItemStateException, ItemStateException {
 
-    /**
-     * Returns the property state with the given name and also takes removed
-     * property states into account.
-     *
-     * @param propertyName the name of the property state to return.
-     * @throws NoSuchItemStateException if there is no property state with the
-     *                                  given name.
-     * @throws ItemStateException       if an error occurs while retrieving the
-     *                                  property state.
-     */
-    public synchronized PropertyState getAnyPropertyState(QName propertyName)
-            throws NoSuchItemStateException, ItemStateException {
         ChildPropertyEntry propEntry = (ChildPropertyEntry) properties.get(propertyName);
         if (propEntry == null) {
             throw new NoSuchItemStateException(idFactory.createPropertyId(getNodeId(), propertyName).toString());
+        } else {
+            PropertyState propState = propEntry.getPropertyState();
+            if (propState.isValid()) {
+                return propState;
+            } else {
+                throw new NoSuchItemStateException(idFactory.createPropertyId(getNodeId(), propertyName).toString());
+            }
         }
-        return propEntry.getPropertyState();
     }
 
     /**
@@ -606,8 +601,8 @@
      * <code>name</code>.
      *
      * @param cne  the <code>ChildNodeEntry</code> instance.
-     * @return the index of the child node entry or <code>0</code> if it is not
-     *         found in this <code>NodeState</code>.
+     * @return the index of the child node entry or <code>Path.INDEX_UNDEFINED</code>
+     * if it is not found in this <code>NodeState</code>.
      */
     public int getChildNodeIndex(ChildNodeEntry cne) {
         List sns = childNodeEntries.get(cne.getName());
@@ -630,6 +625,7 @@
                 }
             } else {
                 // cne has not been resolved yet -> increase counter.
+                // TODO: check if assuption is correct
                 index++;
             }
         }
@@ -715,13 +711,14 @@
     //----------------------------------------------------< Session - State >---
     /**
      * {@inheritDoc}
-     * @see ItemState#refresh(Collection,ChangeLog)
+     * @see ItemState#refresh(ChangeLog)
      */
-    void refresh(Collection events, ChangeLog changeLog) throws IllegalStateException {
+    Set refresh(ChangeLog changeLog) throws IllegalStateException {
 
         // remember parent states that have need to adjust their uuid/mixintypes
         // or that got a new child entry added or existing entries removed.
-        HashMap modParents = new HashMap();
+        Map modParents = new HashMap();
+        Set processedIds = new HashSet();
 
         // process deleted states from the changelog
         for (Iterator it = changeLog.deletedStates(); it.hasNext();) {
@@ -742,7 +739,7 @@
             }
             // don't remove processed state from changelog, but from event list
             // state on changelog is used for check if parent is deleted as well.
-            removeEvent(events, state);
+            processedIds.add(state.getId());
         }
 
         // process added states from the changelog. since the changlog maintains
@@ -790,7 +787,7 @@
                 }
 
                 it.remove();
-                removeEvent(events, addedState);
+                processedIds.add(addedState.getId());
             } catch (ItemStateException e) {
                 log.error("Internal error.", e);
             }
@@ -799,27 +796,50 @@
         for (Iterator it = changeLog.modifiedStates(); it.hasNext();) {
             ItemState modState = (ItemState) it.next();
             if (modState.isNode()) {
-                continue;
+                NodeState modNodeState = (NodeState) modState;
+                // handle moved nodes
+                if (isMovedState(modNodeState)) {
+                    // move overlayed state as well
+                    NodeState newParent = (NodeState) modState.parent.overlayedState;
+                    NodeState overlayed = (NodeState) modState.overlayedState;
+                    ItemId removedId = overlayed.getId();
+                    try {
+                        overlayed.parent.moveEntry(newParent, overlayed, modNodeState.getQName(), modNodeState.getDefinition());
+                    } catch (RepositoryException e) {
+                        // should never occur
+                        log.error("Internal error while moving childnode entries.", e);
+                    }
+                    // and mark the moved state existing
+                    modNodeState.setStatus(Status.EXISTING);
+                    it.remove();
+
+                    processedIds.add(removedId);
+                    processedIds.add(modNodeState.getId());
+                } else {
+                    modifiedParent((NodeState)modState, null, modParents);
+                }
+            } else {
+                // push changes down to overlayed state
+                int type = ((PropertyState) modState).getType();
+                QValue[] values = ((PropertyState) modState).getValues();
+                ((PropertyState) modState.overlayedState).init(type, values);
+
+                modState.setStatus(Status.EXISTING);
+                // if property state defines a modified jcr:mixinTypes
+                // the parent is listed as modified state and needs to be
+                // processed at the end.
+                if (isUuidOrMixin(modState.getQName())) {
+                    modifiedParent(modState.getParent(), modState, modParents);
+                }
+                it.remove();
+                // remove the property-modification event from the set
+                processedIds.add(modState.getId());
             }
-            // push changes down to overlayed state
-            int type = ((PropertyState) modState).getType();
-            QValue[] values = ((PropertyState) modState).getValues();
-            ((PropertyState) modState.overlayedState).init(type, values);
-
-            modState.setStatus(Status.EXISTING);
-            // if property state defines a modified jcr:mixinTypes
-            // the parent is listed as modified state and needs to be
-            // processed at the end.
-            if (isUuidOrMixin(modState.getQName())) {
-                modifiedParent(this, modState, modParents);
-            }
-            // remove the processed event from the set
-            it.remove();
-            removeEvent(events, modState);
         }
 
-        /* process all parent states that need their uuid or mixin-types being
-           adjusted because that property has been added or modified */
+        /* process all parent states that are marked modified and eventually
+           need their uuid or mixin-types being adjusted because that property
+           has been added, modified or removed */
         for (Iterator it = modParents.keySet().iterator(); it.hasNext();) {
             NodeState parent = (NodeState) it.next();
             List l = (List) modParents.get(parent);
@@ -838,6 +858,8 @@
                 // TODO: discard state and force reload of all data
             }
         }
+
+        return processedIds;
     }
 
     /**
@@ -957,6 +979,7 @@
      * @see ItemState#revert(Set)
      */
     void revert(Set affectedItemStates) {
+        // TODO: TOBEFIXED. revert must include an update with the latest state present on the server
         checkIsSessionState();
 
         // copy to new list, when a property is reverted it may call this node
@@ -1215,9 +1238,17 @@
         throws RepositoryException {
         checkIsSessionState();
 
+        moveEntry(newParent, childState, newName, newDefinition);
+        // mark both this and newParent modified
+        markModified();
+        childState.markModified();
+        newParent.markModified();
+    }
+
+    private void moveEntry(NodeState newParent, NodeState childState, QName newName, QNodeDefinition newDefinition) throws RepositoryException {
         ChildNodeEntry oldEntry = childNodeEntries.remove(childState);
         if (oldEntry != null) {
-            childState.rename(newName);
+            childState.name = newName;
             // re-parent target node
             childState.parent = newParent;
             // set definition according to new definition required by the new parent
@@ -1225,26 +1256,8 @@
             // add child node entry to new parent
             newParent.childNodeEntries.add(childState);
         } else {
-            throw new RepositoryException("Unexpected error: Child state to be renamed does not exist.");
+            throw new RepositoryException("Unexpected error: Child state to be moved does not exist.");
         }
-        // mark both this and newParent modified
-        markModified();
-        childState.markModified();
-        newParent.markModified();
-    }
-
-    /**
-     * Renames this node to <code>newName</code>.
-     *
-     * @param newName the new name for this node state.
-     * @throws IllegalStateException if this is the root node.
-     */
-    private synchronized void rename(QName newName) {
-        checkIsSessionState();
-        if (getParent() == null) {
-            throw new IllegalStateException("root node cannot be renamed");
-        }
-        name = newName;
     }
 
     //---------------------------------------------------------< diff methods >
@@ -1369,6 +1382,7 @@
                 }
             } else {
                 // then it has never been accessed and must exist
+                // TODO: check if this assumption is correct
                 return true;
             }
         }
@@ -1449,5 +1463,8 @@
             log.warn("Error while adjusting nodestate: Overlayed state is missing.");
         }
     }
-    //------------------------------------------------------< inner classes >---
+
+    private static boolean isMovedState(NodeState modState) {
+        return modState.overlayedState.parent != modState.parent.overlayedState;
+    }
 }

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java Thu Nov  9 01:09:24 2006
@@ -28,7 +28,7 @@
     /**
      * The starting point to resolve the path.
      */
-    private final ItemState start;
+    private final NodeState start;
 
     /**
      * The path to resolve.
@@ -43,7 +43,7 @@
      * @throws IllegalArgumentException if not normalized or starts with a
      *                                  parent ('..') path element.
      */
-    private PathResolver(ItemState start, Path relPath) {
+    private PathResolver(NodeState start, Path relPath) {
         if (!relPath.isNormalized() || relPath.getElement(0).denotesParent()) {
             throw new IllegalArgumentException("path must be relative and must " +
                     "not contain parent path elements");
@@ -66,7 +66,7 @@
      *                                  or starts with a parent ('..') path
      *                                  element.
      */
-    public static ItemState resolve(ItemState start, Path path)
+    public static ItemState resolve(NodeState start, Path path)
             throws NoSuchItemStateException, ItemStateException {
         return new PathResolver(start, path).resolve();
     }
@@ -87,7 +87,7 @@
      *                                  or starts with a parent ('..') path
      *                                  element.
      */
-    public static ItemState lookup(ItemState start, Path path)
+    public static ItemState lookup(NodeState start, Path path)
             throws NoSuchItemStateException, ItemStateException {
         return new PathResolver(start, path).lookup();
     }
@@ -97,15 +97,11 @@
      *
      * @return the resolved item state.
      * @throws NoSuchItemStateException the the item state does not exist.
-     * @throws ItemStateException       if an error occurs while retrieving the
-     *                                  item state.
+     * @throws ItemStateException if an error occurs while retrieving the item state.
      */
     private ItemState resolve()
             throws NoSuchItemStateException, ItemStateException {
-        if (!start.isNode()) {
-            throw new NoSuchItemStateException(path.toString());
-        }
-        NodeState state = (NodeState) start;
+        NodeState state = start;
         for (int i = 0; i < path.getLength(); i++) {
             Path.PathElement elem = path.getElement(i);
             // check for root element
@@ -119,8 +115,8 @@
 
             // first try to resolve node
             if (state.hasChildNodeEntry(elem.getName(), elem.getNormalizedIndex())) {
-                state = state.getChildNodeEntry(elem.getName(),
-                        elem.getNormalizedIndex()).getNodeState();
+                ChildNodeEntry cne = state.getChildNodeEntry(elem.getName(), elem.getNormalizedIndex());
+                state = cne.getNodeState();
             } else if (elem.getIndex() == 0 // property must not have index
                     && state.hasPropertyName(elem.getName())
                     && i == path.getLength() - 1) { // property must be final path element
@@ -133,21 +129,18 @@
     }
 
     /**
-     * Resolves the path but does not the <code>ItemState</code> if it is not
-     * yet loaded.
+     * Resolves the path but does not return the <code>ItemState</code> if it
+     * has not yet been loaded.
      *
      * @return the resolved item state or <code>null</code> if the item is not
-     *         available.
+     * available.
      * @throws NoSuchItemStateException the the item state does not exist.
-     * @throws ItemStateException       if an error occurs while retrieving the
-     *                                  item state.
+     * @throws ItemStateException if an error occurs while retrieving the
+     * item state.
      */
     private ItemState lookup()
             throws NoSuchItemStateException, ItemStateException {
-        if (!start.isNode()) {
-            throw new NoSuchItemStateException(path.toString());
-        }
-        NodeState state = (NodeState) start;
+        NodeState state = start;
         for (int i = 0; i < path.getLength(); i++) {
             Path.PathElement elem = path.getElement(i);
             // first try to resolve node

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java Thu Nov  9 01:09:24 2006
@@ -35,6 +35,7 @@
 import java.util.Set;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.HashSet;
 
 /**
  * <code>PropertyState</code> represents the state of a <code>Property</code>.
@@ -259,9 +260,10 @@
     //----------------------------------------------------< Session - State >---
     /**
      * {@inheritDoc}
-     * @see ItemState#refresh(Collection,ChangeLog)
+     * @see ItemState#refresh(ChangeLog)
      */
-    void refresh(Collection events, ChangeLog changeLog) throws IllegalStateException {
+    Set refresh(ChangeLog changeLog) throws IllegalStateException {
+        Set processedIds = new HashSet(1);
         for (Iterator it = changeLog.modifiedStates(); it.hasNext();) {
             ItemState modState = (ItemState) it.next();
             if (modState == this) {
@@ -275,9 +277,10 @@
                 setStatus(Status.EXISTING);
                 // parent must not be informed, since all properties that
                 // affect the parent state (uuid, mixins) are protected.
-                removeEvent(events, modState);
+                processedIds.add(modState.getId());
             }
         }
+        return processedIds;
     }
 
     /**
@@ -313,6 +316,7 @@
      * @see ItemState#revert(Set)
      */
     void revert(Set affectedItemStates) {
+        // TODO: TOBEFIXED. revert must include an update with the latest state present on the server
         checkIsSessionState();
 
         switch (getStatus()) {

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java Thu Nov  9 01:09:24 2006
@@ -124,6 +124,7 @@
                        case EXISTING_MODIFIED: /* save, revert */
                        case EXISTING_REMOVED:  /* revert */
                        case STALE_MODIFIED:    /* revert */
+                       case MODIFIED:
                            isValid = true;
                            break;
                        /* REMOVED, STALE_DESTROYED -> false */
@@ -142,9 +143,11 @@
                case REMOVED:
                    isValid = (oldStatus == NEW || oldStatus == EXISTING || oldStatus == EXISTING_REMOVED);
                    break;
-                /* default:
-                   NEW cannot change state to NEW -> false
-                   MODIFIED never applicable to session state -> false */
+               case MODIFIED:
+                   isValid = (oldStatus == EXISTING);
+                   break;
+                   /* default:
+                   NEW cannot change state to NEW -> false */
             }
         }
         return isValid;

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java Thu Nov  9 01:09:24 2006
@@ -24,6 +24,7 @@
 import org.apache.jackrabbit.spi.NodeId;
 import org.apache.jackrabbit.spi.PropertyId;
 import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.jcr2spi.state.entry.ChildNodeEntry;
 
 /**
  * <code>TransientISFactory</code>...
@@ -33,14 +34,14 @@
     private static Logger log = LoggerFactory.getLogger(TransientISFactory.class);
 
     private final IdFactory idFactory;
-    private final ItemStateManager parent;
+    private final ItemStateManager workspaceItemStateMgr;
 
     private ItemStateCache cache;
     private ItemStateCreationListener listener;
 
-    TransientISFactory(IdFactory idFactory, ItemStateManager parent) {
+    TransientISFactory(IdFactory idFactory, ItemStateManager workspaceItemStateMgr) {
         this.idFactory = idFactory;
-        this.parent = parent;
+        this.workspaceItemStateMgr = workspaceItemStateMgr;
     }
 
     //------------------------------------------< TransientItemStateFactory >---
@@ -99,7 +100,7 @@
      */
     public NodeState createRootState(ItemStateManager ism) throws ItemStateException {
         // retrieve state to overlay
-        NodeState overlayedState = (NodeState) parent.getRootState();
+        NodeState overlayedState = (NodeState) workspaceItemStateMgr.getRootState();
         NodeState nodeState = new NodeState(overlayedState, null, Status.EXISTING, this, idFactory);
 
         nodeState.addListener(cache);
@@ -117,17 +118,27 @@
         NodeState nodeState = cache.getNodeState(nodeId);
         if (nodeState == null) {
             // retrieve state to overlay
-            NodeState overlayedState = (NodeState) parent.getItemState(nodeId);
+            NodeState overlayedState = (NodeState) workspaceItemStateMgr.getItemState(nodeId);
             NodeState overlayedParent = overlayedState.getParent();
 
-            NodeState parentState = null;
-            if (overlayedParent != null) {
+            if (overlayedParent == null) {
+                // special case root state
+                return createRootState(ism);
+            }
+            
+            NodeState parentState = (NodeState) overlayedParent.getSessionState();
+            if (parentState == null) {
                 parentState = (NodeState) ism.getItemState(overlayedParent.getId());
             }
 
-            nodeState = new NodeState(overlayedState, parentState, Status.EXISTING, this, idFactory);
-            nodeState.addListener(cache);
-            cache.created(nodeState);
+            ChildNodeEntry cne = parentState.getChildNodeEntry(nodeId);
+            if (cne != null) {
+                nodeState = cne.getNodeState();
+                nodeState.addListener(cache);
+                cache.created(nodeState);
+            } else {
+                throw new NoSuchItemStateException("No such item " + nodeId.toString());
+            }
         }
         return nodeState;
     }
@@ -142,7 +153,7 @@
         NodeState nodeState = cache.getNodeState(nodeId);
         if (nodeState == null) {
             // retrieve state to overlay
-            NodeState overlayedState = (NodeState) parent.getItemState(nodeId);
+            NodeState overlayedState = (NodeState) workspaceItemStateMgr.getItemState(nodeId);
             nodeState = new NodeState(overlayedState, parentState, Status.EXISTING, this, idFactory);
 
             nodeState.addListener(cache);
@@ -162,7 +173,7 @@
         PropertyState propState = cache.getPropertyState(propertyId);
         if (propState == null) {
             // retrieve state to overlay
-            PropertyState overlayedState = (PropertyState) parent.getItemState(propertyId);
+            PropertyState overlayedState = (PropertyState) workspaceItemStateMgr.getItemState(propertyId);
             propState = new PropertyState(overlayedState, parentState, Status.EXISTING, this, idFactory);
 
             propState.addListener(cache);

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java Thu Nov  9 01:09:24 2006
@@ -309,6 +309,10 @@
                 break;
             case Status.STALE_MODIFIED:
                 // state is now stale. keep in modified. wait until refreshed
+            case Status.MODIFIED:
+                // MODIFIED is only possible on EXISTING states -> thus, there
+                // must not be any transient modifications for that state.
+                // we ignore it.
                 break;
             default:
                 log.error("ItemState has invalid status: " + state.getStatus());

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java Thu Nov  9 01:09:24 2006
@@ -73,7 +73,8 @@
      */
     public NodeState createRootState(ItemStateManager ism) throws ItemStateException {
         try {
-            return createNodeState(service.getRootId(sessionInfo), ism);
+            NodeInfo info = service.getNodeInfo(sessionInfo, service.getRootId(sessionInfo));
+            return createNodeState(info, null);
         } catch (RepositoryException e) {
             throw new ItemStateException("Internal error while building root state.");
         }
@@ -90,15 +91,13 @@
             throws NoSuchItemStateException, ItemStateException {
         try {
             NodeInfo info = service.getNodeInfo(sessionInfo, nodeId);
-
-            // get parent
-            NodeId parentId = (info.getParentId() != null) ? info.getParentId() : null;
-            NodeState parent = (parentId != null) ? (NodeState) ism.getItemState(parentId) : null;
-
-            if (parent != null) {
-                return parent.getChildNodeEntry(info.getQName(), info.getIndex()).getNodeState();
+            NodeId parentId = info.getParentId();
+            if (parentId != null) {
+                NodeState parent = (NodeState) ism.getItemState(parentId);
+                return parent.getChildNodeEntry(nodeId).getNodeState();
             } else {
-                return createNodeState(info, parent);
+                // special case for root state
+                return createNodeState(info, null);
             }
         } catch (ItemNotFoundException e) {
             throw new NoSuchItemStateException(e.getMessage(), e);
@@ -129,8 +128,8 @@
     /**
      * Creates the node with information retrieved from <code>info</code>.
      *
-     * @param info   the <code>NodeInfo</code> to use to create the
-     *               <code>NodeState</code>.
+     * @param info the <code>NodeInfo</code> to use to create the
+     * <code>NodeState</code>.
      * @param parent the parent <code>NodeState</code>.
      * @return the new <code>NodeState</code>.
      */

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java Thu Nov  9 01:09:24 2006
@@ -21,6 +21,7 @@
 import org.apache.jackrabbit.spi.Event;
 import org.apache.jackrabbit.spi.EventBundle;
 import org.apache.jackrabbit.spi.EventIterator;
+import org.apache.jackrabbit.spi.ItemId;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -73,7 +74,14 @@
         // that have been persisted now: NEW-states will be connected to their
         // overlayed state, EXISTING_REMOVED states will be definitely removed,
         // EXISTING_MODIFIED states are merged with their workspace-state.
-        changeLog.getTarget().refresh(evs, changeLog);
+        Set processedIds = changeLog.getTarget().refresh(changeLog);
+        for (Iterator it = evs.iterator(); it.hasNext();) {
+            ItemId evId = ((Event)it.next()).getItemId();
+            if (processedIds.contains(evId)) {
+                it.remove();
+            }
+        }
+
         // all events not covered by the changelog must not be handled on the
         // session-states -> treat the same way as events returned by
         // workspace operations.