blob: 72aeab93f0050d8d204b98fe5e9a78d9c0125a9a [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;
import java.util.Collections;
import java.util.List;
import javax.jcr.PropertyType;
import com.google.common.collect.ImmutableList;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.plugins.index.search.IndexDefinition.IndexingRule;
import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.IndexingMode;
import org.apache.jackrabbit.oak.plugins.index.search.util.IndexDefinitionBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.junit.Test;
import static com.google.common.collect.ImmutableSet.of;
import static javax.jcr.PropertyType.TYPENAME_LONG;
import static javax.jcr.PropertyType.TYPENAME_STRING;
import static org.apache.jackrabbit.JcrConstants.NT_BASE;
import static org.apache.jackrabbit.oak.InitialContentHelper.INITIAL_CONTENT;
import static org.apache.jackrabbit.oak.api.Type.NAMES;
import static org.apache.jackrabbit.oak.api.Type.STRINGS;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.INCLUDE_PROPERTY_NAMES;
import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.INCLUDE_PROPERTY_TYPES;
import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.INDEX_RULES;
import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.PROP_NAME;
import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.PROP_NODE;
import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.TIKA;
import static org.apache.jackrabbit.oak.plugins.index.search.TestUtil.registerTestNodeType;
import static org.apache.jackrabbit.oak.plugins.index.search.util.IndexHelper.newFTIndexDefinition;
import static org.apache.jackrabbit.oak.plugins.index.search.util.IndexHelper.newFTPropertyIndexDefinition;
import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
import static org.apache.jackrabbit.oak.plugins.tree.TreeConstants.OAK_CHILD_ORDER;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class IndexDefinitionTest {
private NodeState root = INITIAL_CONTENT;
private final NodeBuilder builder = root.builder();
@Test
public void defaultConfig() throws Exception{
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertFalse(idxDefn.hasSyncPropertyDefinitions());
}
@Test
public void fullTextEnabled() throws Exception{
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexDefinition.IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE);
assertTrue("By default fulltext is enabled", idxDefn.isFullTextEnabled());
assertTrue("By default everything is indexed", rule.isIndexed("foo"));
assertTrue("Property types need to be defined", rule.includePropertyType(PropertyType.DATE));
assertTrue("For fulltext storage is enabled", rule.getConfig("foo").stored);
assertFalse(rule.getConfig("foo").skipTokenization("foo"));
assertTrue(rule.getConfig("jcr:uuid").skipTokenization("jcr:uuid"));
}
@Test
public void propertyTypes() throws Exception{
builder.setProperty(createProperty(INCLUDE_PROPERTY_TYPES, of(TYPENAME_LONG), STRINGS));
builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo" , "bar"), STRINGS));
builder.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false);
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexDefinition.IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE);
assertFalse(idxDefn.isFullTextEnabled());
assertFalse("If fulltext disabled then nothing stored", rule.getConfig("foo").stored);
assertTrue(rule.includePropertyType(PropertyType.LONG));
assertFalse(rule.includePropertyType(PropertyType.STRING));
assertTrue(rule.isIndexed("foo"));
assertTrue(rule.isIndexed("bar"));
assertFalse(rule.isIndexed("baz"));
assertTrue(rule.getConfig("foo").skipTokenization("foo"));
}
@Test
public void propertyDefinition() throws Exception{
builder.child(PROP_NODE).child("foo").setProperty(FulltextIndexConstants.PROP_TYPE, PropertyType.TYPENAME_DATE);
builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo" , "bar"), STRINGS));
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexDefinition.IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE);
assertTrue(rule.isIndexed("foo"));
assertTrue(rule.isIndexed("bar"));
assertEquals(PropertyType.DATE, rule.getConfig("foo").getType());
}
@Test
public void propertyDefinitionWithExcludes() throws Exception{
builder.child(PROP_NODE).child("foo").setProperty(FulltextIndexConstants.PROP_TYPE, PropertyType.TYPENAME_DATE);
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexDefinition.IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE);
assertTrue(rule.isIndexed("foo"));
assertTrue(rule.isIndexed("bar"));
assertEquals(PropertyType.DATE, rule.getConfig("foo").getType());
}
@Test
public void indexRuleSanity() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder").setProperty(FulltextIndexConstants.FIELD_BOOST, 2.0);
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(FulltextIndexConstants.FIELD_BOOST, 3.0)
.setProperty(FulltextIndexConstants.PROP_TYPE, PropertyType.TYPENAME_BOOLEAN);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertNull(defn.getApplicableIndexingRule(asState(newNode("nt:base"))));
IndexingRule rule1 = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertNotNull(rule1);
assertEquals(2.0f, rule1.boost, 0);
assertTrue(rule1.isIndexed("prop1"));
assertFalse(rule1.isIndexed("prop2"));
PropertyDefinition pd = rule1.getConfig("prop1");
assertEquals(3.0f, pd.boost, 0);
assertEquals(PropertyType.BOOLEAN, pd.getType());
}
@Test
public void indexRuleInheritance() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
builder.setProperty(PROP_NAME, "testIndex");
rules.child("nt:hierarchyNode").setProperty(FulltextIndexConstants.FIELD_BOOST, 2.0);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertNull(defn.getApplicableIndexingRule(asState(newNode("nt:base"))));
assertNotNull(defn.getApplicableIndexingRule(asState(newNode("nt:hierarchyNode"))));
assertNotNull(defn.getApplicableIndexingRule(asState(newNode("nt:folder"))));
}
@Test
public void indexRuleMixin() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("mix:title");
TestUtil.child(rules, "mix:title/properties/jcr:title")
.setProperty(FulltextIndexConstants.FIELD_BOOST, 3.0);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertNotNull(defn.getApplicableIndexingRule(asState(newNode("nt:folder", "mix:title"))));
assertNull(defn.getApplicableIndexingRule(asState(newNode("nt:folder"))));
}
@Test
public void indexRuleMixinInheritance() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("mix:mimeType");
TestUtil.child(rules, "mix:mimeType/properties/jcr:mimeType")
.setProperty(FulltextIndexConstants.FIELD_BOOST, 3.0);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertNotNull(defn.getApplicableIndexingRule(asState(newNode("nt:folder", "mix:mimeType"))));
assertNull(defn.getApplicableIndexingRule(asState(newNode("nt:folder"))));
//nt:resource > mix:mimeType
assertNotNull(defn.getApplicableIndexingRule(asState(newNode("nt:resource"))));
}
@Test
public void indexRuleInheritanceDisabled() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
builder.setProperty(PROP_NAME, "testIndex");
rules.child("nt:hierarchyNode")
.setProperty(FulltextIndexConstants.FIELD_BOOST, 2.0)
.setProperty(FulltextIndexConstants.RULE_INHERITED, false);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertNull(defn.getApplicableIndexingRule(asState(newNode("nt:base"))));
assertNotNull(defn.getApplicableIndexingRule(asState(newNode("nt:hierarchyNode"))));
assertNull("nt:folder should not be index as rule is not inheritable",
defn.getApplicableIndexingRule(asState(newNode("nt:folder"))));
}
@Test
public void indexRuleInheritanceOrdering() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.setProperty(OAK_CHILD_ORDER, ImmutableList.of("nt:hierarchyNode", "nt:base"),NAMES);
rules.child("nt:hierarchyNode").setProperty(FulltextIndexConstants.FIELD_BOOST, 2.0);
rules.child("nt:base").setProperty(FulltextIndexConstants.FIELD_BOOST, 3.0);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertEquals(3.0, getRule(defn, "nt:base").boost, 0);
assertEquals(2.0, getRule(defn, "nt:hierarchyNode").boost, 0);
assertEquals(3.0, getRule(defn, "nt:query").boost, 0);
}
@Test
public void indexRuleInheritanceOrdering2() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.setProperty(OAK_CHILD_ORDER, ImmutableList.of("nt:base", "nt:hierarchyNode"),NAMES);
rules.child("nt:hierarchyNode").setProperty(FulltextIndexConstants.FIELD_BOOST, 2.0);
rules.child("nt:base").setProperty(FulltextIndexConstants.FIELD_BOOST, 3.0);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
//As nt:base is defined earlier it would supercede everything
assertEquals(3.0, getRule(defn, "nt:base").boost, 0);
assertEquals(3.0, getRule(defn, "nt:hierarchyNode").boost, 0);
assertEquals(3.0, getRule(defn, "nt:file").boost, 0);
}
@Test
public void indexRuleWithPropertyRegEx() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(FulltextIndexConstants.FIELD_BOOST, 3.0);
TestUtil.child(rules, "nt:folder/properties/prop2")
.setProperty(PROP_NAME, "foo.*")
.setProperty(FulltextIndexConstants.PROP_IS_REGEX, true)
.setProperty(FulltextIndexConstants.FIELD_BOOST, 4.0);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexingRule rule1 = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertNotNull(rule1);
assertTrue(rule1.isIndexed("prop1"));
assertFalse(rule1.isIndexed("prop2"));
assertTrue(rule1.isIndexed("fooProp"));
PropertyDefinition pd = rule1.getConfig("fooProp2");
assertEquals(4.0f, pd.boost, 0);
}
@Test
public void indexRuleWithPropertyRegEx2() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(PROP_NAME, ".*")
.setProperty(FulltextIndexConstants.PROP_IS_REGEX, true);
TestUtil.child(rules, "nt:folder/properties/prop2")
.setProperty(PROP_NAME, "metadata/.*")
.setProperty(FulltextIndexConstants.PROP_IS_REGEX, true)
.setProperty(FulltextIndexConstants.FIELD_BOOST, 4.0);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexingRule rule1 = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertNotNull(rule1);
assertTrue(rule1.isIndexed("prop1"));
assertTrue(rule1.isIndexed("prop2"));
assertFalse(rule1.isIndexed("jcr:content/prop1"));
assertTrue(rule1.isIndexed("metadata/foo"));
assertFalse(rule1.isIndexed("metadata/foo/bar"));
}
@Test
public void indexRuleWithPropertyOrdering() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(PROP_NAME, "foo.*")
.setProperty(FulltextIndexConstants.PROP_IS_REGEX, true)
.setProperty(FulltextIndexConstants.FIELD_BOOST, 3.0);
TestUtil.child(rules, "nt:folder/properties/prop2")
.setProperty(PROP_NAME, ".*")
.setProperty(FulltextIndexConstants.PROP_IS_REGEX, true)
.setProperty(FulltextIndexConstants.FIELD_BOOST, 4.0);
rules.child("nt:folder").child(PROP_NODE).setProperty(OAK_CHILD_ORDER, ImmutableList.of("prop2", "prop1"), NAMES);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexingRule rule1 = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertNotNull(rule1);
assertTrue(rule1.isIndexed("prop1"));
assertTrue(rule1.isIndexed("fooProp"));
assertEquals(4.0f, rule1.getConfig("bazProp2").boost, 0);
//As prop2 is ordered before prop1 its regEx is evaluated first
//hence even with a specific regex of foo.* the defn used is from .*
assertEquals(4.0f, rule1.getConfig("fooProp").boost, 0);
//Order it correctly to get expected result
rules.child("nt:folder").child(PROP_NODE).setProperty(OAK_CHILD_ORDER, ImmutableList.of("prop1", "prop2"), NAMES);
defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
rule1 = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertEquals(3.0f, rule1.getConfig("fooProp").boost, 0);
}
@Test
public void propertyConfigCaseInsensitive() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
TestUtil.child(rules, "nt:folder/properties/foo")
.setProperty(PROP_NAME, "Foo")
.setProperty(FulltextIndexConstants.PROP_PROPERTY_INDEX, true);
TestUtil.child(rules, "nt:folder/properties/bar")
.setProperty(PROP_NAME, "BAR")
.setProperty(FulltextIndexConstants.PROP_PROPERTY_INDEX, true);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexingRule rule1 = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertNotNull(rule1);
assertTrue(rule1.isIndexed("Foo"));
assertTrue(rule1.isIndexed("foo"));
assertTrue(rule1.isIndexed("fOO"));
assertTrue(rule1.isIndexed("bar"));
assertFalse(rule1.isIndexed("baz"));
}
@Test
public void skipTokenization() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
TestUtil.child(rules, "nt:folder/properties/prop2")
.setProperty(PROP_NAME, ".*")
.setProperty(FulltextIndexConstants.PROP_IS_REGEX, true)
.setProperty(FulltextIndexConstants.PROP_ANALYZED, true);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexingRule rule = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertFalse(rule.getConfig("foo").skipTokenization("foo"));
assertTrue(rule.getConfig(JcrConstants.JCR_UUID).skipTokenization(JcrConstants.JCR_UUID));
}
@Test
public void formatUpdate() throws Exception{
NodeBuilder defnb = newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
"lucene", of(TYPENAME_STRING), of("foo", "Bar"), "async");
IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertTrue(defn.isOfOldFormat());
NodeBuilder updated = IndexDefinition.updateDefinition(defnb.getNodeState().builder());
IndexDefinition defn2 = new IndexDefinition(root, updated.getNodeState(), "/foo");
assertFalse(defn2.isOfOldFormat());
IndexingRule rule = defn2.getApplicableIndexingRule(asState(newNode("nt:base")));
assertNotNull(rule);
assertFalse(rule.getConfig("foo").index);
assertFalse(rule.getConfig("Bar").index);
}
@Test
public void propertyRegExAndRelativeProperty() throws Exception{
NodeBuilder defnb = newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
"lucene", of(TYPENAME_STRING), of("foo"), "async");
IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertTrue(defn.isOfOldFormat());
NodeBuilder updated = IndexDefinition.updateDefinition(defnb.getNodeState().builder());
IndexDefinition defn2 = new IndexDefinition(root, updated.getNodeState(), "/foo");
IndexingRule rule = defn2.getApplicableIndexingRule(asState(newNode("nt:base")));
assertNotNull(rule.getConfig("foo"));
assertNull("Property regex used should not allow relative properties", rule.getConfig("foo/bar"));
}
@Test
public void fulltextEnabledAndAggregate() throws Exception{
NodeBuilder defnb = newFTPropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
"lucene", of("foo"), "async");
IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertFalse(defn.isFullTextEnabled());
NodeBuilder aggregates = defnb.child(FulltextIndexConstants.AGGREGATES);
NodeBuilder aggFolder = aggregates.child("nt:base");
aggFolder.child("i1").setProperty(FulltextIndexConstants.AGG_PATH, "*");
defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertTrue(defn.isFullTextEnabled());
}
@Test
public void costConfig() throws Exception {
NodeBuilder defnb = newFTPropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
"lucene", of("foo"), "async");
IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertEquals(1.0, defn.getCostPerEntry(), 0);
assertEquals(1.0, defn.getCostPerExecution(), 0);
assertEquals(IndexDefinition.DEFAULT_ENTRY_COUNT, defn.getEntryCount());
assertFalse(defn.isEntryCountDefined());
defnb.setProperty(FulltextIndexConstants.COST_PER_ENTRY, 2.0);
defnb.setProperty(FulltextIndexConstants.COST_PER_EXECUTION, 3.0);
defnb.setProperty(IndexConstants.ENTRY_COUNT_PROPERTY_NAME, 500);
IndexDefinition defn2 = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertEquals(2.0, defn2.getCostPerEntry(), 0);
assertEquals(3.0, defn2.getCostPerExecution(), 0);
assertEquals(500, defn2.getEntryCount());
}
@Test
public void fulltextCost() throws Exception{
NodeBuilder defnb = newFTPropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
"lucene", of("foo"), "async");
IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertEquals(300, defn.getFulltextEntryCount(300));
assertEquals(IndexDefinition.DEFAULT_ENTRY_COUNT + 100,
defn.getFulltextEntryCount(IndexDefinition.DEFAULT_ENTRY_COUNT + 100));
//Once count is explicitly defined then it would influence the cost
defnb.setProperty(IndexConstants.ENTRY_COUNT_PROPERTY_NAME, 100);
defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertEquals(100, defn.getFulltextEntryCount(300));
assertEquals(50, defn.getFulltextEntryCount(50));
}
@Test
public void customTikaConfig() throws Exception{
NodeBuilder defnb = newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
"lucene", of(TYPENAME_STRING));
IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertFalse(defn.hasCustomTikaConfig());
defnb.child(FulltextIndexConstants.TIKA)
.child(FulltextIndexConstants.TIKA_CONFIG)
.child(JcrConstants.JCR_CONTENT)
.setProperty(JcrConstants.JCR_DATA, "hello".getBytes());
defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertTrue(defn.hasCustomTikaConfig());
}
@Test
public void customTikaMimeTypes() throws Exception{
NodeBuilder defnb = newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
"lucene", of(TYPENAME_STRING));
IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertEquals("application/test", defn.getTikaMappedMimeType("application/test"));
NodeBuilder app =defnb.child(FulltextIndexConstants.TIKA)
.child(FulltextIndexConstants.TIKA_MIME_TYPES)
.child("application");
app.child("test").setProperty(FulltextIndexConstants.TIKA_MAPPED_TYPE, "text/plain");
app.child("test2").setProperty(FulltextIndexConstants.TIKA_MAPPED_TYPE, "text/plain");
defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertEquals("text/plain", defn.getTikaMappedMimeType("application/test"));
assertEquals("text/plain", defn.getTikaMappedMimeType("application/test2"));
assertEquals("application/test-unmapped", defn.getTikaMappedMimeType("application/test-unmapped"));
}
@Test
public void maxExtractLength() throws Exception{
NodeBuilder defnb = newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
"lucene", of(TYPENAME_STRING));
IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertEquals(-IndexDefinition.DEFAULT_MAX_EXTRACT_LENGTH * IndexDefinition.DEFAULT_MAX_FIELD_LENGTH,
defn.getMaxExtractLength());
defnb.child(TIKA).setProperty(FulltextIndexConstants.TIKA_MAX_EXTRACT_LENGTH, 1000);
defn = new IndexDefinition(root, defnb.getNodeState(), "/foo");
assertEquals(1000, defn.getMaxExtractLength());
}
@Test(expected = IllegalStateException.class)
public void nullCheckEnabledWithNtBase() throws Exception{
builder.child(PROP_NODE).child("foo").setProperty(FulltextIndexConstants.PROP_NULL_CHECK_ENABLED, true);
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
}
@Test(expected = IllegalStateException.class)
public void nullCheckEnabledWithRegex() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child(TestUtil.NT_TEST);
TestUtil.child(rules, "oak:TestNode/properties/prop2")
.setProperty(PROP_NAME, ".*")
.setProperty(FulltextIndexConstants.PROP_IS_REGEX, true)
.setProperty(FulltextIndexConstants.PROP_NULL_CHECK_ENABLED, true);
root = registerTestNodeType(builder).getNodeState();
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
}
@Test
public void nullCheckEnabledWithTestNode() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
TestUtil.child(rules, "oak:TestNode/properties/prop2")
.setProperty(PROP_NAME, "foo")
.setProperty(FulltextIndexConstants.PROP_NULL_CHECK_ENABLED, true);
root = registerTestNodeType(builder).getNodeState();
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertTrue(!idxDefn.getApplicableIndexingRule(TestUtil.NT_TEST).getNullCheckEnabledProperties().isEmpty());
}
@Test
public void notNullCheckEnabledWithTestNode() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
TestUtil.child(rules, "oak:TestNode/properties/prop2")
.setProperty(PROP_NAME, "foo")
.setProperty(FulltextIndexConstants.PROP_NOT_NULL_CHECK_ENABLED, true);
root = registerTestNodeType(builder).getNodeState();
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertTrue(!idxDefn.getApplicableIndexingRule(TestUtil.NT_TEST).getNotNullCheckEnabledProperties().isEmpty());
}
//OAK-2477
@Test
public void testSuggestFrequency() throws Exception {
int suggestFreq = 40;
//default config
NodeBuilder indexRoot = builder;
IndexDefinition idxDefn = new IndexDefinition(root, indexRoot.getNodeState(), "/foo");
assertEquals("Default config", 10, idxDefn.getSuggesterUpdateFrequencyMinutes());
//namespaced config shadows old method
indexRoot = builder.child("shadowConfigRoot");
indexRoot.setProperty(FulltextIndexConstants.SUGGEST_UPDATE_FREQUENCY_MINUTES, suggestFreq);
indexRoot.child(FulltextIndexConstants.SUGGESTION_CONFIG);
idxDefn = new IndexDefinition(root, indexRoot.getNodeState(), "/foo");
assertEquals("Namespaced config node should shadow global config",
10, idxDefn.getSuggesterUpdateFrequencyMinutes());
//config for backward config
indexRoot = builder.child("backwardCompatibilityRoot");
indexRoot.setProperty(FulltextIndexConstants.SUGGEST_UPDATE_FREQUENCY_MINUTES, suggestFreq);
idxDefn = new IndexDefinition(root, indexRoot.getNodeState(), "/foo");
assertEquals("Backward compatibility config", suggestFreq, idxDefn.getSuggesterUpdateFrequencyMinutes());
indexRoot = builder.child("indexRoot");
indexRoot.child(FulltextIndexConstants.SUGGESTION_CONFIG)
.setProperty(FulltextIndexConstants.SUGGEST_UPDATE_FREQUENCY_MINUTES, suggestFreq);
idxDefn = new IndexDefinition(root, indexRoot.getNodeState(), "/foo");
assertEquals("Set config", suggestFreq, idxDefn.getSuggesterUpdateFrequencyMinutes());
}
//OAK-2477
@Test
public void testSuggestAnalyzed() throws Exception {
//default config
NodeBuilder indexRoot = builder;
IndexDefinition idxDefn = new IndexDefinition(root, indexRoot.getNodeState(), "/foo");
assertFalse("Default config", idxDefn.isSuggestAnalyzed());
//namespaced config shadows old method
indexRoot = builder.child("shadowConfigRoot");
indexRoot.setProperty(FulltextIndexConstants.SUGGEST_ANALYZED, true);
indexRoot.child(FulltextIndexConstants.SUGGESTION_CONFIG);
idxDefn = new IndexDefinition(root, indexRoot.getNodeState(), "/foo");
assertFalse("Namespaced config node should shadow global config", idxDefn.isSuggestAnalyzed());
//config for backward config
indexRoot = builder.child("backwardCompatibilityRoot");
indexRoot.setProperty(FulltextIndexConstants.SUGGEST_ANALYZED, true);
idxDefn = new IndexDefinition(root, indexRoot.getNodeState(), "/foo");
assertTrue("Backward compatibility config", idxDefn.isSuggestAnalyzed());
indexRoot = builder.child("indexRoot");
indexRoot.child(FulltextIndexConstants.SUGGESTION_CONFIG)
.setProperty(FulltextIndexConstants.SUGGEST_ANALYZED, true);
idxDefn = new IndexDefinition(root, indexRoot.getNodeState(), "/foo");
assertTrue("Set config", idxDefn.isSuggestAnalyzed());
}
@Test
public void testSuggestEnabledOnNamedProp() throws Exception {
NodeBuilder rules = builder.child(INDEX_RULES);
TestUtil.child(rules, "oak:TestNode/properties/prop2")
.setProperty(PROP_NAME, "foo")
.setProperty(FulltextIndexConstants.PROP_USE_IN_SUGGEST, true);
root = registerTestNodeType(builder).getNodeState();
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertTrue(idxDefn.isSuggestEnabled());
}
@Test
public void testSuggestEnabledOnRegexProp() throws Exception {
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child(TestUtil.NT_TEST);
TestUtil.child(rules, "oak:TestNode/properties/prop2")
.setProperty(PROP_NAME, ".*")
.setProperty(FulltextIndexConstants.PROP_IS_REGEX, true)
.setProperty(FulltextIndexConstants.PROP_USE_IN_SUGGEST, true);
root = registerTestNodeType(builder).getNodeState();
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertTrue(idxDefn.isSuggestEnabled());
}
@Test
public void testSuggestDisabled() throws Exception {
NodeBuilder rules = builder.child(INDEX_RULES);
TestUtil.child(rules, "oak:TestNode/properties/prop2")
.setProperty(PROP_NAME, "foo");
root = registerTestNodeType(builder).getNodeState();
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertFalse(idxDefn.isSuggestEnabled());
}
@Test
public void analyzedEnabledForBoostedField() throws Exception {
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(FulltextIndexConstants.FIELD_BOOST, 3.0)
.setProperty(FulltextIndexConstants.PROP_NODE_SCOPE_INDEX, true);
TestUtil.child(rules, "nt:folder/properties/prop2")
.setProperty(FulltextIndexConstants.PROP_ANALYZED, true)
.setProperty(FulltextIndexConstants.PROP_NODE_SCOPE_INDEX, true);
TestUtil.child(rules, "nt:folder/properties/prop3")
.setProperty(FulltextIndexConstants.PROP_PROPERTY_INDEX, true)
.setProperty(FulltextIndexConstants.PROP_NODE_SCOPE_INDEX, true);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexingRule rule1 = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertNotNull(rule1);
PropertyDefinition pd = rule1.getConfig("prop1");
assertEquals(3.0f, pd.boost, 0);
assertTrue("Analyzed should be assumed to be true for boosted fields", pd.analyzed);
assertFalse(rule1.getConfig("prop3").analyzed);
assertEquals(2, rule1.getNodeScopeAnalyzedProps().size());
}
@Test
public void nodeFullTextIndexed_Regex() throws Exception {
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(PROP_NAME, ".*")
.setProperty(FulltextIndexConstants.PROP_ANALYZED, true)
.setProperty(FulltextIndexConstants.PROP_IS_REGEX, true);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexingRule rule = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertNotNull(rule);
assertFalse(rule.isNodeFullTextIndexed());
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(FulltextIndexConstants.PROP_NODE_SCOPE_INDEX, true);
defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
rule = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertTrue(rule.isNodeFullTextIndexed());
assertTrue(rule.indexesAllNodesOfMatchingType());
}
@Test
public void nodeFullTextIndexed_Simple() throws Exception {
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(PROP_NAME, "foo")
.setProperty(FulltextIndexConstants.PROP_ANALYZED, true);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexingRule rule = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertNotNull(rule);
assertFalse(rule.isNodeFullTextIndexed());
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(FulltextIndexConstants.PROP_NODE_SCOPE_INDEX, true);
defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
rule = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertTrue(rule.isNodeFullTextIndexed());
assertTrue(rule.indexesAllNodesOfMatchingType());
}
@Test
public void nodeFullTextIndexed_Aggregates() throws Exception {
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(PROP_NAME, "foo")
.setProperty(FulltextIndexConstants.PROP_ANALYZED, true);
NodeBuilder aggregates = builder.child(FulltextIndexConstants.AGGREGATES);
NodeBuilder aggFolder = aggregates.child("nt:folder");
aggFolder.child("i1").setProperty(FulltextIndexConstants.AGG_PATH, "*");
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexingRule rule = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertNotNull(rule);
assertTrue(rule.isNodeFullTextIndexed());
assertTrue(rule.indexesAllNodesOfMatchingType());
}
@Test
public void nonIndexPropShouldHaveAllOtherConfigDisabled() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(PROP_NAME, "foo")
.setProperty(FulltextIndexConstants.PROP_INDEX, false)
.setProperty(FulltextIndexConstants.PROP_USE_IN_SUGGEST, true)
.setProperty(FulltextIndexConstants.PROP_USE_IN_SPELLCHECK, true)
.setProperty(FulltextIndexConstants.PROP_NULL_CHECK_ENABLED, true)
.setProperty(FulltextIndexConstants.PROP_NOT_NULL_CHECK_ENABLED, true)
.setProperty(FulltextIndexConstants.PROP_USE_IN_EXCERPT, true)
.setProperty(FulltextIndexConstants.PROP_NODE_SCOPE_INDEX, true)
.setProperty(FulltextIndexConstants.PROP_ORDERED, true)
.setProperty(FulltextIndexConstants.PROP_ANALYZED, true);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
IndexingRule rule = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
assertNotNull(rule);
PropertyDefinition pd = rule.getConfig("foo");
//Assert that all other config is false if the index=false for any property
assertFalse(pd.index);
assertFalse(pd.nodeScopeIndex);
assertFalse(pd.useInSuggest);
assertFalse(pd.useInSpellcheck);
assertFalse(pd.nullCheckEnabled);
assertFalse(pd.notNullCheckEnabled);
assertFalse(pd.stored);
assertFalse(pd.ordered);
assertFalse(pd.analyzed);
}
@Test
public void costPerEntry() throws Exception{
builder.setProperty(FulltextIndexConstants.COMPAT_MODE, 2);
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertEquals(1.0, defn.getCostPerEntry(), 0.0);
}
@Test
public void sync() throws Exception{
TestUtil.enableIndexingMode(builder, IndexingMode.SYNC);
IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo");
assertTrue(idxDefn.isSyncIndexingEnabled());
}
@Test
public void hasPersistedIndex() throws Exception{
assertFalse(IndexDefinition.hasPersistedIndex(builder.getNodeState()));
builder.child(":status");
assertTrue(IndexDefinition.hasPersistedIndex(builder.getNodeState()));
}
@Test
public void uniqueIdForFreshIndex() throws Exception{
IndexDefinition defn = IndexDefinition.newBuilder(root, builder.getNodeState(), "/foo").build();
assertEquals("0", defn.getUniqueId());
builder.child(":status");
defn = IndexDefinition.newBuilder(root, builder.getNodeState(),"/foo").build();
assertNull(defn.getUniqueId());
}
@Test
public void nodeTypeChange() throws Exception{
IndexDefinition defn = IndexDefinition.newBuilder(root, builder.getNodeState(), "/foo").build();
NodeBuilder b2 = root.builder();
TestUtil.registerNodeType(b2, TestUtil.TEST_NODE_TYPE);
NodeState root2 = b2.getNodeState();
NodeBuilder b3 = root.builder();
b3.child("x");
NodeState root3 = b3.getNodeState();
assertFalse(defn.hasMatchingNodeTypeReg(root2));
assertTrue(defn.hasMatchingNodeTypeReg(root3));
}
@Test
public void uniqueIsSync() throws Exception{
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.indexRule("nt:base").property("foo").unique();
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
assertTrue(defn.getApplicableIndexingRule("nt:base").getConfig("foo").sync);
assertTrue(defn.getApplicableIndexingRule("nt:base").getConfig("foo").unique);
assertTrue(defn.getApplicableIndexingRule("nt:base").getConfig("foo").propertyIndex);
}
@Test
public void syncIsProperty() throws Exception{
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.indexRule("nt:base").property("foo").sync();
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
assertTrue(defn.getApplicableIndexingRule("nt:base").getConfig("foo").sync);
assertTrue(defn.getApplicableIndexingRule("nt:base").getConfig("foo").propertyIndex);
}
@Test
public void syncPropertyDefinitions() throws Exception{
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.indexRule("nt:base").property("foo").sync();
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
assertTrue(defn.hasSyncPropertyDefinitions());
}
//~----------------------------------< nodetype >
final String testNodeTypeDefn = "[oak:TestMixA]\n" +
" mixin\n" +
"\n" +
"[oak:TestSuperType]\n" +
"- * (UNDEFINED) multiple\n" +
"\n" +
"[oak:TestTypeA] > oak:TestSuperType\n" +
"- * (UNDEFINED) multiple\n" +
"\n" +
"[oak:TestTypeB] > oak:TestSuperType, oak:TestMixA\n" +
"- * (UNDEFINED) multiple";
@Test
public void nodeTypeIndexed() throws Exception{
TestUtil.registerNodeType(builder, testNodeTypeDefn);
root = builder.getNodeState();
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.nodeTypeIndex();
defnb.indexRule("oak:TestSuperType");
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
assertFalse(defn.hasSyncPropertyDefinitions());
IndexingRule ruleSuper = getRule(defn, "oak:TestSuperType");
assertNotNull(ruleSuper);
assertTrue(defn.isPureNodeTypeIndex());
assertTrue(ruleSuper.getConfig(JcrConstants.JCR_PRIMARYTYPE).propertyIndex);
assertTrue(ruleSuper.getConfig(JcrConstants.JCR_MIXINTYPES).propertyIndex);
assertTrue(ruleSuper.indexesAllNodesOfMatchingType());
assertNotNull(getRule(defn, "oak:TestTypeA"));
assertTrue(getRule(defn, "oak:TestTypeA").indexesAllNodesOfMatchingType());
assertNotNull(getRule(defn, "oak:TestTypeB"));
assertNull(getRule(defn, "oak:TestMixA"));
}
@Test
public void nodeTypeIndexedSync() throws Exception{
TestUtil.registerNodeType(builder, testNodeTypeDefn);
root = builder.getNodeState();
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.nodeTypeIndex();
defnb.indexRule("oak:TestSuperType").sync();
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
assertTrue(defn.hasSyncPropertyDefinitions());
IndexingRule ruleSuper = getRule(defn, "oak:TestSuperType");
assertNotNull(ruleSuper);
assertTrue(defn.isPureNodeTypeIndex());
assertTrue(ruleSuper.getConfig(JcrConstants.JCR_PRIMARYTYPE).propertyIndex);
assertTrue(ruleSuper.getConfig(JcrConstants.JCR_PRIMARYTYPE).sync);
assertTrue(ruleSuper.getConfig(JcrConstants.JCR_MIXINTYPES).propertyIndex);
assertTrue(ruleSuper.getConfig(JcrConstants.JCR_MIXINTYPES).sync);
assertTrue(ruleSuper.indexesAllNodesOfMatchingType());
}
@Test
public void nodeTypeIndexed_IgnoreOtherProps() throws Exception{
TestUtil.registerNodeType(builder, testNodeTypeDefn);
root = builder.getNodeState();
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.nodeTypeIndex();
defnb.indexRule("oak:TestSuperType").sync();
defnb.indexRule("oak:TestSuperType").property("foo").propertyIndex();
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
IndexingRule ruleSuper = getRule(defn, "oak:TestSuperType");
assertNotNull(ruleSuper);
assertNull(ruleSuper.getConfig("foo"));
assertNotNull(ruleSuper.getConfig(JcrConstants.JCR_PRIMARYTYPE));
assertNotNull(ruleSuper.getConfig(JcrConstants.JCR_MIXINTYPES));
}
@Test
public void nodeTypeIndexed_IgnoreAggregates() throws Exception{
TestUtil.registerNodeType(builder, testNodeTypeDefn);
root = builder.getNodeState();
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.nodeTypeIndex();
defnb.indexRule("oak:TestSuperType").sync();
defnb.aggregateRule("oak:TestSuperType").include("*");
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
IndexingRule ruleSuper = getRule(defn, "oak:TestSuperType");
assertNotNull(ruleSuper);
assertNull(ruleSuper.getConfig("foo"));
assertTrue(ruleSuper.getAggregate().getIncludes().isEmpty());
assertNotNull(ruleSuper.getConfig(JcrConstants.JCR_PRIMARYTYPE));
assertNotNull(ruleSuper.getConfig(JcrConstants.JCR_MIXINTYPES));
}
@Test
public void nodeTypeIndex_mixin() throws Exception{
TestUtil.registerNodeType(builder, testNodeTypeDefn);
root = builder.getNodeState();
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.nodeTypeIndex();
defnb.indexRule("oak:TestMixA");
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
assertFalse(defn.hasSyncPropertyDefinitions());
assertNotNull(getRule(defn, "oak:TestTypeB"));
assertTrue(getRule(defn, "oak:TestTypeB").indexesAllNodesOfMatchingType());
assertNotNull(getRule(defn, "oak:TestMixA"));
assertTrue(getRule(defn, "oak:TestMixA").indexesAllNodesOfMatchingType());
assertNull(getRule(defn, "oak:TestTypeA"));
assertNull(getRule(defn, "oak:TestSuperType"));
}
@Test
public void mixinAndPrimaryType() throws Exception{
TestUtil.registerNodeType(builder, testNodeTypeDefn);
root = builder.getNodeState();
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.indexRule("oak:TestMixA").property(JcrConstants.JCR_PRIMARYTYPE).propertyIndex();
defnb.indexRule("oak:TestSuperType").property(JcrConstants.JCR_PRIMARYTYPE).propertyIndex().sync();
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
IndexingRule a = getRule(defn, "oak:TestMixA");
assertNotNull(a.getConfig(JcrConstants.JCR_PRIMARYTYPE));
assertNotNull(a.getConfig(JcrConstants.JCR_MIXINTYPES));
assertFalse(a.getConfig(JcrConstants.JCR_MIXINTYPES).sync);
IndexingRule b = getRule(defn, "oak:TestSuperType");
assertNotNull(b.getConfig(JcrConstants.JCR_PRIMARYTYPE));
assertNotNull(b.getConfig(JcrConstants.JCR_MIXINTYPES));
assertTrue(b.getConfig(JcrConstants.JCR_PRIMARYTYPE).sync);
assertTrue(b.getConfig(JcrConstants.JCR_MIXINTYPES).sync);
}
@Test
public void relativeNodeNames_None() {
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.indexRule("nt:base").property("foo").propertyIndex();
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
assertTrue(defn.getRelativeNodeNames().isEmpty());
assertFalse(defn.indexesRelativeNodes());
}
@Test
public void relativeNodeNames_RelativeProp() {
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.indexRule("nt:base").property("jcr:content/foo").propertyIndex();
defnb.indexRule("nt:base").property("bar").propertyIndex();
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
assertThat(defn.getRelativeNodeNames(), containsInAnyOrder("jcr:content"));
assertTrue(defn.indexesRelativeNodes());
}
@Test
public void relativeNodeNames_Aggregate() {
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.indexRule("nt:base").property("jcr:content/foo").propertyIndex();
defnb.aggregateRule("nt:base").include("jcr:content/metadata");
defnb.aggregateRule("nt:base").include("jcr:content/metadata/type/*");
defnb.aggregateRule("nt:base").include("*");
IndexDefinition defn = IndexDefinition.newBuilder(root, defnb.build(), "/foo").build();
assertThat(defn.getRelativeNodeNames(), containsInAnyOrder("jcr:content", "metadata", "type"));
assertTrue(defn.indexesRelativeNodes());
}
@Test
public void regexAllProps() {
IndexDefinitionBuilder builder = new IndexDefinitionBuilder();
builder.indexRule("nt:base").property("p");
builder.indexRule("nt:base").property("all", FulltextIndexConstants.REGEX_ALL_PROPS, true);
IndexDefinition def = IndexDefinition.newBuilder(root, builder.build(), "/foo").build();
IndexingRule rule = def.getApplicableIndexingRule(root);
assertNotNull(rule);
PropertyDefinition pd = rule.getConfig("p");
assertNotNull(pd);
assertFalse(pd.isRegexp);
assertFalse(pd.relative);
assertEquals(0, pd.ancestors.length);
pd = rule.getConfig("all");
assertNotNull(pd);
assertTrue(pd.isRegexp);
assertFalse(pd.relative);
assertEquals(0, pd.ancestors.length);
assertThat(rule.getAggregate().getIncludes(), is(empty()));
assertFalse(rule.getAggregate().hasNodeAggregates());
List<Aggregate.Matcher> matchers = rule.getAggregate()
.createMatchers(new TestRoot("/"));
assertThat(matchers, is(empty()));
assertThat(def.getRelativeNodeNames(), is(empty()));
}
//TODO indexesAllNodesOfMatchingType - with nullCheckEnabled
private static IndexingRule getRule(IndexDefinition defn, String typeName){
return defn.getApplicableIndexingRule(asState(newNode(typeName)));
}
private static NodeState asState(NodeBuilder nb){
return nb.getNodeState();
}
private static NodeBuilder newNode(String typeName){
NodeBuilder builder = EMPTY_NODE.builder();
builder.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName, Type.NAME);
return builder;
}
private static NodeBuilder newNode(String typeName, String mixins){
NodeBuilder builder = EMPTY_NODE.builder();
builder.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName);
builder.setProperty(JcrConstants.JCR_MIXINTYPES, Collections.singleton(mixins), Type.NAMES);
return builder;
}
private static class TestRoot implements Aggregate.AggregateRoot {
private final String path;
public TestRoot(String path) {
this.path = path;
}
@Override
public void markDirty() {
}
@Override
public String getPath() {
return path;
}
}
}