Author: tommaso
Date: Fri Feb 21 13:45:18 2014
New Revision: 1570568

URL: http://svn.apache.org/r1570568
Log:
OAK-1444 - improved precision of Solr default analyzers

Added:
    
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultAnalyzersConfigurationTest.java
   (with props)
Modified:
    jackrabbit/oak/trunk/oak-solr-core/pom.xml
    
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditor.java
    
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java
    
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/util/OakSolrUtils.java
    
jackrabbit/oak/trunk/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml
    
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrCommitHookIT.java
    
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java
    
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryEngineIT.java
    
jackrabbit/oak/trunk/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml

Modified: jackrabbit/oak/trunk/oak-solr-core/pom.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/pom.xml?rev=1570568&r1=1570567&r2=1570568&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-solr-core/pom.xml Fri Feb 21 13:45:18 2014
@@ -46,7 +46,41 @@
               org.apache.jackrabbit.oak.plugins.index.solr.server,
               org.apache.jackrabbit.oak.plugins.index.solr.util
             </Export-Package>
-            <Embed-Dependency>solr-solrj</Embed-Dependency>
+              <_exportcontents>
+                  org.apache.solr.*;version=${solr.version},
+              </_exportcontents>
+              <Import-Package>
+                  org.slf4j.impl;resolution:=optional,
+                  com.ibm.icu.*;resolution:=optional,
+                  org.apache.log4j.jmx;resolution:=optional,
+                  org.apache.log4j.spi;resolution:=optional,
+                  org.jboss.netty.*;resolution:=optional,
+                  jline.*;resolution:=optional,
+                  org.eclipse.jetty.*;resolution:=optional,
+                  javax.servlet.*; version="[2.5.0,4.0.0)",
+                  org.tartarus.snowball;resolution:=optional,
+                  org.restlet;resolution:=optional,
+                  org.restlet.*;resolution:=optional,
+                  org.apache.hadoop.*;resolution:=optional,
+                  com.carrotsearch.hppc.*;resolution:=optional,
+                  
com.googlecode.concurrentlinkedhashmap.*;resolution:=optional,
+                  com.spatial4j.core.*;resolution:=optional,
+                  org.apache.log4j.*;resolution:=optional,
+                  
org.apache.zookeeper.server.quorum.flexible.*;resolution:=optional,
+                  org.joda.time.*;resolution:=optional,
+                  org.apache.lucene.queries.*;resolution:=optional,
+                  org.apache.lucene.queryparser.*;resolution:=optional,
+                  org.apache.lucene.search.grouping.*;resolution:=optional,
+                  org.apache.lucene.search.highlight.*;resolution:=optional,
+                  
org.apache.lucene.search.postingshighlight.*;resolution:=optional,
+                  org.apache.lucene.search.spell.*;resolution:=optional,
+                  org.apache.lucene.search.suggest.*;resolution:=optional,
+                  
org.apache.lucene.search.vectorhighlight.*;resolution:=optional,
+                  org.apache.lucene.spatial.*;resolution:=optional,
+                  *
+              </Import-Package>
+              <DynamicImport-Package>*</DynamicImport-Package>
+              
<Embed-Dependency>solr-solrj,solr-core,org.noggit</Embed-Dependency>
           </instructions>
         </configuration>
       </plugin>
@@ -95,12 +129,29 @@
       <scope>provided</scope>
     </dependency>
 
-    <dependency>
-      <groupId>org.apache.solr</groupId>
-      <artifactId>solr-solrj</artifactId>
-      <version>${solr.version}</version>
-      <scope>provided</scope>
-    </dependency>
+      <dependency>
+          <groupId>org.apache.solr</groupId>
+          <artifactId>solr-core</artifactId>
+          <version>${solr.version}</version>
+          <scope>runtime</scope>
+          <exclusions>
+              <exclusion>
+                  <groupId>org.slf4j</groupId>
+                  <artifactId>slf4j-jdk14</artifactId>
+              </exclusion>
+          </exclusions>
+      </dependency>
+      <dependency>
+          <groupId>org.apache.solr</groupId>
+          <artifactId>solr-solrj</artifactId>
+          <version>${solr.version}</version>
+      </dependency>
+      <dependency>
+          <groupId>org.noggit</groupId>
+          <artifactId>noggit</artifactId>
+          <version>0.5</version>
+          <scope>runtime</scope>
+      </dependency>
 
     <!-- sorlj dependencies needed for OSGi deployments -->
     <dependency>
