You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by al...@apache.org on 2011/10/12 15:53:10 UTC
svn commit: r1182367 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/query/lucene/
test/java/org/apache/jackrabbit/core/query/
test/java/org/apache/jackrabbit/core/query/lucene/
Author: alexparvulescu
Date: Wed Oct 12 13:53:09 2011
New Revision: 1182367
URL: http://svn.apache.org/viewvc?rev=1182367&view=rev
Log:
JCR-2989 Support for embedded index aggregates
Added:
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest2.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AggregateRule.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AggregateRuleImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/AbstractIndexingTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/IndexingQueueTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/TestAll.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AggregateRule.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AggregateRule.java?rev=1182367&r1=1182366&r2=1182367&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AggregateRule.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AggregateRule.java Wed Oct 12 13:53:09 2011
@@ -43,6 +43,14 @@ public interface AggregateRule {
*/
NodeState getAggregateRoot(NodeState nodeState)
throws ItemStateException, RepositoryException;
+
+ /**
+ * recursive aggregation (for same type nodes) limit. embedded aggregation
+ * of nodes that have the same type can go only this levels up.
+ *
+ * A value eq to 0 gives unlimited aggregation.
+ */
+ long getRecursiveAggregationLimit();
/**
* Returns the node states that are part of the indexing aggregate of the
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AggregateRuleImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AggregateRuleImpl.java?rev=1182367&r1=1182366&r2=1182367&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AggregateRuleImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AggregateRuleImpl.java Wed Oct 12 13:53:09 2011
@@ -16,32 +16,32 @@
*/
package org.apache.jackrabbit.core.query.lucene;
-import org.apache.jackrabbit.spi.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.jcr.NamespaceException;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.core.HierarchyManager;
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.core.id.PropertyId;
+import org.apache.jackrabbit.core.state.ChildNodeEntry;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.ItemStateManager;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.PropertyState;
import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.name.PathBuilder;
+import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
-import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.core.state.ItemStateManager;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.ChildNodeEntry;
-import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.HierarchyManager;
-import org.apache.jackrabbit.core.id.NodeId;
-import org.apache.jackrabbit.core.id.PropertyId;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.name.PathBuilder;
import org.apache.jackrabbit.util.Text;
+import org.w3c.dom.CharacterData;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import org.w3c.dom.CharacterData;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.NamespaceException;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Arrays;
/**
* <code>AggregateRule</code> defines a configuration for a node index
@@ -82,6 +82,30 @@ class AggregateRuleImpl implements Aggre
private final HierarchyManager hmgr;
/**
+ * recursive aggregation (for same type nodes) default value.
+ */
+ private static final boolean RECURSIVE_AGGREGATION_DEFAULT = false;
+
+ /**
+ * flag to enable recursive aggregation (for same type nodes).
+ */
+ private final boolean recursiveAggregation;
+
+ /**
+ * recursive aggregation (for same type nodes) limit default value.
+ */
+
+ protected static final long RECURSIVE_AGGREGATION_LIMIT_DEFAULT = 100;
+
+ /**
+ * recursive aggregation (for same type nodes) limit. embedded aggregation
+ * of nodes that have the same type can go only this levels up.
+ *
+ * A value eq to 0 gives unlimited aggregation.
+ */
+ private final long recursiveAggregationLimit;
+
+ /**
* Creates a new indexing aggregate using the given <code>config</code>.
*
* @param config the configuration for this indexing aggregate.
@@ -107,6 +131,8 @@ class AggregateRuleImpl implements Aggre
this.propertyIncludes = getPropertyIncludes(config);
this.ism = ism;
this.hmgr = hmgr;
+ this.recursiveAggregation = getRecursiveAggregation(config);
+ this.recursiveAggregationLimit = getRecursiveAggregationLimit(config);
}
/**
@@ -125,14 +151,21 @@ class AggregateRuleImpl implements Aggre
for (NodeInclude nodeInclude : nodeIncludes) {
NodeState aggregateRoot = nodeInclude.matches(nodeState);
if (aggregateRoot != null && aggregateRoot.getNodeTypeName().equals(nodeTypeName)) {
- return aggregateRoot;
+ boolean sameNodeTypeAsRoot = nodeState.getNodeTypeName().equals(aggregateRoot.getNodeTypeName());
+ if(!sameNodeTypeAsRoot || (sameNodeTypeAsRoot && recursiveAggregation)){
+ return aggregateRoot;
+ }
}
}
+
// check property includes
for (PropertyInclude propertyInclude : propertyIncludes) {
NodeState aggregateRoot = propertyInclude.matches(nodeState);
if (aggregateRoot != null && aggregateRoot.getNodeTypeName().equals(nodeTypeName)) {
- return aggregateRoot;
+ boolean sameNodeTypeAsRoot = nodeState.getNodeTypeName().equals(aggregateRoot.getNodeTypeName());
+ if(!sameNodeTypeAsRoot || (sameNodeTypeAsRoot && recursiveAggregation)){
+ return aggregateRoot;
+ }
}
}
return null;
@@ -153,7 +186,12 @@ class AggregateRuleImpl implements Aggre
if (nodeState.getNodeTypeName().equals(nodeTypeName)) {
List<NodeState> nodeStates = new ArrayList<NodeState>();
for (NodeInclude nodeInclude : nodeIncludes) {
- nodeStates.addAll(Arrays.asList(nodeInclude.resolve(nodeState)));
+ for (NodeState childNs : nodeInclude.resolve(nodeState)) {
+ boolean sameNodeTypeAsRoot = nodeState.getNodeTypeName().equals(childNs.getNodeTypeName());
+ if (!sameNodeTypeAsRoot || (sameNodeTypeAsRoot && recursiveAggregation)) {
+ nodeStates.add(childNs);
+ }
+ }
}
if (nodeStates.size() > 0) {
return nodeStates.toArray(new NodeState[nodeStates.size()]);
@@ -179,6 +217,13 @@ class AggregateRuleImpl implements Aggre
return null;
}
+ /**
+ * {@inheritDoc}
+ */
+ public long getRecursiveAggregationLimit() {
+ return recursiveAggregationLimit;
+ }
+
//---------------------------< internal >-----------------------------------
/**
@@ -269,7 +314,30 @@ class AggregateRuleImpl implements Aggre
}
return includes.toArray(new PropertyInclude[includes.size()]);
}
-
+
+ private boolean getRecursiveAggregation(Node config) {
+ Node rAttr = config.getAttributes().getNamedItem("recursive");
+ if (rAttr == null) {
+ return RECURSIVE_AGGREGATION_DEFAULT;
+ }
+ return Boolean.valueOf(rAttr.getNodeValue());
+ }
+
+ private long getRecursiveAggregationLimit(Node config)
+ throws RepositoryException {
+ Node rAttr = config.getAttributes().getNamedItem("recursiveLimit");
+ if (rAttr == null) {
+ return RECURSIVE_AGGREGATION_LIMIT_DEFAULT;
+ }
+ try {
+ return Long.valueOf(rAttr.getNodeValue());
+ } catch (NumberFormatException e) {
+ throw new RepositoryException(
+ "Unable to read indexing configuration (recursiveLimit).",
+ e);
+ }
+ }
+
//---------------------------< internal >-----------------------------------
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java?rev=1182367&r1=1182366&r2=1182367&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java Wed Oct 12 13:53:09 2011
@@ -1587,29 +1587,73 @@ public class SearchIndex extends Abstrac
/**
* Retrieves the root of the indexing aggregate for <code>state</code> and
- * puts it into <code>map</code>.
+ * puts it into <code>aggregates</code> map.
*
* @param state the node state for which we want to retrieve the aggregate
* root.
- * @param map aggregate roots are collected in this map.
+ * @param aggregates aggregate roots are collected in this map.
*/
- protected void retrieveAggregateRoot(
- NodeState state, Map<NodeId, NodeState> map) {
- if (indexingConfig != null) {
- AggregateRule[] aggregateRules = indexingConfig.getAggregateRules();
- if (aggregateRules == null) {
- return;
- }
+ protected void retrieveAggregateRoot(NodeState state,
+ Map<NodeId, NodeState> aggregates) {
+ retrieveAggregateRoot(state, aggregates, state.getNodeId().toString(), 0);
+ }
+
+ /**
+ * Retrieves the root of the indexing aggregate for <code>state</code> and
+ * puts it into <code>aggregates</code> map.
+ *
+ * @param state
+ * the node state for which we want to retrieve the aggregate
+ * root.
+ * @param aggregates
+ * aggregate roots are collected in this map.
+ * @param originNodeId
+ * the originating node, used for reporting only
+ * @param level
+ * current aggregation level, used to limit recursive aggregation
+ * of nodes that have the same type
+ */
+ private void retrieveAggregateRoot(NodeState state,
+ Map<NodeId, NodeState> aggregates, String originNodeId, long level) {
+ if (indexingConfig == null) {
+ return;
+ }
+ AggregateRule[] aggregateRules = indexingConfig.getAggregateRules();
+ if (aggregateRules == null) {
+ return;
+ }
+ for (AggregateRule aggregateRule : aggregateRules) {
+ NodeState root = null;
try {
- for (AggregateRule aggregateRule : aggregateRules) {
- NodeState root = aggregateRule.getAggregateRoot(state);
- if (root != null) {
- map.put(root.getNodeId(), root);
- }
- }
+ root = aggregateRule.getAggregateRoot(state);
} catch (Exception e) {
- log.warn("Unable to get aggregate root for "
- + state.getNodeId(), e);
+ log.warn("Unable to get aggregate root for " + state.getNodeId(), e);
+ }
+ if (root == null) {
+ continue;
+ }
+ if (root.getNodeTypeName().equals(state.getNodeTypeName())) {
+ level++;
+ } else {
+ level = 0;
+ }
+
+ // JCR-2989 Support for embedded index aggregates
+ if ((aggregateRule.getRecursiveAggregationLimit() == 0)
+ || (aggregateRule.getRecursiveAggregationLimit() != 0 && level <= aggregateRule
+ .getRecursiveAggregationLimit())) {
+
+ // check if the update parent is already in the
+ // map, then all its parents are already there so I can
+ // skip this update subtree
+ if (aggregates.put(root.getNodeId(), root) == null) {
+ retrieveAggregateRoot(root, aggregates, originNodeId, level);
+ }
+ } else {
+ log.warn(
+ "Reached {} levels of recursive aggregation for nodeId {}, type {}, will stop at nodeId {}. Are you sure this did not occur by mistake? Please check the indexing-configuration.xml.",
+ new Object[] { level, originNodeId,
+ root.getNodeTypeName(), root.getNodeId() });
}
}
}
@@ -1618,11 +1662,11 @@ public class SearchIndex extends Abstrac
* Retrieves the root of the indexing aggregate for <code>removedIds</code>
* and puts it into <code>map</code>.
*
- * @param removedIds the ids of removed nodes.
- * @param map aggregate roots are collected in this map
+ * @param removedIds the ids of removed nodes.
+ * @param aggregates aggregate roots are collected in this map
*/
protected void retrieveAggregateRoot(
- Set<NodeId> removedIds, Map<NodeId, NodeState> map) {
+ Set<NodeId> removedIds, Map<NodeId, NodeState> aggregates) {
if(removedIds.isEmpty() || indexingConfig == null){
return;
}
@@ -1648,8 +1692,14 @@ public class SearchIndex extends Abstrac
Document doc = reader.document(
tDocs.doc(), FieldSelectors.UUID);
NodeId nId = new NodeId(doc.get(FieldNames.UUID));
- map.put(nId, (NodeState) ism.getItemState(nId));
+ NodeState nodeState = (NodeState) ism.getItemState(nId);
+ aggregates.put(nId, nodeState);
found++;
+
+ // JCR-2989 Support for embedded index aggregates
+ int sizeBefore = aggregates.size();
+ retrieveAggregateRoot(nodeState, aggregates);
+ found += aggregates.size() - sizeBefore;
}
}
} finally {
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/AbstractIndexingTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/AbstractIndexingTest.java?rev=1182367&r1=1182366&r2=1182367&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/AbstractIndexingTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/AbstractIndexingTest.java Wed Oct 12 13:53:09 2011
@@ -16,8 +16,8 @@
*/
package org.apache.jackrabbit.core.query;
-import javax.jcr.Session;
import javax.jcr.Node;
+import javax.jcr.Session;
/**
* <code>AbstractIndexingTest</code> is a base class for all indexing
@@ -25,7 +25,7 @@ import javax.jcr.Node;
*/
public class AbstractIndexingTest extends AbstractQueryTest {
- protected static final String WORKSPACE_NAME = "indexing-test";
+ private static final String WORKSPACE_NAME = "indexing-test";
protected Session session;
@@ -33,7 +33,7 @@ public class AbstractIndexingTest extend
protected void setUp() throws Exception {
super.setUp();
- session = getHelper().getSuperuserSession(WORKSPACE_NAME);
+ session = getHelper().getSuperuserSession(getWorkspaceName());
testRootNode = cleanUpTestRoot(session);
// overwrite query manager
qm = session.getWorkspace().getQueryManager();
@@ -48,4 +48,8 @@ public class AbstractIndexingTest extend
testRootNode = null;
super.tearDown();
}
+
+ protected String getWorkspaceName() {
+ return WORKSPACE_NAME;
+ }
}
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/IndexingQueueTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/IndexingQueueTest.java?rev=1182367&r1=1182366&r2=1182367&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/IndexingQueueTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/IndexingQueueTest.java Wed Oct 12 13:53:09 2011
@@ -86,7 +86,7 @@ public class IndexingQueueTest extends A
session = null;
superuser.logout();
superuser = null;
- TestHelper.shutdownWorkspace(WORKSPACE_NAME, repo);
+ TestHelper.shutdownWorkspace(getWorkspaceName(), repo);
// delete index
try {
@@ -101,7 +101,7 @@ public class IndexingQueueTest extends A
Thread t = new Thread(new Runnable() {
public void run() {
try {
- session = getHelper().getSuperuserSession(WORKSPACE_NAME);
+ session = getHelper().getSuperuserSession(getWorkspaceName());
} catch (RepositoryException e) {
throw new RuntimeException(e);
}
@@ -142,7 +142,7 @@ public class IndexingQueueTest extends A
session = null;
superuser.logout();
superuser = null;
- TestHelper.shutdownWorkspace(WORKSPACE_NAME, repo);
+ TestHelper.shutdownWorkspace(getWorkspaceName(), repo);
// delete index
try {
@@ -153,7 +153,7 @@ public class IndexingQueueTest extends A
BlockingParser.unblock();
// start workspace again by getting a session
- session = getHelper().getSuperuserSession(WORKSPACE_NAME);
+ session = getHelper().getSuperuserSession(getWorkspaceName());
qm = session.getWorkspace().getQueryManager();
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest.java?rev=1182367&r1=1182366&r2=1182367&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest.java Wed Oct 12 13:53:09 2011
@@ -22,18 +22,23 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
+import java.util.ArrayList;
import java.util.Calendar;
+import java.util.List;
import javax.jcr.Node;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.input.NullInputStream;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.core.query.AbstractIndexingTest;
/**
- * <code>IndexingAggregateTest</code> checks if the nt:file nt:resource
- * aggregate defined in workspace indexing-test works properly.
+ * <code>SQL2IndexingAggregateTest</code> checks if aggregation rules defined in
+ * workspace indexing-test work properly.
+ *
+ * See src/test/repository/workspaces/indexing-test/indexing-configuration.xml
*/
public class SQL2IndexingAggregateTest extends AbstractIndexingTest {
@@ -46,6 +51,112 @@ public class SQL2IndexingAggregateTest e
testRootNode.getSession().save();
}
+ /**
+ *
+ * this test is very similar to
+ * {@link SQL2IndexingAggregateTest#testNtFileAggregate()
+ * testNtFileAggregate} but checks embedded index aggregates.
+ *
+ * The aggregation hierarchy is defined in
+ * src/test/repository/workspaces/indexing-test/indexing-configuration.xml
+ *
+ * basically a folder aggregates other folders and files that aggregate a
+ * stream of content.
+ *
+ * see <a href="https://issues.apache.org/jira/browse/JCR-2989">JCR-2989</a>
+ *
+ * nt:folder: recursive="true" recursiveLimit="10"
+ *
+ */
+ @SuppressWarnings("unchecked")
+ public void testDeepHierarchy() throws Exception {
+
+ // this parameter IS the 'recursiveLimit' defined in the index
+ // config file
+ int definedRecursiveLimit = 10;
+ int levelsDeep = 14;
+
+ List<Node> allNodes = new ArrayList<Node>();
+ List<Node> updatedNodes = new ArrayList<Node>();
+ List<Node> staleNodes = new ArrayList<Node>();
+
+ String sqlBase = "SELECT * FROM [nt:folder] as f WHERE ";
+ String sqlCat = sqlBase + " CONTAINS (f.*, 'cat')";
+ String sqlDog = sqlBase + " CONTAINS (f.*, 'dog')";
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Writer writer = new OutputStreamWriter(out, "UTF-8");
+ writer.write("the quick brown fox jumps over the lazy dog.");
+ writer.flush();
+
+ Node folderRoot = testRootNode.addNode("myFolder", "nt:folder");
+ Node folderChild = folderRoot;
+ allNodes.add(folderChild);
+
+ for (int i = 0; i < levelsDeep; i++) {
+ folderChild.addNode("0" + i + "-dummy", "nt:folder");
+ folderChild = folderChild.addNode("0" + i, "nt:folder");
+ allNodes.add(folderChild);
+
+ // -2 because:
+ // 1 because 'i' starts at 0,
+ // +
+ // 1 because we are talking about same node type aggregation levels
+ // extra to the current node that is updated
+ if (i > levelsDeep - definedRecursiveLimit - 2) {
+ updatedNodes.add(folderChild);
+ }
+ }
+ staleNodes.addAll(CollectionUtils.disjunction(allNodes, updatedNodes));
+
+ Node file = folderChild.addNode("myFile", "nt:file");
+ Node resource = file.addNode("jcr:content", "nt:resource");
+ resource.setProperty("jcr:lastModified", Calendar.getInstance());
+ resource.setProperty("jcr:encoding", "UTF-8");
+ resource.setProperty("jcr:mimeType", "text/plain");
+ resource.setProperty("jcr:data", session.getValueFactory()
+ .createBinary(new ByteArrayInputStream(out.toByteArray())));
+
+ testRootNode.getSession().save();
+
+ // because of the optimizations, the first save is expected to update
+ // ALL nodes
+ // executeSQL2Query(sqlDog, allNodes.toArray(new Node[] {}));
+
+ // update jcr:data
+ out.reset();
+ writer.write("the quick brown fox jumps over the lazy cat.");
+ writer.flush();
+ resource.setProperty("jcr:data", session.getValueFactory()
+ .createBinary(new ByteArrayInputStream(out.toByteArray())));
+ testRootNode.getSession().save();
+ executeSQL2Query(sqlDog, staleNodes.toArray(new Node[] {}));
+ executeSQL2Query(sqlCat, updatedNodes.toArray(new Node[] {}));
+
+ // replace jcr:content with unstructured
+ resource.remove();
+ Node unstrContent = file.addNode("jcr:content", "nt:unstructured");
+ Node foo = unstrContent.addNode("foo");
+ foo.setProperty("text", "the quick brown fox jumps over the lazy dog.");
+ testRootNode.getSession().save();
+ executeSQL2Query(sqlDog, allNodes.toArray(new Node[] {}));
+ executeSQL2Query(sqlCat, new Node[] {});
+
+ // remove foo
+ foo.remove();
+ testRootNode.getSession().save();
+ executeSQL2Query(sqlDog, staleNodes.toArray(new Node[] {}));
+ executeSQL2Query(sqlCat, new Node[] {});
+
+ }
+
+ /**
+ * simple index aggregation from jcr:content to nt:file
+ *
+ * The aggregation hierarchy is defined in
+ * src/test/repository/workspaces/indexing-test/indexing-configuration.xml
+ *
+ */
public void testNtFileAggregate() throws Exception {
String sqlBase = "SELECT * FROM [nt:file] as f"
@@ -75,6 +186,7 @@ public class SQL2IndexingAggregateTest e
resource.setProperty("jcr:data", session.getValueFactory()
.createBinary(new ByteArrayInputStream(out.toByteArray())));
testRootNode.getSession().save();
+ executeSQL2Query(sqlDog, new Node[] {});
executeSQL2Query(sqlCat, new Node[] { file });
// replace jcr:content with unstructured
@@ -84,12 +196,13 @@ public class SQL2IndexingAggregateTest e
foo.setProperty("text", "the quick brown fox jumps over the lazy dog.");
testRootNode.getSession().save();
executeSQL2Query(sqlDog, new Node[] { file });
+ executeSQL2Query(sqlCat, new Node[] {});
// remove foo
foo.remove();
testRootNode.getSession().save();
-
executeSQL2Query(sqlDog, new Node[] {});
+ executeSQL2Query(sqlCat, new Node[] {});
// replace jcr:content again with resource
unstrContent.remove();
@@ -100,11 +213,88 @@ public class SQL2IndexingAggregateTest e
resource.setProperty("jcr:data", session.getValueFactory()
.createBinary(new ByteArrayInputStream(out.toByteArray())));
testRootNode.getSession().save();
+ executeSQL2Query(sqlDog, new Node[] {});
executeSQL2Query(sqlCat, new Node[] { file });
}
/**
+ * By default, the recursive aggregation is turned off.
+ *
+ * The aggregation hierarchy is defined in
+ * src/test/repository/workspaces/indexing-test/indexing-configuration.xml
+ */
+ public void testDefaultRecursiveAggregation() throws Exception {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Writer writer = new OutputStreamWriter(out, "UTF-8");
+ writer.write("the quick brown fox jumps over the lazy dog.");
+ writer.flush();
+
+ Node parent = testRootNode.addNode(
+ "testDefaultRecursiveAggregation_parent",
+ JcrConstants.NT_UNSTRUCTURED);
+
+ Node child = parent.addNode("testDefaultRecursiveAggregation_child",
+ JcrConstants.NT_UNSTRUCTURED);
+ child.setProperty("type", "testnode");
+ child.setProperty("jcr:encoding", "UTF-8");
+ child.setProperty("jcr:mimeType", "text/plain");
+ child.setProperty(
+ "jcr:data",
+ session.getValueFactory().createBinary(
+ new ByteArrayInputStream(out.toByteArray())));
+ testRootNode.getSession().save();
+
+ String sqlBase = "SELECT * FROM [nt:unstructured] as u WHERE CONTAINS (u.*, 'dog') ";
+ String sqlParent = sqlBase + " AND ISCHILDNODE([" + testRoot + "])";
+ String sqlChild = sqlBase + " AND ISCHILDNODE([" + parent.getPath()
+ + "])";
+
+ executeSQL2Query(sqlParent, new Node[] {});
+ executeSQL2Query(sqlChild, new Node[] { child });
+ }
+
+ /**
+ * Tests that even if there is a rule to include same type node aggregates
+ * by property name, the recursive flag will still ignore them.
+ *
+ * It should issue a log warning, though.
+ *
+ * The aggregation hierarchy is defined in
+ * src/test/repository/workspaces/indexing-test/indexing-configuration.xml
+ */
+ public void testRecursiveAggregationExclusion() throws Exception {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Writer writer = new OutputStreamWriter(out, "UTF-8");
+ writer.write("the quick brown fox jumps over the lazy dog.");
+ writer.flush();
+
+ Node parent = testRootNode.addNode(
+ "testDefaultRecursiveAggregation_parent",
+ JcrConstants.NT_UNSTRUCTURED);
+
+ Node child = parent.addNode("aggregated-node",
+ JcrConstants.NT_UNSTRUCTURED);
+ child.setProperty("type", "testnode");
+ child.setProperty("jcr:encoding", "UTF-8");
+ child.setProperty("jcr:mimeType", "text/plain");
+ child.setProperty(
+ "jcr:data",
+ session.getValueFactory().createBinary(
+ new ByteArrayInputStream(out.toByteArray())));
+ testRootNode.getSession().save();
+
+ String sqlBase = "SELECT * FROM [nt:unstructured] as u WHERE CONTAINS (u.*, 'dog') ";
+ String sqlParent = sqlBase + " AND ISCHILDNODE([" + testRoot + "])";
+ String sqlChild = sqlBase + " AND ISCHILDNODE([" + parent.getPath()
+ + "])";
+ executeSQL2Query(sqlParent, new Node[] {});
+ executeSQL2Query(sqlChild, new Node[] { child });
+ }
+
+ /**
* checks that while text extraction runs in the background, the node is
* available for query on any of its properties
*
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest2.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest2.java?rev=1182367&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest2.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest2.java Wed Oct 12 13:53:09 2011
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * 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.core.query.lucene;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import javax.jcr.Node;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.jackrabbit.core.query.AbstractIndexingTest;
+
+/**
+ * <code>SQL2IndexingAggregateTest2</code> checks if aggregation rules defined
+ * in workspace indexing-test-2 work properly.
+ *
+ * See src/test/repository/workspaces/indexing-test-2/indexing-configuration.xml
+ */
+public class SQL2IndexingAggregateTest2 extends AbstractIndexingTest {
+
+ protected static final String WORKSPACE_NAME_NEW = "indexing-test-2";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ for (Node c : JcrUtils.getChildNodes(testRootNode)) {
+ testRootNode.getSession().removeItem(c.getPath());
+ }
+ testRootNode.getSession().save();
+ }
+
+ @Override
+ protected String getWorkspaceName() {
+ return WORKSPACE_NAME_NEW;
+ }
+
+ /**
+ * recursive="true" recursiveLimit="-1"
+ *
+ * The aggregation hierarchy is defined in
+ * src/test/repository/workspaces/indexing-test-2/indexing-configuration.xml
+ *
+ * see <a href="https://issues.apache.org/jira/browse/JCR-2989">JCR-2989</a>
+ */
+ public void testNegativeRecursiveAggregationLimit() throws Exception {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Writer writer = new OutputStreamWriter(out, "UTF-8");
+ writer.write("the quick brown fox jumps over the lazy dog.");
+ writer.flush();
+
+ Node parent = testRootNode.addNode(
+ "testDefaultRecursiveAggregation_parent",
+ JcrConstants.NT_UNSTRUCTURED);
+
+ Node child = parent.addNode("testDefaultRecursiveAggregation_child",
+ JcrConstants.NT_UNSTRUCTURED);
+ child.setProperty("type", "testnode");
+ child.setProperty("jcr:encoding", "UTF-8");
+ child.setProperty("jcr:mimeType", "text/plain");
+ child.setProperty(
+ "jcr:data",
+ session.getValueFactory().createBinary(
+ new ByteArrayInputStream(out.toByteArray())));
+ testRootNode.getSession().save();
+
+ String sqlBase = "SELECT * FROM [nt:unstructured] as u WHERE CONTAINS (u.*, 'dog') ";
+ String sqlParent = sqlBase + " AND ISCHILDNODE([" + testRoot + "])";
+ String sqlChild = sqlBase + " AND ISCHILDNODE([" + parent.getPath()
+ + "])";
+
+ executeSQL2Query(sqlParent, new Node[] {});
+ executeSQL2Query(sqlChild, new Node[] { child });
+ }
+
+ /**
+ * this should traverse the *entire* hierarchy to aggregate indexes
+ *
+ * see <a href="https://issues.apache.org/jira/browse/JCR-2989">JCR-2989</a>
+ */
+ public void testUnlimitedRecursiveAggregation() throws Exception {
+
+ long levelsDeep = AggregateRuleImpl.RECURSIVE_AGGREGATION_LIMIT_DEFAULT + 10;
+ List<Node> expectedNodes = new ArrayList<Node>();
+
+ String sqlBase = "SELECT * FROM [nt:folder] as f WHERE ";
+ String sqlCat = sqlBase + " CONTAINS (f.*, 'cat')";
+ String sqlDog = sqlBase + " CONTAINS (f.*, 'dog')";
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Writer writer = new OutputStreamWriter(out, "UTF-8");
+ writer.write("the quick brown fox jumps over the lazy dog.");
+ writer.flush();
+
+ Node folderRoot = testRootNode.addNode("myFolder", "nt:folder");
+ Node folderChild = folderRoot;
+ expectedNodes.add(folderChild);
+
+ for (int i = 0; i < levelsDeep; i++) {
+ folderChild.addNode("0" + i + "-dummy", "nt:folder");
+ folderChild = folderChild.addNode("0" + i, "nt:folder");
+ expectedNodes.add(folderChild);
+ }
+
+ Node file = folderChild.addNode("myFile", "nt:file");
+ Node resource = file.addNode("jcr:content", "nt:resource");
+ resource.setProperty("jcr:lastModified", Calendar.getInstance());
+ resource.setProperty("jcr:encoding", "UTF-8");
+ resource.setProperty("jcr:mimeType", "text/plain");
+ resource.setProperty("jcr:data", session.getValueFactory()
+ .createBinary(new ByteArrayInputStream(out.toByteArray())));
+
+ testRootNode.getSession().save();
+ executeSQL2Query(sqlDog, expectedNodes.toArray(new Node[] {}));
+
+ // update jcr:data
+ out.reset();
+ writer.write("the quick brown fox jumps over the lazy cat.");
+ writer.flush();
+ resource.setProperty("jcr:data", session.getValueFactory()
+ .createBinary(new ByteArrayInputStream(out.toByteArray())));
+ testRootNode.getSession().save();
+ executeSQL2Query(sqlDog, new Node[] {});
+ executeSQL2Query(sqlCat, expectedNodes.toArray(new Node[] {}));
+
+ // replace jcr:content with unstructured
+ resource.remove();
+ Node unstrContent = file.addNode("jcr:content", "nt:unstructured");
+ Node foo = unstrContent.addNode("foo");
+ foo.setProperty("text", "the quick brown fox jumps over the lazy dog.");
+ testRootNode.getSession().save();
+ executeSQL2Query(sqlDog, expectedNodes.toArray(new Node[] {}));
+ executeSQL2Query(sqlCat, new Node[] {});
+
+ // remove foo
+ foo.remove();
+ testRootNode.getSession().save();
+ executeSQL2Query(sqlDog, new Node[] {});
+ executeSQL2Query(sqlCat, new Node[] {});
+
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/SQL2IndexingAggregateTest2.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/TestAll.java?rev=1182367&r1=1182366&r2=1182367&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/TestAll.java Wed Oct 12 13:53:09 2011
@@ -43,6 +43,7 @@ public class TestAll extends TestCase {
suite.addTestSuite(ChainedTermEnumTest.class);
suite.addTestSuite(IndexingConfigurationImplTest.class);
suite.addTestSuite(SQL2IndexingAggregateTest.class);
+ suite.addTestSuite(SQL2IndexingAggregateTest2.class);
return suite;
}