You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2006/08/08 11:38:58 UTC

svn commit: r429615 - in /jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state: ChangeLog.java NodeState.java PropertyState.java SessionItemStateManager.java TransientChangeLog.java TransientItemStateFactory.java

Author: mreutegg
Date: Tue Aug  8 02:38:56 2006
New Revision: 429615

URL: http://svn.apache.org/viewvc?rev=429615&view=rev
Log:
- implement an ItemStateFactory (ISF) for transient space
- extends ISF with transient specific methods to create new item states
- remove ItemStateManager interface from ChangeLog again

Added:
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateFactory.java   (with props)
Modified:
    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/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/TransientChangeLog.java

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java?rev=429615&r1=429614&r2=429615&view=diff
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java Tue Aug  8 02:38:56 2006
@@ -17,45 +17,38 @@
 package org.apache.jackrabbit.jcr2spi.state;
 
 import org.apache.jackrabbit.jcr2spi.operation.Operation;
-import org.apache.jackrabbit.jcr2spi.IdKeyMap;
-import org.apache.jackrabbit.jcr2spi.DefaultIdKeyMap;
-import org.apache.jackrabbit.spi.ItemId;
-import org.apache.jackrabbit.spi.NodeId;
 
 import java.util.Iterator;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Set;
+import java.util.LinkedHashSet;
 
 /**
  * Registers changes made to states and references and consolidates
  * empty changes.
  */
