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/11/13 10:20:31 UTC

svn commit: r474207 - in /jackrabbit/trunk/contrib/spi: client/src/test/java/org/apache/jackrabbit/jcr2spi/ jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/ jcr2spi/src/main/java/org/apach...

Author: mreutegg
Date: Mon Nov 13 01:20:30 2006
New Revision: 474207

URL: http://svn.apache.org/viewvc?view=rev&rev=474207
Log:
- work in progress: implement invalidate and refresh on ItemState.

Added:
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/CacheBehaviour.java   (with props)
Removed:
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/CacheMaintenance.java
Modified:
    jackrabbit/trunk/contrib/spi/client/src/test/java/org/apache/jackrabbit/jcr2spi/JCR2SPIRepositoryStub.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/RepositoryConfig.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/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/TransientItemStateManager.java

Modified: jackrabbit/trunk/contrib/spi/client/src/test/java/org/apache/jackrabbit/jcr2spi/JCR2SPIRepositoryStub.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/client/src/test/java/org/apache/jackrabbit/jcr2spi/JCR2SPIRepositoryStub.java?view=diff&rev=474207&r1=474206&r2=474207
==============================================================================
--- jackrabbit/trunk/contrib/spi/client/src/test/java/org/apache/jackrabbit/jcr2spi/JCR2SPIRepositoryStub.java (original)
+++ jackrabbit/trunk/contrib/spi/client/src/test/java/org/apache/jackrabbit/jcr2spi/JCR2SPIRepositoryStub.java Mon Nov 13 01:20:30 2006
@@ -21,7 +21,7 @@
 import org.apache.jackrabbit.spi2dav.IdFactoryImpl;
 import org.apache.jackrabbit.spi2dav.ValueFactoryImpl;
 import org.apache.jackrabbit.jcr2spi.config.RepositoryConfig;
-import org.apache.jackrabbit.jcr2spi.config.CacheMaintenance;
+import org.apache.jackrabbit.jcr2spi.config.CacheBehaviour;
 import org.apache.jackrabbit.spi.RepositoryService;
 import org.apache.jackrabbit.spi.IdFactory;
 import org.apache.log4j.PropertyConfigurator;
@@ -85,8 +85,8 @@
                         return name;
                     }
 
