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/15 15:50:27 UTC

svn commit: r431601 - in /jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state: CachingItemStateManager.java TransientItemStateManager.java

Author: mreutegg
Date: Tue Aug 15 06:50:26 2006
New Revision: 431601

URL: http://svn.apache.org/viewvc?rev=431601&view=rev
Log:
TransientItemStatemanager now also extends from CachingItemStateManager.

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/TransientItemStateManager.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?rev=431601&r1=431600&r2=431601&view=diff
==============================================================================
--- 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 Tue Aug 15 06:50:26 2006
@@ -31,7 +31,7 @@
  * <code>CachingItemStateManager</code> implements an {@link ItemStateManager}
  * and decorates it with a caching facility.
  */
-public class CachingItemStateManager implements ItemStateManager, ItemStateLifeCycleListener {
+public class CachingItemStateManager implements ItemStateManager {
 
     /**
      * The logger instance for this class.
@@ -55,9 +55,10 @@
     private final Map recentlyUsed;
 
     /**
-     * The root node of the workspace.
+     * The root node of the workspace or <code>null</code> if it has not been
+     * retrieved yet.
      */
-    private final NodeState root;
+    private NodeState root;
 
     /**
      * The Id factory.
@@ -65,28 +66,32 @@
     private final IdFactory idFactory;
 
     /**
+     * An {@link ItemStateLifeCycleListener} to maintain the LRU and UUID
+     * reference cache.
+     */
+    private final ItemStateLifeCycleListener lifeCycleListener;
+
+    /**
      * Creates a new <code>CachingItemStateManager</code>.
      *
      * @param isf       the item state factory to create item state instances.
      * @param idFactory the id factory.
-     * @throws NoSuchItemStateException if the root node cannot be obtained.
-     * @throws ItemStateException       if any other error occurs while
-     *                                  obtaining the root node.
      */
-    public CachingItemStateManager(ItemStateFactory isf, IdFactory idFactory)
-            throws ItemStateException, NoSuchItemStateException {
+    public CachingItemStateManager(ItemStateFactory isf, IdFactory idFactory) {
         this.isf = isf;
         this.idFactory = idFactory;
         this.uuid2NodeState = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
         this.recentlyUsed = new LRUMap(1000); // TODO: make configurable
-        // initialize root
-        root = isf.createNodeState(idFactory.createNodeId((String) null, Path.ROOT), this);
-        root.addListener(this);
+        this.lifeCycleListener = new ISLifeCycleListener();
     }
 
     //---------------------------------------------------< ItemStateManager >---
 
     public NodeState getRootState() throws ItemStateException {
+        if (root == null) {
+            root = isf.createNodeState(idFactory.createNodeId((String) null, Path.ROOT), this);
+            root.addListener(lifeCycleListener);
+        }
         return root;
     }
 
@@ -130,35 +135,15 @@
         return false;
     }
 
-    //------------------------< ItemStateListener >-----------------------------
-
-    public void statusChanged(ItemState state, int previousStatus) {
-        if (state.getStatus() == ItemState.STATUS_REMOVED ||
-                state.getStatus() == ItemState.STATUS_STALE_DESTROYED) {
-            recentlyUsed.remove(state);
-            if (state.isNode()) {
-                NodeState nodeState = (NodeState) state;
-                if (nodeState.getUUID() != null) {
-                    uuid2NodeState.remove(nodeState.getUUID());
-                }
-            }
-        }
-    }
-
-    public void stateCreated(ItemState created) {
-    }
-
-    public void stateModified(ItemState modified) {
-    }
-
-    public void stateDestroyed(ItemState destroyed) {
-    }
+    //------------------------------< internal >--------------------------------
 
-    public void stateDiscarded(ItemState discarded) {
+    /**
+     * @return the item state factory of this <code>ItemStateManager</code>.
+     */
+    protected final ItemStateFactory getItemStateFactory() {
+        return isf;
     }
 
-    //------------------------------< internal >--------------------------------
-
     /**
      * Called whenever an item state is accessed. Calling this method will update
      * the LRU map which keeps track of most recently used item states.
@@ -183,7 +168,7 @@
         Path relPath = id.getRelativePath();
 
         // start with root node if no uuid part in id
-        NodeState nodeState = root;
+        NodeState nodeState = getRootState();
         // resolve uuid part
         if (uuid != null) {
             nodeState = (NodeState) uuid2NodeState.get(uuid);
@@ -191,7 +176,7 @@
                 // state identified by the uuid is not yet cached -> get from ISM
                 NodeId refId = (relPath == null) ? (NodeId) id : idFactory.createNodeId(uuid);
                 nodeState = isf.createNodeState(refId, this);
-                nodeState.addListener(this);
+                nodeState.addListener(lifeCycleListener);
                 uuid2NodeState.put(uuid, nodeState);
             }
         }
@@ -223,7 +208,12 @@
             }
         } else {
             // start from root
-            state = root;
+            try {
+                state = getRootState();
+            } catch (ItemStateException e) {
+                log.warn("unable to get root node state:" + e.getMessage());
+                return null;
+            }
         }
 
         // resolve relative path
@@ -237,5 +227,35 @@
         }
 
         return state;
+    }
+
+    //------------------------< ItemStateListener >-----------------------------
+
+    private class ISLifeCycleListener implements ItemStateLifeCycleListener {
+
+        public void statusChanged(ItemState state, int previousStatus) {
+            if (state.getStatus() == ItemState.STATUS_REMOVED ||
+                    state.getStatus() == ItemState.STATUS_STALE_DESTROYED) {
+                recentlyUsed.remove(state);
+                if (state.isNode()) {
+                    NodeState nodeState = (NodeState) state;
+                    if (nodeState.getUUID() != null) {
+                        uuid2NodeState.remove(nodeState.getUUID());
+                    }
+                }
+            }
+        }
+
+        public void stateCreated(ItemState created) {
+        }
+
+        public void stateModified(ItemState modified) {
+        }
+
+        public void stateDestroyed(ItemState destroyed) {
+        }
+
+        public void stateDiscarded(ItemState discarded) {
+        }
     }
 }

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?rev=431601&r1=431600&r2=431601&view=diff
==============================================================================
--- 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 Tue Aug 15 06:50:26 2006
@@ -40,8 +40,8 @@
  * {@link #createNodeState(QName, String, QName, NodeState)} and
  * {@link #createPropertyState(NodeState, QName)}.
  */
-public class TransientItemStateManager
-        implements ItemStateManager, ItemStateLifeCycleListener {
+public class TransientItemStateManager extends CachingItemStateManager
+        implements ItemStateLifeCycleListener {
 
     /**
      * Logger instance for this class.
@@ -55,11 +55,6 @@
     private final ChangeLog changeLog;
 
     /**
-     *
-     */
-    private final IdFactory idFactory;
-
-    /**
      * The parent item state manager, which return item states that are then
      * overlayed by transient item states created by this TransientItemStateManager.
      */
@@ -69,7 +64,7 @@
      * The transient item state factory to create new and existing item state
      * instances.
      */
-    private final TransientItemStateFactory isf;
+    private final TransientISFactory isf;
 
     /**
      * ItemStateManager view of the states in the attic; lazily instantiated
@@ -77,121 +72,78 @@
      */
     private AtticItemStateManager attic;
 
+    /**
+     * The root node state or <code>null</code> if it hasn't been retrieved yet.
+     */
+    private NodeState rootNodeState;
+
     TransientItemStateManager(IdFactory idFactory, ItemStateManager parent) {
+        super(new TransientISFactory(idFactory, parent), idFactory);
         this.changeLog = new ChangeLog();
-        this.idFactory = idFactory;
         this.parent = parent;
-        this.isf = new TransientISFactory();
+        this.isf = (TransientISFactory) getItemStateFactory();
+        this.isf.setListener(this);
     }
 
     //-----------------------< ItemStateManager >-------------------------------
 
     /**
-     * Return the root node state or <code>null</code> if the root state has
-     * not been modified yet.
+     * Return the root node state.
      *
-     * @return
-     * @throws ItemStateException
+     * @return the root node state.
+     * @throws ItemStateException if an error occurs while retrieving the root
+     *                            node state.
      * @see ItemStateManager#getRootState()
      */
     public NodeState getRootState() throws ItemStateException {
-        // TODO
-        return null;
+        if (rootNodeState == null) {
+            rootNodeState = isf.createNodeState(parent.getRootState().getNodeId(), this);
+            rootNodeState.addListener(this);
+        }
+        return rootNodeState;
     }
 
     /**
-     * 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 an item state given its id. Please note that this implementation
+     * also returns item states that are in removed state ({@link
+     * ItemState.STATUS_EXISTING_REMOVED} but not yet saved.
      *
-     * @return item state or <code>null</code>
-     * @throws NoSuchItemStateException if the item has been deleted
+     * @return item state.
+     * @throws NoSuchItemStateException if there is no item state (not even a
+     *                                  removed item state) with the given id.
      * @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 = changeLog.addedStates(); it.hasNext(); ) {
-            ItemState s = (ItemState) it.next();
-            if (s.getId().equals(id)) {
-                state = s;
-                break;
-            }
-        }
-        if (state == null) {
-            for (Iterator it = changeLog.modifiedStates(); it.hasNext(); ) {
-                ItemState s = (ItemState) it.next();
-                if (s.getId().equals(id)) {
-                    state = s;
-                    break;
-                }
-            }
-            if (state == null) {
-                for (Iterator it = changeLog.deletedStates(); it.hasNext(); ) {
-                    ItemState s = (ItemState) it.next();
-                    if (s.getId().equals(id)) {
-                        throw new NoSuchItemStateException("State has been marked destroyed: " + id);
-                    }
-                }
-            }
-        }
-        return state;
+        return super.getItemState(id);
     }
 
     /**
      * 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
+     * @return <code>true</code> if item state exists within this item state
+     *         manager; <code>false</code> otherwise
      * @see ItemStateManager#hasItemState(ItemId)
      */
     public boolean hasItemState(ItemId id) {
-        // TODO: too expensive. lookup item and check status
-        for (Iterator it = changeLog.addedStates(); it.hasNext(); ) {
-            ItemState s = (ItemState) it.next();
-            if (s.getId().equals(id)) {
-                return true;
-            }
-        }
-        for (Iterator it = changeLog.modifiedStates(); it.hasNext(); ) {
-            ItemState s = (ItemState) it.next();
-            if (s.getId().equals(id)) {
-                return true;
-            }
-        }
-        return false;
+        return super.hasItemState(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>
+     * Always throws an {@link UnsupportedOperationException}. A transient item
+     * state manager does not maintain node reference.
      * @see ItemStateManager#getNodeReferences(NodeId)
      */
     public NodeReferences getNodeReferences(NodeId id) {
-        // TODO: improve
-        for (Iterator it = changeLog.modifiedRefs(); it.hasNext(); ) {
-            NodeReferences refs = (NodeReferences) it.next();
-            if (refs.getId().equals(id)) {
-                return refs;
-            }
-        }
-        return null;
+        throw new UnsupportedOperationException("getNodeReferences() not implemented");
     }
 
     /**
-     * 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.
+     * Always throws an {@link UnsupportedOperationException}. A transient item
+     * state manager does not maintain node reference.
      * @see ItemStateManager#hasNodeReferences(NodeId)
      */
     public boolean hasNodeReferences(NodeId id) {
-        return getNodeReferences(id) != null;
+        throw new UnsupportedOperationException("hasNodeReferences() not implemented");
     }
 
     /**
@@ -409,99 +361,6 @@
         return changeLog.deletedStates();
     }
 
-    //----------------------< TransientItemStateFactory >-----------------------
-
-    private final class TransientISFactory implements TransientItemStateFactory {
-
-        /**
-         * @inheritDoc
-         * @see TransientItemStateFactory#createNewNodeState(QName, String, NodeState)
-         */
-        public NodeState createNewNodeState(QName name, String uuid, NodeState parent) {
-            NodeState nodeState = new NodeState(name, uuid, parent, null,
-                    ItemState.STATUS_NEW, true, this, idFactory);
-            // get a notification when this item state is saved or invalidated
-            nodeState.addListener(TransientItemStateManager.this);
-            changeLog.added(nodeState);
-            return nodeState;
-        }
-
-        /**
-         * @inheritDoc
-         * @see TransientItemStateFactory#createNewPropertyState(QName, NodeState)
-         */
-        public PropertyState createNewPropertyState(QName name, NodeState parent) {
-            PropertyState propState = new PropertyState(name, parent,
-                    ItemState.STATUS_NEW, true, idFactory);
-            // get a notification when this item state is saved or invalidated
-            propState.addListener(TransientItemStateManager.this);
-            changeLog.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);
-            NodeState nodeState = new NodeState(overlayedState, parentState,
-                    ItemState.STATUS_EXISTING, true, this, idFactory);
-            nodeState.addListener(TransientItemStateManager.this);
-            return nodeState;
-        }
-
-        /**
-         * @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);
-            NodeState nodeState = new NodeState(overlayedState, parentState,
-                    ItemState.STATUS_EXISTING, true, this, idFactory);
-            nodeState.addListener(TransientItemStateManager.this);
-            return nodeState;
-        }
-
-        /**
-         * @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);
-            PropertyState propState = new PropertyState(overlayedState, parentState,
-                    ItemState.STATUS_EXISTING, true, idFactory);
-            propState.addListener(TransientItemStateManager.this);
-            return propState;
-        }
-
-        /**
-         * @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);
-            PropertyState propState = new PropertyState(overlayedState, parentState,
-                    ItemState.STATUS_EXISTING, true, idFactory);
-            propState.addListener(TransientItemStateManager.this);
-            return propState;
-        }
-    }
-
     //-----------------------< ItemStateLifeCycleListener >---------------------
 
     /**
@@ -587,8 +446,8 @@
                 // state is now stale. keep in modified. wait until refreshed
                 break;
             case ItemState.STATUS_NEW:
-                // should never happen
-                log.warn("ItemState changed status to 'new'");
+                // new state has been created
+                changeLog.added(state);
                 break;
             case ItemState.STATUS_UNDEFINED:
                 // should never happen
@@ -673,6 +532,117 @@
         public boolean hasNodeReferences(NodeId id) {
             // n/a
             return false;
+        }
+    }
+
+    //----------------------< TransientItemStateFactory >-----------------------
+
+    private final static class TransientISFactory implements TransientItemStateFactory {
+
+        private final IdFactory idFactory;
+
+        private ItemStateLifeCycleListener listener;
+
+        private final ItemStateManager parent;
+
+        private TransientISFactory(IdFactory idFactory,
+                                   ItemStateManager parent) {
+            this.idFactory = idFactory;
+            this.parent = parent;
+        }
+
+        private void setListener(ItemStateLifeCycleListener listener) {
+            this.listener = listener;
+        }
+
+        /**
+         * @inheritDoc
+         * @see TransientItemStateFactory#createNewNodeState(QName, String, NodeState)
+         */
+        public NodeState createNewNodeState(QName name, String uuid, NodeState parent) {
+            NodeState nodeState = new NodeState(name, uuid, parent, null,
+                    ItemState.STATUS_NEW, true, this, idFactory);
+            // get a notification when this item state is saved or invalidated
+            nodeState.addListener(listener);
+            // notify listener that a node state has been created
+            listener.statusChanged(nodeState, ItemState.STATUS_NEW);
+            return nodeState;
+        }
+
+        /**
+         * @inheritDoc
+         * @see TransientItemStateFactory#createNewPropertyState(QName, NodeState)
+         */
+        public PropertyState createNewPropertyState(QName name, NodeState parent) {
+            PropertyState propState = new PropertyState(name, parent,
+                    ItemState.STATUS_NEW, true, idFactory);
+            // get a notification when this item state is saved or invalidated
+            propState.addListener(listener);
+            // notify listener that a property state has been created
+            listener.statusChanged(propState, ItemState.STATUS_NEW);
+            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);
+            NodeState nodeState = new NodeState(overlayedState, parentState,
+                    ItemState.STATUS_EXISTING, true, this, idFactory);
+            nodeState.addListener(listener);
+            return nodeState;
+        }
+
+        /**
+         * @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);
+            NodeState nodeState = new NodeState(overlayedState, parentState,
+                    ItemState.STATUS_EXISTING, true, this, idFactory);
+            nodeState.addListener(listener);
+            return nodeState;
+        }
+
+        /**
+         * @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);
+            PropertyState propState = new PropertyState(overlayedState, parentState,
+                    ItemState.STATUS_EXISTING, true, idFactory);
+            propState.addListener(listener);
+            return propState;
+        }
+
+        /**
+         * @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);
+            PropertyState propState = new PropertyState(overlayedState, parentState,
+                    ItemState.STATUS_EXISTING, true, idFactory);
+            propState.addListener(listener);
+            return propState;
         }
     }
 }