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 ju...@apache.org on 2013/10/28 15:31:05 UTC

svn commit: r1536366 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins: index/property/PropertyIndexEditor.java nodetype/TypePredicate.java

Author: jukka
Date: Mon Oct 28 14:31:05 2013
New Revision: 1536366

URL: http://svn.apache.org/r1536366
Log:
OAK-1048: Unify node type management in the query index impls

Add a node type predicate class and use it to simplify PropertyIndexEditor

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypePredicate.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditor.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditor.java?rev=1536366&r1=1536365&r2=1536366&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditor.java Mon Oct 28 14:31:05 2013
@@ -16,24 +16,14 @@
  */
 package org.apache.jackrabbit.oak.plugins.index.property;
 
-import static com.google.common.base.Predicates.in;
-import static com.google.common.collect.Iterables.addAll;
-import static com.google.common.collect.Iterables.any;
 import static com.google.common.collect.Sets.newHashSet;
 import static java.util.Collections.singleton;
-import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
-import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
-import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
-import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
 import static org.apache.jackrabbit.oak.api.CommitFailedException.CONSTRAINT;
 import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.DECLARING_NODE_TYPES;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.PROPERTY_NAMES;
 import static org.apache.jackrabbit.oak.plugins.index.property.PropertyIndex.encode;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_MIXIN_SUBTYPES;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_PRIMARY_SUBTYPES;
 
 import java.util.Set;
 
@@ -46,11 +36,14 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
 import org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy;
 import org.apache.jackrabbit.oak.plugins.index.property.strategy.UniqueEntryStoreStrategy;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
 import org.apache.jackrabbit.oak.spi.commit.Editor;
 import org.apache.jackrabbit.oak.spi.query.PropertyValues;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
