You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ch...@apache.org on 2016/12/07 09:27:47 UTC

svn commit: r1773034 - in /jackrabbit/oak/trunk/oak-lucene/src: main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java

Author: chetanm
Date: Wed Dec  7 09:27:47 2016
New Revision: 1773034

URL: http://svn.apache.org/viewvc?rev=1773034&view=rev
Log:
OAK-5234 - IndexDefinitionBuilder should be able to work with existing NodeBuilder

Modified:
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java?rev=1773034&r1=1773033&r2=1773034&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java Wed Dec  7 09:27:47 2016
@@ -29,11 +29,13 @@ import javax.jcr.RepositoryException;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
 import org.apache.jackrabbit.oak.plugins.index.PathFilter;
 import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants;
 import org.apache.jackrabbit.oak.plugins.tree.TreeFactory;
+import org.apache.jackrabbit.oak.spi.state.EqualsDiff;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
@@ -46,20 +48,35 @@ import static org.apache.jackrabbit.oak.
 import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
 
 public final class IndexDefinitionBuilder {
-    private final NodeBuilder builder = EMPTY_NODE.builder();
-    private final Tree tree = TreeFactory.createTree(builder);
+    private final NodeBuilder builder;
+    private final Tree tree;
     private final Map<String, IndexRule> rules = Maps.newHashMap();
     private final Map<String, AggregateRule> aggRules = Maps.newHashMap();
     private final Tree indexRule;
+    private final boolean autoManageReindexFlag;
     private Tree aggregatesTree;
+    private final NodeState initial;
+    private boolean reindexRequired;
+
 
     public IndexDefinitionBuilder(){
+        this(EMPTY_NODE.builder());
+    }
+
+    public IndexDefinitionBuilder(NodeBuilder nodeBuilder){
+        this(nodeBuilder, true);
+    }
+
+    public IndexDefinitionBuilder(NodeBuilder nodeBuilder, boolean autoManageReindexFlag){
+        this.autoManageReindexFlag = autoManageReindexFlag;
+        this.builder = nodeBuilder;
+        this.initial = nodeBuilder.getNodeState();
+        this.tree = TreeFactory.createTree(builder);
         tree.setProperty(LuceneIndexConstants.COMPAT_MODE, 2);
         tree.setProperty("async", "async");
-        tree.setProperty("reindex", true);
         tree.setProperty(IndexConstants.TYPE_PROPERTY_NAME, "lucene");
         tree.setProperty(JCR_PRIMARYTYPE, "oak:QueryIndexDefinition", NAME);
-        indexRule = createChild(tree, LuceneIndexConstants.INDEX_RULES);
+        indexRule = getOrCreateChild(tree, LuceneIndexConstants.INDEX_RULES);
     }
 
     public IndexDefinitionBuilder evaluatePathRestrictions(){
@@ -98,31 +115,49 @@ public final class IndexDefinitionBuilde
     }
 
     public NodeState build(){
+        setReindexFlagIfRequired();
         return builder.getNodeState();
     }
 
     public Tree build(Tree tree){
-        NodeStateCopyUtils.copyToTree(builder.getNodeState(), tree);
+        NodeStateCopyUtils.copyToTree(build(), tree);
         return tree;
     }
 
     public Node build(Node node) throws RepositoryException {
-        NodeStateCopyUtils.copyToNode(builder.getNodeState(), node);
+        NodeStateCopyUtils.copyToNode(build(), node);
         return node;
     }
 
+    public boolean isReindexRequired() {
+        if (reindexRequired){
+            return true;
+        }
+        return !EqualsDiff.equals(initial, builder.getNodeState());
+    }
+
+    private void setReindexFlagIfRequired(){
+        if (!reindexRequired && !EqualsDiff.equals(initial, builder.getNodeState()) && autoManageReindexFlag){
+            tree.setProperty("reindex", true);
+            reindexRequired = true;
+        }
+    }
 
     //~--------------------------------------< IndexRule >
 
     public IndexRule indexRule(String type){
         IndexRule rule = rules.get(type);
         if (rule == null){
-            rule = new IndexRule(createChild(indexRule, type), type);
+            rule = new IndexRule(getOrCreateChild(indexRule, type), type);
             rules.put(type, rule);
         }
         return rule;
     }
 
+    public boolean hasIndexRule(String type){
+        return indexRule.hasChild(type);
+    }
+
     public static class IndexRule {
         private final Tree indexRule;
         private final Tree propsTree;
@@ -132,8 +167,9 @@ public final class IndexDefinitionBuilde
 
         private IndexRule(Tree indexRule, String type) {
             this.indexRule = indexRule;
-            this.propsTree = createChild(indexRule, LuceneIndexConstants.PROP_NODE);
+            this.propsTree = getOrCreateChild(indexRule, LuceneIndexConstants.PROP_NODE);
             this.ruleName = type;
+            loadExisting();
         }
 
         public IndexRule indexNodeName(){
@@ -153,12 +189,40 @@ public final class IndexDefinitionBuilde
         public PropertyRule property(String name, boolean regex){
             PropertyRule propRule = props.get(name);
             if (propRule == null){
-                propRule = new PropertyRule(this, createChild(propsTree, createPropNodeName(name, regex)), name, regex);
+                Tree propTree = findExisting(name);
+                if (propTree == null){
+                    propTree = getOrCreateChild(propsTree, createPropNodeName(name, regex));
+                }
+                propRule = new PropertyRule(this, propTree, name, regex);
                 props.put(name, propRule);
             }
             return propRule;
         }
 
+        private void loadExisting() {
+            for (Tree tree : propsTree.getChildren()){
+                if (!tree.hasProperty(LuceneIndexConstants.PROP_NAME)){
+                    continue;
+                }
+                String name = tree.getProperty(LuceneIndexConstants.PROP_NAME).getValue(Type.STRING);
+                boolean regex = false;
+                if (tree.hasProperty(LuceneIndexConstants.PROP_IS_REGEX)) {
+                    regex = tree.getProperty(LuceneIndexConstants.PROP_IS_REGEX).getValue(Type.BOOLEAN);
+                }
+                PropertyRule pr = new PropertyRule(this, tree, name, regex);
+                props.put(name, pr);
+            }
+        }
+
+        private Tree findExisting(String name) {
+            for (Tree tree : propsTree.getChildren()){
+                if (name.equals(tree.getProperty(LuceneIndexConstants.PROP_NAME).getValue(Type.STRING))){
+                    return tree;
+                }
+            }
+            return null;
+        }
+
         private String createPropNodeName(String name, boolean regex) {
             name = regex ? "prop" : getSafePropName(name);
             if (name.isEmpty()){
@@ -174,6 +238,10 @@ public final class IndexDefinitionBuilde
         public String getRuleName() {
             return ruleName;
         }
+
+        public boolean hasPropertyRule(String propName){
+            return findExisting(propName) != null;
+        }
     }
 
     public static class PropertyRule {
@@ -256,11 +324,11 @@ public final class IndexDefinitionBuilde
 
     public AggregateRule aggregateRule(String type){
         if (aggregatesTree == null){
-            aggregatesTree = createChild(tree, LuceneIndexConstants.AGGREGATES);
+            aggregatesTree = getOrCreateChild(tree, LuceneIndexConstants.AGGREGATES);
         }
         AggregateRule rule = aggRules.get(type);
         if (rule == null){
-            rule = new AggregateRule(createChild(aggregatesTree, type));
+            rule = new AggregateRule(getOrCreateChild(aggregatesTree, type));
             aggRules.put(type, rule);
         }
         return rule;
@@ -280,18 +348,41 @@ public final class IndexDefinitionBuilde
 
         private AggregateRule(Tree aggregate) {
             this.aggregate = aggregate;
+            loadExisting(aggregate);
         }
 
         public Include include(String includePath) {
             Include include = includes.get(includePath);
             if (include == null){
-                include = new Include(createChild(aggregate, "include" + includes.size()));
+                Tree includeTree = findExisting(includePath);
+                if (includeTree == null){
+                    includeTree = getOrCreateChild(aggregate, "include" + includes.size());
+                }
+                include = new Include(includeTree);
                 includes.put(includePath, include);
             }
             include.path(includePath);
             return include;
         }
 
+        private Tree findExisting(String includePath) {
+            for (Tree tree : aggregate.getChildren()){
+                if (includePath.equals(tree.getProperty(LuceneIndexConstants.AGG_PATH).getValue(Type.STRING))){
+                    return tree;
+                }
+            }
+            return null;
+        }
+
+        private void loadExisting(Tree aggregate) {
+            for (Tree tree : aggregate.getChildren()){
+                if (tree.hasProperty(LuceneIndexConstants.AGG_PATH)) {
+                    Include include = new Include(tree);
+                    includes.put(include.getPath(), include);
+                }
+            }
+        }
+
         public static class Include {
             private final Tree include;
 
@@ -308,10 +399,17 @@ public final class IndexDefinitionBuilde
                 include.setProperty(LuceneIndexConstants.AGG_RELATIVE_NODE, true);
                 return this;
             }
+
+            public String getPath(){
+                return include.getProperty(LuceneIndexConstants.AGG_PATH).getValue(Type.STRING);
+            }
         }
     }
 
-    private static Tree createChild(Tree tree, String name){
+    private static Tree getOrCreateChild(Tree tree, String name){
+        if (tree.hasChild(name)){
+            return tree.getChild(name);
+        }
         Tree child = tree.addChild(name);
         child.setOrderableChildren(true);
         child.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED, NAME);

Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java?rev=1773034&r1=1773033&r2=1773034&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java Wed Dec  7 09:27:47 2016
@@ -24,20 +24,25 @@ import java.util.Iterator;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
 import org.apache.jackrabbit.oak.plugins.index.PathFilter;
 import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants;
 import org.apache.jackrabbit.oak.plugins.tree.TreeFactory;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
 import org.junit.After;
 import org.junit.Test;
 
 import static java.util.Arrays.asList;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_PROPERTY_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.AGGREGATES;
 import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
 import static org.junit.Assert.*;
 
 public class IndexDefinitionBuilderTest {
     private IndexDefinitionBuilder builder = new IndexDefinitionBuilder();
+    private NodeBuilder nodeBuilder = EMPTY_NODE.builder();
 
     @After
     public void dumpState(){
@@ -143,4 +148,81 @@ public class IndexDefinitionBuilderTest
         assertTrue(NodeStateUtils.getNode(state, "indexRules/nt:base/properties/prop")
                 .getBoolean(LuceneIndexConstants.PROP_IS_REGEX));
     }
+
+    @Test
+    public void mergeExisting() throws Exception{
+        nodeBuilder.setProperty("foo", "bar");
+        builder = new IndexDefinitionBuilder(nodeBuilder);
+
+        NodeState state = builder.build();
+        assertEquals("bar", state.getString("foo"));
+        assertEquals("async", state.getString("async"));
+    }
+
+    @Test
+    public void mergeExisting_IndexRule() throws Exception{
+        builder.indexRule("nt:unstructured").property("foo").propertyIndex();
+
+        nodeBuilder = builder.build().builder();
+        builder = new IndexDefinitionBuilder(nodeBuilder);
+
+        assertTrue(builder.hasIndexRule("nt:unstructured"));
+        assertFalse(builder.hasIndexRule("nt:base"));
+
+        builder.indexRule("nt:unstructured").property("bar").propertyIndex();
+        builder.indexRule("nt:base");
+
+        assertTrue(builder.indexRule("nt:unstructured").hasPropertyRule("foo"));
+        assertTrue(builder.indexRule("nt:unstructured").hasPropertyRule("bar"));
+    }
+
+    @Test
+    public void mergeExisting_Aggregates() throws Exception{
+        builder.aggregateRule("foo").include("/path1");
+        builder.aggregateRule("foo").include("/path2");
+
+        nodeBuilder = builder.build().builder();
+
+        builder = new IndexDefinitionBuilder(nodeBuilder);
+
+        builder.aggregateRule("foo").include("/path1");
+        builder.aggregateRule("foo").include("/path3");
+
+        NodeState state = builder.build();
+        assertEquals(3, state.getChildNode(AGGREGATES).getChildNode("foo").getChildNodeCount(100));
+    }
+
+    @Test
+    public void noReindexIfNoChange() throws Exception{
+        builder.includedPaths("/a", "/b");
+        builder.indexRule("nt:base")
+                .property("foo")
+                .ordered();
+
+        nodeBuilder = builder.build().builder();
+        nodeBuilder.setProperty(REINDEX_PROPERTY_NAME, false);
+        builder = new IndexDefinitionBuilder(nodeBuilder);
+        builder.includedPaths("/a", "/b");
+
+        assertFalse(builder.isReindexRequired());
+        NodeState state = builder.build();
+        assertFalse(state.getBoolean(REINDEX_PROPERTY_NAME));
+
+
+        NodeState baseState = builder.build();
+        nodeBuilder = baseState.builder();
+        builder = new IndexDefinitionBuilder(nodeBuilder);
+        builder.indexRule("nt:file");
+
+        assertTrue(builder.isReindexRequired());
+        state = builder.build();
+        assertTrue(state.getBoolean(REINDEX_PROPERTY_NAME));
+
+        builder = new IndexDefinitionBuilder(baseState.builder(), false);
+        builder.indexRule("nt:file");
+        assertTrue(builder.isReindexRequired());
+        state = builder.build();
+        assertTrue(builder.isReindexRequired());
+        assertFalse(state.getBoolean(REINDEX_PROPERTY_NAME));
+    }
 }
\ No newline at end of file