From oak-commits-return-2660-apmail-jackrabbit-oak-commits-archive=jackrabbit.apache.org@jackrabbit.apache.org Mon Jan 28 10:24:06 2013
Return-Path:
X-Original-To: apmail-jackrabbit-oak-commits-archive@minotaur.apache.org
Delivered-To: apmail-jackrabbit-oak-commits-archive@minotaur.apache.org
Received: from mail.apache.org (hermes.apache.org [140.211.11.3])
by minotaur.apache.org (Postfix) with SMTP id 5A5A9E786
for ; Mon, 28 Jan 2013 10:24:06 +0000 (UTC)
Received: (qmail 34667 invoked by uid 500); 28 Jan 2013 10:24:06 -0000
Delivered-To: apmail-jackrabbit-oak-commits-archive@jackrabbit.apache.org
Received: (qmail 34636 invoked by uid 500); 28 Jan 2013 10:24:05 -0000
Mailing-List: contact oak-commits-help@jackrabbit.apache.org; run by ezmlm
Precedence: bulk
List-Help:
List-Unsubscribe:
List-Post:
List-Id:
Reply-To: oak-dev@jackrabbit.apache.org
Delivered-To: mailing list oak-commits@jackrabbit.apache.org
Received: (qmail 34608 invoked by uid 99); 28 Jan 2013 10:24:04 -0000
Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136)
by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 28 Jan 2013 10:24:04 +0000
X-ASF-Spam-Status: No, hits=-2000.0 required=5.0
tests=ALL_TRUSTED
X-Spam-Check-By: apache.org
Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4)
by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 28 Jan 2013 10:24:02 +0000
Received: from eris.apache.org (localhost [127.0.0.1])
by eris.apache.org (Postfix) with ESMTP id D8C4723888FE;
Mon, 28 Jan 2013 10:23:43 +0000 (UTC)
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: svn commit: r1439331 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/index/p2/
test/java/org/apache/jackrabbit/oak/plugins/index/p2/
Date: Mon, 28 Jan 2013 10:23:43 -0000
To: oak-commits@jackrabbit.apache.org
From: alexparvulescu@apache.org
X-Mailer: svnmailer-1.0.8-patched
Message-Id: <20130128102343.D8C4723888FE@eris.apache.org>
X-Virus-Checked: Checked by ClamAV on apache.org
Author: alexparvulescu
Date: Mon Jan 28 10:23:43 2013
New Revision: 1439331
URL: http://svn.apache.org/viewvc?rev=1439331&view=rev
Log:
OAK-396
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2Index.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexDiff.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexUpdate.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2Index.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2Index.java?rev=1439331&r1=1439330&r2=1439331&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2Index.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2Index.java Mon Jan 28 10:23:43 2013
@@ -38,7 +38,7 @@ import com.google.common.base.Charsets;
*
* To define a property index on a subtree you have to add an oak:index node.
*
- * Under it follows the index definition node that:
+ * Next (as a child node) follows the index definition node that:
*
* - must be of type
oak:queryIndexDefinition
* - must have the
type property set to p2
@@ -46,10 +46,12 @@ import com.google.common.base.Charsets;
*
*
*
- * Optionally you can specify the uniqueness constraint on a property index by
- * setting the unique flag to true.
+ * Optionally you can specify
+ *
+ * - a uniqueness constraint on a property index by setting the
unique flag to true
+ * - that the property index only applies to a certain node type by setting the
declaringNodeTypes property
+ *
*
- *
*
* Note: propertyNames can be a list of properties, and it is optional.in case it is missing, the node name will be used as a property name reference value
*
@@ -66,6 +68,7 @@ import com.google.common.base.Charsets;
* .setProperty("jcr:primaryType", "oak:queryIndexDefinition", Type.NAME)
* .setProperty("type", "p2")
* .setProperty("propertyNames", "jcr:uuid")
+ * .setProperty("declaringNodeTypes", "mix:referenceable")
* .setProperty("unique", true)
* .setProperty("reindex", true);
* }
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexDiff.java?rev=1439331&r1=1439330&r2=1439331&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexDiff.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexDiff.java Mon Jan 28 10:23:43 2013
@@ -22,14 +22,16 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NODE_TYPE;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_PROPERTY_NAME;
import static org.apache.jackrabbit.oak.plugins.index.p2.Property2Index.TYPE;
+import static com.google.common.collect.Lists.newArrayList;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
+
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Type;
@@ -54,6 +56,11 @@ import org.apache.jackrabbit.oak.spi.sta
*/
class Property2IndexDiff implements IndexHook {
+ protected static String propertyNames = "propertyNames";
+
+ protected static String declaringNodeTypes = "declaringNodeTypes";
+
+
private final IndexStoreStrategy store = new ContentMirrorStoreStrategy();
/**
@@ -138,21 +145,45 @@ class Property2IndexDiff implements Inde
*/
private Iterable getIndexes(String name) {
List indexes = updates.get(name);
- if (indexes != null) {
- return indexes;
- } else {
+ if (indexes == null) {
return ImmutableList.of();
}
+ List filtered = new ArrayList();
+ for (Property2IndexUpdate pi : indexes) {
+ if (pi.getNodeTypeNames() == null
+ || pi.getNodeTypeNames().isEmpty()) {
+ filtered.add(pi);
+ continue;
+ }
+ PropertyState ps = node.getProperty(JCR_PRIMARYTYPE);
+ String type = ps != null && !ps.isArray() ? ps
+ .getValue(Type.STRING) : null;
+ if (type != null) {
+ for (String typeName : pi.getNodeTypeNames()) {
+ if (typeName.equals(type)) {
+ filtered.add(pi);
+ break;
+ }
+ }
+ }
+ }
+ return filtered;
}
private void update(NodeBuilder builder, String indexName) {
- PropertyState ps = builder.getProperty("propertyNames");
+ List typeNames = ImmutableList.of();
+ PropertyState appliesTo = builder.getProperty(declaringNodeTypes);
+ if (appliesTo != null) {
+ typeNames = newArrayList(appliesTo.getValue(Type.STRINGS));
+ }
+ PropertyState ps = builder.getProperty(propertyNames);
+
Iterable propertyNames = ps != null ? ps.getValue(Type.STRINGS)
: ImmutableList.of(indexName);
for (String pname : propertyNames) {
List list = this.updates.get(pname);
if (list == null) {
- list = Lists.newArrayList();
+ list = newArrayList();
this.updates.put(pname, list);
}
boolean exists = false;
@@ -163,7 +194,7 @@ class Property2IndexDiff implements Inde
}
}
if (!exists) {
- list.add(new Property2IndexUpdate(getPath(), builder, store));
+ list.add(new Property2IndexUpdate(getPath(), builder, store, typeNames));
}
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexUpdate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexUpdate.java?rev=1439331&r1=1439330&r2=1439331&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexUpdate.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexUpdate.java Mon Jan 28 10:23:43 2013
@@ -51,6 +51,13 @@ class Property2IndexUpdate {
private final String path;
/**
+ * The node types that this index applies to. If null or
+ * empty then the node type of the indexed node is ignored
+ *
+ */
+ private final List nodeTypeNames;
+
+ /**
* The node where the index definition is stored.
*/
private final NodeBuilder node;
@@ -69,18 +76,29 @@ class Property2IndexUpdate {
*/
private final Map> remove;
- public Property2IndexUpdate(String path, NodeBuilder node, IndexStoreStrategy store) {
+ public Property2IndexUpdate(String path, NodeBuilder node,
+ IndexStoreStrategy store) {
+ this(path, node, store, null);
+ }
+
+ public Property2IndexUpdate(String path, NodeBuilder node,
+ IndexStoreStrategy store, List nodeTypeNames) {
this.path = path;
this.node = node;
this.store = store;
this.insert = Maps.newHashMap();
this.remove = Maps.newHashMap();
+ this.nodeTypeNames = nodeTypeNames;
}
String getPath() {
return path;
}
+ public List getNodeTypeNames() {
+ return nodeTypeNames;
+ }
+
/**
* A property value was added at the given path.
*
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexTest.java?rev=1439331&r1=1439330&r2=1439331&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/p2/Property2IndexTest.java Mon Jan 28 10:23:43 2013
@@ -23,6 +23,7 @@ import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.Set;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.index.IndexHook;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
@@ -130,8 +131,105 @@ public class Property2IndexTest {
} catch (IllegalArgumentException e) {
// expected: no index for "pqr"
}
+ }
+
+ @Test
+ public void testUnique() throws Exception {
+
+ NodeState root = MemoryNodeState.EMPTY_NODE;
+
+ // Add index definition
+ NodeBuilder builder = root.builder();
+ builder.child("oak:index")
+ .child("fooIndex")
+ .setProperty("jcr:primaryType", "oak:queryIndexDefinition",
+ Type.NAME)
+ .setProperty("type", "p2")
+ .setProperty("unique", "true")
+ .setProperty("propertyNames", Arrays.asList("foo"),
+ Type.STRINGS);
+
+ NodeState before = builder.getNodeState();
+ builder = before.builder();
+ builder.child("a").setProperty("foo", "abc");
+ builder.child("b").setProperty("foo", Arrays.asList("abc", "def"),
+ Type.STRINGS);
+ NodeState after = builder.getNodeState();
+ IndexHook p = new Property2IndexDiff(builder);
+ after.compareAgainstBaseState(before, p);
+ try {
+ p.apply();
+ fail("Unique constraint should be respected");
+ } catch (CommitFailedException e) {
+ // expected
+ } finally {
+ p.close();
+ }
}
+ @Test
+ public void testUniqueByTypeOK() throws Exception {
+
+ NodeState root = MemoryNodeState.EMPTY_NODE;
+
+ // Add index definition
+ NodeBuilder builder = root.builder();
+ builder.child("oak:index").child("fooIndex")
+ .setProperty("jcr:primaryType", "oak:queryIndexDefinition", Type.NAME)
+ .setProperty("type", "p2")
+ .setProperty("unique", "true")
+ .setProperty("propertyNames", Arrays.asList("foo"), Type.STRINGS)
+ .setProperty(Property2IndexDiff.declaringNodeTypes, Arrays.asList("typeFoo"), Type.STRINGS);
+ NodeState before = builder.getNodeState();
+ builder = before.builder();
+ builder.child("a")
+ .setProperty("jcr:primaryType", "typeFoo", Type.NAME)
+ .setProperty("foo", "abc");
+ builder.child("b")
+ .setProperty("jcr:primaryType", "typeBar", Type.NAME)
+ .setProperty("foo", "abc");
+ NodeState after = builder.getNodeState();
+
+ IndexHook p = new Property2IndexDiff(builder);
+ after.compareAgainstBaseState(before, p);
+ p.apply();
+ p.close();
+ }
+
+ @Test
+ public void testUniqueByTypeKO() throws Exception {
+
+ NodeState root = MemoryNodeState.EMPTY_NODE;
+
+ // Add index definition
+ NodeBuilder builder = root.builder();
+ builder.child("oak:index").child("fooIndex")
+ .setProperty("jcr:primaryType", "oak:queryIndexDefinition", Type.NAME)
+ .setProperty("type", "p2")
+ .setProperty("unique", "true")
+ .setProperty("propertyNames", Arrays.asList("foo"), Type.STRINGS)
+ .setProperty(Property2IndexDiff.declaringNodeTypes, Arrays.asList("typeFoo"), Type.STRINGS);
+ NodeState before = builder.getNodeState();
+ builder = before.builder();
+ builder.child("a")
+ .setProperty("jcr:primaryType", "typeFoo", Type.NAME)
+ .setProperty("foo", "abc");
+ builder.child("b")
+ .setProperty("jcr:primaryType", "typeFoo", Type.NAME)
+ .setProperty("foo", "abc");
+ NodeState after = builder.getNodeState();
+
+ IndexHook p = new Property2IndexDiff(builder);
+ after.compareAgainstBaseState(before, p);
+ try {
+ p.apply();
+ fail("Unique constraint should be respected");
+ } catch (CommitFailedException e) {
+ // expected
+ } finally {
+ p.close();
+ }
+ }
}