You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ch...@apache.org on 2014/11/16 07:19:16 UTC
svn commit: r1639963 - in /jackrabbit/oak/trunk/oak-lucene/src:
main/java/org/apache/jackrabbit/oak/plugins/index/lucene/
test/java/org/apache/jackrabbit/oak/plugins/index/lucene/
Author: chetanm
Date: Sun Nov 16 06:19:15 2014
New Revision: 1639963
URL: http://svn.apache.org/r1639963
Log:
OAK-2261 - Enable support for NodeType based indexing rules (WIP)
Compatibility support - Impilement logic to adapt existing index config to IndexRule based config
* If no declaredNodeType defined then existing 'properties' config is mapped to rule for type nt:base
* If declaredNodeType defined then non inheritable rule is defined for each nodeType
Modified:
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/LuceneIndexConstants.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/RelativeProperty.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java
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=1639963&r1=1639962&r2=1639963&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 Sun Nov 16 06:19:15 2014
@@ -38,14 +38,18 @@ import com.google.common.collect.Immutab
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
import org.apache.jackrabbit.oak.plugins.tree.ImmutableTree;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.util.TreeUtil;
import org.apache.lucene.codecs.Codec;
@@ -53,8 +57,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Lists.newArrayListWithCapacity;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet;
+import static org.apache.jackrabbit.JcrConstants.NT_BASE;
+import static org.apache.jackrabbit.oak.api.Type.NAMES;
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;
@@ -67,8 +74,10 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.INCLUDE_PROPERTY_TYPES;
import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.ORDERED_PROP_NAMES;
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.PropertyDefinition.DEFAULT_BOOST;
import static org.apache.jackrabbit.oak.plugins.index.lucene.util.ConfigUtil.getOptionalValue;
+import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
import static org.apache.jackrabbit.oak.plugins.tree.TreeConstants.OAK_CHILD_ORDER;
@@ -86,6 +95,12 @@ class IndexDefinition {
*/
static final long DEFAULT_ENTRY_COUNT = 1000;
+ private static String TYPES_ALLOW_ALL_NAME = "allTypes";
+
+ private static final int TYPES_ALLOW_NONE = PropertyType.UNDEFINED;
+
+ private static final int TYPES_ALLOW_ALL = -1;
+
private final int propertyTypes;
private final Set<String> excludes;
@@ -139,20 +154,7 @@ class IndexDefinition {
this.root = root;
this.definition = defn;
this.indexName = determineIndexName(defn, indexPath);
- PropertyState pst = defn.getProperty(INCLUDE_PROPERTY_TYPES);
- if (pst != null) {
- int types = 0;
- for (String inc : pst.getValue(Type.STRINGS)) {
- try {
- types |= 1 << PropertyType.valueFromName(inc);
- } catch (IllegalArgumentException e) {
- log.warn("Unknown property type: " + inc);
- }
- }
- this.propertyTypes = types;
- } else {
- this.propertyTypes = -1;
- }
+ this.propertyTypes = getSupportedTypes(defn, TYPES_ALLOW_ALL);
this.excludes = toLowerCase(getMultiProperty(defn, EXCLUDE_PROPERTY_NAMES));
this.includes = getMultiProperty(defn, INCLUDE_PROPERTY_NAMES);
@@ -161,14 +163,19 @@ class IndexDefinition {
this.blobSize = getOptionalValue(defn, BLOB_SIZE, DEFAULT_BLOB_SIZE);
- this.fullTextEnabled = getOptionalValue(defn, FULL_TEXT_ENABLED, true);
- //Storage is disabled for non full text indexes
- this.storageEnabled = this.fullTextEnabled && getOptionalValue(defn, EXPERIMENTAL_STORAGE, true);
//TODO Flag out invalid propertyNames like one which are absolute
this.relativeProps = collectRelativeProps(Iterables.concat(includes, orderedProps));
this.propDefns = collectPropertyDefns(defn);
- this.indexRules = collectIndexRules(defn.getChildNode(LuceneIndexConstants.INDEX_RULES));
+ NodeState rulesState = defn.getChildNode(LuceneIndexConstants.INDEX_RULES);
+ if (!rulesState.exists()){
+ rulesState = createIndexRules(defn).getNodeState();
+ }
+ this.indexRules = collectIndexRules(rulesState);
+
+ this.fullTextEnabled = hasFulltextEnabledIndexRule(indexRules);
+ //Storage is disabled for non full text indexes
+ this.storageEnabled = this.fullTextEnabled && getOptionalValue(defn, EXPERIMENTAL_STORAGE, true);
this.relativePropNames = collectRelPropertyNames(this.relativeProps.values());
this.relativePropsMaxLevels = getRelPropertyMaxLevels(this.relativeProps.values());
@@ -327,6 +334,8 @@ class IndexDefinition {
private Map<String, PropertyDefinition> collectPropertyDefns(NodeState defn) {
Map<String, PropertyDefinition> propDefns = newHashMap();
+ //TODO FIXME
+ IndexingRule dummyRule = new IndexingRule("nt:base", EMPTY_NODE);
NodeState propNode = defn.getChildNode(LuceneIndexConstants.PROP_NODE);
//Include all immediate child nodes to 'properties' node by default
for (String propName : Iterables.concat(includes, orderedProps, propNode.getChildNodeNames())) {
@@ -338,20 +347,12 @@ class IndexDefinition {
}
if (propDefnNode.exists() && !propDefns.containsKey(propName)) {
- propDefns.put(propName, new PropertyDefinition(this, propName, propDefnNode));
+ propDefns.put(propName, new PropertyDefinition(dummyRule, propName, propDefnNode));
}
}
return ImmutableMap.copyOf(propDefns);
}
- private Set<String> collectRelPropertyNames(Collection<RelativeProperty> props) {
- Set<String> propNames = newHashSet();
- for (RelativeProperty prop : props) {
- propNames.add(prop.name);
- }
- return ImmutableSet.copyOf(propNames);
- }
-
private int getRelPropertyMaxLevels(Collection<RelativeProperty> props) {
int max = -1;
for (RelativeProperty prop : props) {
@@ -377,13 +378,36 @@ class IndexDefinition {
//~---------------------------------------------------< IndexRule >
- /**
- * Returns the first indexing rule that applies to the given node
- * <code>state</code>.
- *
- * @param state a node state.
- * @return the indexing rule or <code>null</code> if none applies.
- */
+ @CheckForNull
+ public IndexingRule getApplicableIndexingRule(String primaryNodeType) {
+ //This method would be invoked for every node. So be as
+ //conservative as possible in object creation
+ List<IndexingRule> rules = null;
+ List<IndexingRule> r = indexRules.get(primaryNodeType);
+ if (r != null) {
+ rules = new ArrayList<IndexingRule>();
+ rules.addAll(r);
+ }
+
+ if (rules != null) {
+ for (IndexingRule rule : rules) {
+ if (rule.appliesTo(primaryNodeType)) {
+ return rule;
+ }
+ }
+ }
+
+ // no applicable rule
+ return null;
+ }
+
+ /**
+ * Returns the first indexing rule that applies to the given node
+ * <code>state</code>.
+ *
+ * @param state a node state.
+ * @return the indexing rule or <code>null</code> if none applies.
+ */
@CheckForNull
public IndexingRule getApplicableIndexingRule(Tree state) {
//This method would be invoked for every node. So be as
@@ -421,6 +445,10 @@ class IndexDefinition {
//TODO if a rule is defined for nt:base then this map would have entry for each
//registered nodeType in the system
+ if (!indexRules.exists()) {
+ return Collections.emptyMap();
+ }
+
if (!hasOrderableChildren(indexRules)){
log.warn("IndexRule node does not have orderable children in [{}]", IndexDefinition.this);
}
@@ -470,17 +498,34 @@ class IndexDefinition {
private final List<NamePattern> namePatterns;
final float boost;
final boolean inherited;
+ final boolean defaultFulltextEnabled;
+ final boolean defaultStorageEnabled;
+ final int propertyTypes;
+ final boolean fulltextEnabled;
+
+ //TODO To be relooked with support for aggregation
+ final Map<String,RelativeProperty> relativeProps;
+ final Set<String> relativePropNames;
+
IndexingRule(String nodeTypeName, NodeState config) {
this.nodeTypeName = nodeTypeName;
this.baseNodeType = nodeTypeName;
this.boost = getOptionalValue(config, FIELD_BOOST, DEFAULT_BOOST);
this.inherited = getOptionalValue(config, LuceneIndexConstants.RULE_INHERITED, true);
+ this.defaultFulltextEnabled = getOptionalValue(config, LuceneIndexConstants.FULL_TEXT_ENABLED, false);
+ //TODO Provide a new proper propertyName for enabling storage
+ this.defaultStorageEnabled = getOptionalValue(config, LuceneIndexConstants.EXPERIMENTAL_STORAGE, false);
+ this.propertyTypes = getSupportedTypes(config, TYPES_ALLOW_ALL);
List<NamePattern> namePatterns = newArrayList();
- this.propConfigs = collectPropConfigs(config, namePatterns);
+ Map<String,RelativeProperty> relativeProps = newHashMap();
+ this.propConfigs = collectPropConfigs(config, namePatterns, relativeProps);
this.namePatterns = ImmutableList.copyOf(namePatterns);
+ this.fulltextEnabled = hasAnyFullTextEnabledProperty();
+ this.relativeProps = ImmutableMap.copyOf(relativeProps);
+ this.relativePropNames = collectRelPropertyNames(this.relativeProps.values());
}
/**
@@ -496,7 +541,13 @@ class IndexDefinition {
this.propConfigs = original.propConfigs;
this.namePatterns = original.namePatterns;
this.boost = original.boost;
+ this.defaultFulltextEnabled = original.defaultFulltextEnabled;
+ this.defaultStorageEnabled = original.defaultStorageEnabled;
this.inherited = original.inherited;
+ this.propertyTypes = original.propertyTypes;
+ this.fulltextEnabled = original.fulltextEnabled;
+ this.relativeProps = original.relativeProps;
+ this.relativePropNames = original.relativePropNames;
}
/**
@@ -538,7 +589,7 @@ class IndexDefinition {
* @return <code>true</code> the rule applies to the given node;
* <code>false</code> otherwise.
*/
- private boolean appliesTo(Tree state) {
+ public boolean appliesTo(Tree state) {
if (!nodeTypeName.equals(getPrimaryTypeName(state))) {
return false;
}
@@ -547,6 +598,18 @@ class IndexDefinition {
return true;
}
+ public boolean appliesTo(String nodeTypeName) {
+ if (!this.nodeTypeName.equals(nodeTypeName)) {
+ return false;
+ }
+
+ //TODO Once condition support is done return false
+ //return condition == null || condition.evaluate(state);
+ return true;
+
+ }
+
+
/**
* @param propertyName name of a property.
* @return the property configuration or <code>null</code> if this
@@ -569,7 +632,30 @@ class IndexDefinition {
return null;
}
- private Map<String, PropertyDefinition> collectPropConfigs(NodeState config, List<NamePattern> patterns) {
+ public boolean includePropertyType(int type){
+ //TODO Rules related to type inclusion need to be synced
+ //Login IndexEditor evaluates differently compared to IndexDefinition
+ if(propertyTypes == TYPES_ALLOW_ALL){
+ return true;
+ }
+
+ if (propertyTypes == TYPES_ALLOW_NONE){
+ return false;
+ }
+
+ return (propertyTypes & (1 << type)) != 0;
+ }
+
+ public Collection<RelativeProperty> getRelativeProps() {
+ return relativeProps.values();
+ }
+
+ boolean hasRelativeProperty(String name) {
+ return relativePropNames.contains(name);
+ }
+
+ private Map<String, PropertyDefinition> collectPropConfigs(NodeState config, List<NamePattern> patterns,
+ Map<String,RelativeProperty> relativeProps) {
Map<String, PropertyDefinition> propDefns = newHashMap();
NodeState propNode = config.getChildNode(LuceneIndexConstants.PROP_NODE);
@@ -584,16 +670,35 @@ class IndexDefinition {
String propName = prop.getName();
NodeState propDefnNode = propNode.getChildNode(propName);
if (propDefnNode.exists() && !propDefns.containsKey(propName)) {
- PropertyDefinition pd = new PropertyDefinition(IndexDefinition.this, propName, propDefnNode);
+ PropertyDefinition pd = new PropertyDefinition(this, propName, propDefnNode);
if(pd.isRegexp){
patterns.add(new NamePattern(pd.name, pd));
} else {
propDefns.put(pd.name, pd);
}
+
+ if (RelativeProperty.isRelativeProperty(pd.name)){
+ relativeProps.put(pd.name, new RelativeProperty(pd.name));
+ }
}
}
return ImmutableMap.copyOf(propDefns);
}
+
+ private boolean hasAnyFullTextEnabledProperty() {
+ for (PropertyDefinition pd : propConfigs.values()){
+ if (pd.fulltextEnabled()){
+ return true;
+ }
+ }
+
+ for (NamePattern np : namePatterns){
+ if (np.getConfig().fulltextEnabled()){
+ return true;
+ }
+ }
+ return false;
+ }
}
/**
@@ -637,6 +742,117 @@ class IndexDefinition {
}
}
+ //~---------------------------------------------< compatibility >
+
+ /**
+ * Constructs IndexingRule based on earlier format of index configuration
+ */
+ private NodeBuilder createIndexRules(NodeState defn){
+ NodeBuilder builder = EMPTY_NODE.builder();
+ Set<String> declaringNodeTypes = getMultiProperty(defn, DECLARING_NODE_TYPES);
+ Set<String> includes = getMultiProperty(defn, INCLUDE_PROPERTY_NAMES);
+ Set<String> excludes = toLowerCase(getMultiProperty(defn, EXCLUDE_PROPERTY_NAMES));
+ Set<String> orderedProps = getMultiProperty(defn, ORDERED_PROP_NAMES);
+ boolean fullTextEnabled = getOptionalValue(defn, FULL_TEXT_ENABLED, true);
+ boolean storageEnabled = getOptionalValue(defn, EXPERIMENTAL_STORAGE, true);
+ NodeState propNodeState = defn.getChildNode(LuceneIndexConstants.PROP_NODE);
+
+ //If no explicit nodeType defined then all config applies for nt:base
+ if (declaringNodeTypes.isEmpty()){
+ declaringNodeTypes = Collections.singleton(NT_BASE);
+ }
+
+ Set<String> propNamesSet = Sets.newHashSet();
+ propNamesSet.addAll(includes);
+ propNamesSet.addAll(excludes);
+ propNamesSet.addAll(orderedProps);
+
+ //Also include all immediate leaf propNode names
+ for (ChildNodeEntry cne : propNodeState.getChildNodeEntries()){
+ if (!propNamesSet.contains(cne.getName())
+ && Iterables.isEmpty(cne.getNodeState().getChildNodeNames())){
+ propNamesSet.add(cne.getName());
+ }
+ }
+
+ List<String> propNames = new ArrayList<String>(propNamesSet);
+
+ final String includeAllProp = ".*";
+ if (fullTextEnabled){
+ //Add the regEx for including all properties at the end
+ //for fulltext index
+ propNames.add(includeAllProp);
+ }
+
+ for (String typeName : declaringNodeTypes){
+ NodeBuilder rule = builder.child(typeName);
+
+ List<String> propNodeNames = newArrayListWithCapacity(propNamesSet.size());
+ NodeBuilder propNodes = rule.child(PROP_NODE);
+ int i = 0;
+ for (String propName : propNames){
+ String propNodeName = "prop" + i++;
+ propNodeNames.add(propNodeName);
+
+ NodeBuilder prop = propNodes.child(propNodeName);
+
+ prop.setProperty(LuceneIndexConstants.PROP_NAME, propName);
+
+ if (excludes.contains(propName)){
+ prop.setProperty(LuceneIndexConstants.PROP_INDEX, false);
+ } else if (fullTextEnabled){
+ prop.setProperty(LuceneIndexConstants.PROP_ANALYZED, true);
+ prop.setProperty(LuceneIndexConstants.PROP_NODE_SCOPE_INDEX, true);
+ prop.setProperty(LuceneIndexConstants.PROP_USE_IN_EXCERPT, storageEnabled);
+ } else {
+ prop.setProperty(LuceneIndexConstants.PROP_PROPERTY_INDEX, true);
+
+ if (orderedProps.contains(propName)){
+ prop.setProperty(LuceneIndexConstants.PROP_ORDERED, true);
+ }
+ }
+
+ if (propName.equals(includeAllProp)){
+ prop.setProperty(LuceneIndexConstants.PROP_IS_REGEX, true);
+ }
+
+ NodeState propDefNode = getPropDefnNode(defn, propName);
+ if (propDefNode != null && propDefNode.hasProperty(LuceneIndexConstants.PROP_TYPE)){
+ prop.setProperty(propDefNode.getProperty(LuceneIndexConstants.PROP_TYPE));
+ }
+ }
+
+ //If no propertyType defined then default to UNKNOWN such that none
+ //of the properties get indexed
+ PropertyState supportedTypes = defn.getProperty(INCLUDE_PROPERTY_TYPES);
+ if (supportedTypes == null){
+ supportedTypes = PropertyStates.createProperty(INCLUDE_PROPERTY_TYPES, TYPES_ALLOW_ALL_NAME);
+ }
+ rule.setProperty(supportedTypes);
+
+ if (!NT_BASE.equals(typeName)) {
+ rule.setProperty(LuceneIndexConstants.RULE_INHERITED, false);
+ }
+
+ propNodes.setProperty(OAK_CHILD_ORDER, propNodeNames ,NAMES);
+ }
+
+ builder.setProperty(OAK_CHILD_ORDER, declaringNodeTypes ,NAMES);
+ return builder;
+ }
+
+ private NodeState getPropDefnNode(NodeState defn, String propName){
+ NodeState propNode = defn.getChildNode(LuceneIndexConstants.PROP_NODE);
+ NodeState propDefNode;
+ if (RelativeProperty.isRelativeProperty(propName)) {
+ propDefNode = new RelativeProperty(propName).getPropDefnNode(propNode);
+ } else {
+ propDefNode = propNode.getChildNode(propName);
+ }
+ return propDefNode.exists() ? propDefNode : null;
+ }
+
+
//~---------------------------------------------< utility >
private static String determineIndexName(NodeState defn, String indexPath) {
@@ -697,7 +913,8 @@ class IndexDefinition {
private static String getPrimaryTypeName(Tree state) {
String primaryType = TreeUtil.getPrimaryTypeName(state);
- //In case not a proper JCR assume nt:base
+ //In case not a proper JCR assume nt:base TODO return null and ignore indexing such nodes
+ //at all
return primaryType != null ? primaryType : "nt:base";
}
@@ -709,4 +926,43 @@ class IndexDefinition {
private static boolean hasOrderableChildren(NodeState state){
return state.hasProperty(OAK_CHILD_ORDER);
}
+
+ private static int getSupportedTypes(NodeState defn, int defaultVal) {
+ PropertyState pst = defn.getProperty(INCLUDE_PROPERTY_TYPES);
+ if (pst != null) {
+ int types = 0;
+ for (String inc : pst.getValue(Type.STRINGS)) {
+ if (TYPES_ALLOW_ALL_NAME.equals(inc)){
+ return TYPES_ALLOW_ALL;
+ }
+
+ try {
+ types |= 1 << PropertyType.valueFromName(inc);
+ } catch (IllegalArgumentException e) {
+ log.warn("Unknown property type: " + inc);
+ }
+ }
+ return types;
+ }
+ return defaultVal;
+ }
+
+ private static boolean hasFulltextEnabledIndexRule(Map<String, List<IndexingRule>> indexRules) {
+ for (List<IndexingRule> rules : indexRules.values()){
+ for (IndexingRule rule : rules){
+ if (rule.fulltextEnabled){
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static Set<String> collectRelPropertyNames(Collection<RelativeProperty> props) {
+ Set<String> propNames = newHashSet();
+ for (RelativeProperty prop : props) {
+ propNames.add(prop.name);
+ }
+ return ImmutableSet.copyOf(propNames);
+ }
}
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=1639963&r1=1639962&r2=1639963&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 Sun Nov 16 06:19:15 2014
@@ -115,5 +115,17 @@ public interface LuceneIndexConstants {
String PROP_IS_REGEX = "isRegexp";
+ String PROP_INDEX = "index";
+
+ String PROP_USE_IN_EXCERPT = "useInExcerpt";
+
+ String PROP_NODE_SCOPE_INDEX = "nodeScopeIndex";
+
+ String PROP_PROPERTY_INDEX = "propertyIndex";
+
+ String PROP_ANALYZED = "analyzed";
+
String RULE_INHERITED = "inherited";
+
+ String PROP_ORDERED = "ordered";
}
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=1639963&r1=1639962&r2=1639963&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 Sun Nov 16 06:19:15 2014
@@ -23,6 +23,8 @@ import javax.jcr.PropertyType;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Type;
+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;
@@ -55,11 +57,36 @@ class PropertyDefinition {
final boolean isRegexp;
- public PropertyDefinition(IndexDefinition idxDefn, String name, NodeState defn) {
+ final boolean index;
+
+ final boolean stored;
+
+ final boolean nodeScopeIndex;
+
+ final boolean propertyIndex;
+
+ final boolean analyzed;
+
+ final boolean ordered;
+
+ public PropertyDefinition(IndexingRule idxDefn, String name, NodeState defn) {
this.isRegexp = getOptionalValue(defn, PROP_IS_REGEX, false);
this.name = getName(defn, name);
this.definition = defn;
this.boost = getOptionalValue(defn, FIELD_BOOST, DEFAULT_BOOST);
+
+ //By default if a property is defined it is indexed
+ this.index = getOptionalValue(defn, LuceneIndexConstants.PROP_INDEX, true);
+ this.stored = getOptionalValue(defn, LuceneIndexConstants.PROP_USE_IN_EXCERPT, idxDefn.defaultStorageEnabled);
+ this.nodeScopeIndex = getOptionalValue(defn, LuceneIndexConstants.PROP_NODE_SCOPE_INDEX, idxDefn.defaultFulltextEnabled);
+ this.analyzed = getOptionalValue(defn, LuceneIndexConstants.PROP_ANALYZED, idxDefn.defaultFulltextEnabled);
+
+ //If node is not set for full text then a property definition indicates that definition is for property index
+ this.propertyIndex = getOptionalValue(defn, LuceneIndexConstants.PROP_PROPERTY_INDEX, !idxDefn.defaultFulltextEnabled);
+ this.ordered = getOptionalValue(defn, LuceneIndexConstants.PROP_ORDERED, false);
+
+ //TODO Add test case for above cases
+
this.propertyType = getPropertyType(idxDefn, name, defn);
}
@@ -67,6 +94,34 @@ class PropertyDefinition {
return propertyType;
}
+ public boolean skipTokenization(String propertyName) {
+ //For regEx case check against a whitelist
+ if (isRegexp){
+ return LuceneIndexHelper.skipTokenization(propertyName);
+ }
+ return !analyzed;
+ }
+
+ public boolean fulltextEnabled(){
+ return index && (analyzed || nodeScopeIndex);
+ }
+
+ @Override
+ public String toString() {
+ return "PropertyDefinition{" +
+ "name='" + name + '\'' +
+ ", propertyType=" + propertyType +
+ ", boost=" + boost +
+ ", isRegexp=" + isRegexp +
+ ", index=" + index +
+ ", stored=" + stored +
+ ", nodeScopeIndex=" + nodeScopeIndex +
+ ", propertyIndex=" + propertyIndex +
+ ", analyzed=" + analyzed +
+ ", ordered=" + ordered +
+ '}';
+ }
+
//~---------------------------------------------< internal >
private static String getName(NodeState definition, String defaultName){
@@ -74,7 +129,7 @@ class PropertyDefinition {
return ps == null ? defaultName : ps.getValue(Type.STRING);
}
- private static int getPropertyType(IndexDefinition idxDefn, String name, NodeState defn) {
+ private static int getPropertyType(IndexingRule idxDefn, String name, NodeState defn) {
int type = PropertyType.UNDEFINED;
if (defn.hasProperty(LuceneIndexConstants.PROP_TYPE)) {
String typeName = defn.getString(LuceneIndexConstants.PROP_TYPE);
Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/RelativeProperty.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/RelativeProperty.java?rev=1639963&r1=1639962&r2=1639963&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/RelativeProperty.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/RelativeProperty.java Sun Nov 16 06:19:15 2014
@@ -52,6 +52,13 @@ class RelativeProperty {
ancestors = computeAncestors(parentPath);
}
+ /**
+ * The first index definition format supported relative property definition
+ * by replicating the property path in 'properties' node. Later version
+ * supported property definition as immediated child node of 'properties' node
+ * where the relative property path is specified as part of 'name' property
+ */
+ @Deprecated
@Nonnull
public NodeState getPropDefnNode(NodeState propNode) {
NodeState result = propNode;
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=1639963&r1=1639962&r2=1639963&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 Sun Nov 16 06:19:15 2014
@@ -36,6 +36,7 @@ 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 org.apache.jackrabbit.JcrConstants.NT_BASE;
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.lucene.LuceneIndexConstants.INCLUDE_PROPERTY_NAMES;
@@ -62,14 +63,15 @@ public class IndexDefinitionTest {
@Test
public void fullTextEnabled() throws Exception{
- IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
- assertTrue("By default fulltext is enabled", defn.isFullTextEnabled());
- assertTrue("By default everything is indexed", defn.includeProperty("foo"));
- assertFalse("Property types need to be defined", defn.includePropertyType(PropertyType.DATE));
- assertTrue("For fulltext storage is enabled", defn.isStored("foo"));
+ IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState());
+ 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(defn.skipTokenization("foo"));
- assertTrue(defn.skipTokenization("jcr:uuid"));
+ assertFalse(rule.getConfig("foo").skipTokenization("foo"));
+ assertTrue(rule.getConfig("jcr:uuid").skipTokenization("jcr:uuid"));
}
@Test
@@ -77,42 +79,43 @@ public class IndexDefinitionTest {
builder.setProperty(createProperty(INCLUDE_PROPERTY_TYPES, of(TYPENAME_LONG), STRINGS));
builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo" , "bar"), STRINGS));
builder.setProperty(LuceneIndexConstants.FULL_TEXT_ENABLED, false);
- IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
-
- assertFalse(defn.isFullTextEnabled());
- assertFalse("If fulltext disabled then nothing stored",defn.isStored("foo"));
-
- assertTrue(defn.includePropertyType(PropertyType.LONG));
- assertFalse(defn.includePropertyType(PropertyType.STRING));
-
- assertTrue(defn.includeProperty("foo"));
- assertTrue(defn.includeProperty("bar"));
- assertFalse(defn.includeProperty("baz"));
+ IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState());
+ 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(defn.skipTokenization("foo"));
+ assertTrue(rule.getConfig("foo").skipTokenization("foo"));
}
@Test
public void propertyDefinition() throws Exception{
builder.child(PROP_NODE).child("foo").setProperty(LuceneIndexConstants.PROP_TYPE, PropertyType.TYPENAME_DATE);
builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo" , "bar"), STRINGS));
- IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState());
+ IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE);
- assertTrue(defn.hasPropertyDefinition("foo"));
- assertFalse(defn.hasPropertyDefinition("bar"));
+ assertTrue(rule.isIndexed("foo"));
+ assertTrue(rule.isIndexed("bar"));
- assertEquals(PropertyType.DATE, defn.getPropDefn("foo").getPropertyType());
+ assertEquals(PropertyType.DATE, rule.getConfig("foo").getPropertyType());
}
@Test
public void propertyDefinitionWithExcludes() throws Exception{
builder.child(PROP_NODE).child("foo").setProperty(LuceneIndexConstants.PROP_TYPE, PropertyType.TYPENAME_DATE);
- IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState());
+ IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE);
+ assertTrue(rule.isIndexed("foo"));
+ assertTrue(rule.isIndexed("bar"));
- assertTrue(defn.hasPropertyDefinition("foo"));
- assertFalse(defn.hasPropertyDefinition("bar"));
-
- assertEquals(PropertyType.DATE, defn.getPropDefn("foo").getPropertyType());
+ assertEquals(PropertyType.DATE, rule.getConfig("foo").getPropertyType());
}
@Test
@@ -135,12 +138,13 @@ public class IndexDefinitionTest {
@Test
public void relativeProperty() throws Exception{
builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo" , "foo1/bar"), STRINGS));
- IndexDefinition defn = new IndexDefinition(root, builder.getNodeState());
+ IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState());
+ IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE);
- assertEquals(1, defn.getRelativeProps().size());
- assertEquals(new RelativeProperty("foo1/bar"), Iterables.getFirst(defn.getRelativeProps(), null));
- assertTrue(defn.hasRelativeProperty("bar"));
- assertFalse(defn.hasRelativeProperty("foo"));
+ assertEquals(1, rule.getRelativeProps().size());
+ assertEquals(new RelativeProperty("foo1/bar"), Iterables.getFirst(rule.getRelativeProps(), null));
+ assertTrue(rule.hasRelativeProperty("bar"));
+ assertFalse(rule.hasRelativeProperty("foo"));
}
@Test