Author: chetanm
Date: Wed Feb 18 16:58:00 2015
New Revision: 1660676
URL: http://svn.apache.org/r1660676
Log:
OAK-2517 - Support IS NULL based property restrictions in LucenePropertyIndex
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldNames.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlannerTest.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/TestUtil.java
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldNames.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldNames.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldNames.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldNames.java
Wed Feb 18 16:58:00 2015
@@ -75,6 +75,12 @@ public final class FieldNames {
public static final String FULLTEXT_RELATIVE_NODE = "fullnode:";
/**
+ * Name of the field that contains those property names which are not found
+ * (or were null) for the given
+ */
+ public static final String NULL_PROPS = ":nullProps";
+
+ /**
* Used to select only the PATH field from the lucene documents
*/
public static final Set<String> PATH_SELECTOR = new HashSet<String>(
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
Wed Feb 18 16:58:00 2015
@@ -72,7 +72,6 @@ import static org.apache.jackrabbit.JcrC
import static org.apache.jackrabbit.JcrConstants.NT_BASE;
import static org.apache.jackrabbit.oak.api.Type.NAMES;
import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath;
-import static org.apache.jackrabbit.oak.commons.PathUtils.isAbsolute;
import static
org.apache.jackrabbit.oak.plugins.index.IndexConstants.DECLARING_NODE_TYPES;
import static
org.apache.jackrabbit.oak.plugins.index.IndexConstants.ENTRY_COUNT_PROPERTY_NAME;
import static
org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_COUNT;
@@ -562,6 +561,7 @@ class IndexDefinition implements Aggrega
private final String nodeTypeName;
private final Map<String, PropertyDefinition> propConfigs;
private final List<NamePattern> namePatterns;
+ private final List<PropertyDefinition> nullCheckEnabledProperties;
private final boolean indexesAllNodesOfMatchingType;
final float boost;
@@ -582,15 +582,18 @@ class IndexDefinition implements Aggrega
this.propertyTypes = getSupportedTypes(config,
INCLUDE_PROPERTY_TYPES, TYPES_ALLOW_ALL);
List<NamePattern> namePatterns = newArrayList();
+ List<PropertyDefinition> nonExistentProperties = newArrayList();
List<Aggregate.Include> propIncludes = newArrayList();
- this.propConfigs = collectPropConfigs(config, namePatterns,
propIncludes);
+ this.propConfigs = collectPropConfigs(config, namePatterns,
propIncludes, nonExistentProperties);
this.propAggregate = new Aggregate(nodeTypeName, propIncludes);
this.aggregate = combine(propAggregate, nodeTypeName);
this.namePatterns = ImmutableList.copyOf(namePatterns);
+ this.nullCheckEnabledProperties =
ImmutableList.copyOf(nonExistentProperties);
this.fulltextEnabled = aggregate.hasNodeAggregates() ||
hasAnyFullTextEnabledProperty();
this.propertyIndexEnabled = hasAnyPropertyIndexConfigured();
this.indexesAllNodesOfMatchingType =
allMatchingNodeByTypeIndexed();
+ validateRuleDefinition();
}
/**
@@ -610,6 +613,7 @@ class IndexDefinition implements Aggrega
this.propertyTypes = original.propertyTypes;
this.propertyIndexEnabled = original.propertyIndexEnabled;
this.propAggregate = original.propAggregate;
+ this.nullCheckEnabledProperties =
original.nullCheckEnabledProperties;
this.aggregate = combine(propAggregate, nodeTypeName);
this.fulltextEnabled = aggregate.hasNodeAggregates() ||
original.fulltextEnabled;
this.indexesAllNodesOfMatchingType =
allMatchingNodeByTypeIndexed();
@@ -637,6 +641,10 @@ class IndexDefinition implements Aggrega
return nodeTypeName;
}
+ public List<PropertyDefinition> getNullCheckEnabledProperties() {
+ return nullCheckEnabledProperties;
+ }
+
@Override
public String toString() {
String str = "IndexRule: "+ nodeTypeName;
@@ -729,7 +737,8 @@ class IndexDefinition implements Aggrega
}
private Map<String, PropertyDefinition> collectPropConfigs(NodeState
config, List<NamePattern> patterns,
-
List<Aggregate.Include> propAggregate) {
+
List<Aggregate.Include> propAggregate,
+
List<PropertyDefinition> nonExistentProperties) {
Map<String, PropertyDefinition> propDefns = newHashMap();
NodeState propNode =
config.getChildNode(LuceneIndexConstants.PROP_NODE);
@@ -755,9 +764,13 @@ class IndexDefinition implements Aggrega
propDefns.put(pd.name, pd);
}
- if (isRelativeProperty(pd.name)){
+ if (pd.relative){
propAggregate.add(new Aggregate.PropertyInclude(pd));
}
+
+ if (pd.nullCheckEnabled){
+ nonExistentProperties.add(pd);
+ }
}
}
return ImmutableMap.copyOf(propDefns);
@@ -800,6 +813,15 @@ class IndexDefinition implements Aggrega
return true;
}
+ //If there is nullCheckEnabled property which is not relative then
+ //all nodes would be indexed. relativeProperty with
nullCheckEnabled might
+ //not ensure that (OAK-1085)
+ for (PropertyDefinition pd : nullCheckEnabledProperties){
+ if (!pd.relative) {
+ return true;
+ }
+ }
+
//jcr:primaryType is present on all node. So if such a property
//is indexed then it would mean all nodes covered by this index
rule
//are indexed
@@ -819,6 +841,13 @@ class IndexDefinition implements Aggrega
}
return new Aggregate(nodeTypeName, includes);
}
+
+ private void validateRuleDefinition() {
+ if (!nullCheckEnabledProperties.isEmpty() && isBasedOnNtBase()){
+ throw new IllegalStateException("nt:base based rule cannot
have a " +
+ "PropertyDefinition with nullCheckEnabled");
+ }
+ }
}
/**
@@ -948,7 +977,7 @@ class IndexDefinition implements Aggrega
String propNodeName = propName;
//For proper propName use the propName as childNode name
- if(isRelativeProperty(propName)
+ if(PropertyDefinition.isRelativeProperty(propName)
|| propName.equals(includeAllProp)){
propNodeName = "prop" + i++;
}
@@ -1010,7 +1039,7 @@ class IndexDefinition implements Aggrega
private static NodeState getPropDefnNode(NodeState defn, String propName){
NodeState propNode = defn.getChildNode(LuceneIndexConstants.PROP_NODE);
NodeState propDefNode;
- if (isRelativeProperty(propName)) {
+ if (PropertyDefinition.isRelativeProperty(propName)) {
NodeState result = propNode;
for (String name : PathUtils.elements(propName)) {
result = result.getChildNode(name);
@@ -1239,7 +1268,4 @@ class IndexDefinition implements Aggrega
return defn.getChildNode(LuceneIndexConstants.INDEX_RULES).exists();
}
- private static boolean isRelativeProperty(String propertyName){
- return !isAbsolute(propertyName) &&
PathUtils.getNextSlash(propertyName, 0) > 0;
- }
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
Wed Feb 18 16:58:00 2015
@@ -139,12 +139,11 @@ class IndexPlanner {
//for property index
if (indexingRule.propertyIndexEnabled) {
for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
- if (pr.isNullRestriction()) {
- // ignore for planning
- continue;
- }
PropertyDefinition pd =
indexingRule.getConfig(pr.propertyName);
if (pd != null && pd.propertyIndexEnabled()) {
+ if (pr.isNullRestriction() && !pd.nullCheckEnabled){
+ continue;
+ }
indexedProps.add(pr.propertyName);
result.propDefns.put(pr.propertyName, pd);
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java
Wed Feb 18 16:58:00 2015
@@ -241,4 +241,10 @@ public interface LuceneIndexConstants {
* whether use this property values for spellchecking
*/
String PROP_USE_IN_SPELLCHECK = "useInSpellcheck";
+
+ /**
+ * Property definition config indicating that null check support should be
+ * enabled for this property
+ */
+ String PROP_NULL_CHECK_ENABLED = "nullCheckEnabled";
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java
Wed Feb 18 16:58:00 2015
@@ -303,6 +303,7 @@ public class LuceneIndexEditor implement
}
dirty |= indexAggregates(path, fields, state);
+ dirty |= indexNullCheckEnabledProps(path, fields, state);
if (isUpdate && !dirty) {
// updated the state but had no relevant changes
@@ -514,6 +515,46 @@ public class LuceneIndexEditor implement
return fields;
}
+ //~-------------------------------------------------------< NullCheck
Support >
+
+ private boolean indexNullCheckEnabledProps(String path, List<Field>
fields, NodeState state) {
+ boolean fieldAdded = false;
+ for (PropertyDefinition pd :
indexingRule.getNullCheckEnabledProperties()) {
+ if (isPropertyNull(state, pd)) {
+ fields.add(new StringField(FieldNames.NULL_PROPS, pd.name,
Field.Store.NO));
+ fieldAdded = true;
+ }
+ }
+ return fieldAdded;
+ }
+
+ /**
+ * Determine if the property as defined by PropertyDefinition exists or
not.
+ *
+ * <p>For relative property if the intermediate nodes do not exist then
property is
+ * <bold>not</bold> considered to be null</p>
+ *
+ * @return true if the property does not exist
+ */
+ private boolean isPropertyNull(NodeState state, PropertyDefinition pd){
+ NodeState propertyNode = getPropertyNode(state, pd);
+ if (!propertyNode.exists()){
+ return false;
+ }
+ return !propertyNode.hasProperty(pd.nonRelativeName);
+ }
+
+ private static NodeState getPropertyNode(NodeState nodeState,
PropertyDefinition pd) {
+ if (!pd.relative){
+ return nodeState;
+ }
+ NodeState node = nodeState;
+ for (String name : pd.ancestors) {
+ node = node.getChildNode(name);
+ }
+ return node;
+ }
+
//~-------------------------------------------------------< Aggregate >
@Override
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
Wed Feb 18 16:58:00 2015
@@ -718,6 +718,11 @@ public class LucenePropertyIndex impleme
private static Query createQuery(PropertyRestriction pr,
PropertyDefinition defn) {
int propType = determinePropertyType(defn, pr);
+
+ if (pr.isNullRestriction()){
+ return new TermQuery(new Term(FieldNames.NULL_PROPS, defn.name));
+ }
+
switch (propType) {
case PropertyType.DATE: {
Long first = pr.first != null ?
FieldFactory.dateToLong(pr.first.getValue(Type.DATE)) : null;
@@ -772,7 +777,7 @@ public class LucenePropertyIndex impleme
in.add(NumericRangeQuery.newDoubleRange(pr.propertyName, doubleVal, doubleVal,
true, true), BooleanClause.Occur.SHOULD);
}
return in;
- } else if (pr.first == null && pr.last == null ) {
+ } else if (pr.isNotNullRestriction()) {
// not null.
return NumericRangeQuery.newDoubleRange(pr.propertyName,
Double.MIN_VALUE, Double.MAX_VALUE, true, true);
}
@@ -801,7 +806,7 @@ public class LucenePropertyIndex impleme
in.add(NumericRangeQuery.newLongRange(pr.propertyName,
longVal, longVal, true, true), BooleanClause.Occur.SHOULD);
}
return in;
- } else if (pr.first == null && pr.last == null ) {
+ } else if (pr.isNotNullRestriction()) {
// not null.
return NumericRangeQuery.newLongRange(pr.propertyName,
Long.MIN_VALUE, Long.MAX_VALUE, true, true);
}
@@ -835,7 +840,7 @@ public class LucenePropertyIndex impleme
in.add(new TermQuery(new Term(pr.propertyName,
strVal)), BooleanClause.Occur.SHOULD);
}
return in;
- } else if (pr.first == null && pr.last == null ) {
+ } else if (pr.isNotNullRestriction()) {
return new TermRangeQuery(pr.propertyName, null, null,
true, true);
}
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java
Wed Feb 18 16:58:00 2015
@@ -19,16 +19,22 @@
package org.apache.jackrabbit.oak.plugins.index.lucene;
+import javax.annotation.CheckForNull;
import javax.jcr.PropertyType;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
import
org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.IndexingRule;
import org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static com.google.common.collect.ImmutableList.copyOf;
+import static com.google.common.collect.Iterables.toArray;
+import static org.apache.jackrabbit.oak.commons.PathUtils.elements;
+import static org.apache.jackrabbit.oak.commons.PathUtils.isAbsolute;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.FIELD_BOOST;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PROP_IS_REGEX;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.util.ConfigUtil.getOptionalValue;
@@ -68,15 +74,29 @@ class PropertyDefinition {
final boolean ordered;
+ final boolean nullCheckEnabled;
+
final int includedPropertyTypes;
- boolean useInSuggest;
+ final boolean relative;
+
+ final boolean useInSuggest;
+
+ final boolean useInSpellcheck;
- boolean useInSpellcheck;
+ final String[] ancestors;
+
+ /**
+ * Property name excluding the relativePath. For regular expression based
definition
+ * its set to null
+ */
+ @CheckForNull
+ final String nonRelativeName;
- public PropertyDefinition(IndexingRule idxDefn, String name, NodeState
defn) {
+ public PropertyDefinition(IndexingRule idxDefn, String nodeName, NodeState
defn) {
this.isRegexp = getOptionalValue(defn, PROP_IS_REGEX, false);
- this.name = getName(defn, name);
+ this.name = getName(defn, nodeName);
+ this.relative = isRelativeProperty(name);
this.boost = getOptionalValue(defn, FIELD_BOOST, DEFAULT_BOOST);
//By default if a property is defined it is indexed
@@ -93,11 +113,16 @@ class PropertyDefinition {
//TODO Add test case for above cases
- this.propertyType = getPropertyType(idxDefn, name, defn);
+ this.propertyType = getPropertyType(idxDefn, nodeName, defn);
this.useInSuggest = getOptionalValue(defn,
LuceneIndexConstants.PROP_USE_IN_SUGGEST, false);
this.useInSpellcheck = getOptionalValue(defn,
LuceneIndexConstants.PROP_USE_IN_SPELLCHECK, false);
+ this.nullCheckEnabled = getOptionalValue(defn,
LuceneIndexConstants.PROP_NULL_CHECK_ENABLED, false);
+ this.nonRelativeName = determineNonRelativeName();
+ this.ancestors = computeAncestors(name);
+ validate();
}
+
/**
* If 'analyzed' is enabled then property value would be used to evaluate
the
* contains clause related to those properties. In such mode also some
properties
@@ -156,12 +181,40 @@ class PropertyDefinition {
", analyzed=" + analyzed +
", ordered=" + ordered +
", useInSuggest=" + useInSuggest+
- ", useInSpellcheck=" + useInSpellcheck+
+ ", nullCheckEnabled=" + nullCheckEnabled+
'}';
}
+ static boolean isRelativeProperty(String propertyName){
+ return !isAbsolute(propertyName) &&
PathUtils.getNextSlash(propertyName, 0) > 0;
+ }
+
//~---------------------------------------------< internal >
+ private void validate() {
+ if (nullCheckEnabled && isRegexp){
+ throw new IllegalStateException(String.format("%s can be set to
true for property definition using " +
+ "regular expression",
LuceneIndexConstants.PROP_NULL_CHECK_ENABLED));
+ }
+ }
+
+ private String determineNonRelativeName() {
+ if (isRegexp){
+ return null;
+ }
+
+ if (!relative){
+ return name;
+ }
+
+ return PathUtils.getName(name);
+ }
+
+ private static String[] computeAncestors(String parentPath) {
+ return toArray(copyOf(elements(PathUtils.getParentPath(parentPath))),
String.class);
+ }
+
+
private static String getName(NodeState definition, String defaultName){
PropertyState ps =
definition.getProperty(LuceneIndexConstants.PROP_NAME);
return ps == null ? defaultName : ps.getValue(Type.STRING);
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java
Wed Feb 18 16:58:00 2015
@@ -24,7 +24,6 @@ import javax.jcr.PropertyType;
import com.google.common.collect.ImmutableList;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.plugins.index.lucene.util.TokenizerChain;
import org.apache.jackrabbit.oak.plugins.tree.TreeFactory;
@@ -34,7 +33,6 @@ import org.apache.lucene.codecs.Codec;
import
org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.IndexingRule;
import org.junit.Test;
-import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableSet.of;
import static javax.jcr.PropertyType.TYPENAME_LONG;
import static javax.jcr.PropertyType.TYPENAME_STRING;
@@ -51,12 +49,14 @@ import static org.apache.jackrabbit.oak.
import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PROP_NAME;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PROP_NODE;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.TIKA;
+import static
org.apache.jackrabbit.oak.plugins.index.lucene.TestUtil.registerTestNodeType;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLuceneIndexDefinition;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLucenePropertyIndexDefinition;
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.nodetype.write.InitialContent.INITIAL_CONTENT;
import static
org.apache.jackrabbit.oak.plugins.tree.impl.TreeConstants.OAK_CHILD_ORDER;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -154,13 +154,15 @@ public class IndexDefinitionTest {
assertNotNull(rule.getConfig("foo1/bar"));
assertEquals(PropertyType.DATE, rule.getConfig("foo1/bar").getType());
assertEquals(PropertyType.LONG,
rule.getConfig("foo2/bar2/baz").getType());
+ assertTrue(rule.getConfig("foo1/bar").relative);
+ assertArrayEquals(new String[]{"foo2", "bar2"},
rule.getConfig("foo2/bar2/baz").ancestors);
}
@Test
public void indexRuleSanity() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder").setProperty(LuceneIndexConstants.FIELD_BOOST,
2.0);
- child(rules, "nt:folder/properties/prop1")
+ TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(LuceneIndexConstants.FIELD_BOOST, 3.0)
.setProperty(LuceneIndexConstants.PROP_TYPE,
PropertyType.TYPENAME_BOOLEAN);
@@ -243,9 +245,9 @@ public class IndexDefinitionTest {
public void indexRuleWithPropertyRegEx() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
- child(rules, "nt:folder/properties/prop1")
+ TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(LuceneIndexConstants.FIELD_BOOST, 3.0);
- child(rules, "nt:folder/properties/prop2")
+ TestUtil.child(rules, "nt:folder/properties/prop2")
.setProperty(LuceneIndexConstants.PROP_NAME, "foo.*")
.setProperty(LuceneIndexConstants.PROP_IS_REGEX, true)
.setProperty(LuceneIndexConstants.FIELD_BOOST, 4.0);
@@ -267,10 +269,10 @@ public class IndexDefinitionTest {
public void indexRuleWithPropertyRegEx2() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
- child(rules, "nt:folder/properties/prop1")
+ TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(LuceneIndexConstants.PROP_NAME, ".*")
.setProperty(LuceneIndexConstants.PROP_IS_REGEX, true);
- child(rules, "nt:folder/properties/prop2")
+ TestUtil.child(rules, "nt:folder/properties/prop2")
.setProperty(LuceneIndexConstants.PROP_NAME, "metadata/.*")
.setProperty(LuceneIndexConstants.PROP_IS_REGEX, true)
.setProperty(LuceneIndexConstants.FIELD_BOOST, 4.0);
@@ -293,11 +295,11 @@ public class IndexDefinitionTest {
public void indexRuleWithPropertyOrdering() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
- child(rules, "nt:folder/properties/prop1")
+ TestUtil.child(rules, "nt:folder/properties/prop1")
.setProperty(LuceneIndexConstants.PROP_NAME, "foo.*")
.setProperty(LuceneIndexConstants.PROP_IS_REGEX, true)
.setProperty(LuceneIndexConstants.FIELD_BOOST, 3.0);
- child(rules, "nt:folder/properties/prop2")
+ TestUtil.child(rules, "nt:folder/properties/prop2")
.setProperty(LuceneIndexConstants.PROP_NAME, ".*")
.setProperty(LuceneIndexConstants.PROP_IS_REGEX, true)
.setProperty(LuceneIndexConstants.FIELD_BOOST, 4.0);
@@ -328,7 +330,7 @@ public class IndexDefinitionTest {
public void skipTokenization() throws Exception{
NodeBuilder rules = builder.child(INDEX_RULES);
rules.child("nt:folder");
- child(rules, "nt:folder/properties/prop2")
+ TestUtil.child(rules, "nt:folder/properties/prop2")
.setProperty(LuceneIndexConstants.PROP_NAME, ".*")
.setProperty(LuceneIndexConstants.PROP_IS_REGEX, true)
.setProperty(LuceneIndexConstants.PROP_ANALYZED, true);
@@ -519,6 +521,37 @@ public class IndexDefinitionTest {
assertEquals(1000, defn.getMaxExtractLength());
}
+ @Test(expected = IllegalStateException.class)
+ public void nullCheckEnabledWithNtBase() throws Exception{
+
builder.child(PROP_NODE).child("foo").setProperty(LuceneIndexConstants.PROP_NULL_CHECK_ENABLED,
true);
+ IndexDefinition idxDefn = new IndexDefinition(root,
builder.getNodeState());
+ }
+
+ @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(LuceneIndexConstants.PROP_NAME, ".*")
+ .setProperty(LuceneIndexConstants.PROP_IS_REGEX, true)
+ .setProperty(LuceneIndexConstants.PROP_NULL_CHECK_ENABLED,
true);
+ root = registerTestNodeType(builder).getNodeState();
+ IndexDefinition idxDefn = new IndexDefinition(root,
builder.getNodeState());
+ }
+
+ @Test
+ public void nullCheckEnabledWithTestNode() throws Exception{
+ NodeBuilder rules = builder.child(INDEX_RULES);
+ TestUtil.child(rules, "oak:TestNode/properties/prop2")
+ .setProperty(LuceneIndexConstants.PROP_NAME, "foo")
+ .setProperty(LuceneIndexConstants.PROP_NULL_CHECK_ENABLED,
true);
+ root = registerTestNodeType(builder).getNodeState();
+ IndexDefinition idxDefn = new IndexDefinition(root,
builder.getNodeState());
+
assertTrue(!idxDefn.getApplicableIndexingRule(TestUtil.NT_TEST).getNullCheckEnabledProperties().isEmpty());
+ }
+
+ //TODO indexesAllNodesOfMatchingType - with nullCheckEnabled
+
private static IndexingRule getRule(IndexDefinition defn, String typeName){
return defn.getApplicableIndexingRule(newTree(newNode(typeName)));
}
@@ -533,10 +566,4 @@ public class IndexDefinitionTest {
return builder;
}
- private static NodeBuilder child(NodeBuilder nb, String path) {
- for (String name : PathUtils.elements(checkNotNull(path))) {
- nb = nb.child(name);
- }
- return nb;
- }
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlannerTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlannerTest.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlannerTest.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlannerTest.java
Wed Feb 18 16:58:00 2015
@@ -55,8 +55,11 @@ import static org.apache.jackrabbit.oak.
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.lucene.LuceneIndexConstants.INDEX_DATA_CHILD_NAME;
+import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.INDEX_RULES;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.ORDERED_PROP_NAMES;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.VERSION;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.TestUtil.NT_TEST;
+import static
org.apache.jackrabbit.oak.plugins.index.lucene.TestUtil.registerTestNodeType;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLuceneIndexDefinition;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLucenePropertyIndexDefinition;
import static
org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
@@ -324,6 +327,42 @@ public class IndexPlannerTest {
assertEquals(numofDocs, plan.getEstimatedEntryCount());
}
+ @Test
+ public void nullPropertyCheck() throws Exception{
+ NodeBuilder defn = newLucenePropertyIndexDefinition(builder, "test",
of("foo"), "async");
+
+ IndexNode node = createIndexNode(new IndexDefinition(root,
defn.getNodeState()));
+ FilterImpl filter = createFilter("nt:base");
+ filter.restrictProperty("foo", Operator.EQUAL, null);
+ IndexPlanner planner = new IndexPlanner(node, "/foo", filter,
Collections.<OrderEntry>emptyList());
+ QueryIndex.IndexPlan plan = planner.getPlan();
+ assertNull("For null checks no plan should be returned",plan);
+ }
+
+ @Test
+ public void nullPropertyCheck2() throws Exception{
+ root = registerTestNodeType(builder).getNodeState();
+ NodeBuilder defn = newLucenePropertyIndexDefinition(builder, "test",
of("foo"), "async");
+ NodeBuilder rules = defn.child(INDEX_RULES);
+ TestUtil.child(rules, "oak:TestNode/properties/prop2")
+ .setProperty(LuceneIndexConstants.PROP_NAME, "foo")
+ .setProperty(LuceneIndexConstants.PROP_NULL_CHECK_ENABLED,
true)
+ .setProperty(LuceneIndexConstants.PROP_PROPERTY_INDEX, true);
+
+ IndexDefinition idxDefn = new IndexDefinition(root,
builder.getNodeState().getChildNode("test"));
+ IndexNode node = createIndexNode(idxDefn);
+
+ FilterImpl filter = createFilter(NT_TEST);
+ filter.restrictProperty("foo", Operator.EQUAL, null);
+
+ IndexPlanner planner = new IndexPlanner(node, "/foo", filter,
Collections.<OrderEntry>emptyList());
+ QueryIndex.IndexPlan plan = planner.getPlan();
+ assertNotNull("For null checks plan should be returned with
nullCheckEnabled", plan);
+ IndexPlanner.PlanResult pr =
+ (IndexPlanner.PlanResult)
plan.getAttribute(LucenePropertyIndex.ATTR_PLAN_RESULT);
+ assertNotNull(pr.getPropDefn(filter.getPropertyRestriction("foo")));
+ }
+
private IndexNode createIndexNode(IndexDefinition defn, long numOfDocs)
throws IOException {
return new IndexNode("foo", defn, createSampleDirectory(numOfDocs));
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
Wed Feb 18 16:58:00 2015
@@ -48,6 +48,8 @@ import static org.apache.jackrabbit.oak.
import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PERSISTENCE_FILE;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PERSISTENCE_NAME;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PERSISTENCE_PATH;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.TestUtil.NT_TEST;
+import static
org.apache.jackrabbit.oak.plugins.index.lucene.TestUtil.createNodeWithType;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLuceneIndexDefinition;
import static
org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLucenePropertyIndexDefinition;
import static
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
@@ -227,6 +229,81 @@ public class LuceneIndexTest {
}
@Test
+ public void testPropertyNonExistence() throws Exception {
+ root = TestUtil.registerTestNodeType(builder).getNodeState();
+
+ NodeBuilder index =
newLucenePropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME),
+ "lucene", ImmutableSet.of("foo"), null);
+ NodeBuilder rules = index.child(INDEX_RULES);
+ NodeBuilder propNode =
rules.child(NT_TEST).child(LuceneIndexConstants.PROP_NODE);
+
+ NodeBuilder fooProp = propNode.child("foo");
+ fooProp.setProperty(LuceneIndexConstants.PROP_PROPERTY_INDEX, true);
+ fooProp.setProperty(LuceneIndexConstants.PROP_NULL_CHECK_ENABLED,
true);
+
+ NodeState before = builder.getNodeState();
+ createNodeWithType(builder, "a", NT_TEST).setProperty("foo", "bar");
+ createNodeWithType(builder, "b", NT_TEST).setProperty("foo", "bar");
+ createNodeWithType(builder, "c", NT_TEST);
+
+ NodeState after = builder.getNodeState();
+
+ NodeState indexed = HOOK.processCommit(before, after,CommitInfo.EMPTY);
+
+ IndexTracker tracker = new IndexTracker();
+ tracker.update(indexed);
+ AdvancedQueryIndex queryIndex = new LucenePropertyIndex(tracker);
+
+ FilterImpl filter = createFilter(NT_TEST);
+ filter.restrictProperty("foo", Operator.EQUAL, null);
+ assertFilter(filter, queryIndex, indexed, ImmutableList.of("/c"));
+ }
+
+ @Test
+ public void testRelativePropertyNonExistence() throws Exception {
+ root = TestUtil.registerTestNodeType(builder).getNodeState();
+
+ NodeBuilder index =
newLucenePropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME),
+ "lucene", ImmutableSet.of("foo"), null);
+ NodeBuilder rules = index.child(INDEX_RULES);
+ NodeBuilder propNode =
rules.child(NT_TEST).child(LuceneIndexConstants.PROP_NODE);
+
+ propNode.child("bar")
+ .setProperty(LuceneIndexConstants.PROP_NAME, "jcr:content/bar")
+ .setProperty(LuceneIndexConstants.PROP_PROPERTY_INDEX, true)
+ .setProperty(LuceneIndexConstants.PROP_NULL_CHECK_ENABLED,
true);
+
+ NodeState before = builder.getNodeState();
+
+ NodeBuilder a1 = createNodeWithType(builder, "a1", NT_TEST);
+ a1.child("jcr:content").setProperty("bar", "foo");
+
+ NodeBuilder b1 = createNodeWithType(builder, "b1", NT_TEST);
+ b1.child("jcr:content");
+
+ NodeState after = builder.getNodeState();
+
+ NodeState indexed = HOOK.processCommit(before, after,CommitInfo.EMPTY);
+
+ IndexTracker tracker = new IndexTracker();
+ tracker.update(indexed);
+ AdvancedQueryIndex queryIndex = new LucenePropertyIndex(tracker);
+
+ FilterImpl filter = createFilter(NT_TEST);
+ filter.restrictProperty("jcr:content/bar", Operator.EQUAL, null);
+ assertFilter(filter, queryIndex, indexed, ImmutableList.of("/b1"));
+
+ builder.child("b1").child("jcr:content").setProperty("bar", "foo");
+ after = builder.getNodeState();
+ indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
+ tracker.update(indexed);
+
+ filter = createFilter(NT_TEST);
+ filter.restrictProperty("jcr:content/bar", Operator.EQUAL, null);
+ assertFilter(filter, queryIndex, indexed,
Collections.<String>emptyList());
+ }
+
+ @Test
public void testPathRestrictions() throws Exception {
NodeBuilder idx =
newLucenePropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME),
"lucene", ImmutableSet.of("foo"), null);
@@ -494,7 +571,8 @@ public class LuceneIndexTest {
for (String p : expected) {
assertTrue("Expected path " + p + " not found", paths.contains(p));
}
- assertEquals("Result set size is different", expected.size(),
paths.size());
+ assertEquals("Result set size is different \nExpected: " +
+ expected + "\nActual: " + paths, expected.size(),
paths.size());
return paths;
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
Wed Feb 18 16:58:00 2015
@@ -33,6 +33,7 @@ import com.google.common.collect.Immutab
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.Oak;
import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -46,6 +47,7 @@ import org.apache.jackrabbit.oak.plugins
import
org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.NodeTypeRegistry;
import org.apache.jackrabbit.oak.query.AbstractQueryTest;
import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
@@ -296,8 +298,9 @@ public class LucenePropertyIndexTest ext
assertQuery(propabQuery, asList("/test/a", "/test/b", "/test"));
}
- private static void setNodeType(Tree t, String typeName){
+ private static Tree setNodeType(Tree t, String typeName){
t.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName, Type.NAME);
+ return t;
}
@Test
@@ -328,6 +331,35 @@ public class LucenePropertyIndexTest ext
assertQuery("select [jcr:path] from [nt:base] where propa is not
null", asList("/test/a", "/test/b"));
}
+
+ @Test
+ public void propertyNonExistenceQuery() throws Exception {
+ NodeTypeRegistry.register(root,
IOUtils.toInputStream(TestUtil.TEST_NODE_TYPE), "test nodeType");
+
+ Tree idx = createIndex("test1", of("propa", "propb"));
+ Tree props = TestUtil.newRulePropTree(idx, TestUtil.NT_TEST);
+ Tree prop = props.addChild(TestUtil.unique("prop"));
+ prop.setProperty(LuceneIndexConstants.PROP_NAME, "propa");
+ prop.setProperty(LuceneIndexConstants.PROP_PROPERTY_INDEX, true);
+ prop.setProperty(LuceneIndexConstants.PROP_NULL_CHECK_ENABLED, true);
+ root.commit();
+
+ Tree test = root.getTree("/").addChild("test");
+ createNodeWithType(test, "a", "oak:TestNode").setProperty("propa",
"a");
+ createNodeWithType(test, "b", "oak:TestNode").setProperty("propa",
"c");
+ createNodeWithType(test, "c", "oak:TestNode").setProperty("propb",
"e");
+ root.commit();
+
+ String propabQuery = "select [jcr:path] from [oak:TestNode] where
[propa] is null";
+ assertThat(explain(propabQuery),
containsString("lucene:test1(/oak:index/test1) :nullProps:propa"));
+ assertQuery(propabQuery, asList("/test/c"));
+ }
+
+ private static Tree createNodeWithType(Tree t, String nodeName, String
typeName){
+ t = t.addChild(nodeName);
+ t.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName, Type.NAME);
+ return t;
+ }
@Test
public void orderByScore() throws Exception {
@@ -781,9 +813,9 @@ public class LucenePropertyIndexTest ext
getSortedPaths(tuples, OrderDirection.ASC))));
// Append the path of property added as timestamp string to the sorted
list
assertOrderedQuery(
- "select [jcr:path] from [nt:base] where [bar] = 'baz' order by
[foo] DESC", Lists
- .newArrayList(Iterables.concat(getSortedPaths(tuples,
OrderDirection.DESC),
- Lists.newArrayList("/test/n0"))));
+ "select [jcr:path] from [nt:base] where [bar] = 'baz' order by
[foo] DESC", Lists
+ .newArrayList(Iterables.concat(getSortedPaths(tuples,
OrderDirection.DESC),
+ Lists.newArrayList("/test/n0"))));
}
@Test
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/TestUtil.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/TestUtil.java?rev=1660676&r1=1660675&r2=1660676&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/TestUtil.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/TestUtil.java
Wed Feb 18 16:58:00 2015
@@ -26,13 +26,38 @@ import java.util.concurrent.atomic.Atomi
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.JcrConstants;
+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.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
+import org.apache.jackrabbit.oak.plugins.memory.ModifiedNodeState;
+import org.apache.jackrabbit.oak.plugins.name.NamespaceEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.NodeTypeRegistry;
+import org.apache.jackrabbit.oak.plugins.tree.RootFactory;
+import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
+import org.apache.jackrabbit.oak.spi.commit.EditorHook;
+import org.apache.jackrabbit.oak.spi.state.ApplyDiff;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+import static com.google.common.base.Preconditions.checkNotNull;
public class TestUtil {
private static final AtomicInteger COUNTER = new AtomicInteger();
+ public static final String NT_TEST = "oak:TestNode";
+
+ public static final String TEST_NODE_TYPE = "[oak:TestNode]\n" +
+ " - * (UNDEFINED) multiple\n" +
+ " - * (UNDEFINED)\n" +
+ " + * (nt:base) = oak:TestNode VERSION";
+
static void useV2(NodeBuilder idxNb) {
idxNb.setProperty(LuceneIndexConstants.COMPAT_MODE,
IndexFormatVersion.V2.getVersion());
}
@@ -88,6 +113,13 @@ public class TestUtil {
return props;
}
+ public static NodeBuilder child(NodeBuilder nb, String path) {
+ for (String name : PathUtils.elements(checkNotNull(path))) {
+ nb = nb.child(name);
+ }
+ return nb;
+ }
+
static class AggregatorBuilder {
private final Tree aggs;
@@ -108,4 +140,34 @@ public class TestUtil {
static String unique(String name){
return name + COUNTER.getAndIncrement();
}
+
+ public static NodeBuilder registerTestNodeType(NodeBuilder builder){
+ registerNodeType(builder, TEST_NODE_TYPE);
+ return builder;
+ }
+
+ public static void registerNodeType(NodeBuilder builder, String
nodeTypeDefn){
+ //Taken from
org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent
+ NodeState base = ModifiedNodeState.squeeze(builder.getNodeState());
+ NodeStore store = new MemoryNodeStore(base);
+ Root root = RootFactory.createSystemRoot(
+ store, new EditorHook(new CompositeEditorProvider(
+ new NamespaceEditorProvider(),
+ new TypeEditorProvider())), null, null, null, null);
+ NodeTypeRegistry.register(root, IOUtils.toInputStream(nodeTypeDefn),
"test node types");
+ NodeState target = store.getRoot();
+ target.compareAgainstBaseState(base, new ApplyDiff(builder));
+ }
+
+ public static Tree createNodeWithType(Tree t, String nodeName, String
typeName){
+ t = t.addChild(nodeName);
+ t.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName, Type.NAME);
+ return t;
+ }
+
+ public static NodeBuilder createNodeWithType(NodeBuilder builder, String
nodeName, String typeName){
+ builder = builder.child(nodeName);
+ builder.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName, Type.NAME);
+ return builder;
+ }
}