+import com.google.common.base.Predicate;
+
 /**
  * Index editor for keeping a property index up to date.
  * 
@@ -81,10 +74,8 @@ class PropertyIndexEditor implements Ind
 
     private final Set<String> propertyNames;
 
-    private final Set<String> primaryTypes;
+    private final Predicate<NodeState> typePredicate;
 
-    private final Set<String> mixinTypes;
-    
     private final boolean unique;
 
     private final Set<String> keysToCheckForUniqueness;
@@ -119,23 +110,10 @@ class PropertyIndexEditor implements Ind
         // get declaring types, and all their subtypes
         // TODO: should we reindex when type definitions change?
         if (definition.hasProperty(DECLARING_NODE_TYPES)) {
-            this.primaryTypes = newHashSet();
-            this.mixinTypes = newHashSet();
-            NodeState types =
-                    root.getChildNode(JCR_SYSTEM).getChildNode(JCR_NODE_TYPES);
-            for (String name : definition.getNames(DECLARING_NODE_TYPES)) {
-                NodeState type = types.getChildNode(name);
-                if (type.getBoolean(JCR_ISMIXIN)) {
-                    mixinTypes.add(name);
-                } else {
-                    primaryTypes.add(name);
-                }
-                addAll(mixinTypes, type.getNames(OAK_MIXIN_SUBTYPES));
-                addAll(primaryTypes, type.getNames(OAK_PRIMARY_SUBTYPES));
-            }
+            this.typePredicate = new TypePredicate(
+                    root, definition.getNames(DECLARING_NODE_TYPES));
         } else {
-            this.primaryTypes = null;
-            this.mixinTypes = null;
+            this.typePredicate = NodeState.EXISTS;
         }
 
         // keep track of modified keys for uniqueness checks
@@ -154,8 +132,7 @@ class PropertyIndexEditor implements Ind
         this.path = null;
         this.definition = parent.definition;
         this.propertyNames = parent.propertyNames;
-        this.primaryTypes = parent.primaryTypes;
-        this.mixinTypes = parent.mixinTypes;
+        this.typePredicate = parent.typePredicate;
         this.unique = parent.unique;
         this.keysToCheckForUniqueness = parent.keysToCheckForUniqueness;
     }
@@ -170,13 +147,6 @@ class PropertyIndexEditor implements Ind
         return path;
     }
 
-    private boolean isOfMatchingType(NodeState state) {
-        // no type limitations
-        return primaryTypes == null 
-                || primaryTypes.contains(state.getName(JCR_PRIMARYTYPE))
-                || any(state.getNames(JCR_MIXINTYPES), in(mixinTypes));
-    }
-
     private static void addValueKeys(Set<String> keys, PropertyState property) {
         if (property.getType().tag() != PropertyType.BINARY) {
             keys.addAll(encode(PropertyValues.create(property)));
@@ -196,8 +166,8 @@ class PropertyIndexEditor implements Ind
     @Override
     public void enter(NodeState before, NodeState after)
             throws CommitFailedException {
-        boolean beforeMatches = before.exists() && isOfMatchingType(before);
-        boolean afterMatches  = after.exists()  && isOfMatchingType(after);
+        boolean beforeMatches = typePredicate.apply(before);
+        boolean afterMatches  = typePredicate.apply(after);
 
         if (beforeMatches || afterMatches) {
             beforeKeys = newHashSet();

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypePredicate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypePredicate.java?rev=1536366&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypePredicate.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypePredicate.java Mon Oct 28 14:31:05 2013
@@ -0,0 +1,115 @@
+/*
+ * 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.nodetype;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.in;
+import static com.google.common.collect.Iterables.addAll;
+import static com.google.common.collect.Iterables.any;
+import static com.google.common.collect.Sets.newHashSet;
+import static com.google.common.collect.Sets.union;
+import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_MIXIN_SUBTYPES;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_PRIMARY_SUBTYPES;
+
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.base.Predicate;
+
+/**
+ * Inheritance-aware node type predicate for {@link NodeState node states}.
+ *
+ * @since Oak 0.11
+ */
+public class TypePredicate implements Predicate<NodeState> {
+
+    private final Set<String> primaryTypes = newHashSet();
+
+    private final Set<String> mixinTypes = newHashSet();
+
+    /**
+     * Creates a predicate for checking whether a node state is an instance of
+     * the named node type. This is an O(1) operation in terms of item
+     * accesses.
+     *
+     * @param root root node state
+     * @param name Oak name of the node type to check for
+     */
+    public TypePredicate(@Nonnull NodeState root, @Nonnull String name) {
+        NodeState types = checkNotNull(root)
+                .getChildNode(JCR_SYSTEM)
+                .getChildNode(JCR_NODE_TYPES);
+        addNodeType(types, checkNotNull(name));
+    }
+
+    /**
+     * Creates a predicate for checking whether a node state is an instance of
+     * any of the named node types. This is an O(n) operation in terms of item
+     * accesses, with n being the number of given node types.
+     *
+     * @param root root node state
+     * @param names Oak names of the node types to check for
+     */
+    public TypePredicate(
+            @Nonnull NodeState root, @Nonnull Iterable<String> names) {
+        NodeState types = checkNotNull(root)
+                .getChildNode(JCR_SYSTEM)
+                .getChildNode(JCR_NODE_TYPES);
+        for (String name : checkNotNull(names)) {
+            addNodeType(types, name);
+        }
+    }
+
+    private void addNodeType(NodeState types, String name) {
+        NodeState type = types.getChildNode(name);
+        addAll(primaryTypes, type.getNames(OAK_PRIMARY_SUBTYPES));
+        if (type.getBoolean(JCR_ISMIXIN)) {
+            mixinTypes.add(name);
+            // Only mixin types can have mixin descendants, so we
+            // only fill the mixinTypes set in this branch of code.
+            addAll(mixinTypes, type.getNames(OAK_MIXIN_SUBTYPES));
+        } else {
+            // No need to check whether the type actually exists, as if
+            // it doesn't there should in any case be no matching content.
+            primaryTypes.add(name);
+        }
+    }
+
+    //---------------------------------------------------------< Predicate >--
+
+    @Override
+    public boolean apply(NodeState input) {
+        return primaryTypes.contains(input.getName(JCR_PRIMARYTYPE))
+                || any(input.getNames(JCR_MIXINTYPES), in(mixinTypes));
+    }
+
+    //------------------------------------------------------------< Object >--
+
+    @Override
+    public String toString() {
+        return union(primaryTypes, mixinTypes).toString();
+    }
+
+}