@@ -137,7 +188,7 @@
     <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
-      <version>4.1.3</version>
+      <version>4.2.6</version>
       <scope>runtime</scope>
       <optional>true</optional>
       <exclusions>
@@ -150,7 +201,7 @@
     <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpmime</artifactId>
-      <version>4.1.3</version>
+      <version>4.2.6</version>
       <scope>runtime</scope>
       <optional>true</optional>
       <exclusions>
@@ -184,30 +235,18 @@
       <classifier>tests</classifier>
     </dependency>
     <dependency>
-      <groupId>org.apache.jackrabbit</groupId>
-      <artifactId>oak-mk</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.solr</groupId>
-      <artifactId>solr-core</artifactId>
-      <version>${solr.version}</version>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>org.slf4j</groupId>
-          <artifactId>slf4j-jdk14</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>servlet-api</artifactId>
       <version>2.5</version>
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>oak-mk</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>log4j-over-slf4j</artifactId>
       <optional>true</optional>
@@ -228,7 +267,20 @@
       <groupId>org.mockito</groupId>
       <artifactId>mockito-core</artifactId>
       <version>1.9.5</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.lucene</groupId>
+      <artifactId>lucene-test-framework</artifactId>
+      <version>${solr.version}</version>
+      <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.lucene</groupId>
+      <artifactId>lucene-core</artifactId>
+      <version>${solr.version}</version>
+    </dependency>
+
   </dependencies>
 
 </project>

Modified: 
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditor.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditor.java?rev=1570568&r1=1570567&r2=1570568&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditor.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditor.java
 Fri Feb 21 13:45:18 2014