-// DIFF JR: implements ItemStateManager instead of separate 'get' 'has'
-public class ChangeLog implements ItemStateManager {
+public class ChangeLog {
 
     /**
      * Added states
      */
-    // TODO: TO-BE-FIXED. With SPI_ItemId simple map cannot be used any more
-    protected final IdKeyMap addedStates = new DefaultIdKeyMap(); // JR: new LinkedMap();
+    protected final Set addedStates = new LinkedHashSet();
 
     /**
      * Modified states
      */
-    // TODO: TO-BE-FIXED. With SPI_ItemId simple map cannot be used any more
-    protected final IdKeyMap modifiedStates = new DefaultIdKeyMap(); // JR: new LinkedMap();
+    protected final Set modifiedStates = new LinkedHashSet();
 
     /**
      * Deleted states
      */
-    // TODO: TO-BE-FIXED. With SPI_ItemId simple map cannot be used any more
-    protected final IdKeyMap deletedStates = new DefaultIdKeyMap(); // JR: new LinkedMap();
+    protected final Set deletedStates = new LinkedHashSet();
 
     /**
      * Modified references
      */
-    // TODO: TO-BE-FIXED. With SPI_ItemId simple map cannot be used any more
-    protected final IdKeyMap modifiedRefs = new DefaultIdKeyMap(); // JR: new LinkedMap();
+    protected final Set modifiedRefs = new LinkedHashSet();
 
     /**
      * Type of operation this changelog is collection state modifications for.
@@ -80,7 +73,7 @@
      * @param state state that has been added
      */
     public void added(ItemState state) {
-        addedStates.put(state.getId(), state);
+        addedStates.add(state);
     }
 
     /**
@@ -92,9 +85,9 @@
      * @param state state that has been modified
      */
     public void modified(ItemState state) {
-        if (!addedStates.containsKey(state.getId())) {
+        if (!addedStates.contains(state)) {
             state.disconnect();
-            modifiedStates.put(state.getId(), state);
+            modifiedStates.add(state);
         }
     }
 
@@ -108,10 +101,10 @@
      * @param state state that has been deleted
      */
     public void deleted(ItemState state) {
-        if (addedStates.remove(state.getId()) == null) {
+        if (addedStates.remove(state)) {
             state.disconnect();
-            modifiedStates.remove(state.getId());
-            deletedStates.put(state.getId(), state);
+            modifiedStates.remove(state);
+            deletedStates.add(state);
         }
     }
 
@@ -121,7 +114,7 @@
      * @param refs refs that has been modified
      */
     public void modified(NodeReferences refs) {
-        modifiedRefs.put(refs.getId(), refs);
+        modifiedRefs.add(refs);
     }
 
     //----------------------< Retrieve information present in the ChangeLog >---
@@ -145,7 +138,7 @@
      * @return iterator over all added states.
      */
     public Iterator addedStates() {
-        return addedStates.values().iterator();
+        return addedStates.iterator();
     }
 
     /**
@@ -154,7 +147,7 @@
      * @return iterator over all modified states.
      */
     public Iterator modifiedStates() {
-        return modifiedStates.values().iterator();
+        return modifiedStates.iterator();
     }
 
     /**
@@ -163,7 +156,7 @@
      * @return iterator over all deleted states.
      */
     public Iterator deletedStates() {
-        return deletedStates.values().iterator();
+        return deletedStates.iterator();
     }
 
     /**
@@ -172,7 +165,7 @@
      * @return iterator over all modified references.
      */
     public Iterator modifiedRefs() {
-        return modifiedRefs.values().iterator();
+        return modifiedRefs.iterator();
     }
 
     //-----------------------------< Inform ChangeLog about Success/Failure >---
@@ -286,65 +279,6 @@
             ((ItemState) iter.next()).discard();
         }
         reset();
-    }
-
-    //---------------------------------------------------< ItemStateManager >---
-    /**
-     * Return an item state given its id. Returns <code>null</code>
-     * if the item state is neither in the added nor in the modified
-     * section. Throws a <code>NoSuchItemStateException</code> if
-     * the item state is in the deleted section.
-     *
-     * @return item state or <code>null</code>
-     * @throws NoSuchItemStateException if the item has been deleted
-     * @see ItemStateManager#getItemState(ItemId)
-     */
-    public ItemState getItemState(ItemId id) throws NoSuchItemStateException, ItemStateException {
-        ItemState state = (ItemState) addedStates.get(id);
-        if (state == null) {
-            state = (ItemState) modifiedStates.get(id);
-            if (state == null) {
-                if (deletedStates.containsKey(id)) {
-                    throw new NoSuchItemStateException("State has been marked destroyed: " + id);
-                }
-            }
-        }
-        return state;
-    }
-
-    /**
-     * Return a flag indicating whether a given item state exists.
-     *
-     * @return <code>true</code> if item state exists within this
-     *         log; <code>false</code> otherwise
-     * @see ItemStateManager#hasItemState(ItemId)
-     */
-    public boolean hasItemState(ItemId id) {
-        return addedStates.containsKey(id) || modifiedStates.containsKey(id);
-    }
-
-    /**
-     * Return a node references object given its id. Returns
-     * <code>null</code> if the node reference is not in the modified
-     * section.
-     *
-     * @return node references or <code>null</code>
-     * @see ItemStateManager#getNodeReferences(NodeId)
-     */
-    public NodeReferences getNodeReferences(NodeId id) throws NoSuchItemStateException, ItemStateException {
-        return (NodeReferences) modifiedRefs.get(id);
-    }
-
-    /**
-     * Returns <code>false</code> if the node reference is not in the modified
-     * section.
-     *
-     * @return false if no references are present in this changelog for the
-     * given id.
-     * @see ItemStateManager#hasNodeReferences(NodeId)
-     */
-    public boolean hasNodeReferences(NodeId id) {
-        return modifiedRefs.get(id) != null;
     }
 
     //-------------------------------------------------------------< Object >---

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?rev=429615&r1=429614&r2=429615&view=diff
==============================================================================
--- 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 Tue Aug  8 02:38:56 2006
@@ -134,20 +134,22 @@
     }
 
     /**
-     * Constructs a new <code>NodeState</code> that is initially connected to
-     * an overlayed state.
+     * Constructs a new <code>NodeState</code> that is initially connected to an
+     * overlayed state.
      *
      * @param overlayedState the backing node state being overlayed
+     * @param parent         the parent of this NodeState
      * @param initialStatus  the initial status of the node state object
-     * @param isTransient    flag indicating whether this state is transient or not
+     * @param isTransient    flag indicating whether this state is transient or
+     *                       not
      */
-    public NodeState(NodeState overlayedState, int initialStatus,
-                     boolean isTransient) {
+    public NodeState(NodeState overlayedState, NodeState parent, int initialStatus,
+                     boolean isTransient, ItemStateFactory isf) {
         super(overlayedState, initialStatus, isTransient);
         pull();
-        idFactory = overlayedState.idFactory;
-        // TODO: remove this constructor
-        this.isf = null;
+        this.parent = parent;
+        idFactory = parent.idFactory;
+        this.isf = isf;
     }
 
     /**

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?rev=429615&r1=429614&r2=429615&view=diff
==============================================================================
--- 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 Tue Aug  8 02:38:56 2006
@@ -64,10 +64,11 @@
      * @param initialStatus  the initial status of the property state object
      * @param isTransient    flag indicating whether this state is transient or not
      */
-    public PropertyState(PropertyState overlayedState, int initialStatus,
+    public PropertyState(PropertyState overlayedState, NodeState parent, int initialStatus,
                          boolean isTransient) {
         super(overlayedState, initialStatus, isTransient);
         pull();
+        this.parent = parent;
     }
 
     /**

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java?rev=429615&r1=429614&r2=429615&view=diff
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java Tue Aug  8 02:38:56 2006
@@ -142,7 +142,7 @@
         this.rootId = rootId;
         this.workspaceItemStateMgr = workspaceItemStateMgr;
         // DIFF JACKRABBIT: this.transientStateMgr = new TransientItemStateManager();
-        this.transientStateMgr = new TransientChangeLog(idFactory);
+        this.transientStateMgr = new TransientChangeLog(idFactory, workspaceItemStateMgr);
         // DIFF JR: validator added
         this.validator = validator;
         // DIFF JR: idFactory added
@@ -333,7 +333,7 @@
         }
 
         // list of transient items that should be discarded
-        ChangeLog changeLog = new TransientChangeLog(idFactory);
+        ChangeLog changeLog = new TransientChangeLog(idFactory, workspaceItemStateMgr);
 
         // check status of current item's state
         if (state.isTransient()) {
@@ -636,7 +636,7 @@
      * @throws ItemStateException
      */
     private ChangeLog getChangeLog(ItemState itemState) throws StaleItemStateException, ItemStateException {
-        ChangeLog changeLog = new TransientChangeLog(idFactory);
+        ChangeLog changeLog = new TransientChangeLog(idFactory, workspaceItemStateMgr);
         if (rootId.equals(itemState.getId())) {
             // get all item states
             for (Iterator it = transientStateMgr.addedStates(); it.hasNext(); ) {

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientChangeLog.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientChangeLog.java?rev=429615&r1=429614&r2=429615&view=diff
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientChangeLog.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientChangeLog.java Tue Aug  8 02:38:56 2006
@@ -18,6 +18,7 @@
 
 import org.apache.jackrabbit.jcr2spi.operation.Operation;
 import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.name.Path;
 import org.apache.jackrabbit.spi.NodeId;
 import org.apache.jackrabbit.spi.ItemId;
 import org.apache.jackrabbit.spi.PropertyId;
@@ -33,7 +34,8 @@
  * Furthermore the item states of a transient change log are not disconnected
  * when added.
  */
-public class TransientChangeLog extends ChangeLog implements TransientItemStateManager {
+public class TransientChangeLog extends ChangeLog
+        implements TransientItemStateManager, TransientItemStateFactory, ItemStateListener {
 
     // TODO: TO-BE-FIXED. Usage of SPI_ItemId requries different handling
 
@@ -48,14 +50,21 @@
     private final IdFactory idFactory;
 
     /**
+     * The parent item state manager, which return item states that are then
+     * overlayed by transient item states created by this TransientChangeLog.
+     */
+    private final ItemStateManager parent;
+
+    /**
      * ItemStateManager view of the states in the attic; lazily instantiated
      * in {@link #getAttic()}
      */
     private AtticItemStateManager attic;
 
 
-    TransientChangeLog(IdFactory idFactory) {
+    TransientChangeLog(IdFactory idFactory, ItemStateManager parent) {
         this.idFactory = idFactory;
+        this.parent = parent;
     }
 
     //------------------< ChangeLog overwrites >--------------------------------
@@ -68,8 +77,8 @@
      * @param state state that has been modified
      */
     public void modified(ItemState state) {
-        if (!addedStates.containsKey(state.getId())) {
-            modifiedStates.put(state.getId(), state);
+        if (!addedStates.contains(state)) {
+            modifiedStates.add(state);
         }
     }
 
@@ -82,10 +91,107 @@
      * @param state state that has been deleted
      */
     public void deleted(ItemState state) {
-        if (addedStates.remove(state.getId()) == null) {
-            modifiedStates.remove(state.getId());
-            deletedStates.put(state.getId(), state);
+        if (addedStates.remove(state)) {
+            modifiedStates.remove(state);
+            deletedStates.add(state);
+        }
+    }
+
+    //-----------------------< ItemStateManager >-------------------------------
+
+    /**
+     * Return an item state given its id. Returns <code>null</code>
+     * if the item state is neither in the added nor in the modified
+     * section. Throws a <code>NoSuchItemStateException</code> if
+     * the item state is in the deleted section.
+     *
+     * @return item state or <code>null</code>
+     * @throws NoSuchItemStateException if the item has been deleted
+     * @see ItemStateManager#getItemState(ItemId)
+     */
+    public ItemState getItemState(ItemId id) throws NoSuchItemStateException, ItemStateException {
+        // TODO: this is expensive. Improvement: Lookup item, then check its state
+        ItemState state = null;
+        for (Iterator it = addedStates.iterator(); it.hasNext(); ) {
+            ItemState s = (ItemState) it.next();
+            if (s.getId().equals(id)) {
+                state = s;
+                break;
+            }
+        }
+        if (state == null) {
+            for (Iterator it = modifiedStates.iterator(); it.hasNext(); ) {
+                ItemState s = (ItemState) it.next();
+                if (s.getId().equals(id)) {
+                    state = s;
+                    break;
+                }
+            }
+            if (state == null) {
+                for (Iterator it = deletedStates.iterator(); it.hasNext(); ) {
+                    ItemState s = (ItemState) it.next();
+                    if (s.getId().equals(id)) {
+                        throw new NoSuchItemStateException("State has been marked destroyed: " + id);
+                    }
+                }
+            }
+        }
+        return state;
+    }
+
+    /**
+     * Return a flag indicating whether a given item state exists.
+     *
+     * @return <code>true</code> if item state exists within this
+     *         log; <code>false</code> otherwise
+     * @see ItemStateManager#hasItemState(ItemId)
+     */
+    public boolean hasItemState(ItemId id) {
+        // TODO: too expensive. lookup item and check status
+        for (Iterator it = addedStates.iterator(); it.hasNext(); ) {
+            ItemState s = (ItemState) it.next();
+            if (s.getId().equals(id)) {
+                return true;
+            }
+        }
+        for (Iterator it = modifiedStates.iterator(); it.hasNext(); ) {
+            ItemState s = (ItemState) it.next();
+            if (s.getId().equals(id)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return a node references object given its id. Returns
+     * <code>null</code> if the node reference is not in the modified
+     * section.
+     *
+     * @return node references or <code>null</code>
+     * @see ItemStateManager#getNodeReferences(NodeId)
+     */
+    public NodeReferences getNodeReferences(NodeId id) {
+        // TODO: improve
+        for (Iterator it = modifiedRefs.iterator(); it.hasNext(); ) {
+            NodeReferences refs = (NodeReferences) it.next();
+            if (refs.getId().equals(id)) {
+                return refs;
+            }
         }
+        return null;
+    }
+
+    /**
+     * Returns <code>false</code> if the node reference is not in the modified
+     * section.
+     *
+     * @return false if no references are present in this changelog for the
+     * given id.
+     * @see ItemStateManager#hasNodeReferences(NodeId)
+     */
+    public boolean hasNodeReferences(NodeId id) {
+        return getNodeReferences(id) != null;
     }
 
     //-----------------< TransientItemStateManager >----------------------------
@@ -122,6 +228,7 @@
     }
 
     /**
+     * TODO: remove this method
      * @inheritDoc
      */
     public NodeState createNodeState(NodeId id,
@@ -143,11 +250,12 @@
 //            return state;
 //        }
 
-        ItemStateFactory isf = null; // TODO: probably not correct
-        return new NodeState(id, parent, nodeTypeName, ItemState.STATUS_NEW, true, isf);
+        // TODO: replace with call to createNewNodeState() and finally remove method
+        return new NodeState(id, parent, nodeTypeName, ItemState.STATUS_NEW, true, this);
     }
 
     /**
+     * TODO: remove this method
      * @inheritDoc
      */
     public NodeState createNodeState(NodeState overlayedState) {
@@ -156,21 +264,22 @@
         // check map; synchronized to ensure an entry is not created twice.
         synchronized (addedStates) {
             NodeState state;
-            if ((state = (NodeState) addedStates.get(id)) != null
-                    || (state = (NodeState) modifiedStates.get(id)) != null) {
-                String msg = "there's already a node state instance with id " + id;
-                log.warn(msg);
-                return state;
-            }
+//            if ((state = (NodeState) addedStates.get(id)) != null
+//                    || (state = (NodeState) modifiedStates.get(id)) != null) {
+//                String msg = "there's already a node state instance with id " + id;
+//                log.warn(msg);
+//                return state;
+//            }
 
-            state = new NodeState(overlayedState, ItemState.STATUS_EXISTING_MODIFIED, true);
+            state = new NodeState(overlayedState, null, ItemState.STATUS_EXISTING_MODIFIED, true, this);
             // put transient state in the map
-            modifiedStates.put(id, state);
+            modifiedStates.add(state);
             return state;
         }
     }
 
     /**
+     * TODO: remove this method
      * @inheritDoc
      */
     public PropertyState createPropertyState(NodeState parentState, QName propName) {
@@ -179,6 +288,7 @@
     }
 
     /**
+     * TODO: remove this method
      * @inheritDoc
      */
     public PropertyState createPropertyState(PropertyState overlayedState) {
@@ -188,16 +298,16 @@
         // check map; synchronized to ensure an entry is not created twice.
         synchronized (addedStates) {
             PropertyState state;
-            if ((state = (PropertyState) addedStates.get(id)) != null
-                    || (state = (PropertyState) modifiedStates.get(id)) != null) {
-                String msg = "there's already a property state instance with id " + id;
-                log.warn(msg);
-                return state;
-            }
+//            if ((state = (PropertyState) addedStates.get(id)) != null
+//                    || (state = (PropertyState) modifiedStates.get(id)) != null) {
+//                String msg = "there's already a property state instance with id " + id;
+//                log.warn(msg);
+//                return state;
+//            }
 
-            state = new PropertyState(overlayedState, ItemState.STATUS_EXISTING_MODIFIED, true);
+            state = new PropertyState(overlayedState, null, ItemState.STATUS_EXISTING_MODIFIED, true);
             // put transient state in the map
-            modifiedStates.put(id, state);
+            modifiedStates.add(state);
             return state;
         }
     }
@@ -212,8 +322,8 @@
      */
     public void disposeItemState(ItemState state) {
         state.discard();
-        if (addedStates.remove(state.getId()) == null) {
-            modifiedStates.remove(state.getId());
+        if (addedStates.remove(state)) {
+            modifiedStates.remove(state);
         }
         state.onDisposed();
     }
@@ -227,10 +337,10 @@
      * @param state state that has been deleted
      */
     public void moveItemStateToAttic(ItemState state) {
-        if (addedStates.remove(state.getId()) == null) {
-            modifiedStates.remove(state.getId());
+        if (addedStates.remove(state)) {
+            modifiedStates.remove(state);
         }
-        deletedStates.put(state.getId(), state);
+        deletedStates.add(state);
     }
 
     /**
@@ -242,7 +352,7 @@
      */
     public void disposeItemStateInAttic(ItemState state) {
         state.discard();
-        deletedStates.remove(state.getId());
+        deletedStates.remove(state);
         state.onDisposed();
     }
 
@@ -281,6 +391,123 @@
         }
     }
 
+    //----------------------< TransientItemStateFactory >-----------------------
+
+    /**
+     * @inheritDoc
+     * @see TransientItemStateFactory#createNewNodeState(QName, String, NodeState)
+     */
+    public NodeState createNewNodeState(QName name, String uuid, NodeState parent) {
+        NodeId id;
+        if (uuid == null) {
+            id = idFactory.createNodeId(parent.getNodeId(), Path.create(name, 0));
+        } else {
+            id = idFactory.createNodeId(uuid);
+        }
+        NodeState nodeState = new NodeState(id, parent, null, ItemState.STATUS_NEW, true, this);
+        // get a notification when this item state is saved or invalidated
+        nodeState.addListener(this);
+        added(nodeState);
+        return nodeState;
+    }
+
+    /**
+     * @inheritDoc
+     * @see TransientItemStateFactory#createNewPropertyState(QName, NodeState)
+     */
+    public PropertyState createNewPropertyState(QName name, NodeState parent) {
+        PropertyId id = idFactory.createPropertyId(parent.getNodeId(), name);
+        PropertyState propState = new PropertyState(id, parent, ItemState.STATUS_NEW, true);
+        // get a notification when this item state is saved or invalidated
+        propState.addListener(this);
+        added(propState);
+        return propState;
+    }
+
+    /**
+     * @inheritDoc
+     * @see TransientItemStateFactory#createNodeState(NodeId, ItemStateManager)
+     */
+    public NodeState createNodeState(NodeId nodeId, ItemStateManager ism)
+            throws NoSuchItemStateException, ItemStateException {
+        // retrieve state to overlay
+        NodeState overlayedState = (NodeState) parent.getItemState(nodeId);
+        NodeId parentId = overlayedState.getParent().getNodeId();
+        NodeState parentState = (NodeState) ism.getItemState(parentId);
+        return new NodeState(overlayedState, parentState, ItemState.STATUS_EXISTING, true, this);
+    }
+
+    /**
+     * @inheritDoc
+     * @see TransientItemStateFactory#createNodeState(NodeId, NodeState)
+     */
+    public NodeState createNodeState(NodeId nodeId, NodeState parentState)
+            throws NoSuchItemStateException, ItemStateException {
+        // retrieve state to overlay
+        NodeState overlayedState = (NodeState) parent.getItemState(nodeId);
+        return new NodeState(overlayedState, parentState, ItemState.STATUS_EXISTING, true, this);
+    }
+
+    /**
+     * @inheritDoc
+     * @see TransientItemStateFactory#createPropertyState(PropertyId, ItemStateManager)
+     */
+    public PropertyState createPropertyState(PropertyId propertyId,
+                                             ItemStateManager ism)
+            throws NoSuchItemStateException, ItemStateException {
+        // retrieve state to overlay
+        PropertyState overlayedState = (PropertyState) parent.getItemState(propertyId);
+        NodeId parentId = overlayedState.getParent().getNodeId();
+        NodeState parentState = (NodeState) ism.getItemState(parentId);
+        return new PropertyState(overlayedState, parentState, ItemState.STATUS_EXISTING, true);
+    }
+
+    /**
+     * @inheritDoc
+     * @see TransientItemStateFactory#createPropertyState(PropertyId, NodeState)
+     */
+    public PropertyState createPropertyState(PropertyId propertyId,
+                                             NodeState parentState)
+            throws NoSuchItemStateException, ItemStateException {
+        // retrieve state to overlay
+        PropertyState overlayedState = (PropertyState) parent.getItemState(propertyId);
+        return new PropertyState(overlayedState, parentState, ItemState.STATUS_EXISTING, true);
+    }
+
+    //---------------------------< ItemStateListener >--------------------------
+
+    /**
+     * @inheritDoc
+     * @see ItemStateListener#stateCreated(ItemState)
+     */
+    public void stateCreated(ItemState created) {
+        // TODO: remove from added set of change log
+    }
+
+    /**
+     * @inheritDoc
+     * @see ItemStateListener#stateModified(ItemState)
+     */
+    public void stateModified(ItemState modified) {
+        // TODO: remove from modified set of change log
+    }
+
+    /**
+     * @inheritDoc
+     * @see ItemStateListener#stateDestroyed(ItemState)
+     */
+    public void stateDestroyed(ItemState destroyed) {
+        // TODO: remove from deleted set of change log
+    }
+
+    /**
+     * @inheritDoc
+     * @see ItemStateListener#stateDiscarded(ItemState)
+     */
+    public void stateDiscarded(ItemState discarded) {
+        // TODO: remove from modified (and deleted?) set of change log
+    }
+
     //--------------------------------------------------------< inner classes >
 
     /**
@@ -299,7 +526,14 @@
         public ItemState getItemState(ItemId id)
                 throws NoSuchItemStateException, ItemStateException {
 
-            ItemState state = (ItemState) deletedStates.get(id);
+            // TODO: too expensive. rather lookup item and check state
+            ItemState state = null;
+            for (Iterator it = deletedStates.iterator(); it.hasNext(); ) {
+                ItemState s = (ItemState) it.next();
+                if (s.getId().equals(id)) {
+                    state = s;
+                }
+            }
             if (state != null) {
                 return state;
             } else {
@@ -311,7 +545,14 @@
          * {@inheritDoc}
          */
         public boolean hasItemState(ItemId id) {
-            return deletedStates.containsKey(id);
+            // TODO: too expensive. rather lookup item and check state
+            for (Iterator it = deletedStates.iterator(); it.hasNext(); ) {
+                ItemState s = (ItemState) it.next();
+                if (s.getId().equals(id)) {
+                    return true;
+                }
+            }
+            return false;
         }
 
         /**

Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateFactory.java?rev=429615&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateFactory.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateFactory.java Tue Aug  8 02:38:56 2006
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.jcr2spi.state;
+
+import org.apache.jackrabbit.name.QName;
+
+/**
+ * <code>TransientItemStateFactory</code> extends the item state factory and
+ * adds new methods for creating node states and property states that are new.
+ */
+public interface TransientItemStateFactory extends ItemStateFactory {
+
+    /**
+     * Creates a transient child <code>NodeState</code> with the given
+     * <code>name</code>.
+     *
+     * @param name   the name of the <code>NodeState</code> to create.
+     * @param uuid   the uuid of the <code>NodeState</code> to create or
+     *               <code>null</code> if the created <code>NodeState</code>
+     *               cannot be identified by a UUID.
+     * @param parent the parent of the <code>NodeState</code> to create.
+     * @return the created <code>NodeState</code>.
+     */
+    public NodeState createNewNodeState(QName name,
+                                        String uuid,
+                                        NodeState parent);
+
+    /**
+     * Creates a transient <code>PropertyState</code> with the given
+     * <code>name</code>.
+     *
+     * @param name   the name of the <code>PropertyState</code> to create.
+     * @param parent the parent of the <code>PropertyState</code> to create.
+     * @return the created <code>PropertyState</code>.
+     */
+    public PropertyState createNewPropertyState(QName name,
+                                                NodeState parent);
+}

Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native