-                    public CacheMaintenance getCacheMaintenanceStrategy() {
-                        return CacheMaintenance.OBSERVATION;
+                    public CacheBehaviour getCacheBehaviour() {
+                        return CacheBehaviour.OBSERVATION;
                     }
                 };
 

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java?view=diff&rev=474207&r1=474206&r2=474207
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java Mon Nov 13 01:20:30 2006
@@ -243,31 +243,27 @@
     public void refresh(boolean keepChanges) throws InvalidItemStateException, RepositoryException {
         checkStatus();
 
-        if (keepChanges) {
-            // TODO: TOBEFIXED. make sure item is updated to status present on the server.
-            return;
-        }
+        if (!keepChanges) {
+            // check status of this item's state
+            switch (state.getStatus()) {
+                case Status.NEW:
+                    String msg = "Cannot refresh a new item (" + safeGetJCRPath() + ").";
+                    log.debug(msg);
+                    throw new RepositoryException(msg);
+            }
 
-        // check status of this item's state
-        switch (state.getStatus()) {
-            case Status.NEW:
-                String msg = "Cannot refresh a new item (" + safeGetJCRPath() + ").";
-                log.debug(msg);
-                throw new RepositoryException(msg);
-            case Status.STALE_DESTROYED:
-                msg = "Cannot refresh on a deleted item (" + safeGetJCRPath() + ").";
+            // reset all transient modifications from this item and its decendants.
+            try {
+                session.getSessionItemStateManager().undo(state);
+            } catch (ItemStateException e) {
+                String msg = "Unable to undo item (" + safeGetJCRPath() + ")";
                 log.debug(msg);
-                throw new InvalidItemStateException(msg);
+                throw new RepositoryException(msg, e);
+            }
         }
 
-        // reset all transient modifications from this item and its decendants.
-        try {
-            session.getSessionItemStateManager().undo(state);
-        } catch (ItemStateException e) {
-            String msg = "Unable to update item (" + safeGetJCRPath() + ")";
-            log.debug(msg);
-            throw new RepositoryException(msg, e);
-        }
+        // now refresh to persistent state on server
+        state.refresh();
     }
 
     /**
@@ -393,7 +389,10 @@
 
     //------------------------------------------------------< check methods >---
     /**
-     * Performs a sanity check on this item and the associated session.
+     * Performs a sanity check on this item and the associated session. If
+     * the underlying item state is in an invalidated state then it will be
+     * refreshed to get the current status of the item state. The status
+     * check is then performed on the newly retrieved status.
      *
      * @throws RepositoryException if this item has been rendered invalid for some reason
      */
@@ -401,9 +400,17 @@
         // check session status
         session.checkIsAlive();
         // check status of this item for read operation
-        if (state == null || !state.isValid()) {
-            throw new InvalidItemStateException("Item '" + this + "' doesn't exist anymore");
+        if (state != null) {
+            if (state.getStatus() == Status.INVALIDATED) {
+                // refresh to get current status from persistent storage
+                state.refresh();
+            }
+            // now check if valid
+            if (state.isValid()) {
+                return;
+            }
         }
+        throw new InvalidItemStateException("Item '" + this + "' doesn't exist anymore");
     }
 
     /**

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java?view=diff&rev=474207&r1=474206&r2=474207
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java Mon Nov 13 01:20:30 2006
@@ -38,6 +38,7 @@
 import org.apache.jackrabbit.jcr2spi.operation.Operation;
 import org.apache.jackrabbit.jcr2spi.name.LocalNamespaceMappings;
 import org.apache.jackrabbit.jcr2spi.config.RepositoryConfig;
+import org.apache.jackrabbit.jcr2spi.config.CacheBehaviour;
 import org.apache.jackrabbit.name.MalformedPathException;
 import org.apache.jackrabbit.name.NamespaceResolver;
 import org.apache.jackrabbit.name.QName;
@@ -746,6 +747,10 @@
 
     NodeTypeManagerImpl getNodeTypeManager() {
         return ntManager;
+    }
+
+    CacheBehaviour getCacheBehaviour() {
+        return config.getCacheBehaviour();
     }
 
     //--------------------------------------------------------------------------

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java?view=diff&rev=474207&r1=474206&r2=474207
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java Mon Nov 13 01:20:30 2006
@@ -108,6 +108,7 @@
         this.session = session;
 
         wspManager = createManager(service, sessionInfo);
+        wspManager.setCacheBehaviour(session.getCacheBehaviour());
     }
 
     //----------------------------------------------------------< Workspace >---

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java?view=diff&rev=474207&r1=474206&r2=474207
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java Mon Nov 13 01:20:30 2006
@@ -56,6 +56,7 @@
 import org.apache.jackrabbit.jcr2spi.operation.RemoveLabel;
 import org.apache.jackrabbit.jcr2spi.security.AccessManager;
 import org.apache.jackrabbit.jcr2spi.observation.InternalEventListener;
+import org.apache.jackrabbit.jcr2spi.config.CacheBehaviour;
 import org.apache.jackrabbit.name.Path;
 import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.name.MalformedPathException;
@@ -127,6 +128,7 @@
     private final SessionInfo sessionInfo;
 
     private final ItemStateManager cache;
+    private CacheBehaviour cacheBehaviour = CacheBehaviour.OBSERVATION;
 
     private final NamespaceRegistryImpl nsRegistry;
     private final NodeTypeRegistry ntRegistry;
@@ -286,6 +288,28 @@
                                          boolean noLocal)
             throws UnsupportedRepositoryOperationException {
         return service.createEventFilter(eventTypes, path, isDeep, uuids, nodeTypes, noLocal);
+    }
+
+    //----------------------------------------------------< package private >---
+
+    /**
+     * Returns the current cache behaviour. Defaults to {@link
+     * CacheBehaviour#OBSERVATION} unless otherwise set using {@link
+     * #setCacheBehaviour(CacheBehaviour)}.
+     *
+     * @return the current cache behaviour.
+     */
+    CacheBehaviour getCacheBehaviour() {
+        return cacheBehaviour;
+    }
+
+    /**
+     * Sets the cache behaviour for this WorkspaceManager.
+     *
+     * @param behaviour the cache behaviour.
+     */
+    void setCacheBehaviour(CacheBehaviour behaviour) {
+        this.cacheBehaviour = behaviour;
     }
 
     //--------------------------------------------------------------------------

Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/CacheBehaviour.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/CacheBehaviour.java?view=auto&rev=474207
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/CacheBehaviour.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/CacheBehaviour.java Mon Nov 13 01:20:30 2006
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  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.config;
+
+/**
+ * <code>CacheBehaviour</code> defines constants for the various cache
+ * maintenance strategies. The effective strategy depends on two factors,
+ * whether the repository implementation supports observation and the behaviour
+ * provided in the {@link RepositoryConfig}.
+ */
+public final class CacheBehaviour {
+
+    /**
+     * Cache maintenance is stictly done on a manual basis even though the
+     * repository implementation might support observation. Only the result of a
+     * <code>save()</code> upon a transient modification is reflected in the
+     * cache. The client has to call {@link javax.jcr.Item#refresh(boolean)}
+     * <i>manually</i> to get the full effect of his action. E.g. workspace
+     * operations will not change any cached state.
+     */
+    public static final CacheBehaviour MANUAL = new CacheBehaviour();
+
+    /**
+     * Cache maintenance is done by invalidating affected items of an operation
+     * and forcing the jcr2spi implementation to reload the item states when
+     * they are accessed next time. No event listener is used for cache
+     * maintenance even though the repository implementation might support
+     * observation.
+     */
+    public static final CacheBehaviour INVALIDATE = new CacheBehaviour();
+
+    /**
+     * Cache maintenance is done using events from the repository. After an
+     * operation has been executed on the RepositoryService events are retrieved
+     * from the repository and the cache is updated based on the returned
+     * events. This strategy requires that the repository implementation
+     * supports observation.
+     */
+    public static final CacheBehaviour OBSERVATION = new CacheBehaviour();
+
+    private CacheBehaviour() {
+    }
+}

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

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/RepositoryConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/RepositoryConfig.java?view=diff&rev=474207&r1=474206&r2=474207
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/RepositoryConfig.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/config/RepositoryConfig.java Mon Nov 13 01:20:30 2006
@@ -33,5 +33,5 @@
 
     public String getDefaultWorkspaceName();
 
-    public CacheMaintenance getCacheMaintenanceStrategy();
+    public CacheBehaviour getCacheBehaviour();
 }

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=474207&r1=474206&r2=474207
==============================================================================
--- 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 Mon Nov 13 01:20:30 2006
@@ -249,7 +249,7 @@
      *
      * @return the status of this item.
      */
