Author: tommaso
Date: Wed Feb  4 11:58:21 2015
New Revision: 1657128

URL: http://svn.apache.org/r1657128
Log:
OAK-2455 - support for suggestions via query (rep:suggest)

Added:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SuggestImpl.java
   (with props)
Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1657128&r1=1657127&r2=1657128&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
 Wed Feb  4 11:58:21 2015
@@ -63,6 +63,7 @@ import org.apache.jackrabbit.oak.query.a
 import org.apache.jackrabbit.oak.query.ast.SimilarImpl;
 import org.apache.jackrabbit.oak.query.ast.SourceImpl;
 import org.apache.jackrabbit.oak.query.ast.SpellcheckImpl;
+import org.apache.jackrabbit.oak.query.ast.SuggestImpl;
 import org.apache.jackrabbit.oak.query.ast.UpperCaseImpl;
 import org.apache.jackrabbit.oak.query.index.FilterImpl;
 import org.apache.jackrabbit.oak.query.index.TraversingIndex;
@@ -107,6 +108,11 @@ public class QueryImpl implements Query
      */
     public static final String REP_SPELLCHECK = "rep:spellcheck()";
 
+    /**
+     * The "rep:suggest" pseudo-property.
+     */
+    public static final String REP_SUGGEST = "rep:suggest()";
+
     private static final Logger LOG = LoggerFactory.getLogger(QueryImpl.class);
 
     SourceImpl source;
@@ -248,6 +254,13 @@ public class QueryImpl implements Query
                 node.setQuery(query);
                 node.bindSelector(source);
                 return super.visit(node);
+            }
+
+            @Override
+            public boolean visit(SuggestImpl node) {
+                node.setQuery(query);
+                node.bindSelector(source);
+                return super.visit(node);
             }
 
             @Override

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java?rev=1657128&r1=1657127&r2=1657128&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
 Wed Feb  4 11:58:21 2015
@@ -566,6 +566,15 @@ public class SQL2Parser {
                 selectorName = getOnlySelectorName();
             }
             c = factory.spellcheck(selectorName, parseStaticOperand());        
    
+        } else if ("SUGGEST".equalsIgnoreCase(functionName)) {
+            String selectorName;
+            if (currentTokenType == IDENTIFIER) {
+                selectorName = readName();
+                read(",");
+            } else {
+                selectorName = getOnlySelectorName();
+            }
+            c = factory.suggest(selectorName, parseStaticOperand());
         } else {
             return null;
         }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java?rev=1657128&r1=1657127&r2=1657128&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
 Wed Feb  4 11:58:21 2015
@@ -161,4 +161,7 @@ public class AstElementFactory {
         return new SpellcheckImpl(selectorName, expression);
     }
 
+    public ConstraintImpl suggest(String selectorName, StaticOperandImpl 
expression) {
+        return new SuggestImpl(selectorName, expression);
+    }
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java?rev=1657128&r1=1657127&r2=1657128&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java
 Wed Feb  4 11:58:21 2015
@@ -85,4 +85,5 @@ public interface AstVisitor {
     
     boolean visit(SpellcheckImpl node);
 
+    boolean visit(SuggestImpl suggest);
 }
\ No newline at end of file

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java?rev=1657128&r1=1657127&r2=1657128&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
 Wed Feb  4 11:58:21 2015
@@ -93,6 +93,15 @@ public abstract class AstVisitorBase imp
     }
 
     /**
+     * Calls accept on the static operand in the suggest search constraint.
+     */
+    @Override
+    public boolean visit(SuggestImpl node) {
+        node.getExpression().accept(this);
+        return true;
+    }
+
+    /**
      * Calls accept on the two sources and the join condition in the join node.
      */
     @Override

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1657128&r1=1657127&r2=1657128&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
 Wed Feb  4 11:58:21 2015
@@ -635,7 +635,13 @@ public class SelectorImpl extends Source
         } else if (oakPropertyName.equals(QueryImpl.REP_EXCERPT)) {
             result = currentRow.getValue(QueryImpl.REP_EXCERPT);
         } else if (oakPropertyName.equals(QueryImpl.REP_SPELLCHECK)) {
+            // TODO : filter spellcheck corrections by ACLs ?
             result = currentRow.getValue(QueryImpl.REP_SPELLCHECK);
+        } else if (oakPropertyName.equals(QueryImpl.REP_SUGGEST)) {
+            // TODO : filter suggestions by ACLs
+            PropertyValue value = currentRow.getValue(QueryImpl.REP_SUGGEST);
+
+            result = value;
         } else {
             result = PropertyValues.create(t.getProperty(oakPropertyName));
         }

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SuggestImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SuggestImpl.java?rev=1657128&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SuggestImpl.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SuggestImpl.java
 Wed Feb  4 11:58:21 2015
