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