jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mreut...@apache.org
Subject svn commit: r156039 - in incubator/jackrabbit/trunk/src: java/org/apache/jackrabbit/core/ java/org/apache/jackrabbit/core/observation/ java/org/apache/jackrabbit/core/state/ test/org/apache/jackrabbit/test/api/observation/
Date Thu, 03 Mar 2005 14:05:39 GMT
Author: mreutegg
Date: Thu Mar  3 06:05:35 2005
New Revision: 156039

URL: http://svn.apache.org/viewcvs?view=rev&rev=156039
Log:
- Extended observation test cases
- fixed observation bug that caused ItemStateException in case a property is removed and added
again with the same name

Added:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ChangeLogBasedHierarchyMgr.java
  (with props)
Modified:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeRemovedTest.java
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyAddedTest.java
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyChangedTest.java

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java?view=diff&r1=156038&r2=156039
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java Thu
Mar  3 06:05:35 2005
@@ -954,7 +954,7 @@
 
         if (obsMgr == null) {
             try {
-                obsMgr = rep.getObservationManagerFactory(wspConfig.getName()).createObservationManager(session,
session.hierMgr, session.getItemManager());
+                obsMgr = rep.getObservationManagerFactory(wspConfig.getName()).createObservationManager(session,
session.getItemManager());
             } catch (NoSuchWorkspaceException nswe) {
                 // should never get here
                 String msg = "internal error: failed to instantiate observation manager";

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ChangeLogBasedHierarchyMgr.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ChangeLogBasedHierarchyMgr.java?view=auto&rev=156039
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ChangeLogBasedHierarchyMgr.java
(added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ChangeLogBasedHierarchyMgr.java
Thu Mar  3 06:05:35 2005
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.observation;
+
+import org.apache.jackrabbit.core.HierarchyManager;
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.HierarchyManagerImpl;
+import org.apache.jackrabbit.core.NamespaceResolver;
+import org.apache.jackrabbit.core.state.ChangeLog;
+import org.apache.jackrabbit.core.state.ItemStateManager;
+import org.apache.jackrabbit.core.state.ItemState;
+import org.apache.jackrabbit.core.state.NoSuchItemStateException;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NodeReferences;
+import org.apache.jackrabbit.core.state.NodeReferencesId;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * Implements a {@link HierarchyManager} that uses a {@link ChangeLog} for
+ * the 'transient' changes on an underlying {@link ItemStateManager}.
+ * {@link ItemState}s in attic are provided from the removed {@link ItemState}s
+ * in the {@link ChangeLog}. The modified and added {@link ItemState}s in
+ * the {@link ChangeLog} overlay the {@link ItemState}s in the
+ * {@link ItemStateManager}.
+ */
+class ChangeLogBasedHierarchyMgr extends HierarchyManagerImpl {
+
+    /**
+     * Creates a new <code>ChangeLogBasedHierarchyMgr</code> that overlays
+     * <code>manager</code> with <code>changes</code> and uses the
deleted
+     * map of the <code>changes</code> as an attic <code>ItemStateManager</code>.
+     * @param rootNodeUUID the uuid of the root node.
+     * @param manager the item state manager.
+     * @param changes the changes that will be applied on the item state manager.
+     * @param resolver the namespace resolver of the current session.
+     */
+    ChangeLogBasedHierarchyMgr(String rootNodeUUID,
+                               ItemStateManager manager,
+                               ChangeLog changes,
+                               NamespaceResolver resolver) {
+        super(rootNodeUUID,
+                new ChangeLogItemStateManager(manager, changes),
+                resolver,
+                new AtticItemStateManager(changes));
+    }
+
+    /**
+     * Implements an ItemStateManager that is overlayed by a ChangeLog.
+     */
+    private static class ChangeLogItemStateManager implements ItemStateManager {
+
+        /**
+         * The changes that will be applied to the {@link #base}.
+         */
+        private final ChangeLog changes;
+
+        /**
+         * The underlying {@link ItemStateManager}.
+         */
+        private final ItemStateManager base;
+
+        /**
+         * Creates a new <code>ChangeLogItemStateManager</code> that overlays
+         * the {@link ItemState}s in <code>base</code> with the one found in
+         * <code>changes</code>.
+         * @param base the underlying {@link ItemStateManager}.
+         * @param changes
+         */
+        private ChangeLogItemStateManager(ItemStateManager base, ChangeLog changes) {
+            this.base = base;
+            this.changes = changes;
+        }
+
+        /**
+         * Returns the {@link ItemState} with the <code>id</code>. This
+         * ItemState manager first looks up the <code>ChangeLog</code> and then
+         * tries to find the ItemState in the base {@link ItemStateManager}.
+         * @param id the id of the {@link ItemState}.
+         * @return the {@link ItemState} with <code>id</code>.
+         * @throws NoSuchItemStateException if there is no ItemState with
+         * <code>id</code>.
+         * @throws ItemStateException if any other error occurs.
+         */
+        public ItemState getItemState(ItemId id) throws NoSuchItemStateException, ItemStateException
{
+            // check ChangeLog first
+            try {
+                ItemState state = changes.get(id);
+                if (state != null) {
+                    return state;
+                }
+            } catch (NoSuchItemStateException e) {
+                // item has been deleted, but we still return it by asking base
+            }
+            return base.getItemState(id);
+        }
+
+        /**
+         * Returns <code>true</code> if there exists a {@link ItemState} either
+         * in the {@link ChangeLog} or the base {@link ItemStateManager};
+         * otherwise <code>false</code> is returned.
+         * @param id the id of the {@link ItemState}.
+         * @return <code>true</code> if there exists a {@link ItemState} either
+         * in the {@link ChangeLog} or the base {@link ItemStateManager};
+         * otherwise <code>false</code>.
+         */
+        public boolean hasItemState(ItemId id) {
+            // check ChangeLog first
+            try {
+                ItemState state = changes.get(id);
+                if (state != null) {
+                    return true;
+                }
+            } catch (NoSuchItemStateException e) {
+                // item has been deleted, but we still might return true by asking base
+            }
+            return base.hasItemState(id);
+        }
+
+        /**
+         * Always throws a {@link UnsupportedOperationException}.
+         */
+        public NodeReferences getNodeReferences(NodeReferencesId id)
+                throws NoSuchItemStateException, ItemStateException {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    /**
+     * Returns the removed {@link ItemState}s from the ChangeLog.
+     */
+    private static class AtticItemStateManager implements ItemStateManager {
+
+        /**
+         * Map of deleted {@link ItemState}s indexed by {@link ItemId}.
+         */
+        private final Map deleted = new HashMap();
+
+        /**
+         * Creates a new <code>AtticItemStateManager</code> based on
+         * <code>changes</code>.
+         * @param changes deleted {@link ItemState} are retrieved from this
+         *  <code>ChangeLog</code>.
+         */
+        private AtticItemStateManager(ChangeLog changes) {
+            for (Iterator it = changes.deletedStates(); it.hasNext();) {
+                ItemState state = (ItemState) it.next();
+                deleted.put(state.getId(), state);
+            }
+        }
+
+        /**
+         * Returns an {@link ItemState} it is found in the deleted map of the
+         * {@link ChangeLog}.
+         * @param id the id of the {@link ItemState}.
+         * @return the deleted {@link ItemState}.
+         * @throws NoSuchItemStateException if the {@link ItemState} cannot
+         * be found in the deleted map.
+         * @throws ItemStateException if any other error occurs.
+         */
+        public ItemState getItemState(ItemId id) throws NoSuchItemStateException, ItemStateException
{
+            ItemState state = (ItemState) deleted.get(id);
+            if (state != null) {
+                return state;
+            } else {
+                throw new NoSuchItemStateException();
+            }
+        }
+
+        /**
+         * Returns <code>true</code> if an {@link ItemState} with <code>id</code>
+         * is found in the deleted map of the {@link ChangeLog}; <code>false</code>
+         * otherwise.
+         * @param id the id of the {@link ItemState}.
+         * @return <code>true</code> if an {@link ItemState} with <code>id</code>
+         * is found in the deleted map of the {@link ChangeLog}; <code>false</code>
+         * otherwise.
+         */
+        public boolean hasItemState(ItemId id) {
+            return deleted.containsKey(id);
+        }
+
+        /**
+         * Always throws a {@link UnsupportedOperationException}.
+         */
+        public NodeReferences getNodeReferences(NodeReferencesId id)
+                throws NoSuchItemStateException, ItemStateException {
+            throw new UnsupportedOperationException();
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ChangeLogBasedHierarchyMgr.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java?view=diff&r1=156038&r2=156039
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
Thu Mar  3 06:05:35 2005
@@ -66,33 +66,32 @@
     private final SessionImpl session;
 
     /**
-     * The HierarchyManager of the session that creates the events.
-     */
-    private final HierarchyManager hmgr;
-
-    /**
      * Creates a new empty <code>EventStateCollection</code>.
      *
      * @param session the session that created these events.
      */
     EventStateCollection(ObservationManagerFactory dispatcher,
-                         SessionImpl session,
-                         HierarchyManager hmgr) {
+                         SessionImpl session) {
         this.dispatcher = dispatcher;
         this.session = session;
-        this.hmgr = hmgr;
     }
 
     /**
      * Creates {@link EventState} instances from <code>ItemState</code>
      * <code>changes</code>.
+     * @param rootNodeUUID the UUID of the root node.
      * @param changes the changes on <code>ItemState</code>s.
      * @param provider an <code>ItemStateProvider</code> to provide <code>ItemState</code>
      * of items that are not contained in the <code>changes</code> collection.
      * @throws ItemStateException if an error occurs while creating events
      * states for the item state changes.
      */
-    public void createEventStates(ChangeLog changes, ItemStateManager provider) throws ItemStateException
{
+    public void createEventStates(String rootNodeUUID, ChangeLog changes, ItemStateManager
provider) throws ItemStateException {
+        // create a hierarchy manager, that is based on the ChangeLog and
+        // the ItemStateProvider
+        // todo use CachingHierarchyManager ?
+        HierarchyManager hmgr = new ChangeLogBasedHierarchyMgr(rootNodeUUID, provider, changes,
session.getNamespaceResolver());
+
         for (Iterator it = changes.modifiedStates(); it.hasNext();) {
             ItemState state = (ItemState) it.next();
             if (state.isNode()) {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java?view=diff&r1=156038&r2=156039
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
Thu Mar  3 06:05:35 2005
@@ -21,7 +21,6 @@
 import org.apache.commons.collections.UnboundedFifoBuffer;
 import org.apache.log4j.Logger;
 import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.core.HierarchyManager;
 import org.apache.jackrabbit.core.ItemManager;
 
 import java.util.Collections;
@@ -141,9 +140,8 @@
      * @return an <code>ObservationManager</code>.
      */
     public ObservationManagerImpl createObservationManager(SessionImpl session,
-                                                           HierarchyManager hmgr,
                                                            ItemManager itemMgr) {
-        return new ObservationManagerImpl(this, session, hmgr, itemMgr);
+        return new ObservationManagerImpl(this, session, itemMgr);
     }
 
     /**

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerImpl.java?view=diff&r1=156038&r2=156039
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerImpl.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerImpl.java
Thu Mar  3 06:05:35 2005
@@ -11,14 +11,12 @@
  * accordance with the terms of the license agreement you entered into
  * with Day.
  */
-
 package org.apache.jackrabbit.core.observation;
 
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.ItemManager;
 import org.apache.jackrabbit.core.Path;
 import org.apache.jackrabbit.core.MalformedPathException;
-import org.apache.jackrabbit.core.HierarchyManager;
 import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
 import org.apache.log4j.Logger;
@@ -45,11 +43,6 @@
     private final SessionImpl session;
 
     /**
-     * The <code>HierarchyManager</code> of the session.
-     */
-    private final HierarchyManager hmgr;
-
-    /**
      * The <code>ItemManager</code> for this <code>ObservationManager</code>.
      */
     private final ItemManager itemMgr;
@@ -62,7 +55,6 @@
      *
      * @param session the <code>Session</code> this ObservationManager
      *                belongs to.
-     * @param hmgr    the <code>HierarchyManager</code> of the <code>session</code>.
      * @param itemMgr {@link org.apache.jackrabbit.core.ItemManager} of the passed
      *                <code>Session</code>.
      * @throws NullPointerException if <code>session</code> or <code>itemMgr</code>
@@ -70,7 +62,6 @@
      */
     ObservationManagerImpl(ObservationManagerFactory obsMgrFactory,
                            SessionImpl session,
-                           HierarchyManager hmgr,
                            ItemManager itemMgr) {
         if (session == null) {
             throw new NullPointerException("session");
@@ -81,7 +72,6 @@
 
         this.obsMgrFactory = obsMgrFactory;
         this.session = session;
-        this.hmgr = hmgr;
         this.itemMgr = itemMgr;
     }
 
@@ -159,7 +149,7 @@
      * @return a new <code>EventStateCollection</code>.
      */
     public EventStateCollection createEventStateCollection() {
-        return new EventStateCollection(obsMgrFactory, session, hmgr);
+        return new EventStateCollection(obsMgrFactory, session);
     }
 
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?view=diff&r1=156038&r2=156039
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
Thu Mar  3 06:05:35 2005
@@ -440,7 +440,7 @@
         EventStateCollection events = null;
         if (obsMgr != null) {
             events = obsMgr.createEventStateCollection();
-            events.createEventStates(local, this);
+            events.createEventStates(root.getUUID(), local, this);
             events.prepare();
         }
 

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeRemovedTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeRemovedTest.java?view=diff&r1=156038&r2=156039
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeRemovedTest.java
(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeRemovedTest.java
Thu Mar  3 06:05:35 2005
@@ -43,7 +43,7 @@
     public void testSingleNodeRemoved() throws RepositoryException {
         EventResult result = new EventResult(log);
         addEventListener(result, Event.NODE_REMOVED);
-        Node foo = testRootNode.addNode(nodeName1);
+        Node foo = testRootNode.addNode(nodeName1, testNodeType);
         testRootNode.save();
         foo.remove();
         testRootNode.save();
@@ -59,7 +59,7 @@
     public void testMultiNodesRemoved() throws RepositoryException {
         EventResult result = new EventResult(log);
         addEventListener(result, Event.NODE_REMOVED);
-        Node n1 = testRootNode.addNode(nodeName1);
+        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
         n1.addNode(nodeName2);
         testRootNode.save();
         n1.remove();

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyAddedTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyAddedTest.java?view=diff&r1=156038&r2=156039
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyAddedTest.java
(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyAddedTest.java
Thu Mar  3 06:05:35 2005
@@ -46,7 +46,7 @@
     public void testSystemGenerated() throws RepositoryException {
         EventResult result = new EventResult(log);
         addEventListener(result, Event.PROPERTY_ADDED);
-        testRootNode.addNode(nodeName1);
+        testRootNode.addNode(nodeName1, testNodeType);
         testRootNode.save();
         removeEventListener(result);
         Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
@@ -64,7 +64,7 @@
      * @throws RepositoryException
      */
     public void testSinglePropertyAdded() throws RepositoryException {
-        Node foo = testRootNode.addNode(nodeName1);
+        Node foo = testRootNode.addNode(nodeName1, testNodeType);
         testRootNode.save();
         EventResult result = new EventResult(log);
         addEventListener(result, Event.PROPERTY_ADDED);
@@ -80,7 +80,7 @@
      * when multiple properties are added.
      */
     public void testMultiPropertyAdded() throws RepositoryException {
-        Node foo = testRootNode.addNode(nodeName1);
+        Node foo = testRootNode.addNode(nodeName1, testNodeType);
         testRootNode.save();
         EventResult result = new EventResult(log);
         addEventListener(result, Event.PROPERTY_ADDED);

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyChangedTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyChangedTest.java?view=diff&r1=156038&r2=156039
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyChangedTest.java
(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyChangedTest.java
Thu Mar  3 06:05:35 2005
@@ -16,8 +16,14 @@
  */
 package org.apache.jackrabbit.test.api.observation;
 
+import org.apache.jackrabbit.test.NotExecutableException;
+
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
+import javax.jcr.PropertyType;
+import javax.jcr.StringValue;
+import javax.jcr.LongValue;
+import javax.jcr.nodetype.NodeType;
 import javax.jcr.observation.Event;
 
 /**
@@ -42,7 +48,7 @@
      * triggered when a single property is changed.
      */
     public void testSinglePropertyChanged() throws RepositoryException {
-        Node node = testRootNode.addNode(nodeName1);
+        Node node = testRootNode.addNode(nodeName1, testNodeType);
         node.setProperty(propertyName1, "foo");
         testRootNode.save();
         EventResult result = new EventResult(log);
@@ -60,7 +66,7 @@
      * @throws RepositoryException
      */
     public void testMultiPropertyChanged() throws RepositoryException {
-        Node node = testRootNode.addNode(nodeName1);
+        Node node = testRootNode.addNode(nodeName1, testNodeType);
         node.setProperty(propertyName1, "foo");
         node.setProperty(propertyName2, "bar");
         testRootNode.save();
@@ -80,7 +86,7 @@
      * triggered only for changed properties and not for new properties.
      */
     public void testSinglePropertyChangedWithAdded() throws RepositoryException {
-        Node node = testRootNode.addNode(nodeName1);
+        Node node = testRootNode.addNode(nodeName1, testNodeType);
         node.setProperty(propertyName1, "foo");
         testRootNode.save();
         EventResult result = new EventResult(log);
@@ -93,4 +99,49 @@
         checkPropertyChanged(events, new String[]{nodeName1 + "/" + propertyName1});
     }
 
+    /**
+     * Tests if either a
+     * <ul>
+     * <li>{@link Event#PROPERTY_CHANGED}</li>
+     * <li>{@link Event#PROPERTY_REMOVED} and {@link Event#PROPERTY_ADDED}</li>
+     * </ul>
+     * is triggered if a property is transiently removed and set again with
+     * the same name but different type and then saved.
+     * <p/>
+     * If the node type {@link #testNodeType} does not suppport a property with
+     * name {@link #propertyName1} of type {@link PropertyType#UNDEFINED} a
+     * {@link NotExecutableException} is thrown.
+     */
+    public void testPropertyRemoveCreate()
+            throws RepositoryException, NotExecutableException {
+        Node n = testRootNode.addNode(nodeName1, testNodeType);
+        NodeType nt = superuser.getWorkspace().getNodeTypeManager().getNodeType(testNodeType);
+        StringValue v1 = new StringValue("foo");
+        LongValue v2 = new LongValue(System.currentTimeMillis());
+        if (!nt.canSetProperty(propertyName1, v1) || !nt.canSetProperty(propertyName1, v2))
{
+            throw new NotExecutableException("Property " + propertyName1 + " is not of type
UNDEFINED");
+        }
+        n.setProperty(propertyName1, v1);
+        testRootNode.save();
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED);
+        n.getProperty(propertyName1).remove();
+        n.setProperty(propertyName1, v2);
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+
+        if (events.length == 1) {
+            checkPropertyChanged(events, new String[]{nodeName1 + "/" + propertyName1});
+        } else {
+            // prop remove and add event
+            assertEquals("Expected 2 events for a property type change.", 2, events.length);
+            int type = Event.PROPERTY_ADDED | Event.PROPERTY_REMOVED;
+            String path = testRoot + "/" + nodeName1 + "/" + propertyName1;
+            for (int i = 0; i < events.length; i++) {
+                assertTrue("Event is not of type PROPERTY_REMOVED or PROPERTY_ADDED", (events[i].getType()
& type) > 0);
+                assertEquals("Path for event is wrong.", path, events[i].getPath());
+            }
+        }
+    }
 }



Mime
View raw message