@@ -0,0 +1,112 @@
+/*
+ * 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.query.ast;
+
+import java.util.Collections;
+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.FilterImpl;
+import org.apache.jackrabbit.oak.spi.query.PropertyValues;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex.FulltextQueryIndex;
+
+/**
+ * Support for "suggest(...)
+ */
+public class SuggestImpl extends ConstraintImpl {
+
+    public static final String NATIVE_LUCENE_LANGUAGE = "lucene";
+
+    public static final String SUGGEST_PREFIX = "suggest?term=";
+
+    private final String selectorName;
+    private final StaticOperandImpl expression;
+    private SelectorImpl selector;
+
+    SuggestImpl(String selectorName, StaticOperandImpl expression) {
+        this.selectorName = selectorName;
+        this.expression = expression;
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("suggest(");
+        builder.append(quote(selectorName));
+        builder.append(", ");
+        builder.append(getExpression());
+        builder.append(')');
+        return builder.toString();
+    }
+    
+    @Override
+    public boolean evaluate() {
+        // disable evaluation if a fulltext index is used,
+        // and because we don't know how to process native
+        // conditions
+        if (!(selector.getIndex() instanceof FulltextQueryIndex)) {
+            throw new IllegalArgumentException("No full-text index was found 
that can process the condition " + toString());
+        }
+        // we assume the index only returns the requested entries
+        return true;
+    }
+
+    @Override
+    public Set<PropertyExistenceImpl> getPropertyExistenceConditions() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public void restrict(FilterImpl f) {
+        if (f.getSelector().equals(selector)) {
+            PropertyValue p = expression.currentValue();
+            String term = p.getValue(Type.STRING);
+            String query = SUGGEST_PREFIX + term;
+            PropertyValue v = PropertyValues.newString(query);
+            f.restrictProperty(NativeFunctionImpl.NATIVE_PREFIX + 
NATIVE_LUCENE_LANGUAGE, Operator.EQUAL, v);
+        }
+    }
+
+    @Override
+    public void restrictPushDown(SelectorImpl s) {
+        if (s.equals(selector)) {
+            selector.restrictSelector(this);
+        }
+    }
+
+    @Override
+    public Set<SelectorImpl> getSelectors() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    boolean accept(AstVisitor v) {
+        return v.visit(this);
+    }
+
+    public void bindSelector(SourceImpl source) {
+        selector = source.getExistingSelector(selectorName);
+    }
+    
+    public StaticOperandImpl getExpression() {
+        return expression;
+    }
+
+}
\ No newline at end of file

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

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java?rev=1657128&r1=1657127&r2=1657128&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
 Wed Feb  4 11:58:21 2015
@@ -578,6 +578,37 @@ abstract class Expression {
     }
 
     /**
+     * A rep:suggest condition.
+     */
+    static class Suggest extends Expression {
+
+        final Expression term;
+
+        Suggest(Expression term) {
+            this.term = term;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder buff = new StringBuilder("suggest(");
+            buff.append(term);
+            buff.append(')');
+            return buff.toString();
+        }
+
+        @Override
+        boolean isCondition() {
+            return true;
+        }
+
+        @Override
+        boolean isName() {
+            return false;
+        }
+
+    }
+
+    /**
      * A function call.
      */
     static class Function extends Expression {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java?rev=1657128&r1=1657127&r2=1657128&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
 Wed Feb  4 11:58:21 2015
@@ -215,6 +215,10 @@ public class XPathToSQL2Converter {
                         read(")");                        
                         Expression.Property p = new 
Expression.Property(currentSelector, "rep:spellcheck()", false);
                         statement.addSelectColumn(p);
+                    } else if (readIf("rep:suggest")) {
+                        readExcerpt();
+                        Expression.Property p = new 
Expression.Property(currentSelector, "rep:suggest()", false);
+                        statement.addSelectColumn(p);
                     }
                 } while (readIf("|"));
                 read(")");
@@ -631,9 +635,13 @@ public class XPathToSQL2Converter {
             Expression term = parseExpression();
             read(")");
             return new Expression.Spellcheck(term);
+        } else if ("rep:suggest".equals(functionName)) {
+            Expression term = parseExpression();
+            read(")");
+            return new Expression.Suggest(term);
         } else {
             throw getSyntaxError("jcr:like | jcr:contains | jcr:score | 
xs:dateTime | " + 
-                    "fn:lower-case | fn:upper-case | fn:name | rep:similar | 
rep:spellcheck");
+                    "fn:lower-case | fn:upper-case | fn:name | rep:similar | 
rep:spellcheck | rep:suggest");
         }
     }
 


Reply via email to