jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mreut...@apache.org
Subject svn commit: r1406080 - in /jackrabbit/oak/trunk: oak-core/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/ oak-core/src/main/java/org/apache/jackrabbit/oa...
Date Tue, 06 Nov 2012 10:04:40 GMT
Author: mreutegg
Date: Tue Nov  6 10:04:38 2012
New Revision: 1406080

URL: http://svn.apache.org/viewvc?rev=1406080&view=rev
Log:
OAK-388: Add NodeType Index
- Initial implementation of a node type index using PropertyIndex
- Implemented cost for PropertyIndex (NodeTypeIndex delegates cost calculation to PropertyIndex)
- Moved Cursor implementations to new factory class Cursors
- InitialContent now indexes jcr:mixinTypes in addition to jcr:primaryType (otherwise the node type index will not be effective)

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexLookup.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexProvider.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java   (with props)
Removed:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingCursor.java
Modified:
    jackrabbit/oak/trunk/oak-core/pom.xml
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/InitialContent.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/PropertyValues.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java

Modified: jackrabbit/oak/trunk/oak-core/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/pom.xml?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-core/pom.xml Tue Nov  6 10:04:38 2012
@@ -50,6 +50,7 @@
                 org.apache.jackrabbit.oak.plugins.identifier,
                 org.apache.jackrabbit.oak.plugins.index,
                 org.apache.jackrabbit.oak.plugins.index.lucene,