@@ -157,7 +157,7 @@ public class SolrIndexEditor implements 
 
         try {
             solrServer.deleteByQuery(String.format(
-                    "%s:%s\\/*", configuration.getPathField(), path));
+                    "%s:%s*", configuration.getPathField(), path));
             updateCallback.indexUpdate();
         } catch (SolrServerException e) {
             throw new CommitFailedException(
@@ -173,9 +173,6 @@ public class SolrIndexEditor implements 
     private SolrInputDocument docFromState(NodeState state) {
         SolrInputDocument inputDocument = new SolrInputDocument();
         String path = getPath();
-        if (!path.endsWith("/")) {
-            path = path + "/";
-        }
         inputDocument.addField(configuration.getPathField(), path);
         for (PropertyState property : state.getProperties()) {
             // try to get the field to use for this property from configuration

Modified: 
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java?rev=1570568&r1=1570567&r2=1570568&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java
 Fri Feb 21 13:45:18 2014
@@ -89,13 +89,6 @@ public class SolrQueryIndex implements Q
                 queryBuilder.append(fieldName);
                 queryBuilder.append(':');
                 queryBuilder.append(path);
-                if (!path.equals("\\/")) {
-                    queryBuilder.append("\\/");
-                }
-                // TODO: Also handle other path restriction types
-                if 
(pathRestriction.equals(Filter.PathRestriction.ALL_CHILDREN)) {
-                    queryBuilder.append("*");
-                }
                 queryBuilder.append(" ");
             }
         }
@@ -122,9 +115,6 @@ public class SolrQueryIndex implements Q
                     queryBuilder.append(configuration.getPathField());
                     queryBuilder.append(':');
                     queryBuilder.append(first);
-                    if (first!= null && !"\\/".equals(first)) {
-                        queryBuilder.append("\\/");
-                    }
                 } else {
                     queryBuilder.append(fieldName).append(':');
                     if (pr.first != null && pr.last != null && 
pr.first.equals(pr.last)) {
@@ -205,7 +195,7 @@ public class SolrQueryIndex implements Q
         try {
             SolrQuery query = getQuery(filter);
             if (log.isDebugEnabled()) {
-                log.info("sending query {}", query);
+                log.debug("sending query {}", query);
             }
             QueryResponse queryResponse = solrServer.query(query);
             cursor = new SolrCursor(queryResponse);
@@ -244,13 +234,8 @@ public class SolrQueryIndex implements Q
                 return new IndexRow() {
                     @Override
                     public String getPath() {
-                        String path = String.valueOf(doc.getFieldValue(
+                        return String.valueOf(doc.getFieldValue(
                                 configuration.getPathField()));
-                        if ("/".equals(path)) {
-                            return "/";
-                        } else {
-                            return path.substring(0, path.length() - 1);
-                        }
                     }
 
                     @Override

Modified: 
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/util/OakSolrUtils.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/util/OakSolrUtils.java?rev=1570568&r1=1570567&r2=1570568&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/util/OakSolrUtils.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/util/OakSolrUtils.java
 Fri Feb 21 13:45:18 2014
@@ -17,9 +17,6 @@
 package org.apache.jackrabbit.oak.plugins.index.solr.util;
 
 import java.io.IOException;
-
-import javax.annotation.Nonnull;
-
 import org.apache.jackrabbit.oak.plugins.index.solr.configuration.CommitPolicy;
 import 
org.apache.jackrabbit.oak.plugins.index.solr.configuration.DefaultSolrConfigurationProvider;
 import 
org.apache.jackrabbit.oak.plugins.index.solr.configuration.OakSolrConfigurationProvider;
@@ -40,22 +37,6 @@ import org.osgi.framework.ServiceReferen
 public class OakSolrUtils {
 
     /**
-     * Check if a given Solr instance is alive
-     * 
-     * @param solrServer
-     *            the {@link org.apache.solr.client.solrj.SolrServer} used to 
communicate with the Solr instance
-     * @return <code>true</code> if the given Solr instance is alive and 
responding
-     * @throws java.io.IOException
-     *             if any low level IO error occurs
-     * @throws org.apache.solr.client.solrj.SolrServerException
-     *             if any error occurs while trying to communicate with the 
Solr instance
-     */
-    public static boolean checkServerAlive(@Nonnull SolrServer solrServer) 
-                    throws IOException, SolrServerException {
-        return solrServer.ping().getStatus() == 0;
-    }
-
-    /**
      * adapts the OSGi Solr {@link 
org.apache.jackrabbit.oak.spi.query.QueryIndexProvider} service
      * 
      * @return a {@link 
org.apache.jackrabbit.oak.plugins.index.solr.query.SolrQueryIndexProvider}

Modified: 
jackrabbit/oak/trunk/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml?rev=1570568&r1=1570567&r2=1570568&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml 
(original)
+++ 
jackrabbit/oak/trunk/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml 
Fri Feb 21 13:45:18 2014
@@ -28,22 +28,26 @@
     </fieldType>
     <fieldType name="children_path" class="solr.TextField">
       <analyzer type="index">
-        <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" 
skip="1" reverse="true" />
-        <filter class="solr.PatternReplaceFilterFactory" pattern="/" 
replacement="" replace="all"/>
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <filter class="solr.ReverseStringFilterFactory" />
+        <filter class="solr.LengthFilterFactory" min="2" max="2147483647"/>
+        <filter class="solr.PatternReplaceFilterFactory" 
pattern="([^\/]+)(\/)" replacement="$2" replace="first"/>
+        <filter class="solr.PatternReplaceFilterFactory" pattern="(\/)(.+)" 
replacement="$2" replace="first"/>
+        <filter class="solr.ReverseStringFilterFactory" />
       </analyzer>
       <analyzer type="query">
         <tokenizer class="solr.KeywordTokenizerFactory" />
-        <filter class="solr.PatternReplaceFilterFactory" pattern="/" 
replacement="" replace="all"/>
       </analyzer>
     </fieldType>
     <fieldType name="parent_path" class="solr.TextField">
       <analyzer type="index">
         <tokenizer class="solr.KeywordTokenizerFactory" />
-        <filter class="solr.PatternReplaceFilterFactory" pattern="/" 
replacement="" replace="all"/>
       </analyzer>
       <analyzer type="query">
-        <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" 
skip="1" reverse="true"/>
-        <filter class="solr.PatternReplaceFilterFactory" pattern="/" 
replacement="" replace="all"/>
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <filter class="solr.ReverseStringFilterFactory" />
+        <filter class="solr.PatternReplaceFilterFactory" pattern="[^\/]+\/" 
replacement="" replace="first"/>
+        <filter class="solr.ReverseStringFilterFactory" />
       </analyzer>
     </fieldType>
     <fieldType name="text_keepcase" class="solr.TextField" 
positionIncrementGap="100">
@@ -100,7 +104,7 @@
   </types>
   <fields>
     <field name="path_exact" type="string" indexed="true" stored="true"/>
-    <field name="path_child" type="children_path" indexed="true" 
stored="false"/>
+    <field name="path_child" type="children_path" indexed="true" 
stored="true"/>
     <field name="path_anc" type="parent_path" indexed="true" stored="false"/>
     <field name="path_des" type="descendent_path" indexed="true" 
stored="false"/>
     <field name="ignored" type="ignored" multiValued="true"/>

Added: 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultAnalyzersConfigurationTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultAnalyzersConfigurationTest.java?rev=1570568&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultAnalyzersConfigurationTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultAnalyzersConfigurationTest.java
 Fri Feb 21 13:45:18 2014
@@ -0,0 +1,230 @@
+/*
+ * 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.solr.configuration;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.regex.Pattern;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.BaseTokenStreamTestCase;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.Tokenizer;
+import org.apache.lucene.analysis.core.KeywordTokenizer;
+import org.apache.lucene.analysis.miscellaneous.LengthFilter;
+import org.apache.lucene.analysis.path.PathHierarchyTokenizer;
+import org.apache.lucene.analysis.pattern.PatternReplaceFilter;
+import org.apache.lucene.analysis.reverse.ReverseStringFilter;
+import org.apache.lucene.util.Version;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Testcase for checking default analyzers configurations behave as expected 
with regards to path related restrictions
+ *
+ * Note that default Solr analyzers for Oak should be equivalent to the ones 
programmtically defined here.
+ */
+public class DefaultAnalyzersConfigurationTest extends BaseTokenStreamTestCase 
{
+
+    private Analyzer parentPathIndexingAnalyzer;
+    private Analyzer parentPathSearchingAnalyzer;
+    private Analyzer exactPathAnalyzer;
+    private Analyzer directChildrenPathIndexingAnalyzer;
+    private Analyzer directChildrenPathSearchingAnalyzer;
+    private Analyzer allChildrenPathIndexingAnalyzer;
+    private Analyzer allChildrenPathSearchingAnalyzer;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        this.exactPathAnalyzer = new Analyzer() {
+            @Override
+            protected TokenStreamComponents createComponents(String fieldName, 
Reader reader) {
+                Tokenizer source = new KeywordTokenizer(reader);
+                return new TokenStreamComponents(source);
+            }
+        };
+        this.parentPathIndexingAnalyzer = new Analyzer() {
+            @Override
+            protected TokenStreamComponents createComponents(String fieldName, 
Reader reader) {
+                Tokenizer source = new KeywordTokenizer(reader);
+                return new TokenStreamComponents(source);
+            }
+        };
+        this.parentPathSearchingAnalyzer = new Analyzer() {
+            @Override
+            protected TokenStreamComponents createComponents(String fieldName, 
Reader reader) {
+                Tokenizer source = new KeywordTokenizer(reader);
+                TokenStream filter = new 
ReverseStringFilter(Version.LUCENE_41, source);
+                filter = new PatternReplaceFilter(filter, 
Pattern.compile("[^\\/]+\\/"), "", false);
+                filter = new ReverseStringFilter(Version.LUCENE_41, filter);
+                return new TokenStreamComponents(source, filter);
+            }
+        };
+
+        this.directChildrenPathIndexingAnalyzer = new Analyzer() {
+            @Override
+            protected TokenStreamComponents createComponents(String fieldName, 
Reader reader) {
+                Tokenizer source = new KeywordTokenizer(reader);
+                TokenStream filter = new 
ReverseStringFilter(Version.LUCENE_41, source);
+                filter = new LengthFilter(false, filter, 2, Integer.MAX_VALUE);
+                filter = new PatternReplaceFilter(filter, 
Pattern.compile("([^\\/]+)(\\/)"), "$2", false);
+                filter = new PatternReplaceFilter(filter, 
Pattern.compile("(\\/)(.+)"), "$2", false);
+                filter = new ReverseStringFilter(Version.LUCENE_41, filter);
+                return new TokenStreamComponents(source, filter);
+            }
+        };
+        this.directChildrenPathSearchingAnalyzer = new Analyzer() {
+            @Override
+            protected TokenStreamComponents createComponents(String fieldName, 
Reader reader) {
+                Tokenizer source = new KeywordTokenizer(reader);
+                return new TokenStreamComponents(source);
+            }
+        };
+
+        this.allChildrenPathIndexingAnalyzer = new Analyzer() {
+            @Override
+            protected TokenStreamComponents createComponents(String fieldName, 
Reader reader) {
+                Tokenizer source = new PathHierarchyTokenizer(reader);
+                return new TokenStreamComponents(source);
+            }
+        };
+        this.allChildrenPathSearchingAnalyzer = new Analyzer() {
+            @Override
+            protected TokenStreamComponents createComponents(String fieldName, 
Reader reader) {
+                Tokenizer source = new KeywordTokenizer(reader);
+                return new TokenStreamComponents(source);
+            }
+        };
+    }
+
+    @Test
+    public void testAllChildrenIndexingTokenization() throws Exception {
+        try {
+            TokenStream ts = 
allChildrenPathIndexingAnalyzer.tokenStream("text", new 
StringReader("/jcr:a/jcr:b/c/jcr:d"));
+            assertTokenStreamContents(ts, new String[]{"/jcr:a", 
"/jcr:a/jcr:b", "/jcr:a/jcr:b/c", "/jcr:a/jcr:b/c/jcr:d"});
+        } finally {
+            allChildrenPathIndexingAnalyzer.close();
+        }
+    }
+
+    @Test
+    public void testAllChildrenSearchingTokenization() throws Exception {
+        try {
+            TokenStream ts = 
allChildrenPathSearchingAnalyzer.tokenStream("text", new 
StringReader("/jcr:a/jcr:b/jcr:c"));
+            assertTokenStreamContents(ts, new String[]{"/jcr:a/jcr:b/jcr:c"});
+        } finally {
+            allChildrenPathSearchingAnalyzer.close();
+        }
+    }
+
+    @Test
+    public void testDirectChildrenPathIndexingTokenization() throws Exception {
+        try {
+            TokenStream ts = 
directChildrenPathIndexingAnalyzer.tokenStream("text", new 
StringReader("/jcr:a/b/jcr:c"));
+            assertTokenStreamContents(ts, new String[]{"/jcr:a/b"});
+            ts = directChildrenPathIndexingAnalyzer.tokenStream("text", new 
StringReader("/jcr:a"));
+            assertTokenStreamContents(ts, new String[]{"/"});
+            ts = directChildrenPathIndexingAnalyzer.tokenStream("text", new 
StringReader("/"));
+            assertTokenStreamContents(ts, new String[]{});
+        } finally {
+            directChildrenPathIndexingAnalyzer.close();
+        }
+    }
+
+    @Test
+    public void testDirectChildrenPathSearchingTokenization() throws Exception 
{
+        try {
+            TokenStream ts = 
directChildrenPathSearchingAnalyzer.tokenStream("text", new 
StringReader("/jcr:a/jcr:b"));
+            assertTokenStreamContents(ts, new String[]{"/jcr:a/jcr:b"});
+        } finally {
+            directChildrenPathSearchingAnalyzer.close();
+        }
+    }
+
+    @Test
+    public void testExactPathIndexingTokenizationAndSearch() throws Exception {
+        try {
+            TokenStream ts = exactPathAnalyzer.tokenStream("text", new 
StringReader("/jcr:a/jcr:b/c"));
+            assertTokenStreamContents(ts, new String[]{"/jcr:a/jcr:b/c"});
+        } finally {
+            exactPathAnalyzer.close();
+        }
+    }
+
+    @Test
+    public void testParentPathSearchingTokenization() throws Exception {
+        try {
+            TokenStream ts = parentPathSearchingAnalyzer.tokenStream("text", 
new StringReader("/jcr:a/b/jcr:c"));
+            assertTokenStreamContents(ts, new String[]{"/jcr:a/b"});
+        } finally {
+            parentPathSearchingAnalyzer.close();
+        }
+    }
+
+    @Test
+    public void testParentPathIndexingTokenization() throws Exception {
+        try {
+            TokenStream ts = parentPathIndexingAnalyzer.tokenStream("text", 
new StringReader("/a/b"));
+            assertTokenStreamContents(ts, new String[]{"/a/b"});
+        } finally {
+            parentPathIndexingAnalyzer.close();
+        }
+    }
+
+    @Test
+    public void testAllChildrenPathMatching() throws Exception {
+        String nodePath = "/jcr:a/jcr:b/c";
+        String descendantPath = nodePath + "/d/jcr:e";
+        assertAnalyzesTo(allChildrenPathIndexingAnalyzer, descendantPath, new 
String[]{"/jcr:a", "/jcr:a/jcr:b", "/jcr:a/jcr:b/c", "/jcr:a/jcr:b/c/d", 
"/jcr:a/jcr:b/c/d/jcr:e"});
+        assertAnalyzesTo(allChildrenPathSearchingAnalyzer, nodePath, new 
String[]{nodePath});
+        assertAnalyzesTo(allChildrenPathSearchingAnalyzer, "/jcr:a", new 
String[]{"/jcr:a"});
+        assertAnalyzesTo(allChildrenPathSearchingAnalyzer, "/jcr:a/b", new 
String[]{"/jcr:a/b"});
+        assertAnalyzesTo(allChildrenPathSearchingAnalyzer, "/a/b/c", new 
String[]{"/a/b/c"});
+        assertAnalyzesTo(allChildrenPathSearchingAnalyzer, "/a/b/c/d", new 
String[]{"/a/b/c/d"});
+        assertAnalyzesTo(allChildrenPathSearchingAnalyzer, "/a/b/c/d/jcr:e", 
new String[]{"/a/b/c/d/jcr:e"});
+    }
+
+    @Test
+    public void testDirectChildrenPathMatching() throws Exception {
+        String nodePath = "/a/b/c";
+        String childPath = nodePath + "/d";
+        assertAnalyzesTo(directChildrenPathIndexingAnalyzer, childPath, new 
String[]{nodePath});
+        assertAnalyzesTo(directChildrenPathSearchingAnalyzer, nodePath, new 
String[]{nodePath});
+
+        nodePath = "/";
+        childPath = nodePath + "/jcr:a";
+        assertAnalyzesTo(directChildrenPathIndexingAnalyzer, childPath, new 
String[]{nodePath});
+        assertAnalyzesTo(directChildrenPathSearchingAnalyzer, nodePath, new 
String[]{nodePath});
+
+        String childPath1 = "/test/jcr:resource";
+        String childPath2 = "/test/resource";
+
+        nodePath = "/test";
+        assertAnalyzesTo(directChildrenPathIndexingAnalyzer, childPath1, new 
String[]{nodePath});
+        assertAnalyzesTo(directChildrenPathIndexingAnalyzer, childPath2, new 
String[]{nodePath});
+        assertAnalyzesTo(directChildrenPathSearchingAnalyzer, nodePath, new 
String[]{nodePath});
+    }
+
+    @Test
+    public void testParentPathMatching() throws Exception {
+        String parentPath = "/a/b";
+        String nodePath = parentPath + "/jcr:c";
+        assertAnalyzesTo(parentPathIndexingAnalyzer, parentPath, new 
String[]{parentPath});
+        assertAnalyzesTo(parentPathSearchingAnalyzer, nodePath, new 
String[]{parentPath});
+    }
+
+}

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

Modified: 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrCommitHookIT.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrCommitHookIT.java?rev=1570568&r1=1570567&r2=1570568&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrCommitHookIT.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrCommitHookIT.java
 Fri Feb 21 13:45:18 2014
@@ -58,7 +58,7 @@ public class SolrCommitHookIT extends So
 
         // check the node is not in Solr anymore
         SolrQuery query = new SolrQuery();
-        query.setQuery("path_exact:\\/testRemoveNode\\/");
+        query.setQuery("path_exact:\\/testRemoveNode");
         assertTrue("item with id:testRemoveNode was not found in the index",
                 server.query(query).getResults().size() > 0);
 

Modified: 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java?rev=1570568&r1=1570567&r2=1570568&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java
 Fri Feb 21 13:45:18 2014
@@ -85,8 +85,8 @@ public class SolrIndexQueryTest extends 
     @Test
     public void descendantTest() throws Exception {
         Tree test = root.getTree("/").addChild("test");
-        test.addChild("a");
-        test.addChild("b");
+        test.addChild("a").addChild("c");
+        test.addChild("b").addChild("d");
         root.commit();
 
         Iterator<String> result = executeQuery(
@@ -94,14 +94,19 @@ public class SolrIndexQueryTest extends 
                 "JCR-SQL2").iterator();
         assertTrue(result.hasNext());
         assertEquals("/test/a", result.next());
+        assertTrue(result.hasNext());
+        assertEquals("/test/a/c", result.next());
+        assertTrue(result.hasNext());
         assertEquals("/test/b", result.next());
+        assertTrue(result.hasNext());
+        assertEquals("/test/b/d", result.next());
         assertFalse(result.hasNext());
     }
 
     @Test
     public void descendantTest2() throws Exception {
         Tree test = root.getTree("/").addChild("test");
-        test.addChild("a").setProperty("name", asList("Hello", "World"), 
STRINGS);
+        test.addChild("a").addChild("c").setProperty("name", asList("Hello", 
"World"), STRINGS);
         test.addChild("b").setProperty("name", "Hello");
         root.commit();
 
@@ -109,7 +114,7 @@ public class SolrIndexQueryTest extends 
                 "select [jcr:path] from [nt:base] where 
isdescendantnode('/test') and name='World'",
                 "JCR-SQL2").iterator();
         assertTrue(result.hasNext());
-        assertEquals("/test/a", result.next());
+        assertEquals("/test/a/c", result.next());
         assertFalse(result.hasNext());
     }
 
@@ -132,9 +137,29 @@ public class SolrIndexQueryTest extends 
                 "JCR-SQL2").iterator();
         assertTrue(result.hasNext());
         assertEquals("/, /children", result.next());
+        assertTrue(result.hasNext());
         assertEquals("/, /jcr:system", result.next());
+        assertTrue(result.hasNext());
         assertEquals("/, /oak:index", result.next());
+        assertTrue(result.hasNext());
         assertEquals("/, /parents", result.next());
         assertFalse(result.hasNext());
+
+    }
+
+    @Test
+    public void ischildnodeTest2() throws Exception {
+        Tree tree = root.getTree("/");
+        Tree test = tree.addChild("test");
+        test.addChild("jcr:resource").addChild("x");
+        test.addChild("resource");
+        root.commit();
+
+        Iterator<String> strings = executeQuery("select [jcr:path] from 
[nt:base] as b where ischildnode(b, '/test')", "JCR-SQL2").iterator();
+        assertTrue(strings.hasNext());
+        assertEquals("/test/jcr:resource", strings.next());
+        assertTrue(strings.hasNext());
+        assertEquals("/test/resource", strings.next());
+        assertFalse(strings.hasNext());
     }
 }

Modified: 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryEngineIT.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryEngineIT.java?rev=1570568&r1=1570567&r2=1570568&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryEngineIT.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryEngineIT.java
 Fri Feb 21 13:45:18 2014
@@ -103,13 +103,13 @@ public class SolrQueryEngineIT extends S
         Cursor cursor = index.query(filter, store.getRoot());
         assertNotNull(cursor);
         assertTrue(cursor.hasNext());
-        assertEquals("/somenode/child1", cursor.next().getPath());
+        assertEquals("/somenode", cursor.next().getPath());
         assertTrue(cursor.hasNext());
-        assertEquals("/somenode/child2/descendant", cursor.next().getPath());
+        assertEquals("/somenode/child1", cursor.next().getPath());
         assertTrue(cursor.hasNext());
         assertEquals("/somenode/child2", cursor.next().getPath());
         assertTrue(cursor.hasNext());
-        assertEquals("/somenode", cursor.next().getPath());
+        assertEquals("/somenode/child2/descendant", cursor.next().getPath());
         assertFalse(cursor.hasNext());
     }
 

Modified: 
jackrabbit/oak/trunk/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml?rev=1570568&r1=1570567&r2=1570568&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml 
(original)
+++ 
jackrabbit/oak/trunk/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml 
Fri Feb 21 13:45:18 2014
@@ -28,22 +28,26 @@
         </fieldType>
         <fieldType name="children_path" class="solr.TextField">
             <analyzer type="index">
-                <tokenizer class="solr.PathHierarchyTokenizerFactory" 
delimiter="/" skip="1" reverse="true" />
-                <filter class="solr.PatternReplaceFilterFactory" pattern="/" 
replacement="" replace="all"/>
+                <tokenizer class="solr.KeywordTokenizerFactory"/>
+                <filter class="solr.ReverseStringFilterFactory" />
+                <filter class="solr.LengthFilterFactory" min="2" 
max="2147483647"/>
+                <filter class="solr.PatternReplaceFilterFactory" 
pattern="([^\/]+)(\/)" replacement="$2" replace="first"/>
+                <filter class="solr.PatternReplaceFilterFactory" 
pattern="(\/)(.+)" replacement="$2" replace="first"/>
+                <filter class="solr.ReverseStringFilterFactory" />
             </analyzer>
             <analyzer type="query">
                 <tokenizer class="solr.KeywordTokenizerFactory" />
-                <filter class="solr.PatternReplaceFilterFactory" pattern="/" 
replacement="" replace="all"/>
             </analyzer>
         </fieldType>
         <fieldType name="parent_path" class="solr.TextField">
             <analyzer type="index">
                 <tokenizer class="solr.KeywordTokenizerFactory" />
-                <filter class="solr.PatternReplaceFilterFactory" pattern="/" 
replacement="" replace="all"/>
             </analyzer>
             <analyzer type="query">
-                <tokenizer class="solr.PathHierarchyTokenizerFactory" 
delimiter="/" skip="1" reverse="true"/>
-                <filter class="solr.PatternReplaceFilterFactory" pattern="/" 
replacement="" replace="all"/>
+                <tokenizer class="solr.KeywordTokenizerFactory"/>
+                <filter class="solr.ReverseStringFilterFactory" />
+                <filter class="solr.PatternReplaceFilterFactory" 
pattern="[^\/]+\/" replacement="" replace="first"/>
+                <filter class="solr.ReverseStringFilterFactory" />
             </analyzer>
         </fieldType>
         <fieldType name="text_keepcase" class="solr.TextField" 
positionIncrementGap="100">
@@ -96,13 +100,14 @@
                    geo="true" distErrPct="0.025" maxDistErr="0.000009" 
units="degrees" />
 
         <fieldType name="currency" class="solr.CurrencyField" 
precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
-
+        <fieldtype name="ignored" stored="false" indexed="false" 
multiValued="true" class="solr.StrField"/>
     </types>
     <fields>
         <field name="path_exact" type="string" indexed="true" stored="true"/>
-        <field name="path_child" type="children_path" indexed="true" 
stored="false"/>
+        <field name="path_child" type="children_path" indexed="true" 
stored="true"/>
         <field name="path_anc" type="parent_path" indexed="true" 
stored="false"/>
         <field name="path_des" type="descendent_path" indexed="true" 
stored="false"/>
+        <field name="ignored" type="ignored" multiValued="true"/>
         <field name="catch_all" type="text_general" indexed="true" 
stored="false" multiValued="true"/>
         <field name="_version_" type="long" indexed="true" stored="true"/>
 


Reply via email to