Author: mduerig Date: Wed Jul 9 07:52:46 2014 New Revision: 1609046 URL: http://svn.apache.org/r1609046 Log: OAK-1669: JCR Event Info should contain NodeType for all Events
Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/differences.md jackrabbit/oak/trunk/oak-jcr/pom.xml jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFactory.java jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/QueueingHandler.java jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/differences.md URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/differences.md?rev=1609046&r1=1609045&r2=1609046&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-doc/src/site/markdown/differences.md (original) +++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/differences.md Wed Jul 9 07:52:46 2014 @@ -85,10 +85,9 @@ See the [query overview page](query.html Observation ----------- -* `Event.getInfo()` contains the primary and mixin node types of the added/removed node - in the case of `Event.NODE_ADDED` and `Event.NODE_REMOVED`. The key `jcr:primaryType` - maps to the primary type and the key `jcr:mixinTypes` maps to an array containing - the mixin types. +* `Event.getInfo()` contains the primary and mixin node types of the associated parent node of the + event. The key `jcr:primaryType` maps to the primary type and the key `jcr:mixinTypes` maps to an + array containing the mixin types. * `Event.getUserId()`, `Event.getUserData()`and `Event.getDate()` will only be available for locally generated events (i.e. on the same cluster node). To help identifying potential trouble spots, Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1609046&r1=1609045&r2=1609046&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/pom.xml (original) +++ jackrabbit/oak/trunk/oak-jcr/pom.xml Wed Jul 9 07:52:46 2014 @@ -69,8 +69,7 @@ org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testImplicitUnlock2 <!-- Observation --> - org.apache.jackrabbit.test.api.observation.GetInfoTest#testNodeAdded <!-- OAK-1661 --> - org.apache.jackrabbit.test.api.observation.GetInfoTest#testNodeRemoved <!-- OAK-1661 --> + org.apache.jackrabbit.test.api.observation.GetInfoTest <!-- OAK-1661, OAK-1669, uncomment if test expectations gets changed see JCR-3765 --> org.apache.jackrabbit.test.api.observation.NodeRemovedTest#testMultiNodesRemoved <!-- OAK-1459 --> org.apache.jackrabbit.test.api.observation.NodeMovedTest#testMoveWithRemove <!-- OAK-1459 --> org.apache.jackrabbit.test.api.observation.GetIdentifierTest#testNodeMoved <!-- Move in 2nd session not reflected in nodes of 1st session --> Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFactory.java?rev=1609046&r1=1609045&r2=1609046&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFactory.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFactory.java Wed Jul 9 07:52:46 2014 @@ -75,46 +75,49 @@ public class EventFactory { } } - Event propertyAdded(String path, String name, String identifier) { + Event propertyAdded( + final String primaryType, final Iterable<String> mixinTypes, + String path, String name, String identifier) { return new EventImpl(path, name, identifier) { @Override public int getType() { return PROPERTY_ADDED; } + @Override + public Map<?, ?> getInfo() { + return createInfoMap(primaryType, mixinTypes); + } }; } - Event propertyChanged(String path, String name, String identifier) { + Event propertyChanged( + final String primaryType, final Iterable<String> mixinTypes, + String path, String name, String identifier) { return new EventImpl(path, name, identifier) { @Override public int getType() { return PROPERTY_CHANGED; } + @Override + public Map<?, ?> getInfo() { + return createInfoMap(primaryType, mixinTypes); + } }; } - Event propertyDeleted(String path, String name, String identifier) { + Event propertyDeleted( + final String primaryType, final Iterable<String> mixinTypes, + String path, String name, String identifier) { return new EventImpl(path, name, identifier) { @Override public int getType() { return PROPERTY_REMOVED; } - }; - } - - private Map<String, ?> createInfoMap(String primaryType, Iterable<String> mixinTypes) { - if (isEmpty(mixinTypes)) { - return ImmutableMap.of( - JCR_PRIMARYTYPE, mapper.getJcrName(primaryType)); - } else { - List<String> jcrNames = Lists.newArrayList(); - for (String name : mixinTypes) { - jcrNames.add(mapper.getJcrName(name)); + @Override + public Map<?, ?> getInfo() { + return createInfoMap(primaryType, mixinTypes); } - return ImmutableMap.of( - JCR_PRIMARYTYPE, mapper.getJcrName(primaryType), - JCR_MIXINTYPES, toArray(jcrNames, String.class)); - } + }; } Event nodeAdded(final String primaryType, final Iterable<String> mixinTypes, @@ -146,6 +149,7 @@ public class EventFactory { } Event nodeMoved( + final String primaryType, final Iterable<String> mixinTypes, String parent, String name, String identifier, final String sourcePath) { return new EventImpl(parent, name, identifier) { @@ -155,14 +159,17 @@ public class EventFactory { } @Override public Map<?, ?> getInfo() { - return ImmutableMap.of( - "srcAbsPath", mapper.getJcrPath(sourcePath), - "destAbsPath", getPath()); + return ImmutableMap.builder() + .put("srcAbsPath", mapper.getJcrPath(sourcePath)) + .put("destAbsPath", getPath()) + .putAll(createInfoMap(primaryType, mixinTypes)) + .build(); } }; } Event nodeReordered( + final String primaryType, final Iterable<String> mixinTypes, String parent, String name, String identifier, final String destName) { return new EventImpl(parent, name, identifier) { @@ -172,13 +179,30 @@ public class EventFactory { } @Override public Map<?, ?> getInfo() { - return ImmutableMap.of( - "srcChildRelPath", mapper.getJcrName(name), - "destChildRelPath", mapper.getJcrName(destName)); + return ImmutableMap.builder() + .put("srcChildRelPath", mapper.getJcrName(name)) + .put("destChildRelPath", mapper.getJcrName(destName)) + .putAll(createInfoMap(primaryType, mixinTypes)) + .build(); } }; } + private Map<String, ?> createInfoMap(String primaryType, Iterable<String> mixinTypes) { + if (isEmpty(mixinTypes)) { + return ImmutableMap.of( + JCR_PRIMARYTYPE, mapper.getJcrName(primaryType)); + } else { + List<String> jcrNames = Lists.newArrayList(); + for (String name : mixinTypes) { + jcrNames.add(mapper.getJcrName(name)); + } + return ImmutableMap.of( + JCR_PRIMARYTYPE, mapper.getJcrName(primaryType), + JCR_MIXINTYPES, toArray(jcrNames, String.class)); + } + } + //---------------------------------------------------------< EventImpl >-- private abstract class EventImpl implements JackrabbitEvent { Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/QueueingHandler.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/QueueingHandler.java?rev=1609046&r1=1609045&r2=1609046&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/QueueingHandler.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/QueueingHandler.java Wed Jul 9 07:52:46 2014 @@ -44,6 +44,10 @@ class QueueingHandler extends DefaultEve private final PathTracker pathTracker; + private final String parentType; + + private final Iterable<String> parentMixins; + // need to track identifiers for both before and after trees, // to get correct identifiers for events in removed subtrees private final IdentifierTracker beforeIdentifierTracker; @@ -59,8 +63,12 @@ class QueueingHandler extends DefaultEve this.beforeIdentifierTracker = new IdentifierTracker(before); if (after.exists()) { this.identifierTracker = new IdentifierTracker(after); + this.parentType = getPrimaryType(after); + this.parentMixins = getMixinTypes(after); } else { this.identifierTracker = beforeIdentifierTracker; + this.parentType = getPrimaryType(before); + this.parentMixins = getMixinTypes(before); } } @@ -75,8 +83,12 @@ class QueueingHandler extends DefaultEve if (after.exists()) { this.identifierTracker = parent.identifierTracker.getChildTracker(name, after); + this.parentType = getPrimaryType(after); + this.parentMixins = getMixinTypes(after); } else { this.identifierTracker = beforeIdentifierTracker; + this.parentType = getPrimaryType(before); + this.parentMixins = getMixinTypes(before); } } @@ -91,6 +103,7 @@ class QueueingHandler extends DefaultEve @Override public void propertyAdded(PropertyState after) { queue.addEvent(factory.propertyAdded( + parentType, parentMixins, pathTracker.getPath(), after.getName(), identifierTracker.getIdentifier())); } @@ -98,6 +111,7 @@ class QueueingHandler extends DefaultEve @Override public void propertyChanged(PropertyState before, PropertyState after) { queue.addEvent(factory.propertyChanged( + parentType, parentMixins, pathTracker.getPath(), after.getName(), identifierTracker.getIdentifier())); } @@ -105,28 +119,11 @@ class QueueingHandler extends DefaultEve @Override public void propertyDeleted(PropertyState before) { queue.addEvent(factory.propertyDeleted( + parentType, parentMixins, pathTracker.getPath(), before.getName(), identifierTracker.getIdentifier())); } - private static String getPrimaryType(NodeState before) { - PropertyState primaryType = before.getProperty(JCR_PRIMARYTYPE); - if (primaryType != null && primaryType.getType() == NAME) { - return primaryType.getValue(NAME); - } else { - return null; - } - } - - private static Iterable<String> getMixinTypes(NodeState before) { - PropertyState mixinTypes = before.getProperty(JCR_MIXINTYPES); - if (mixinTypes != null && mixinTypes.getType() == NAMES) { - return mixinTypes.getValue(NAMES); - } else { - return emptyList(); - } - } - @Override public void nodeAdded(String name, NodeState after) { IdentifierTracker tracker = @@ -152,6 +149,7 @@ class QueueingHandler extends DefaultEve IdentifierTracker tracker = identifierTracker.getChildTracker(name, moved); queue.addEvent(factory.nodeMoved( + getPrimaryType(moved), getMixinTypes(moved), pathTracker.getPath(), name, tracker.getIdentifier(), sourcePath)); } @@ -162,8 +160,27 @@ class QueueingHandler extends DefaultEve IdentifierTracker tracker = identifierTracker.getChildTracker(name, reordered); queue.addEvent(factory.nodeReordered( + getPrimaryType(reordered), getMixinTypes(reordered), pathTracker.getPath(), name, tracker.getIdentifier(), destName)); } + private static String getPrimaryType(NodeState before) { + PropertyState primaryType = before.getProperty(JCR_PRIMARYTYPE); + if (primaryType != null && primaryType.getType() == NAME) { + return primaryType.getValue(NAME); + } else { + return null; + } + } + + private static Iterable<String> getMixinTypes(NodeState before) { + PropertyState mixinTypes = before.getProperty(JCR_MIXINTYPES); + if (mixinTypes != null && mixinTypes.getType() == NAMES) { + return mixinTypes.getValue(NAMES); + } else { + return emptyList(); + } + } + } Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java?rev=1609046&r1=1609045&r2=1609046&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java Wed Jul 9 07:52:46 2014 @@ -165,18 +165,38 @@ public class ObservationTest extends Abs @Test public void infoMap() throws RepositoryException, ExecutionException, InterruptedException { + Node n = getNode(TEST_PATH); + Node n3 = n.addNode("n3"); + n3.setProperty("p1", "q1"); + n3.setProperty("p2", "q2"); + getAdminSession().save(); + ExpectationListener listener = new ExpectationListener(); - observationManager.addEventListener(listener, NODE_ADDED, "/", true, null, null, false); + observationManager.addEventListener(listener, ALL_EVENTS, "/", true, null, null, false); try { - Node n = getNode(TEST_PATH); n.addNode("n1", "oak:Unstructured"); n.addNode("n2"); n.getNode("n2").addMixin(TEST_TYPE); + n3.setProperty("p1", "changed"); + n3.setProperty("p2", (String) null); listener.expect(new Expectation("infoMap for n1") { @Override public boolean onEvent(Event event) throws Exception { - if (event.getPath().endsWith("n1")) { + if (event.getType() == NODE_ADDED && event.getPath().endsWith("n1")) { + Map<?, ?> info = event.getInfo(); + return info != null && + "oak:Unstructured".equals(info.get(JCR_PRIMARYTYPE)); + } else { + return false; + } + } + }); + listener.expect(new Expectation("infoMap for n1/jcr:primaryType") { + @Override + public boolean onEvent(Event event) throws Exception { + if (event.getType() == PROPERTY_ADDED && + event.getPath().endsWith("n1/jcr:primaryType")) { Map<?, ?> info = event.getInfo(); return info != null && "oak:Unstructured".equals(info.get(JCR_PRIMARYTYPE)); @@ -189,7 +209,7 @@ public class ObservationTest extends Abs listener.expect(new Expectation("infoMap for n2") { @Override public boolean onEvent(Event event) throws Exception { - if (event.getPath().endsWith("n2")) { + if (event.getType() == NODE_ADDED && event.getPath().endsWith("n2")) { Map<?, ?> info = event.getInfo(); if (info == null) { return false; @@ -209,6 +229,47 @@ public class ObservationTest extends Abs } } }); + listener.expect(new Expectation("n2/jcr:primaryType") { + @Override + public boolean onEvent(Event event) throws Exception { + return event.getType() == PROPERTY_ADDED && + event.getPath().endsWith("n2/jcr:primaryType"); + } + }); + listener.expect(new Expectation("n2/jcr:mixinTypes") { + @Override + public boolean onEvent(Event event) throws Exception { + return event.getType() == PROPERTY_ADDED && + event.getPath().endsWith("n2/jcr:mixinTypes"); + } + }); + + listener.expect(new Expectation("infoMap for n3/p1") { + @Override + public boolean onEvent(Event event) throws Exception { + if (event.getType() == PROPERTY_CHANGED && + event.getPath().endsWith("n3/p1")) { + Map<?, ?> info = event.getInfo(); + return info != null && + NT_UNSTRUCTURED.equals(info.get(JCR_PRIMARYTYPE)); + } else { + return false; + } + } + }); + listener.expect(new Expectation("infoMap for n3/p2") { + @Override + public boolean onEvent(Event event) throws Exception { + if (event.getType() == PROPERTY_REMOVED && + event.getPath().endsWith("n3/p2")) { + Map<?, ?> info = event.getInfo(); + return info != null && + NT_UNSTRUCTURED.equals(info.get(JCR_PRIMARYTYPE)); + } else { + return false; + } + } + }); getAdminSession().save();