+                org.apache.jackrabbit.oak.plugins.index.nodetype,
                 org.apache.jackrabbit.oak.plugins.index.property,
                 org.apache.jackrabbit.oak.plugins.memory,
                 org.apache.jackrabbit.oak.plugins.name,

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java?rev=1406080&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java Tue Nov  6 10:04:38 2012
@@ -0,0 +1,130 @@
+/*
+ * 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.nodetype;
+
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NodeTypeIterator;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.core.ReadOnlyTree;
+import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexLookup;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
+import org.apache.jackrabbit.oak.spi.query.Cursor;
+import org.apache.jackrabbit.oak.spi.query.Cursors;
+import org.apache.jackrabbit.oak.spi.query.Filter;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.collect.Sets;
+
+/**
+ * <code>NodeTypeIndex</code> implements a {@link QueryIndex} using
+ * {@link PropertyIndexLookup}s on <code>jcr:primaryType</code> and
+ * <code>jcr:mixinTypes</code> to evaluate a node type restriction on
+ * {@link Filter}. The cost for this index is the sum of the costs of the
+ * {@link PropertyIndexLookup} for queries on <code>jcr:primaryType</code> and
+ * <code>jcr:mixinTypes</code>.
+ */
+class NodeTypeIndex implements QueryIndex, JcrConstants {
+
+    @Override
+    public double getCost(Filter filter, NodeState root) {
+        if (!hasNodeTypeRestriction(filter)) {
+            // this is not an appropriate index if the filter
+            // doesn't have a node type restriction
+            return Double.MAX_VALUE;
+        }
+        NodeTypeIndexLookup lookup = new NodeTypeIndexLookup(root);
+        if (lookup.isIndexed(filter.getPath())) {
+            return lookup.getCost(resolveNodeType(root, filter.getNodeType()));
+        } else {
+            return Double.MAX_VALUE;
+        }
+    }
+
+    @Override
+    public Cursor query(Filter filter, NodeState root) {
+        NodeTypeIndexLookup lookup = new NodeTypeIndexLookup(root);
+        if (!hasNodeTypeRestriction(filter) || !lookup.isIndexed(filter.getPath())) {
+            return Cursors.newTraversingCursor("?", filter, root);
+        }
+        return Cursors.newPathCursor(lookup.find(
+                resolveNodeType(root, filter.getNodeType())));
+    }
+
+    @Override
+    public String getPlan(Filter filter, NodeState root) {
+        // TODO: return plan according to query()
+        return null;
+    }
+
+    @Override
+    public String getIndexName() {
+        return "nodetype";
+    }
+
+    //----------------------------< internal >----------------------------------
+
+    private static boolean hasNodeTypeRestriction(Filter filter) {
+        return filter.getNodeType() != null
+                && !filter.getNodeType().equals(NT_BASE);
+    }
+
+    private static Iterable<String> resolveNodeType(NodeState root, String nodeType) {
+        ReadOnlyNodeTypeManager ntMgr = new NTManager(root);
+        Set<String> ntNames = Sets.newHashSet();
+        try {
+            NodeType nt = ntMgr.getNodeType(nodeType);
+            for (NodeTypeIterator types = nt.getSubtypes(); types.hasNext(); ) {
+                ntNames.add(types.nextNodeType().getName());
+            }
+            ntNames.add(nodeType);
+        } catch (RepositoryException e) {
+            // unknown node type
+        }
+        return ntNames;
+    }
+
+    private static final class NTManager extends ReadOnlyNodeTypeManager {
+
+        private final NodeState root;
+
+        NTManager(NodeState root) {
+            this.root = root;
+        }
+
+        @Override
+        protected Tree getTypes() {
+            Tree t = new ReadOnlyTree(root);
+            for (String name : PathUtils.elements(NodeTypeConstants.NODE_TYPES_PATH)) {
+                t = t.getChild(name);
+                if (t == null) {
+                    break;
+                }
+            }
+            return t;
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexLookup.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexLookup.java?rev=1406080&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexLookup.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexLookup.java Tue Nov  6 10:04:38 2012
@@ -0,0 +1,91 @@
+/*
+ * 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.nodetype;
+
+import java.util.Set;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexLookup;
+import org.apache.jackrabbit.oak.spi.query.PropertyValues;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.collect.Sets;
+
+/**
+ * <code>NodeTypeIndexLookup</code> uses {@link PropertyIndexLookup} internally
+ * for cost calculation and queries.
+ */
+class NodeTypeIndexLookup implements JcrConstants {
+
+    private final NodeState root;
+
+    public NodeTypeIndexLookup(NodeState root) {
+        this.root = root;
+    }
+
+    /**
+     * Returns <code>true</code> if a node type index lookup exists at the given
+     * <code>path</code> or further up the tree.
+     *
+     * @param path the path to check.
+     * @return <code>true</code> if a node type index exists; <code>false</code>
+     *         otherwise.
+     */
+    public boolean isIndexed(String path) {
+        PropertyIndexLookup lookup = new PropertyIndexLookup(root);
+        if (lookup.isIndexed(JCR_PRIMARYTYPE, path)
+                && lookup.isIndexed(JCR_MIXINTYPES, path)) {
+            return true;
+        }
+
+        if (path.startsWith("/")) {
+            path = path.substring(1);
+        }
+        int slash = path.indexOf('/');
+        if (slash == -1) {
+            return false;
+        }
+
+        NodeState child = root.getChildNode(path.substring(0, slash));
+        return new NodeTypeIndexLookup(child).isIndexed(
+                path.substring(slash));
+    }
+
+    public double getCost(Iterable<String> nodeTypes) {
+        PropertyValue ntNames = PropertyValues.newName(nodeTypes);
+        PropertyIndexLookup lookup = new PropertyIndexLookup(root);
+        return lookup.getCost(JCR_PRIMARYTYPE, ntNames)
+                + lookup.getCost(JCR_MIXINTYPES, ntNames);
+    }
+
+    /**
+     * Returns the paths that match the given node types.
+     *
+     * @param nodeTypes the names of the node types to match.
+     * @return the set of matched paths.
+     */
+    public Set<String> find(Iterable<String> nodeTypes) {
+        Set<String> paths = Sets.newHashSet();
+        PropertyIndexLookup lookup = new PropertyIndexLookup(root);
+        PropertyValue ntNames = PropertyValues.newName(nodeTypes);
+        paths.addAll(lookup.find(JCR_PRIMARYTYPE, ntNames));
+        paths.addAll(lookup.find(JCR_MIXINTYPES, ntNames));
+        return paths;
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexLookup.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexLookup.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexProvider.java?rev=1406080&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexProvider.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexProvider.java Tue Nov  6 10:04:38 2012
@@ -0,0 +1,42 @@
+/*
+ * 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.nodetype;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.spi.query.QueryIndex;
+import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * <code>NodeTypeIndexProvider</code> is a {@link QueryIndexProvider} for
+ * {@link NodeTypeIndex} instances.
+ */
+public class NodeTypeIndexProvider implements QueryIndexProvider {
+
+    @Nonnull
+    @Override
+    public List<? extends QueryIndex> getQueryIndexes(NodeState nodeState) {
+        return ImmutableList.of(new NodeTypeIndex());
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexProvider.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java Tue Nov  6 10:04:38 2012
@@ -19,27 +19,21 @@ package org.apache.jackrabbit.oak.plugin
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
 import org.apache.jackrabbit.oak.api.PropertyValue;
 import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.query.index.IndexRowImpl;
-import org.apache.jackrabbit.oak.query.index.TraversingCursor;
 import org.apache.jackrabbit.oak.spi.query.Cursor;
+import org.apache.jackrabbit.oak.spi.query.Cursors;
 import org.apache.jackrabbit.oak.spi.query.Filter;
 import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction;
-import org.apache.jackrabbit.oak.spi.query.IndexRow;
 import org.apache.jackrabbit.oak.spi.query.QueryIndex;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
 import com.google.common.base.Charsets;
 import com.google.common.collect.Sets;
 
-import static org.apache.jackrabbit.oak.commons.PathUtils.isAbsolute;
-
 /**
  * Provides a QueryIndex that does lookups against a property index
  * 
@@ -113,8 +107,16 @@ public class PropertyIndex implements Qu
 
     @Override
     public double getCost(Filter filter, NodeState root) {
-        // TODO: proper cost calculation
-        return 1.0;
+        PropertyIndexLookup lookup = new PropertyIndexLookup(root);
+        for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
+            if (pr.firstIncluding && pr.lastIncluding
+                    && pr.first.equals(pr.last) // TODO: range queries
+                    && lookup.isIndexed(pr.propertyName, "/")) { // TODO: path
+                return lookup.getCost(pr.propertyName, pr.first);
+            }
+        }
+        // not an appropriate index
+        return Double.MAX_VALUE;
     }
 
     @Override
@@ -136,9 +138,9 @@ public class PropertyIndex implements Qu
         }
 
         if (paths != null) {
-            return new PathCursor(paths);
+            return Cursors.newPathCursor(paths);
         } else {
-            return new TraversingCursor("?", filter, root);
+            return Cursors.newTraversingCursor("?", filter, root);
         }
     }
 
@@ -146,34 +148,4 @@ public class PropertyIndex implements Qu
     public String getPlan(Filter filter, NodeState root) {
         return "oak:index"; // TODO: better plans
     }
-
-    private static class PathCursor implements Cursor {
-
-        private final Iterator<String> iterator;
-
-        private String path;
-
-        public PathCursor(Collection<String> paths) {
-            this.iterator = paths.iterator();
-        }
-
-        @Override
-        public boolean next() {
-            if (iterator.hasNext()) {
-                path = iterator.next();
-                return true;
-            } else {
-                path = null;
-                return false;
-            }
-        }
-
-        @Override
-        public IndexRow currentRow() {
-            // TODO support jcr:score and possibly rep:exceprt
-            return new IndexRowImpl(isAbsolute(path) ? path : "/" + path);
-        }
-
-    }
-
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java Tue Nov  6 10:04:38 2012
@@ -158,6 +158,23 @@ public class PropertyIndexLookup {
         return paths;
     }
 
+    public double getCost(String name, PropertyValue value) {
+        double cost = 0.0;
+        NodeState state = getIndexDefinitionNode(name);
+        if (state != null && state.getChildNode(":index") != null) {
+            state = state.getChildNode(":index");
+            for (String p : PropertyIndex.encode(value)) {
+                PropertyState property = state.getProperty(p);
+                if (property != null) {
+                    cost += property.count();
+                }
+            }
+        } else {
+            cost = Double.MAX_VALUE;
+        }
+        return cost;
+    }
+
     @Nullable
     private NodeState getIndexDefinitionNode(String name) {
         NodeState state = root.getChildNode(INDEX_DEFINITIONS_NAME);
@@ -175,5 +192,4 @@ public class PropertyIndexLookup {
         }
         return null;
     }
-
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/InitialContent.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/InitialContent.java?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/InitialContent.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/InitialContent.java Tue Nov  6 10:04:38 2012
@@ -18,15 +18,19 @@ package org.apache.jackrabbit.oak.plugin
 
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.core.RootImpl;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
 import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
 import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.apache.jackrabbit.oak.spi.state.NodeStoreBranch;
 
+import com.google.common.collect.ImmutableList;
+
 /**
  * {@code InitialContent} implements a {@link RepositoryInitializer} and
  * registers built-in node types when the micro kernel becomes available.
@@ -96,11 +100,14 @@ public class InitialContent implements R
                 .setProperty("propertyNames", "jcr:uuid")
                 .setProperty("reindex", true)
                 .setProperty("unique", true);
-            index.child("primaryType")
+            index.child("nodetype")
                 .setProperty("jcr:primaryType", "oak:queryIndexDefinition", Type.NAME)
                 .setProperty("type", "property")
                 .setProperty("reindex", true)
-                .setProperty("propertyNames", "jcr:primaryType");
+                .setProperty(PropertyStates.createProperty(
+                        "propertyNames",
+                        ImmutableList.of(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.JCR_MIXINTYPES),
+                        Type.STRINGS));
             // FIXME: user-mgt related unique properties (rep:authorizableId, rep:principalName) are implementation detail and not generic for repo
             // FIXME OAK-396: rep:principalName only needs to be unique if defined with user/group nodes -> add defining nt-info to uniqueness constraint otherwise ac-editing will fail.
             index.child("authorizableId")

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java Tue Nov  6 10:04:38 2012
@@ -125,7 +125,7 @@ public class QueryEngineImpl {
         for (QueryIndex index : getIndexes()) {
             double cost = index.getCost(filter, root);
             if (LOG.isDebugEnabled()) {
-                LOG.debug("cost for " + index + " is " + cost);
+                LOG.debug("cost for " + index.getIndexName() + " is " + cost);
             }
             if (cost < bestCost) {
                 bestCost = cost;

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java Tue Nov  6 10:04:38 2012
@@ -24,6 +24,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map.Entry;
 
+import javax.annotation.CheckForNull;
 import javax.jcr.PropertyType;
 
 import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -98,6 +99,7 @@ public class FilterImpl implements Filte
     }
 
     @Override
+    @CheckForNull
     public String getNodeType() {
         return nodeType;
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java Tue Nov  6 10:04:38 2012
@@ -20,6 +20,7 @@ package org.apache.jackrabbit.oak.query.
 
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.spi.query.Cursor;
+import org.apache.jackrabbit.oak.spi.query.Cursors;
 import org.apache.jackrabbit.oak.spi.query.Filter;
 import org.apache.jackrabbit.oak.spi.query.QueryIndex;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -37,7 +38,7 @@ public class TraversingIndex implements 
 
     @Override
     public Cursor query(Filter filter, NodeState root) {
-        return new TraversingCursor(statement, filter, root);
+        return Cursors.newTraversingCursor(statement, filter, root);
     }
 
     @Override

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java?rev=1406080&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java Tue Nov  6 10:04:38 2012
@@ -0,0 +1,211 @@
+/*
+ * 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.spi.query;
+
+import java.util.Deque;
+import java.util.Iterator;
+
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry;
+import org.apache.jackrabbit.oak.query.index.IndexRowImpl;
+import org.apache.jackrabbit.oak.query.index.TraversingIndex;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Queues;
+
+import static org.apache.jackrabbit.oak.commons.PathUtils.isAbsolute;
+import static org.apache.jackrabbit.oak.spi.query.Filter.PathRestriction.ALL_CHILDREN;
+
+/**
+ * <code>Cursors</code> provides factory methods to create {@link Cursor}s.
+ */
+public class Cursors {
+
+    private Cursors() {
+    }
+
+    /**
+     * Creates a {@link Cursor} over paths.
+     *
+     * @param paths the paths to iterate over.
+     * @return the Cursor.
+     */
+    public static Cursor newPathCursor(Iterable<String> paths) {
+        return new PathCursor(paths);
+    }
+
+    /**
+     * Returns a traversing cursor based on the path restriction in the given
+     * {@link Filter}.
+     *
+     * @param statement the query statement. This string is only used for
+     *                  logging purposes.
+     * @param filter    the filter.
+     * @param root      the root {@link NodeState}.
+     * @return the {@link Cursor}.
+     */
+    public static Cursor newTraversingCursor(String statement,
+                                             Filter filter,
+                                             NodeState root) {
+        return new TraversingCursor(statement, filter, root);
+    }
+
+    /**
+     * <code>PathCursor</code> implements a simple {@link Cursor} that iterates
+     * over a {@link String} based path {@link Iterable}.
+     */
+    private static class PathCursor implements Cursor {
+
+        private final Iterator<String> iterator;
+
+        private String path;
+
+        public PathCursor(Iterable<String> paths) {
+            this.iterator = paths.iterator();
+        }
+
+        @Override
+        public boolean next() {
+            if (iterator.hasNext()) {
+                path = iterator.next();
+                return true;
+            } else {
+                path = null;
+                return false;
+            }
+        }
+
+        @Override
+        public IndexRow currentRow() {
+            // TODO support jcr:score and possibly rep:exceprt
+            return new IndexRowImpl(isAbsolute(path) ? path : "/" + path);
+        }
+    }
+
+    /**
+     * A cursor that reads all nodes in a given subtree.
+     */
+    private static class TraversingCursor implements Cursor {
+
+        private static final Logger LOG = LoggerFactory.getLogger(TraversingIndex.class);
+
+        private final String statement;
+
+        private final Filter filter;
+
+        private final Deque<Iterator<? extends ChildNodeEntry>> nodeIterators =
+                Queues.newArrayDeque();
+
+        private String parentPath;
+
+        private String currentPath;
+
+        private long readCount;
+
+        public TraversingCursor(String statement, Filter filter, NodeState root) {
+            this.statement = statement;
+            this.filter = filter;
+
+            String path = filter.getPath();
+            parentPath = null;
+            currentPath = "/";
+            NodeState parent = null;
+            NodeState node = root;
+            if (!path.equals("/")) {
+                for (String name : path.substring(1).split("/")) {
+                    parentPath = currentPath;
+                    currentPath = PathUtils.concat(parentPath, name);
+
+                    parent = node;
+                    node = parent.getChildNode(name);
+
+                    if (node == null) {
+                        // nothing can match this filter, leave nodes empty
+                        return;
+                    }
+                }
+            }
+            Filter.PathRestriction restriciton = filter.getPathRestriction();
+            switch (restriciton) {
+            case EXACT:
+            case ALL_CHILDREN:
+                nodeIterators.add(Iterators.singletonIterator(
+                        new MemoryChildNodeEntry(currentPath, node)));
+                parentPath = "";
+                break;
+            case PARENT:
+                if (parent != null) {
+                    nodeIterators.add(Iterators.singletonIterator(
+                            new MemoryChildNodeEntry(parentPath, parent)));
+                    parentPath = "";
+                }
+                break;
+            case DIRECT_CHILDREN:
+                nodeIterators.add(node.getChildNodeEntries().iterator());
+                parentPath = currentPath;
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown restriction: " + restriciton);
+            }
+        }
+
+        @Override
+        public IndexRow currentRow() {
+            return new IndexRowImpl(currentPath);
+        }
+
+        @Override
+        public boolean next() {
+            while (!nodeIterators.isEmpty()) {
+                Iterator<? extends ChildNodeEntry> iterator = nodeIterators.getLast();
+                if (iterator.hasNext()) {
+                    ChildNodeEntry entry = iterator.next();
+
+                    readCount++;
+                    if (readCount % 100 == 0) {
+                        LOG.warn("Traversed " + readCount + " nodes with filter " + filter + " for query " + statement + "; consider creating an index or changing the query");
+                    }
+
+                    NodeState node = entry.getNodeState();
+
+                    String name = entry.getName();
+                    if (NodeStateUtils.isHidden(name)) {
+                        continue;
+                    }
+                    currentPath = PathUtils.concat(parentPath, name);
+
+                    if (filter.getPathRestriction() == ALL_CHILDREN) {
+                        nodeIterators.addLast(node.getChildNodeEntries().iterator());
+                        parentPath = currentPath;
+                    }
+                    return true;
+                } else {
+                    nodeIterators.removeLast();
+                    parentPath = PathUtils.getParentPath(parentPath);
+                }
+            }
+            currentPath = null;
+            return false;
+        }
+
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java Tue Nov  6 10:04:38 2012
@@ -20,6 +20,7 @@ package org.apache.jackrabbit.oak.spi.qu
 
 import java.util.Collection;
 
+import javax.annotation.CheckForNull;
 import javax.jcr.PropertyType;
 
 import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -65,6 +66,10 @@ public interface Filter {
      */
     String getPath();
 
+    /**
+     * @return the node type restriction or <code>null</code> if none is set.
+     */
+    @CheckForNull
     String getNodeType();
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/PropertyValues.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/PropertyValues.java?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/PropertyValues.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/PropertyValues.java Tue Nov  6 10:04:38 2012
@@ -36,6 +36,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.memory.DoublePropertyState;
 import org.apache.jackrabbit.oak.plugins.memory.GenericPropertyState;
 import org.apache.jackrabbit.oak.plugins.memory.LongPropertyState;
+import org.apache.jackrabbit.oak.plugins.memory.MultiGenericPropertyState;
 import org.apache.jackrabbit.oak.plugins.memory.MultiStringPropertyState;
 import org.apache.jackrabbit.oak.plugins.memory.StringPropertyState;
 
@@ -107,6 +108,11 @@ public final class PropertyValues {
     }
 
     @Nonnull
+    public static PropertyValue newName(Iterable<String> value) {
+        return new PropertyStateValue(MultiGenericPropertyState.nameProperty("", value));
+    }
+
+    @Nonnull
     public static PropertyValue newPath(String value) {
         return new PropertyStateValue(GenericPropertyState.pathProperty("", value));
     }

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java?rev=1406080&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java Tue Nov  6 10:04:38 2012
@@ -0,0 +1,128 @@
+/*
+ * 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.nodetype;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Set;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.mk.core.MicroKernelImpl;
+import org.apache.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.kernel.KernelNodeStore;
+import org.apache.jackrabbit.oak.plugins.index.IndexHookManager;
+import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexHookProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.InitialContent;
+import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.commit.CompositeHook;
+import org.apache.jackrabbit.oak.spi.query.Cursor;
+import org.apache.jackrabbit.oak.spi.query.Cursors;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStoreBranch;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * <code>NodeTypeIndexTest</code> performs tests on {@link NodeTypeIndex}.
+ */
+public class NodeTypeIndexTest {
+
+    private KernelNodeStore store;
+
+    @Before
+    public void setup() {
+        MicroKernel mk = new MicroKernelImpl();
+        store = new KernelNodeStore(mk);
+        store.setHook(new CompositeHook(new IndexHookManager(new PropertyIndexHookProvider())));
+        // initialize node types & index definitions
+        new InitialContent().initialize(store);
+    }
+
+    @Test
+    public void nodeType() throws Exception {
+        NodeStoreBranch branch = store.branch();
+        NodeBuilder root = branch.getRoot().builder();
+
+        root.removeNode("rep:security"); // interferes with tests
+        addFolder(root, "folder-1");
+        addFolder(root, "folder-2");
+        addFile(root, "file-1");
+
+        branch.setRoot(root.getNodeState());
+        branch.merge();
+
+        NodeState rootState = store.getRoot();
+        NodeTypeIndex index = new NodeTypeIndex();
+        FilterImpl filter = new FilterImpl(null);
+
+        filter.setNodeType(JcrConstants.NT_FOLDER);
+        // note on cost: this is currently twice the number of matches
+        // because jcr:primaryType and jcr:mixinTypes are indexed together
+        assertEquals(4.0, index.getCost(filter, rootState), 0.0);
+        checkCursor(index.query(filter, rootState), "/folder-1", "/folder-2");
+
+        filter.setNodeType(JcrConstants.NT_FILE);
+        assertEquals(2.0, index.getCost(filter, rootState), 0.0);
+        checkCursor(index.query(filter, rootState), "/file-1");
+
+        filter.setNodeType(JcrConstants.NT_HIERARCHYNODE);
+        assertEquals(6.0, index.getCost(filter, rootState), 0.0);
+        checkCursor(index.query(filter, rootState), "/folder-1", "/folder-2", "/file-1");
+    }
+
+    private void checkCursor(Cursor cursor, String... matches) {
+        // make sure the index is actually used
+        // and does not traverse
+        assertEquals(Cursors.class.getName() + "$PathCursor",
+                cursor.getClass().getName());
+        Set<String> expected = Sets.newHashSet();
+        expected.addAll(Arrays.asList(matches));
+        Set<String> actual = Sets.newHashSet();
+        while (cursor.next()) {
+            actual.add(cursor.currentRow().getPath());
+        }
+        assertEquals(expected, actual);
+    }
+
+    private NodeBuilder addFolder(NodeBuilder node, String name) {
+        return addChild(node, name, JcrConstants.NT_FOLDER);
+    }
+
+    private NodeBuilder addFile(NodeBuilder node, String name)
+            throws IOException {
+        NodeBuilder file = addChild(node, name, JcrConstants.NT_FILE);
+        NodeBuilder content = addChild(file, JcrConstants.JCR_CONTENT,
+                JcrConstants.NT_RESOURCE);
+        content.setProperty(JcrConstants.JCR_MIMETYPE, "text/plain");
+        Blob blob = store.createBlob(new ByteArrayInputStream("Apache Oak".getBytes()));
+        content.setProperty(JcrConstants.JCR_DATA, blob);
+        return file;
+    }
+
+    private NodeBuilder addChild(NodeBuilder node, String name, String nodeType) {
+        return node.child(name).setProperty(
+                JcrConstants.JCR_PRIMARYTYPE, nodeType, Type.NAME);
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java Tue Nov  6 10:04:38 2012
@@ -29,6 +29,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.index.IndexHookManager;
 import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexHookProvider;
 import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexProvider;
+import org.apache.jackrabbit.oak.plugins.index.nodetype.NodeTypeIndexProvider;
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexHookProvider;
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexProvider;
 import org.apache.jackrabbit.oak.plugins.name.NameValidatorProvider;
@@ -79,6 +80,7 @@ public class Jcr {
         with(new AnnotatingConflictHandler());
 
         with(new PropertyIndexProvider());
+        with(new NodeTypeIndexProvider());
         with(new LuceneIndexProvider());
     }
 

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java?rev=1406080&r1=1406079&r2=1406080&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java Tue Nov  6 10:04:38 2012
@@ -21,7 +21,13 @@ package org.apache.jackrabbit.oak.jcr.qu
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
 import static org.junit.Assert.assertFalse;
+
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.NoSuchElementException;
+import java.util.Set;
+
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
@@ -32,6 +38,9 @@ import javax.jcr.query.QueryManager;
 import javax.jcr.query.QueryResult;
 import javax.jcr.query.Row;
 import javax.jcr.query.RowIterator;
+
+import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.jackrabbit.commons.iterator.RowIterable;
 import org.apache.jackrabbit.oak.jcr.AbstractRepositoryTest;
 import org.junit.Test;
 
@@ -196,4 +205,24 @@ public class QueryTest extends AbstractR
         }
     }
 
+    @Test
+    public void nodeTypeConstraint() throws Exception {
+        Session session = getAdminSession();
+        Node root = session.getRootNode();
+        Node folder1 = root.addNode("folder1", "nt:folder");
+        Node folder2 = root.addNode("folder2", "nt:folder");
+        JcrUtils.putFile(folder1, "file", "text/plain",
+                new ByteArrayInputStream("foo bar".getBytes("UTF-8")));
+        folder2.addNode("folder3", "nt:folder");
+        session.save();
+
+        QueryManager qm = session.getWorkspace().getQueryManager();
+        Query q = qm.createQuery("//element(*, nt:folder)", Query.XPATH);
+        Set<String> paths = new HashSet<String>();
+        for (Row r : new RowIterable(q.execute().getRows())) {
+            paths.add(r.getPath());
+        }
+        assertEquals(new HashSet<String>(Arrays.asList("/folder1", "/folder2", "/folder2/folder3")),
+                paths);
+    }
 }



Mime
View raw message