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");
}
}