You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2008/03/31 14:32:01 UTC
svn commit: r642979 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/query/lucene/
test/java/org/apache/jackrabbit/core/query/qom/
Author: mreutegg
Date: Mon Mar 31 05:31:56 2008
New Revision: 642979
URL: http://svn.apache.org/viewvc?rev=642979&view=rev
Log:
JCR-1104: JSR 283 support
- query (work in progress)
Added:
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/BindVariableValueTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/NodeNameTest.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JQOM2LuceneQueryBuilder.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardQuery.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/AbstractQOMTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/TestAll.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JQOM2LuceneQueryBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JQOM2LuceneQueryBuilder.java?rev=642979&r1=642978&r2=642979&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JQOM2LuceneQueryBuilder.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JQOM2LuceneQueryBuilder.java Mon Mar 31 05:31:56 2008
@@ -39,7 +39,6 @@
import org.apache.jackrabbit.spi.commons.query.qom.ComparisonImpl;
import org.apache.jackrabbit.spi.commons.query.qom.StaticOperandImpl;
import org.apache.jackrabbit.spi.commons.query.qom.DynamicOperandImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.DefaultTraversingQOMTreeVisitor;
import org.apache.jackrabbit.spi.commons.query.qom.PropertyValueImpl;
import org.apache.jackrabbit.spi.commons.query.qom.LengthImpl;
import org.apache.jackrabbit.spi.commons.query.qom.NodeLocalNameImpl;
@@ -110,12 +109,12 @@
private final SessionImpl session;
/**
- * The shared item state manager of the workspace.
+ * The item state manager of the workspace.
*/
- private final ItemStateManager sharedItemMgr;
+ private final ItemStateManager ism;
/**
- * A hierarchy manager based on {@link #sharedItemMgr} to resolve paths.
+ * A hierarchy manager based on {@link #ism} to resolve paths.
*/
private final HierarchyManager hmgr;
@@ -160,9 +159,8 @@
*
* @param qomTree the root of the query object model.
* @param session of the user executing this query.
- * @param sharedItemMgr the shared item state manager of the
- * workspace.
- * @param hmgr a hierarchy manager based on sharedItemMgr.
+ * @param ism the item state manager of the workspace.
+ * @param hmgr a hierarchy manager based on ism.
* @param nsMappings namespace resolver for internal prefixes.
* @param analyzer for parsing the query statement of the contains
* function.
@@ -173,7 +171,7 @@
*/
private JQOM2LuceneQueryBuilder(QueryObjectModelTree qomTree,
SessionImpl session,
- ItemStateManager sharedItemMgr,
+ ItemStateManager ism,
HierarchyManager hmgr,
NamespaceMappings nsMappings,
Analyzer analyzer,
@@ -182,7 +180,7 @@
Map bindVariableValues) {
this.qomTree = qomTree;
this.session = session;
- this.sharedItemMgr = sharedItemMgr;
+ this.ism = ism;
this.hmgr = hmgr;
this.nsMappings = nsMappings;
this.npResolver = NamePathResolverImpl.create(nsMappings);
@@ -301,157 +299,7 @@
}
public Object visit(ComparisonImpl node, Object data) throws Exception {
- Value v = (Value) ((StaticOperandImpl) node.getOperand2()).accept(this, data);
- final String stringValue;
- switch (v.getType()) {
- case PropertyType.BINARY:
- throw new InvalidQueryException("Binary value not supported in comparison");
- case PropertyType.BOOLEAN:
- stringValue = v.getString();
- break;
- case PropertyType.DATE:
- stringValue = DateField.dateToString(v.getDate().getTime());
- break;
- case PropertyType.DOUBLE:
- stringValue = DoubleField.doubleToString(v.getDouble());
- break;
- case PropertyType.LONG:
- stringValue = LongField.longToString(v.getLong());
- break;
- case PropertyType.NAME:
- Name n = session.getQName(v.getString());
- stringValue = nsMappings.translatePropertyName(n);
- break;
- case PropertyType.PATH:
- Path p = session.getQPath(v.getString());
- stringValue = npResolver.getJCRPath(p);
- break;
- case PropertyType.REFERENCE:
- stringValue = v.getString();
- break;
- case PropertyType.STRING:
- stringValue = v.getString();
- break;
- default:
- // TODO: support for new types defined in JSR 283
- throw new InvalidQueryException("Unsupported property type "
- + PropertyType.nameFromValue(v.getType()));
- }
-
- final int operator = node.getOperator();
-
- return ((DynamicOperandImpl) node.getOperand1()).accept(
- new DefaultTraversingQOMTreeVisitor() {
- public Object visit(PropertyValueImpl node, Object data) throws Exception {
- String propName = npResolver.getJCRName(node.getPropertyQName());
- String text = FieldNames.createNamedValue(propName, stringValue);
- switch (operator) {
- case QueryObjectModelConstants.OPERATOR_EQUAL_TO:
- return new TermQuery(new Term(FieldNames.PROPERTIES, text));
- case QueryObjectModelConstants.OPERATOR_GREATER_THAN:
- Term lower = new Term(FieldNames.PROPERTIES, text);
- Term upper = new Term(FieldNames.PROPERTIES,
- FieldNames.createNamedValue(propName, "\uFFFF"));
- return new RangeQuery(lower, upper, false);
- case QueryObjectModelConstants.OPERATOR_GREATER_THAN_OR_EQUAL_TO:
- lower = new Term(FieldNames.PROPERTIES, text);
- upper = new Term(FieldNames.PROPERTIES,
- FieldNames.createNamedValue(propName, "\uFFFF"));
- return new RangeQuery(lower, upper, true);
- case QueryObjectModelConstants.OPERATOR_LESS_THAN:
- lower = new Term(FieldNames.PROPERTIES,
- FieldNames.createNamedValue(propName, ""));
- upper = new Term(FieldNames.PROPERTIES, text);
- return new RangeQuery(lower, upper, false);
- case QueryObjectModelConstants.OPERATOR_LESS_THAN_OR_EQUAL_TO:
- lower = new Term(FieldNames.PROPERTIES,
- FieldNames.createNamedValue(propName, ""));
- upper = new Term(FieldNames.PROPERTIES, text);
- return new RangeQuery(lower, upper, true);
- case QueryObjectModelConstants.OPERATOR_LIKE:
- if (stringValue.equals("%")) {
- return new MatchAllQuery(propName);
- } else {
- return new WildcardQuery(FieldNames.PROPERTIES,
- propName, stringValue);
- }
- case QueryObjectModelConstants.OPERATOR_NOT_EQUAL_TO:
- MatchAllQuery all = new MatchAllQuery(propName);
- BooleanQuery b = new BooleanQuery();
- b.add(all, BooleanClause.Occur.SHOULD);
- b.add(new TermQuery(new Term(FieldNames.PROPERTIES, text)),
- BooleanClause.Occur.MUST_NOT);
- return b;
- default:
- throw new InvalidQueryException(
- "Unknown operator " + operator);
- }
- }
-
- public Object visit(LengthImpl node, Object data) throws Exception {
- // TODO: implement
- return super.visit(node, data);
- }
-
- public Object visit(NodeLocalNameImpl node, Object data) throws Exception {
- // TODO: implement
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Object visit(NodeNameImpl node, Object data) throws Exception {
- // TODO: implement
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Object visit(FullTextSearchScoreImpl node, Object data)
- throws Exception {
- // TODO: implement
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Object visit(UpperCaseImpl node, Object data) throws Exception {
- Object obj = super.visit(node, data);
- if (obj instanceof Transformable) {
- ((Transformable) obj).setTransformation(TransformConstants.TRANSFORM_UPPER_CASE);
- return obj;
- } else if (obj instanceof TermQuery) {
- return transformTermQuery((TermQuery) obj, true);
- } else {
- throw new InvalidQueryException(
- "upper-case not supported on operand "
- + node.getOperand().getClass().getName());
- }
- }
-
- public Object visit(LowerCaseImpl node, Object data) throws Exception {
- Object obj = super.visit(node, data);
- if (obj instanceof Transformable) {
- ((Transformable) obj).setTransformation(TransformConstants.TRANSFORM_LOWER_CASE);
- return obj;
- } else if (obj instanceof TermQuery) {
- return transformTermQuery((TermQuery) obj, false);
- } else {
- throw new InvalidQueryException(
- "lower-case not supported on operand "
- + node.getOperand().getClass().getName());
- }
- }
-
- private Query transformTermQuery(TermQuery query, boolean toUpper)
- throws InvalidQueryException {
- if (query.getTerm().field() == FieldNames.PROPERTIES) {
- if (toUpper) {
- return new CaseTermQuery.Upper(query.getTerm());
- } else {
- return new CaseTermQuery.Lower(query.getTerm());
- }
- } else {
- throw new InvalidQueryException(
- "Upper/LowerCase not supported on field "
- + query.getTerm().field());
- }
- }
- }, data);
+ return ((DynamicOperandImpl) node.getOperand1()).accept(this, node);
}
public Object visit(DescendantNodeImpl node, Object data) throws Exception {
@@ -554,9 +402,18 @@
return node.getValue();
}
- public Object visit(LowerCaseImpl node, Object data) {
- // query builder should not use this method
- throw new IllegalStateException();
+ public Object visit(LowerCaseImpl node, Object data) throws Exception {
+ Object obj = ((DynamicOperandImpl) node.getOperand()).accept(this, data);
+ if (obj instanceof Transformable) {
+ ((Transformable) obj).setTransformation(TransformConstants.TRANSFORM_LOWER_CASE);
+ return obj;
+ } else if (obj instanceof TermQuery) {
+ return transformTermQuery((TermQuery) obj, false);
+ } else {
+ throw new InvalidQueryException(
+ "lower-case not supported on operand "
+ + node.getOperand().getClass().getName());
+ }
}
public Object visit(NodeLocalNameImpl node, Object data) {
@@ -564,9 +421,78 @@
throw new UnsupportedOperationException("not yet implemented");
}
- public Object visit(NodeNameImpl node, Object data) {
- // TODO: implement
- throw new UnsupportedOperationException("not yet implemented");
+ public Object visit(NodeNameImpl node, Object data) throws Exception {
+ if (data instanceof ComparisonImpl) {
+ ComparisonImpl comp = ((ComparisonImpl) data);
+ int operator = comp.getOperator();
+ Value v = (Value) ((StaticOperandImpl) comp.getOperand2()).accept(this, data);
+ switch (v.getType()) {
+ case PropertyType.DATE:
+ case PropertyType.DOUBLE:
+ // TODO case PropertyType.DECIMAL:
+ case PropertyType.LONG:
+ case PropertyType.BOOLEAN:
+ case PropertyType.REFERENCE:
+ // TODO case PropertyType.WEAKREFERENCE:
+ // TODO case PropertyType.URI
+ throw new InvalidQueryException(v.getString() +
+ " cannot be converted into a NAME value");
+ }
+
+ Name value;
+ try {
+ value = JQOM2LuceneQueryBuilder.this.session.getQName(v.getString());
+ } catch (RepositoryException e) {
+ throw new InvalidQueryException(v.getString() +
+ " cannot be converted into a NAME value");
+ }
+ String stringValue = npResolver.getJCRName(value);
+ // the prefix including colon
+ String prefix = stringValue.substring(0, stringValue.indexOf(':') + 1);
+
+ switch (operator) {
+ case QueryObjectModelConstants.OPERATOR_EQUAL_TO:
+ return new TermQuery(new Term(FieldNames.LABEL, stringValue));
+ case QueryObjectModelConstants.OPERATOR_GREATER_THAN:
+ Term lower = new Term(FieldNames.LABEL, stringValue);
+ Term upper = new Term(FieldNames.LABEL,
+ prefix + "\uFFFF");
+ return new RangeQuery(lower, upper, false);
+ case QueryObjectModelConstants.OPERATOR_GREATER_THAN_OR_EQUAL_TO:
+ lower = new Term(FieldNames.LABEL, stringValue);
+ upper = new Term(FieldNames.LABEL,
+ prefix + "\uFFFF");
+ return new RangeQuery(lower, upper, true);
+ case QueryObjectModelConstants.OPERATOR_LESS_THAN:
+ lower = new Term(FieldNames.LABEL, prefix);
+ upper = new Term(FieldNames.LABEL, stringValue);
+ return new RangeQuery(lower, upper, false);
+ case QueryObjectModelConstants.OPERATOR_LESS_THAN_OR_EQUAL_TO:
+ lower = new Term(FieldNames.LABEL, prefix);
+ upper = new Term(FieldNames.LABEL, stringValue);
+ return new RangeQuery(lower, upper, true);
+ case QueryObjectModelConstants.OPERATOR_LIKE:
+ if (stringValue.equals("%")) {
+ return new MatchAllDocsQuery();
+ } else {
+ return new WildcardQuery(FieldNames.LABEL,
+ null, stringValue);
+ }
+ case QueryObjectModelConstants.OPERATOR_NOT_EQUAL_TO:
+ MatchAllDocsQuery all = new MatchAllDocsQuery();
+ BooleanQuery b = new BooleanQuery();
+ b.add(all, BooleanClause.Occur.SHOULD);
+ b.add(new TermQuery(new Term(FieldNames.LABEL, stringValue)),
+ BooleanClause.Occur.MUST_NOT);
+ return b;
+ default:
+ throw new InvalidQueryException(
+ "Unknown operator " + operator);
+ }
+ } else {
+ // TODO
+ throw new InvalidQueryException("not yet implemented");
+ }
}
public Object visit(NotImpl node, Object data) throws Exception {
@@ -594,9 +520,59 @@
return new MatchAllQuery(propName);
}
- public Object visit(PropertyValueImpl node, Object data) {
- // query builder should not use this method
- throw new IllegalStateException();
+ public Object visit(PropertyValueImpl node, Object data) throws Exception {
+ if (data instanceof ComparisonImpl) {
+ ComparisonImpl comp = ((ComparisonImpl) data);
+ int operator = comp.getOperator();
+ Value v = (Value) ((StaticOperandImpl) comp.getOperand2()).accept(this, data);
+ String stringValue = stringValueOf(v);
+ String propName = npResolver.getJCRName(node.getPropertyQName());
+ String text = FieldNames.createNamedValue(propName, stringValue);
+ switch (operator) {
+ case QueryObjectModelConstants.OPERATOR_EQUAL_TO:
+ return new TermQuery(new Term(FieldNames.PROPERTIES, text));
+ case QueryObjectModelConstants.OPERATOR_GREATER_THAN:
+ Term lower = new Term(FieldNames.PROPERTIES, text);
+ Term upper = new Term(FieldNames.PROPERTIES,
+ FieldNames.createNamedValue(propName, "\uFFFF"));
+ return new RangeQuery(lower, upper, false);
+ case QueryObjectModelConstants.OPERATOR_GREATER_THAN_OR_EQUAL_TO:
+ lower = new Term(FieldNames.PROPERTIES, text);
+ upper = new Term(FieldNames.PROPERTIES,
+ FieldNames.createNamedValue(propName, "\uFFFF"));
+ return new RangeQuery(lower, upper, true);
+ case QueryObjectModelConstants.OPERATOR_LESS_THAN:
+ lower = new Term(FieldNames.PROPERTIES,
+ FieldNames.createNamedValue(propName, ""));
+ upper = new Term(FieldNames.PROPERTIES, text);
+ return new RangeQuery(lower, upper, false);
+ case QueryObjectModelConstants.OPERATOR_LESS_THAN_OR_EQUAL_TO:
+ lower = new Term(FieldNames.PROPERTIES,
+ FieldNames.createNamedValue(propName, ""));
+ upper = new Term(FieldNames.PROPERTIES, text);
+ return new RangeQuery(lower, upper, true);
+ case QueryObjectModelConstants.OPERATOR_LIKE:
+ if (stringValue.equals("%")) {
+ return new MatchAllQuery(propName);
+ } else {
+ return new WildcardQuery(FieldNames.PROPERTIES,
+ propName, stringValue);
+ }
+ case QueryObjectModelConstants.OPERATOR_NOT_EQUAL_TO:
+ MatchAllQuery all = new MatchAllQuery(propName);
+ BooleanQuery b = new BooleanQuery();
+ b.add(all, BooleanClause.Occur.SHOULD);
+ b.add(new TermQuery(new Term(FieldNames.PROPERTIES, text)),
+ BooleanClause.Occur.MUST_NOT);
+ return b;
+ default:
+ throw new InvalidQueryException(
+ "Unknown operator " + operator);
+ }
+ } else {
+ // TODO
+ throw new InvalidQueryException("not yet implemented");
+ }
}
public Object visit(QueryObjectModelTree node, Object data)
@@ -702,7 +678,62 @@
}
public Object visit(UpperCaseImpl node, Object data) throws Exception {
- // query builder should not use this method
- throw new IllegalStateException();
+ Object obj = ((DynamicOperandImpl) node.getOperand()).accept(this, data);
+ if (obj instanceof Transformable) {
+ ((Transformable) obj).setTransformation(TransformConstants.TRANSFORM_UPPER_CASE);
+ return obj;
+ } else if (obj instanceof TermQuery) {
+ return transformTermQuery((TermQuery) obj, true);
+ } else {
+ throw new InvalidQueryException(
+ "upper-case not supported on operand "
+ + node.getOperand().getClass().getName());
+ }
+ }
+
+ //------------------------------< internal >--------------------------------
+
+ private String stringValueOf(Value value) throws RepositoryException {
+ switch (value.getType()) {
+ case PropertyType.BINARY:
+ return value.getString();
+ case PropertyType.BOOLEAN:
+ return value.getString();
+ case PropertyType.DATE:
+ return DateField.dateToString(value.getDate().getTime());
+ case PropertyType.DOUBLE:
+ return DoubleField.doubleToString(value.getDouble());
+ case PropertyType.LONG:
+ return LongField.longToString(value.getLong());
+ case PropertyType.NAME:
+ Name n = session.getQName(value.getString());
+ return nsMappings.translatePropertyName(n);
+ case PropertyType.PATH:
+ Path p = session.getQPath(value.getString());
+ return npResolver.getJCRPath(p);
+ case PropertyType.REFERENCE:
+ return value.getString();
+ case PropertyType.STRING:
+ return value.getString();
+ default:
+ // TODO: support for new types defined in JSR 283
+ throw new InvalidQueryException("Unsupported property type "
+ + PropertyType.nameFromValue(value.getType()));
+ }
+ }
+
+ private Query transformTermQuery(TermQuery query, boolean toUpper)
+ throws InvalidQueryException {
+ if (query.getTerm().field() == FieldNames.PROPERTIES) {
+ if (toUpper) {
+ return new CaseTermQuery.Upper(query.getTerm());
+ } else {
+ return new CaseTermQuery.Lower(query.getTerm());
+ }
+ } else {
+ throw new InvalidQueryException(
+ "Upper/LowerCase not supported on field "
+ + query.getTerm().field());
+ }
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardQuery.java?rev=642979&r1=642978&r2=642979&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardQuery.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardQuery.java Mon Mar 31 05:31:56 2008
@@ -126,7 +126,7 @@
* @throws IOException if an error occurs while reading from the index.
*/
public Query rewrite(IndexReader reader) throws IOException {
- Query stdWildcardQuery = new MultiTermQuery(new Term(FieldNames.PROPERTIES, pattern)) {
+ Query stdWildcardQuery = new MultiTermQuery(new Term(field, pattern)) {
protected FilteredTermEnum getEnum(IndexReader reader) throws IOException {
return new WildcardTermEnum(reader, field, propName, pattern, transform);
}
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/AbstractQOMTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/AbstractQOMTest.java?rev=642979&r1=642978&r2=642979&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/AbstractQOMTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/AbstractQOMTest.java Mon Mar 31 05:31:56 2008
@@ -21,6 +21,11 @@
import org.apache.jackrabbit.spi.commons.query.jsr283.qom.QueryObjectModelFactory;
import org.apache.jackrabbit.spi.commons.query.jsr283.qom.QueryObjectModelConstants;
import org.apache.jackrabbit.core.query.QueryManagerImpl;
+import org.apache.jackrabbit.core.query.QueryImpl;
+
+import javax.jcr.query.Query;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
/**
* <code>AbstractQOMTest</code> is a base class for test cases on the JQOM.
@@ -35,5 +40,22 @@
super.setUp();
QueryManagerImpl qm = (QueryManagerImpl) superuser.getWorkspace().getQueryManager();
qomFactory = qm.getQOMFactory();
+ }
+
+ /**
+ * Binds the given <code>value</code> to the variable named
+ * <code>var</code>.
+ *
+ * @param q the query
+ * @param var name of variable in query
+ * @param value value to bind
+ * @throws IllegalArgumentException if <code>var</code> is not a valid
+ * variable in this query.
+ * @throws RepositoryException if an error occurs.
+ */
+ protected void bindVariableValue(Query q, String var, Value value)
+ throws RepositoryException {
+ // TODO: remove cast when bindValue() is available on JSR 283 Query
+ ((QueryImpl) q).bindValue(var, value);
}
}
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/BindVariableValueTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/BindVariableValueTest.java?rev=642979&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/BindVariableValueTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/BindVariableValueTest.java Mon Mar 31 05:31:56 2008
@@ -0,0 +1,167 @@
+/*
+ * 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.core.query.qom;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.ValueFactory;
+import javax.jcr.Value;
+import javax.jcr.query.Query;
+import java.util.Calendar;
+
+/**
+ * <code>BindVariableValueTest</code>...
+ */
+public class BindVariableValueTest extends AbstractQOMTest {
+
+ private static final String STRING_VALUE = "JSR";
+
+ private static final long LONG_VALUE = 283;
+
+ private static final double DOUBLE_VALUE = Math.PI;
+
+ private static final boolean BOOLEAN_VALUE = true;
+
+ private static final Calendar DATE_VALUE = Calendar.getInstance();
+
+ private Query query;
+
+ private ValueFactory vf;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ vf = superuser.getValueFactory();
+ query = qomFactory.createQuery(
+ qomFactory.selector(testNodeType, "s"),
+ qomFactory.and(
+ qomFactory.childNode("s", testRoot),
+ qomFactory.comparison(
+ qomFactory.propertyValue(propertyName1),
+ OPERATOR_EQUAL_TO,
+ qomFactory.bindVariable("v")
+ )
+ ), null, null);
+ }
+
+ protected void tearDown() throws Exception {
+ vf = null;
+ query = null;
+ super.tearDown();
+ }
+
+ public void testIllegalArgumentException() throws RepositoryException {
+ try {
+ bindVariableValue(query, "x", vf.createValue(STRING_VALUE));
+ fail("Query.bindValue() must throw IllegalArgumentException for unknown variable name");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testString() throws RepositoryException {
+ Node n = testRootNode.addNode(nodeName1, testNodeType);
+ n.setProperty(propertyName1, STRING_VALUE);
+ testRootNode.save();
+
+ bindVariableValue(query, "v", vf.createValue(STRING_VALUE));
+ checkResult(query.execute(), new Node[]{n});
+ }
+
+ public void testDate() throws RepositoryException {
+ Node n = testRootNode.addNode(nodeName1, testNodeType);
+ n.setProperty(propertyName1, DATE_VALUE);
+ testRootNode.save();
+
+ bindVariableValue(query, "v", vf.createValue(DATE_VALUE));
+ checkResult(query.execute(), new Node[]{n});
+ }
+
+ public void testLong() throws RepositoryException {
+ Node n = testRootNode.addNode(nodeName1, testNodeType);
+ n.setProperty(propertyName1, LONG_VALUE);
+ testRootNode.save();
+
+ bindVariableValue(query, "v", vf.createValue(LONG_VALUE));
+ checkResult(query.execute(), new Node[]{n});
+ }
+
+ public void testDouble() throws RepositoryException {
+ Node n = testRootNode.addNode(nodeName1, testNodeType);
+ n.setProperty(propertyName1, DOUBLE_VALUE);
+ testRootNode.save();
+
+ bindVariableValue(query, "v", vf.createValue(DOUBLE_VALUE));
+ checkResult(query.execute(), new Node[]{n});
+ }
+
+ public void testBoolean() throws RepositoryException {
+ Node n = testRootNode.addNode(nodeName1, testNodeType);
+ n.setProperty(propertyName1, BOOLEAN_VALUE);
+ testRootNode.save();
+
+ bindVariableValue(query, "v", vf.createValue(BOOLEAN_VALUE));
+ checkResult(query.execute(), new Node[]{n});
+ }
+
+ public void testName() throws RepositoryException {
+ Value name = vf.createValue(STRING_VALUE);
+ Node n = testRootNode.addNode(nodeName1, testNodeType);
+ n.setProperty(propertyName1, name);
+ testRootNode.save();
+
+ bindVariableValue(query, "v", name);
+ checkResult(query.execute(), new Node[]{n});
+ }
+
+ public void testPath() throws RepositoryException {
+ Node n = testRootNode.addNode(nodeName1, testNodeType);
+ Value path = vf.createValue(n.getPath());
+ n.setProperty(propertyName1, path);
+ testRootNode.save();
+
+ bindVariableValue(query, "v", path);
+ checkResult(query.execute(), new Node[]{n});
+ }
+
+ public void testReference() throws RepositoryException {
+ Node n = testRootNode.addNode(nodeName1, testNodeType);
+ testRootNode.save();
+
+ if (!n.isNodeType(mixReferenceable)) {
+ n.addMixin(mixReferenceable);
+ n.save();
+ }
+ n.setProperty(propertyName1, n);
+ n.save();
+
+
+ bindVariableValue(query, "v", vf.createValue(n));
+ checkResult(query.execute(), new Node[]{n});
+ }
+
+ public void testWeakReference() throws RepositoryException {
+ // TODO
+ }
+
+ public void testURI() throws RepositoryException {
+ // TODO
+ }
+
+ public void testDecimal() throws RepositoryException {
+ // TODO
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/BindVariableValueTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/NodeNameTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/NodeNameTest.java?rev=642979&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/NodeNameTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/NodeNameTest.java Mon Mar 31 05:31:56 2008
@@ -0,0 +1,239 @@
+/*
+ * 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.core.query.qom;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.Node;
+import javax.jcr.PropertyType;
+import javax.jcr.query.Query;
+import javax.jcr.query.InvalidQueryException;
+import java.util.Calendar;
+
+/**
+ * <code>NodeNameTest</code> checks if conversion of literals is correctly
+ * performed and operators work as specified.
+ */
+public class NodeNameTest extends AbstractQOMTest {
+
+ private Node node1;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ node1 = testRootNode.addNode(nodeName1, testNodeType);
+ testRootNode.save();
+ }
+
+ protected void tearDown() throws Exception {
+ node1 = null;
+ super.tearDown();
+ }
+
+ public void testStringLiteral() throws RepositoryException {
+ Value literal = superuser.getValueFactory().createValue(nodeName1);
+ Query q = createQuery(OPERATOR_EQUAL_TO, literal);
+ checkResult(q.execute(), new Node[]{node1});
+ }
+
+ public void testBinaryLiteral() throws RepositoryException {
+ Value literal = superuser.getValueFactory().createValue(
+ nodeName1, PropertyType.BINARY);
+ Query q = createQuery(OPERATOR_EQUAL_TO, literal);
+ checkResult(q.execute(), new Node[]{node1});
+ }
+
+ public void testDateLiteral() throws RepositoryException {
+ Value literal = superuser.getValueFactory().createValue(Calendar.getInstance());
+ try {
+ createQuery(OPERATOR_EQUAL_TO, literal).execute();
+ fail("NodeName comparison with DATE must fail with InvalidQueryException");
+ } catch (InvalidQueryException e) {
+ // expected
+ }
+ }
+
+ public void testDoubleLiteral() throws RepositoryException {
+ Value literal = superuser.getValueFactory().createValue(Math.PI);
+ try {
+ createQuery(OPERATOR_EQUAL_TO, literal).execute();
+ fail("NodeName comparison with DOUBLE must fail with InvalidQueryException");
+ } catch (InvalidQueryException e) {
+ // expected
+ }
+ }
+
+ public void testDecimalLiteral() throws RepositoryException {
+ // TODO must throw InvalidQueryException
+ }
+
+ public void testLongLiteral() throws RepositoryException {
+ Value literal = superuser.getValueFactory().createValue(283);
+ try {
+ createQuery(OPERATOR_EQUAL_TO, literal).execute();
+ fail("NodeName comparison with LONG must fail with InvalidQueryException");
+ } catch (InvalidQueryException e) {
+ // expected
+ }
+ }
+
+ public void testBooleanLiteral() throws RepositoryException {
+ Value literal = superuser.getValueFactory().createValue(true);
+ try {
+ createQuery(OPERATOR_EQUAL_TO, literal).execute();
+ fail("NodeName comparison with BOOLEAN must fail with InvalidQueryException");
+ } catch (InvalidQueryException e) {
+ // expected
+ }
+ }
+
+ public void testNameLiteral() throws RepositoryException {
+ Value literal = superuser.getValueFactory().createValue(
+ nodeName1, PropertyType.NAME);
+ Query q = createQuery(OPERATOR_EQUAL_TO, literal);
+ checkResult(q.execute(), new Node[]{node1});
+ }
+
+ public void testPathLiteral() throws RepositoryException {
+ Value literal = superuser.getValueFactory().createValue(
+ nodeName1, PropertyType.PATH);
+ Query q = createQuery(OPERATOR_EQUAL_TO, literal);
+ checkResult(q.execute(), new Node[]{node1});
+
+ literal = superuser.getValueFactory().createValue(
+ node1.getPath(), PropertyType.PATH);
+ try {
+ createQuery(OPERATOR_EQUAL_TO, literal).execute();
+ fail("NodeName comparison with absolute PATH must fail with InvalidQueryException");
+ } catch (InvalidQueryException e) {
+ // expected
+ }
+
+ literal = superuser.getValueFactory().createValue(
+ nodeName1 + "/" + nodeName1, PropertyType.PATH);
+ try {
+ createQuery(OPERATOR_EQUAL_TO, literal).execute();
+ fail("NodeName comparison with PATH length >1 must fail with InvalidQueryException");
+ } catch (InvalidQueryException e) {
+ // expected
+ }
+ }
+
+ public void testReferenceLiteral() throws RepositoryException {
+ if (!node1.isNodeType(mixReferenceable)) {
+ node1.addMixin(mixReferenceable);
+ }
+ node1.save();
+ Value literal = superuser.getValueFactory().createValue(node1);
+ try {
+ createQuery(OPERATOR_EQUAL_TO, literal).execute();
+ fail("NodeName comparison with REFERENCE must fail with InvalidQueryException");
+ } catch (InvalidQueryException e) {
+ // expected
+ }
+ }
+
+ public void testWeakReferenceLiteral() throws RepositoryException {
+ // TODO: must throw InvalidQueryException
+ }
+
+ /**
+ * If the URI consists of a single path segment without a colon (for
+ * example, simply bar) it is converted to a NAME by percent-unescaping
+ * followed by UTF-8-decoding of the byte sequence. If it has a redundant
+ * leading ./ followed by a single segment (with or without a colon, like
+ * ./bar or ./foo:bar ) the redundant ./ is removed and the remainder is
+ * converted to a NAME in the same way. Otherwise a ValueFormatException is
+ * thrown.
+ */
+ public void testURILiteral() throws RepositoryException {
+ // TODO
+ }
+
+ public void testEqualTo() throws RepositoryException {
+ checkOperator(OPERATOR_EQUAL_TO, false, true, false);
+ }
+
+ public void testGreaterThan() throws RepositoryException {
+ checkOperator(OPERATOR_GREATER_THAN, true, false, false);
+ }
+
+ public void testGreaterThanOrEqualTo() throws RepositoryException {
+ checkOperator(OPERATOR_GREATER_THAN_OR_EQUAL_TO, true, true, false);
+ }
+
+ public void testLessThan() throws RepositoryException {
+ checkOperator(OPERATOR_LESS_THAN, false, false, true);
+ }
+
+ public void testLessThanOrEqualTo() throws RepositoryException {
+ checkOperator(OPERATOR_LESS_THAN_OR_EQUAL_TO, false, true, true);
+ }
+
+ public void testLike() throws RepositoryException {
+ checkOperator(OPERATOR_LIKE, false, true, false);
+ }
+
+ public void testNotEqualTo() throws RepositoryException {
+ checkOperator(OPERATOR_NOT_EQUAL_TO, true, false, true);
+ }
+
+ //------------------------------< helper >----------------------------------
+
+ private void checkOperator(int operator,
+ boolean matchesLesser,
+ boolean matchesEqual,
+ boolean matchesGreater)
+ throws RepositoryException {
+ checkOperatorSingleLiteral(createLexicographicallyLesser(nodeName1), operator, matchesLesser);
+ checkOperatorSingleLiteral(nodeName1, operator, matchesEqual);
+ checkOperatorSingleLiteral(createLexicographicallyGreater(nodeName1), operator, matchesGreater);
+ }
+
+ private void checkOperatorSingleLiteral(String literal,
+ int operator,
+ boolean matches)
+ throws RepositoryException {
+ Value value = superuser.getValueFactory().createValue(literal);
+ Query q = createQuery(operator, value);
+ checkResult(q.execute(), matches ? new Node[]{node1} : new Node[0]);
+ }
+
+ private String createLexicographicallyGreater(String name) {
+ StringBuffer tmp = new StringBuffer(name);
+ tmp.setCharAt(tmp.length() - 1, (char) (tmp.charAt(tmp.length() - 1) + 1));
+ return tmp.toString();
+ }
+
+ private String createLexicographicallyLesser(String name) {
+ StringBuffer tmp = new StringBuffer(name);
+ tmp.setCharAt(tmp.length() - 1, (char) (tmp.charAt(tmp.length() - 1) - 1));
+ return tmp.toString();
+ }
+
+ private Query createQuery(int operator, Value literal) throws RepositoryException {
+ return qomFactory.createQuery(
+ qomFactory.selector(testNodeType, "s"),
+ qomFactory.and(
+ qomFactory.childNode("s", testRoot),
+ qomFactory.comparison(
+ qomFactory.nodeName("s"),
+ operator,
+ qomFactory.literal(literal)
+ )
+ ), null, null);
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/NodeNameTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/TestAll.java?rev=642979&r1=642978&r2=642979&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/TestAll.java Mon Mar 31 05:31:56 2008
@@ -29,8 +29,10 @@
public static Test suite() {
TestSuite suite = new TestSuite("QOM tests");
+ suite.addTestSuite(BindVariableValueTest.class);
suite.addTestSuite(ChildNodeTest.class);
suite.addTestSuite(DescendantNodeTest.class);
+ suite.addTestSuite(NodeNameTest.class);
suite.addTestSuite(QueryObjectModelFactoryTest.class);
suite.addTestSuite(SameNodeTest.class);
suite.addTestSuite(SelectorTest.class);