-    public int getStatus() {
+    public final int getStatus() {
         return status;
     }
 
@@ -293,6 +293,23 @@
     }
 
     /**
+     * Refreshes this item state recursively according to {@link
+     * javax.jcr.Item#refresh(boolean) Item.refresh(true)}. That is, changes
+     * are kept and updated to reflect the current persistent state of this
+     * item.
+     * todo throw exception in case of error?
+     */
+    public abstract void refresh();
+
+    /**
+     * Invalidates this item state recursively. In contrast to {@link #refresh}
+     * this method only sets the status of this item state to {@link
+     * Status#INVALIDATED} and does not acutally update it with the persistent
+     * state in the repository.
+     */
+    public abstract void invalidate();
+
+    /**
      * Add an <code>ItemStateLifeCycleListener</code>
      *
      * @param listener the new listener to be informed on modifications
@@ -337,7 +354,7 @@
             switch (state.getStatus()) {
                 case Status.MODIFIED:
                     // underlying state has been modified by external changes
-                    if (status == Status.EXISTING) {
+                    if (status == Status.EXISTING || status == Status.INVALIDATED) {
                         synchronized (this) {
                             reset();
                         }
@@ -355,6 +372,10 @@
                         setStatus(Status.REMOVED);
                     }
                     break;
+                case Status.INVALIDATED:
+                    // invalidate session state as well
+                    setStatus(Status.INVALIDATED);
+                    break;
                 default:
                     // Should never occur, since 'setStatus(int)' already validates
                     log.error("Workspace state cannot have its state changed to " + state.getStatus());
@@ -396,7 +417,7 @@
     }
 
     /**
-     * @throws IllegalStateException if this state is a 'workspace' state.
+     * @throws IllegalStateException if this state is a 'session' state.
      */
     public void checkIsSessionState() {
         if (isWorkspaceState) {
@@ -442,6 +463,7 @@
     }
 
     //----------------------------------------------------< Session - State >---
+
     /**
      * Used on the target state of a save call AFTER the changelog has been
      * successfully submitted to the SPI..

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=474207&r1=474206&r2=474207
==============================================================================
--- 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 Mon Nov 13 01:20:30 2006
@@ -150,6 +150,56 @@
         return getPropertyId();
     }
 
+    /**
+     * {@inheritDoc}
+     * @see ItemState#refresh()
+     */
+    public void refresh() {
+        if (isWorkspaceState()) {
+            // refresh from persistent storage
+            try {
+                PropertyState tmp = isf.createPropertyState(getPropertyId(), parent);
+                init(tmp.getType(), tmp.getValues());
+                setStatus(Status.MODIFIED);
+            } catch (NoSuchItemStateException e) {
+                // does not exist anymore
+                setStatus(Status.REMOVED);
+                // todo also remove from parent? how do we make sure the parent
+                // todo does not get modified by this removal?
+                // parent.propertyStateRemoved(this);
+            } catch (ItemStateException e) {
+                // todo rather throw? remove from parent?
+                log.warn("Exception while refreshing property state: " + e);
+                log.debug("Stacktrace: ", e);
+            }
+        } else {
+            // session state
+            if (getStatus() == Status.EXISTING || getStatus() == Status.INVALIDATED) {
+                // calling refresh on the workspace state will in turn
+                // also refresh / reset the session state
+                overlayedState.refresh();
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see ItemState#invalidate()
+     */
+    public void invalidate() {
+        if (isWorkspaceState()) {
+            // workspace state
+            setStatus(Status.INVALIDATED);
+        } else {
+            // todo only invalidate if existing?
+            if (getStatus() == Status.EXISTING) {
+                // set workspace state invalidated, this will in turn invalidate
+                // this (session) state as well
+                overlayedState.invalidate();
+            }
+        }
+    }
+
     //------------------------------------------------------< PropertyState >---
     /**
      * Returns the identifier of this property.

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=474207&r1=474206&r2=474207
==============================================================================
--- 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 Mon Nov 13 01:20:30 2006
@@ -24,6 +24,13 @@
     private static Logger log = LoggerFactory.getLogger(Status.class);
 
     /**
+     * A state once read from persistent storage has been set to invalid. This
+     * means that the state needs to be re-fetched from persistent storage when
+     * accessed the next time.
+     */
+    public static final int INVALIDATED = 0;
+
+    /**
      * 'existing', i.e. persistent state
      */
     public static final int EXISTING = 1;
@@ -93,10 +100,37 @@
         return status == EXISTING || status == EXISTING_MODIFIED || status == NEW;
     }
 
+    /**
+     * Returns <code>true</code> if <code>status</code> is one of:
+     * <ul>
+     * <li>{@link #STALE_DESTROYED}</li>
+     * <li>{@link #STALE_MODIFIED}</li>
+     * </ul>
+     *
+     * @param status the status to check.
+     * @return <code>true</code> if <code>status</code> indicates that an item
+     *         state is stale.
+     */
     public static boolean isStale(int status) {
         return status == STALE_DESTROYED || status == STALE_MODIFIED;
     }
 
+    /**
+     * Returns <code>true</code> if <code>status</code> is one of:
+     * <ul>
+     * <li>{@link #EXISTING_MODIFIED}</li>
+     * <li>{@link #EXISTING_REMOVED}</li>
+     * <li>{@link #NEW}</li>
+     * </ul>
+     *
+     * @param status the status to check.
+     * @return <code>true</code> if <code>status</code> indicates that an item
+     *         state is stale.
+     */
+    public static boolean isTransient(int status) {
+        return status == EXISTING_MODIFIED || status == EXISTING_REMOVED || status == NEW;
+    }
+
     public static boolean isValidStatusChange(int oldStatus, int newStatus,
                                               boolean isWorkspaceState) {
         if (oldStatus == newStatus) {
@@ -105,49 +139,67 @@
         boolean isValid = false;
         if (isWorkspaceState) {
             switch (newStatus) {
+                case INVALIDATED:
+                    isValid = (oldStatus == EXISTING);
+                    break;
                 case EXISTING:
                     isValid = (oldStatus == MODIFIED);
                     break;
                 case MODIFIED:
-                    isValid = (oldStatus == EXISTING);
+                    // temporary state when workspace state is updated or refreshed
+                    switch (oldStatus) {
+                        case EXISTING: // refresh of existing item state
+                        case INVALIDATED: // invalidated item state is refreshed
+                            isValid = true;
+                            break;
+                    }
                     break;
                 case REMOVED:
-                    isValid = (oldStatus == EXISTING);
+                    switch (oldStatus) {
+                        case EXISTING: // existing workspace state is externally removed
+                        case INVALIDATED: // invalidated item state is refreshed
+                            isValid = true;
+                            break;
+                    }
                     break;
                 // default: no other status possible : -> false
             }
         } else {
             switch (newStatus) {
-               case EXISTING:
-                   switch (oldStatus) {
-                       case NEW: /* save */
-                       case EXISTING_MODIFIED: /* save, revert */
-                       case EXISTING_REMOVED:  /* revert */
-                       case STALE_MODIFIED:    /* revert */
-                       case MODIFIED:
-                           isValid = true;
-                           break;
-                       /* REMOVED, STALE_DESTROYED -> false */
-                   }
-                   break;
-               case EXISTING_MODIFIED:
-                   isValid = (oldStatus == EXISTING);
-                   break;
-               case EXISTING_REMOVED:
-                   isValid = (oldStatus == EXISTING || oldStatus == EXISTING_MODIFIED);
-                   break;
-               case STALE_MODIFIED:
-               case STALE_DESTROYED:
-                   isValid = (oldStatus == EXISTING_MODIFIED);
-                   break;
-               case REMOVED:
-                   isValid = (oldStatus == NEW || oldStatus == EXISTING || oldStatus == EXISTING_REMOVED);
-                   break;
-               case MODIFIED:
-                   isValid = (oldStatus == EXISTING);
-                   break;
-                   /* default:
-                   NEW cannot change state to NEW -> false */
+                case INVALIDATED:
+                    isValid = (oldStatus == EXISTING); // invalidate
+                    break;
+                case EXISTING:
+                    switch (oldStatus) {
+                        case INVALIDATED: /* refresh */
+                        case NEW: /* save */
+                        case EXISTING_MODIFIED: /* save, revert */
+                        case EXISTING_REMOVED:  /* revert */
+                        case STALE_MODIFIED:    /* revert */
+                        case MODIFIED:
+                            isValid = true;
+                            break;
+                            /* REMOVED, STALE_DESTROYED -> false */
+                    }
+                    break;
+                case EXISTING_MODIFIED:
+                    isValid = (oldStatus == EXISTING);
+                    break;
+                case EXISTING_REMOVED:
+                    isValid = (oldStatus == EXISTING || oldStatus == EXISTING_MODIFIED);
+                    break;
+                case STALE_MODIFIED:
+                case STALE_DESTROYED:
+                    isValid = (oldStatus == EXISTING_MODIFIED);
+                    break;
+                case REMOVED:
+                    isValid = (oldStatus == NEW || oldStatus == EXISTING || oldStatus == EXISTING_REMOVED || oldStatus == INVALIDATED);
+                    break;
+                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/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=474207&r1=474206&r2=474207
==============================================================================
--- 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 Mon Nov 13 01:20:30 2006
@@ -313,6 +313,9 @@
                 // MODIFIED is only possible on EXISTING states -> thus, there
                 // must not be any transient modifications for that state.
                 // we ignore it.
+            case Status.INVALIDATED:
+                // only non transient states can change their status to
+                // invalidated -> nothing to do here.
                 break;
             default:
                 log.error("ItemState has invalid status: " + state.getStatus());