You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2014/04/01 10:04:49 UTC
svn commit: r1583563 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/query/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/
oak-lucene/src/main/java/...
Author: thomasm
Date: Tue Apr 1 08:04:49 2014
New Revision: 1583563
URL: http://svn.apache.org/r1583563
Log:
OAK-319 Similar (rep:similar) support
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SimilarImpl.java
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/xpath/Expression.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldFactory.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/MoreLikeThisHelper.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.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=1583563&r1=1583562&r2=1583563&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 Tue Apr 1 08:04:49 2014
@@ -60,6 +60,7 @@ import org.apache.jackrabbit.oak.query.a
import org.apache.jackrabbit.oak.query.ast.SameNodeImpl;
import org.apache.jackrabbit.oak.query.ast.SameNodeJoinConditionImpl;
import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
+import org.apache.jackrabbit.oak.query.ast.SimilarImpl;
import org.apache.jackrabbit.oak.query.ast.SourceImpl;
import org.apache.jackrabbit.oak.query.ast.UpperCaseImpl;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
@@ -209,6 +210,13 @@ public class QueryImpl implements Query
node.bindSelector(source);
return super.visit(node);
}
+
+ @Override
+ public boolean visit(SimilarImpl node) {
+ node.setQuery(query);
+ node.bindSelector(source);
+ return super.visit(node);
+ }
@Override
public boolean visit(FullTextSearchScoreImpl node) {
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=1583563&r1=1583562&r2=1583563&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 Tue Apr 1 08:04:49 2014
@@ -516,6 +516,32 @@ public class SQL2Parser {
} else {
c = factory.descendantNode(getOnlySelectorName(), name);
}
+ } else if ("SIMILAR".equalsIgnoreCase(functionName)) {
+ if (readIf(".") || readIf("*")) {
+ read(",");
+ c = factory.similar(
+ getOnlySelectorName(), null, parseStaticOperand());
+ } else {
+ String name = readName();
+ if (readIf(".")) {
+ if (readIf("*")) {
+ read(",");
+ c = factory.fullTextSearch(
+ name, null, parseStaticOperand());
+ } else {
+ String selector = name;
+ name = readName();
+ read(",");
+ c = factory.fullTextSearch(
+ selector, name, parseStaticOperand());
+ }
+ } else {
+ read(",");
+ c = factory.fullTextSearch(
+ getOnlySelectorName(), name,
+ parseStaticOperand());
+ }
+ }
} else if ("NATIVE".equalsIgnoreCase(functionName)) {
String selectorName;
if (currentTokenType == IDENTIFIER) {
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=1583563&r1=1583562&r2=1583563&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 Tue Apr 1 08:04:49 2014
@@ -152,4 +152,9 @@ public class AstElementFactory {
return new NativeFunctionImpl(selectorName, language, expression);
}
+ public SimilarImpl similar(String selectorName, String propertyName,
+ StaticOperandImpl path) {
+ return new SimilarImpl(selectorName, propertyName, path);
+ }
+
}
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=1583563&r1=1583562&r2=1583563&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 Tue Apr 1 08:04:49 2014
@@ -81,4 +81,6 @@ public interface AstVisitor {
boolean visit(NativeFunctionImpl nativeFunctionImpl);
+ boolean visit(SimilarImpl similarImpl);
+
}
\ 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=1583563&r1=1583562&r2=1583563&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 Tue Apr 1 08:04:49 2014
@@ -69,6 +69,16 @@ public abstract class AstVisitorBase imp
*/
@Override
public boolean visit(NativeFunctionImpl node) {
+ node.getNativeSearchExpression().accept(this);
+ return true;
+ }
+
+ /**
+ * Calls accept on the static operand in the similar search constraint.
+ */
+ @Override
+ public boolean visit(SimilarImpl node) {
+ node.getPathExpression().accept(this);
return true;
}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SimilarImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SimilarImpl.java?rev=1583563&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SimilarImpl.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SimilarImpl.java Tue Apr 1 08:04:49 2014
@@ -0,0 +1,136 @@
+/*
+ * 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.Map;
+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 "similar(...)
+ */
+public class SimilarImpl extends ConstraintImpl {
+
+ public static final String NATIVE_LUCENE_LANGUAGE = "lucene";
+
+ public static final String MORE_LIKE_THIS_PREFIX = "mlt?mlt.fl=:path&mlt.mindf=0&stream.body=";
+
+ private final String selectorName;
+ private final String propertyName;
+ private final StaticOperandImpl pathExpression;
+ private SelectorImpl selector;
+
+ SimilarImpl(String selectorName, String propertyName, StaticOperandImpl pathExpression) {
+ this.selectorName = selectorName;
+ this.propertyName = propertyName;
+ this.pathExpression = pathExpression;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("similar(");
+ builder.append(quote(selectorName));
+ if (propertyName != null) {
+ builder.append(".").append(propertyName);
+ }
+ builder.append(", ");
+ builder.append(getPathExpression());
+ 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());
+ }
+ // verify the path is readable
+ PropertyValue p = pathExpression.currentValue();
+ String path = p.getValue(Type.STRING);
+ if (selector.getTree(path) == null) {
+ return false;
+ }
+ if (propertyName != null) {
+ if (selector.currentProperty(propertyName) == null) {
+ // property not found
+ return false;
+ }
+ }
+
+ // we assume the index only returns the requested entries
+ return true;
+ }
+
+ @Override
+ public Set<PropertyExistenceImpl> getPropertyExistenceConditions() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public void restrict(FilterImpl f) {
+ if (f.getSelector().equals(selector)) {
+ PropertyValue p = pathExpression.currentValue();
+ String path = p.getValue(Type.STRING);
+ String query = MORE_LIKE_THIS_PREFIX + path;
+ 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 getPathExpression() {
+ return pathExpression;
+ }
+
+}
\ No newline at end of file
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=1583563&r1=1583562&r2=1583563&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 Tue Apr 1 08:04:49 2014
@@ -358,7 +358,39 @@ abstract class Expression {
return false;
}
- }
+ }
+
+ /**
+ * A rep:similar condition.
+ */
+ static class Similar extends Expression {
+
+ final Expression property, path;
+
+ Similar(Expression property, Expression path) {
+ this.property = property;
+ this.path = path;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buff = new StringBuilder("similar(");
+ buff.append(property);
+ buff.append(", ").append(path).append(')');
+ return buff.toString();
+ }
+
+ @Override
+ boolean isCondition() {
+ return true;
+ }
+
+ @Override
+ boolean isName() {
+ return false;
+ }
+
+ }
/**
* A function call.
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=1583563&r1=1583562&r2=1583563&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 Tue Apr 1 08:04:49 2014
@@ -615,8 +615,12 @@ public class XPathToSQL2Converter {
Expression.NativeFunction f = new Expression.NativeFunction(selectorName, language, expr);
return f;
} else if ("rep:similar".equals(functionName)) {
- // TODO maybe support rep:similar
- throw getSyntaxError("rep:similar is not supported");
+ Expression property = parseExpression();
+ read(",");
+ Expression path = parseExpression();
+ read(")");
+ Expression.Similar f = new Expression.Similar(property, path);
+ return f;
} else if ("rep:spellcheck".equals(functionName)) {
// TODO maybe support rep:spellcheck as in
// /jcr:root[rep:spellcheck('${query}')]/(rep:spellcheck())
Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldFactory.java?rev=1583563&r1=1583562&r2=1583563&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldFactory.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldFactory.java Tue Apr 1 08:04:49 2014
@@ -41,6 +41,7 @@ public final class FieldFactory {
static {
OAK_TYPE.setIndexed(true);
OAK_TYPE.setOmitNorms(true);
+ OAK_TYPE.setStored(true);
OAK_TYPE.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
OAK_TYPE.setTokenized(true);
OAK_TYPE.freeze();
Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/MoreLikeThisHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/MoreLikeThisHelper.java?rev=1583563&r1=1583562&r2=1583563&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/MoreLikeThisHelper.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/MoreLikeThisHelper.java Tue Apr 1 08:04:49 2014
@@ -17,10 +17,21 @@
package org.apache.jackrabbit.oak.plugins.index.lucene.util;
import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.plugins.index.lucene.FieldNames;
import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.Term;
import org.apache.lucene.queries.mlt.MoreLikeThis;
+import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
/**
* Helper class for generating a {@link org.apache.lucene.queries.mlt.MoreLikeThisQuery} from the native query <code>String</code>
@@ -33,6 +44,7 @@ public class MoreLikeThisHelper {
mlt.setAnalyzer(analyzer);
try {
String text = null;
+ String[] fields = {};
for (String param : mltQueryString.split("&")) {
String[] keyValuePair = param.split("=");
if (keyValuePair.length != 2 || keyValuePair[0] == null || keyValuePair[1] == null) {
@@ -41,7 +53,7 @@ public class MoreLikeThisHelper {
if ("stream.body".equals(keyValuePair[0])) {
text = keyValuePair[1];
} else if ("mlt.fl".equals(keyValuePair[0])) {
- mlt.setFieldNames(keyValuePair[1].split(","));
+ fields = keyValuePair[1].split(",");
} else if ("mlt.mindf".equals(keyValuePair[0])) {
mlt.setMinDocFreq(Integer.parseInt(keyValuePair[1]));
} else if ("mlt.mintf".equals(keyValuePair[0])) {
@@ -66,7 +78,30 @@ public class MoreLikeThisHelper {
}
}
if (text != null) {
- moreLikeThisQuery = mlt.like(new StringReader(text), mlt.getFieldNames()[0]);
+ if (FieldNames.PATH.equals(fields[0])) {
+ IndexSearcher searcher = new IndexSearcher(reader);
+ TermQuery q = new TermQuery(new Term(FieldNames.PATH, text));
+ TopDocs top = searcher.search(q, 1);
+ if (top.totalHits == 0) {
+ mlt.setFieldNames(fields);
+ moreLikeThisQuery = mlt.like(new StringReader(text), mlt.getFieldNames()[0]);
+ } else{
+ ScoreDoc d = top.scoreDocs[0];
+ Document doc = reader.document(d.doc);
+ List<String> fieldNames = new ArrayList<String>();
+ for (IndexableField f : doc.getFields()) {
+ if (!FieldNames.PATH.equals(f.name())) {
+ fieldNames.add(f.name());
+ }
+ }
+ String[] docFields = fieldNames.toArray(new String[0]);
+ mlt.setFieldNames(docFields);
+ moreLikeThisQuery = mlt.like(d.doc);
+ }
+ } else {
+ mlt.setFieldNames(fields);
+ moreLikeThisQuery = mlt.like(new StringReader(text), mlt.getFieldNames()[0]);
+ }
}
return moreLikeThisQuery;
} catch (Exception e) {
Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java?rev=1583563&r1=1583562&r2=1583563&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java Tue Apr 1 08:04:49 2014
@@ -266,22 +266,61 @@ public class LuceneIndexQueryTest extend
}
@Test
- public void testNativeMLTQuery() throws Exception {
- String nativeQueryString = "select [jcr:path] from [nt:base] where native('lucene', 'mlt?stream.body=World&mlt.fl=name&mlt.mindf=0&mlt.mintf=0')";
-
- Tree tree = root.getTree("/");
- Tree test = tree.addChild("test");
- test.addChild("a").setProperty("name", "Hello World, today weather is nice");
- test.addChild("b").setProperty("name", "Cheers World, today weather is quite nice");
- tree.addChild("c");
+ public void testRepSimilarAsNativeQuery() throws Exception {
+ String nativeQueryString = "select [jcr:path] from [nt:base] where " +
+ "native('lucene', 'mlt?stream.body=/test/a&mlt.fl=:path&mlt.mindf=0&mlt.mintf=0')";
+ Tree test = root.getTree("/").addChild("test");
+ test.addChild("a").setProperty("text", "Hello World");
+ test.addChild("b").setProperty("text", "He said Hello and then the world said Hello as well.");
+ test.addChild("c").setProperty("text", "He said Hi.");
+ root.commit();
+ Iterator<String> result = executeQuery(nativeQueryString, "JCR-SQL2").iterator();
+ assertTrue(result.hasNext());
+ assertEquals("/test/a", result.next());
+ assertTrue(result.hasNext());
+ assertEquals("/test/b", result.next());
+ assertFalse(result.hasNext());
+ }
+
+ @Test
+ public void testRepSimilarQuery() throws Exception {
+ String query = "select [jcr:path] from [nt:base] where similar(., '/test/a')";
+ Tree test = root.getTree("/").addChild("test");
+ test.addChild("a").setProperty("text", "Hello World Hello World");
+ test.addChild("b").setProperty("text", "Hello World");
+ test.addChild("c").setProperty("text", "World");
+ test.addChild("d").setProperty("text", "Hello");
+ test.addChild("e").setProperty("text", "World");
+ test.addChild("f").setProperty("text", "Hello");
+ test.addChild("g").setProperty("text", "World");
+ test.addChild("h").setProperty("text", "Hello");
root.commit();
+ Iterator<String> result = executeQuery(query, "JCR-SQL2").iterator();
+ assertTrue(result.hasNext());
+ assertEquals("/test/a", result.next());
+ assertTrue(result.hasNext());
+ assertEquals("/test/b", result.next());
+ assertTrue(result.hasNext());
+ }
- Iterator<String> strings = executeQuery(nativeQueryString, "JCR-SQL2").iterator();
- assertTrue(strings.hasNext());
- assertEquals("/test/a", strings.next());
- assertTrue(strings.hasNext());
- assertEquals("/test/b", strings.next());
- assertFalse(strings.hasNext());
+ @Test
+ public void testRepSimilarXPathQuery() throws Exception {
+ String query = "//element(*, nt:base)[rep:similar(., '/test/a')]";
+ Tree test = root.getTree("/").addChild("test");
+ test.addChild("a").setProperty("text", "Hello World Hello World");
+ test.addChild("b").setProperty("text", "Hello World");
+ test.addChild("c").setProperty("text", "World");
+ test.addChild("d").setProperty("text", "Hello");
+ test.addChild("e").setProperty("text", "World");
+ test.addChild("f").setProperty("text", "Hello");
+ test.addChild("g").setProperty("text", "World");
+ test.addChild("h").setProperty("text", "Hello");
+ root.commit();
+ Iterator<String> result = executeQuery(query, "xpath").iterator();
+ assertTrue(result.hasNext());
+ assertEquals("/test/a", result.next());
+ assertTrue(result.hasNext());
+ assertEquals("/test/b", result.next());
}
@Test