blob: 89d880892040b0c72f835c3c219a40f64da83617 [file] [log] [blame]
/*
* 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.oak.plugins.index.search.util;
import java.util.Iterator;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.core.ImmutableRoot;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants;
import org.apache.jackrabbit.oak.plugins.tree.factories.TreeFactory;
import org.apache.jackrabbit.oak.spi.filter.PathFilter;
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.search.FulltextIndexConstants.AGGREGATES;
import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class IndexDefinitionBuilderTest {
private IndexDefinitionBuilder builder = new IndexDefinitionBuilder();
private NodeBuilder nodeBuilder = EMPTY_NODE.builder();
@After
public void dumpState(){
System.out.println(NodeStateUtils.toString(builder.build()));
}
@Test
public void defaultvSetup() throws Exception{
NodeState state = builder.build();
assertEquals("async", state.getString("async"));
assertEquals("fulltext", state.getString("type"));
}
@Test
public void indexRule() throws Exception{
builder.includedPaths("/a", "/b");
builder.queryPaths("/c", "/d");
builder.supersedes("/e", "/f");
builder.indexRule("nt:base")
.property("foo")
.ordered()
.enclosingRule()
.property("bar")
.analyzed()
.propertyIndex()
.enclosingRule()
.property("baz")
.propertyIndex();
NodeState state = builder.build();
assertTrue(state.getChildNode("indexRules").exists());
assertTrue(state.getChildNode("indexRules").getChildNode("nt:base").exists());
assertEquals(asList("/a", "/b"), state.getProperty(PathFilter.PROP_INCLUDED_PATHS).getValue(Type.STRINGS));
assertEquals(asList("/c", "/d"), state.getProperty(IndexConstants.QUERY_PATHS).getValue(Type.STRINGS));
assertEquals(asList("/e", "/f"), state.getProperty(IndexConstants.SUPERSEDED_INDEX_PATHS).getValue(Type.STRINGS));
}
@Test
public void propertyDefIndexPropertySetIndexFalse() throws Exception {
builder.indexRule("nt:base")
.property("foo")
.disable();
PropertyState state = builder.build().
getChildNode("indexRules").
getChildNode("nt:base").
getChildNode("properties").
getChildNode("foo").
getProperty("index");
assertNotNull("index property must exist", state);
assertFalse("Incorrect default value of index property", state.getValue(Type.BOOLEAN));
}
@Test
public void aggregates() throws Exception{
builder.aggregateRule("cq:Page").include("jcr:content").relativeNode();
builder.aggregateRule("dam:Asset", "*", "*/*");
NodeState state = builder.build();
assertTrue(state.getChildNode("aggregates").exists());
assertTrue(state.getChildNode("aggregates").getChildNode("dam:Asset").exists());
assertTrue(state.getChildNode("aggregates").getChildNode("cq:Page").exists());
}
@Test
public void duplicatePropertyName() throws Exception{
builder.indexRule("nt:base")
.property("foo")
.ordered()
.enclosingRule()
.property("jcr:content/foo")
.analyzed()
.propertyIndex()
.enclosingRule()
.property("metadata/content/foo")
.propertyIndex();
NodeState state = builder.build();
assertTrue(state.getChildNode("indexRules").exists());
assertTrue(state.getChildNode("indexRules").getChildNode("nt:base").exists());
assertEquals(3, state.getChildNode("indexRules").getChildNode("nt:base")
.getChildNode("properties").getChildNodeCount(10));
}
@Test
public void ruleOrder() throws Exception{
builder.indexRule("nt:unstructured");
builder.indexRule("nt:base");
Tree tree = TreeFactory.createTree(EMPTY_NODE.builder());
builder.build(tree);
//Assert the order
Iterator<Tree> children = tree.getChild("indexRules").getChildren().iterator();
assertEquals("nt:unstructured", children.next().getName());
assertEquals("nt:base", children.next().getName());
}
@Test
public void regexProperty() throws Exception{
builder.indexRule("nt:base")
.property(FulltextIndexConstants.REGEX_ALL_PROPS, true);
NodeState state = builder.build();
assertTrue(NodeStateUtils.getNode(state, "indexRules/nt:base/properties/prop")
.getBoolean(FulltextIndexConstants.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));
}
@Test
public void reindexAndAsyncFlagChange() throws Exception{
builder.async("async", IndexConstants.INDEXING_MODE_NRT);
nodeBuilder = builder.build().builder();
nodeBuilder.setProperty(REINDEX_PROPERTY_NAME, false);
NodeState oldState = nodeBuilder.getNodeState();
builder = new IndexDefinitionBuilder(nodeBuilder);
builder.async("async", IndexConstants.INDEXING_MODE_SYNC);
assertFalse(builder.build().getBoolean(REINDEX_PROPERTY_NAME));
builder = new IndexDefinitionBuilder(oldState.builder());
builder.async("fulltext-async", IndexConstants.INDEXING_MODE_SYNC);
assertTrue(builder.build().getBoolean(REINDEX_PROPERTY_NAME));
}
@Test
public void propRuleCustomName() throws Exception{
builder.indexRule("nt:base").property("foo").property("bar");
builder.indexRule("nt:base").property("fooProp", "foo2");
builder.indexRule("nt:base").property("fooProp", "foo2");
Root idx = new ImmutableRoot(builder.build());
assertTrue(idx.getTree("/indexRules/nt:base/properties/fooProp").exists());
assertTrue(idx.getTree("/indexRules/nt:base/properties/bar").exists());
assertTrue(idx.getTree("/indexRules/nt:base/properties/foo").exists());
}
@Test
public void typeNotChangedIfSet() throws Exception{
NodeState state = builder.build();
assertEquals("fulltext", state.getString("type"));
NodeBuilder updated = state.builder();
updated.setProperty("type", "disabled");
IndexDefinitionBuilder newBuilder = new IndexDefinitionBuilder(updated);
NodeState updatedState = newBuilder.build();
assertEquals("disabled", updatedState.getString("type"));
//Type other than 'disabled' would be reset
updated.setProperty("type", "foo");
assertEquals("fulltext", new IndexDefinitionBuilder(updated).build().getString("type"));
}
@Test
public void nodeTypeIndex() throws Exception{
builder.nodeTypeIndex();
builder.indexRule("nt:file");
NodeState state = builder.build();
assertTrue(state.getChildNode("indexRules").exists());
NodeState ntFileRule = state.getChildNode("indexRules").getChildNode("nt:file");
assertTrue(ntFileRule.exists());
assertTrue(state.getBoolean(FulltextIndexConstants.PROP_INDEX_NODE_TYPE));
assertFalse(ntFileRule.getBoolean(FulltextIndexConstants.PROP_SYNC));
}
@Test
public void nodeTypeIndexSync() throws Exception{
builder.nodeTypeIndex();
builder.indexRule("nt:file").sync();
NodeState state = builder.build();
assertTrue(state.getChildNode("indexRules").exists());
NodeState ntFileRule = state.getChildNode("indexRules").getChildNode("nt:file");
assertTrue(ntFileRule.exists());
assertTrue(state.getBoolean(FulltextIndexConstants.PROP_INDEX_NODE_TYPE));
assertTrue(ntFileRule.getBoolean(FulltextIndexConstants.PROP_SYNC));
}
@Test
public void noPropertiesNodeForEmptyRule() throws Exception{
builder.nodeTypeIndex();
builder.indexRule("nt:file").sync();
NodeState state = builder.build();
assertFalse(NodeStateUtils.getNode(state, "/indexRules/nt:file/properties").exists());
}
}