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/04 09:57:34 UTC

svn commit: r633394 - in /jackrabbit/trunk: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/common...

Author: mreutegg
Date: Tue Mar  4 00:57:31 2008
New Revision: 633394

URL: http://svn.apache.org/viewvc?rev=633394&view=rev
Log:
JCR-1104: JSR 283 support
- Implemented SameNode, ChildNode and DescendantNode
- Added test cases

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DefaultQueryHits.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHitsQuery.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/ChildNodeTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/DescendantNodeTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/SameNodeTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/TestAll.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/JackrabbitQuery.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/ChildNodeImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/DescendantNodeImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/DynamicOperandImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/EquiJoinConditionImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/FullTextSearchScoreImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/JoinImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/LengthImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/LowerCaseImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/NodeLocalNameImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/NodeNameImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/PropertyValueImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/QueryObjectModelTree.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SameNodeImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SameNodeJoinConditionImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SelectorImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SourceImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/UpperCaseImpl.java

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DefaultQueryHits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DefaultQueryHits.java?rev=633394&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DefaultQueryHits.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DefaultQueryHits.java Tue Mar  4 00:57:31 2008
@@ -0,0 +1,67 @@
+/*
+ * 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.lucene;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * <code>DefaultQueryHits</code> implements {@link QueryHits} based on a
+ * collection of {@link ScoreNode}s.
+ */
+public class DefaultQueryHits extends AbstractQueryHits {
+
+    /**
+     * The total number of score nodes.
+     */
+    private final int size;
+
+    /**
+     * An iterator over the query nodes.
+     */
+    private final Iterator scoreNodes;
+
+    /**
+     * Creates a new <code>DefaultQueryHits</code> instance based on the passed
+     * <code>scoreNodes</code>.
+     *
+     * @param scoreNodes a collection of {@link ScoreNode}s.
+     */
+    public DefaultQueryHits(Collection scoreNodes) {
+        this.size = scoreNodes.size();
+        this.scoreNodes = scoreNodes.iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ScoreNode nextScoreNode() throws IOException {
+        if (scoreNodes.hasNext()) {
+            return (ScoreNode) scoreNodes.next();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getSize() {
+        return size;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DefaultQueryHits.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=633394&r1=633393&r2=633394&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 Tue Mar  4 00:57:31 2008
@@ -73,6 +73,9 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.PropertyType;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.NodeIterator;
+import javax.jcr.Node;
 import javax.jcr.query.InvalidQueryException;
 import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.nodetype.NodeType;
@@ -83,6 +86,7 @@
 import java.util.Arrays;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.Collections;
 
 /**
  * Implements a query builder that takes an JQOM and creates a lucene {@link
@@ -265,8 +269,25 @@
     }
 
     public Object visit(ChildNodeImpl node, Object data) {
-        // TODO: implement
-        throw new UnsupportedOperationException("not yet implemented");
+        Name ntName = qomTree.getSelector(node.getSelectorQName()).getNodeTypeQName();
+        List scoreNodes = new ArrayList();
+        try {
+            Node parent = session.getNode(node.getPath());
+            for (NodeIterator it = parent.getNodes(); it.hasNext(); ) {
+                NodeImpl n = (NodeImpl) it.nextNode();
+                if (n.isNodeType(ntName)) {
+                    scoreNodes.add(new ScoreNode(n.getNodeId(), 1.0f));
+                }
+            }
+            return new QueryHitsQuery(new DefaultQueryHits(scoreNodes));
+        } catch (PathNotFoundException e) {
+            // node does not exist
+        } catch (RepositoryException e) {
+            log.warn("Exception while constructing query: " + e);
+            log.debug("Stacktrace: ", e);
+        }
+        // return a dummy query, which does not match any nodes
+        return new BooleanQuery();
     }
 
     public Object visit(ChildNodeJoinConditionImpl node, Object data) {
@@ -433,9 +454,23 @@
         }, data);
     }
 
-    public Object visit(DescendantNodeImpl node, Object data) {
-        // TODO: implement
-        throw new UnsupportedOperationException("not yet implemented");
+    public Object visit(DescendantNodeImpl node, Object data) throws Exception {
+        // TODO simplify, is there a way to aggregate constraints for the same selector?
+        Query selectorQuery = (Query) qomTree.getSelector(node.getSelectorQName()).accept(this, null);
+        try {
+            NodeImpl n = (NodeImpl) session.getNode(node.getPath());
+            ScoreNode sn = new ScoreNode(n.getNodeId(), 1.0f);
+            Query context = new QueryHitsQuery(new DefaultQueryHits(
+                    Collections.singletonList(sn)));
+            return new DescendantSelfAxisQuery(context, selectorQuery, false);
+        } catch (PathNotFoundException e) {
+            // node does not exist
+        } catch (RepositoryException e) {
+            log.warn("Exception while constructing query: " + e);
+            log.debug("Stacktrace: ", e);
+        }
+        // return a dummy query, which does not match any nodes
+        return new BooleanQuery();
     }
 
     public Object visit(DescendantNodeJoinConditionImpl node, Object data) {
@@ -579,8 +614,22 @@
     }
 
     public Object visit(SameNodeImpl node, Object data) {
-        // TODO: implement
-        throw new UnsupportedOperationException("not yet implemented");
+        Name ntName = qomTree.getSelector(node.getSelectorQName()).getNodeTypeQName();
+        try {
+            NodeImpl n = (NodeImpl) session.getNode(node.getPath());
+            if (n.isNodeType(ntName)) {
+                ScoreNode sn = new ScoreNode(n.getNodeId(), 1.0f);
+                return new QueryHitsQuery(new DefaultQueryHits(
+                        Collections.singletonList(sn)));
+            }
+        } catch (PathNotFoundException e) {
+            // node does not exist
+        } catch (RepositoryException e) {
+            log.warn("Exception while constructing query: " + e);
+            log.debug("Stacktrace: ", e);
+        }
+        // return a dummy query, which does not match any nodes
+        return new BooleanQuery();
     }
 
     public Object visit(SameNodeJoinConditionImpl node, Object data) {

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitQuery.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitQuery.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitQuery.java Tue Mar  4 00:57:31 2008
@@ -33,9 +33,10 @@
      * Executes this query and returns {@link QueryHits} or <code>null</code> if
      * this query should be executed using the regular Lucene API.
      * <p/>
-     * <b>Important note:</b> an implementation <b>must not</b> call {@link
-     * JackrabbitIndexSearcher#execute(Query, Sort)} with this query instance as
-     * a parameter, otherwise a stack overflow will occur.
+     * <b>Important note:</b> an implementation <b>must not</b> call
+     * {@link JackrabbitIndexSearcher#execute(org.apache.lucene.search.Query, Sort)}
+     * with this query instance as a parameter, otherwise a stack overflow will
+     * occur.
      *
      * @param searcher the jackrabbit index searcher.
      * @param session  the session that executes the query.

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHitsQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHitsQuery.java?rev=633394&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHitsQuery.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHitsQuery.java Tue Mar  4 00:57:31 2008
@@ -0,0 +1,259 @@
+/*
+ * 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.lucene;
+
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermDocs;
+import org.apache.jackrabbit.core.SessionImpl;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.TreeSet;
+
+/**
+ * <code>QueryHitsQuery</code> exposes a {@link QueryHits} implementation again
+ * as a Lucene Query.
+ */
+public class QueryHitsQuery extends Query implements JackrabbitQuery{
+
+    /**
+     * The underlying query hits.
+     */
+    private final QueryHits hits;
+
+    /**
+     * Creates a new query based on {@link QueryHits}.
+     *
+     * @param hits the query hits.
+     */
+    public QueryHitsQuery(QueryHits hits) {
+        this.hits = hits;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected Weight createWeight(Searcher searcher) throws IOException {
+        return new QueryHitsQueryWeight(searcher.getSimilarity());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString(String field) {
+        return "QueryHitsQuery";
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void extractTerms(Set terms) {
+        // no terms
+    }
+
+    //-----------------------< JackrabbitQuery >--------------------------------
+
+    /**
+     * {@inheritDoc}
+     */
+    public QueryHits execute(JackrabbitIndexSearcher searcher,
+                             SessionImpl session,
+                             Sort sort) throws IOException {
+        if (sort.getSort().length == 0) {
+            return hits;
+        } else {
+            return null;
+        }
+    }
+
+    //------------------------< QueryHitsQueryWeight >--------------------------
+
+    /**
+     * The Weight implementation for this query.
+     */
+    public class QueryHitsQueryWeight implements Weight {
+
+        /**
+         * The similarity.
+         */
+        private final Similarity similarity;
+
+        /**
+         * Creates a new weight with the given <code>similarity</code>.
+         *
+         * @param similarity the similarity.
+         */
+        public QueryHitsQueryWeight(Similarity similarity) {
+            this.similarity = similarity;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Query getQuery() {
+            return QueryHitsQuery.this;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public float getValue() {
+            return 1.0f;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public float sumOfSquaredWeights() throws IOException {
+            return 1.0f;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void normalize(float norm) {
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Scorer scorer(IndexReader reader) throws IOException {
+            return new QueryHitsQueryScorer(reader, similarity);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Explanation explain(IndexReader reader, int doc) throws IOException {
+            return new Explanation();
+        }
+    }
+
+    //-------------------< QueryHitsQueryScorer >-------------------------------
+
+    /**
+     * the scorer implementation for this query.
+     */
+    public class QueryHitsQueryScorer extends Scorer {
+
+        /**
+         * Iterator over <code>Integer</code> instances identifying the
+         * lucene documents. Document numbers are iterated in ascending order.
+         */
+        private final Iterator docs;
+
+        /**
+         * Maps <code>Integer</code> document numbers to <code>Float</code>
+         * scores.
+         */
+        private final Map scores = new HashMap();
+
+        /**
+         * The current document number.
+         */
+        private Integer currentDoc = null;
+
+        /**
+         * Creates a new scorer.
+         *
+         * @param reader     the index reader.
+         * @param similarity the similarity implementation.
+         * @throws IOException if an error occurs while reading from the index.
+         */
+        protected QueryHitsQueryScorer(IndexReader reader,
+                                       Similarity similarity)
+                throws IOException {
+            super(similarity);
+            ScoreNode node;
+            Set sortedDocs = new TreeSet();
+            try {
+                while ((node = hits.nextScoreNode()) != null) {
+                    String uuid = node.getNodeId().getUUID().toString();
+                    Term id = new Term(FieldNames.UUID, uuid);
+                    TermDocs tDocs = reader.termDocs(id);
+                    try {
+                        if (tDocs.next()) {
+                            Integer doc = new Integer(tDocs.doc());
+                            sortedDocs.add(doc);
+                            scores.put(doc, new Float(node.getScore()));
+                        }
+                    } finally {
+                        tDocs.close();
+                    }
+                }
+            } finally {
+                hits.close();
+            }
+            docs = sortedDocs.iterator();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean next() throws IOException {
+            if (docs.hasNext()) {
+                currentDoc = (Integer) docs.next();
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public int doc() {
+            return currentDoc.intValue();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public float score() throws IOException {
+            return ((Float) scores.get(currentDoc)).floatValue();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean skipTo(int target) throws IOException {
+            do {
+                if (!next()) {
+                    return false;
+                }
+            } while (target > doc());
+            return true;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Explanation explain(int doc) throws IOException {
+            return new Explanation();
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHitsQuery.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/ChildNodeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/ChildNodeTest.java?rev=633394&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/ChildNodeTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/ChildNodeTest.java Tue Mar  4 00:57:31 2008
@@ -0,0 +1,178 @@
+/*
+ * 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 org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.NodeTypeIterator;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.query.Query;
+import javax.jcr.query.InvalidQueryException;
+
+/**
+ * <code>ChildNodeTest</code>...
+ * TODO: add tests with default selector
+ */
+public class ChildNodeTest extends AbstractQOMTest {
+
+    public void testChildNode() throws RepositoryException {
+        Node n = testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.childNode("s", testRoot), null, null);
+        checkResult(q.execute(), new Node[]{n});
+
+        // using default selector
+        q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                qomFactory.childNode(testRoot), null, null);
+        checkResult(q.execute(), new Node[]{n});
+    }
+
+    public void testChildNodes() throws RepositoryException {
+        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
+        Node n2 = testRootNode.addNode(nodeName2, testNodeType);
+        Node n3 = testRootNode.addNode(nodeName3, testNodeType);
+        testRootNode.save();
+
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.childNode("s", testRoot), null, null);
+        checkResult(q.execute(), new Node[]{n1, n2, n3});
+
+        // using default selector
+        q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                qomFactory.childNode(testRoot), null, null);
+        checkResult(q.execute(), new Node[]{n1, n2, n3});
+    }
+
+    public void testPathDoesNotExist() throws RepositoryException {
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.childNode("s", testRoot + "/" + nodeName1),
+                null, null);
+        checkResult(q.execute(), new Node[]{});
+
+        // using default selector
+        q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                qomFactory.childNode(testRoot + "/" + nodeName1),
+                null, null);
+        checkResult(q.execute(), new Node[]{});
+    }
+
+    public void testChildNodesDoNotMatchSelector()
+            throws RepositoryException, NotExecutableException {
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+
+        NodeTypeManager ntMgr = superuser.getWorkspace().getNodeTypeManager();
+        NodeTypeIterator it = ntMgr.getPrimaryNodeTypes();
+        NodeType testNt = ntMgr.getNodeType(testNodeType);
+        while (it.hasNext()) {
+            NodeType nt = it.nextNodeType();
+            if (!testNt.isNodeType(nt.getName())) {
+                // perform test
+                Query q = qomFactory.createQuery(qomFactory.selector(nt.getName(), "s"),
+                        qomFactory.childNode("s", testRoot), null, null);
+                checkResult(q.execute(), new Node[]{});
+
+                // using default selector
+                q = qomFactory.createQuery(qomFactory.selector(nt.getName()),
+                        qomFactory.childNode(testRoot), null, null);
+                checkResult(q.execute(), new Node[]{});
+                return;
+            }
+        }
+        throw new NotExecutableException("No suitable node type found to " +
+                "perform test against '" + testNodeType + "' nodes");
+    }
+
+    public void testRelativePath() throws RepositoryException {
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                    qomFactory.childNode("s", testPath), null, null);
+            q.execute();
+            fail("ChildNode with relative path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+
+        // using default selector
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                    qomFactory.childNode(testPath), null, null);
+            q.execute();
+            fail("ChildNode with relative path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+    }
+
+    public void testSyntacticallyInvalidPath() throws RepositoryException {
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                    qomFactory.childNode("s", testRoot + "/" + nodeName1 + "["),
+                    null, null);
+            q.execute();
+            fail("ChildNode with syntactically invalid path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+
+        // using default selector
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                    qomFactory.childNode(testRoot + "/" + nodeName1 + "["),
+                    null, null);
+            q.execute();
+            fail("ChildNode with syntactically invalid path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+    }
+
+    public void testNotASelectorName() throws RepositoryException {
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                    qomFactory.childNode("x", testRoot), null, null);
+            q.execute();
+            fail("ChildNode with an invalid selector name must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+
+        // using default selector
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                    qomFactory.childNode("x", testRoot), null, null);
+            q.execute();
+            fail("ChildNode with an invalid selector name must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+    }
+
+    public void testDefaultSelector() throws RepositoryException {
+        Node n = testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.childNode(testRoot), null, null);
+        checkResult(q.execute(), new Node[]{n});
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/ChildNodeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/DescendantNodeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/DescendantNodeTest.java?rev=633394&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/DescendantNodeTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/DescendantNodeTest.java Tue Mar  4 00:57:31 2008
@@ -0,0 +1,177 @@
+/*
+ * 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 org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.NodeTypeIterator;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.query.Query;
+import javax.jcr.query.InvalidQueryException;
+
+/**
+ * <code>DescendantNodeTest</code>...
+ */
+public class DescendantNodeTest extends AbstractQOMTest {
+
+    public void testDescendantNode() throws RepositoryException {
+        Node n = testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.descendantNode("s", testRoot), null, null);
+        checkResult(q.execute(), new Node[]{n});
+
+        // using default selector
+        q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                qomFactory.descendantNode(testRoot), null, null);
+        checkResult(q.execute(), new Node[]{n});
+    }
+
+    public void testDescendantNodes() throws RepositoryException {
+        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
+        Node n2 = testRootNode.addNode(nodeName2, testNodeType);
+        Node n21 = n2.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.descendantNode("s", testRoot), null, null);
+        checkResult(q.execute(), new Node[]{n1, n2, n21});
+
+        // using default selector
+        q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                qomFactory.descendantNode(testRoot), null, null);
+        checkResult(q.execute(), new Node[]{n1, n2, n21});
+    }
+
+    public void testPathDoesNotExist() throws RepositoryException {
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.descendantNode("s", testRoot + "/" + nodeName1),
+                null, null);
+        checkResult(q.execute(), new Node[]{});
+
+        // using default selector
+        q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                qomFactory.descendantNode(testRoot + "/" + nodeName1),
+                null, null);
+        checkResult(q.execute(), new Node[]{});
+    }
+
+    public void testDescendantNodesDoNotMatchSelector()
+            throws RepositoryException, NotExecutableException {
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+
+        NodeTypeManager ntMgr = superuser.getWorkspace().getNodeTypeManager();
+        NodeTypeIterator it = ntMgr.getPrimaryNodeTypes();
+        NodeType testNt = ntMgr.getNodeType(testNodeType);
+        while (it.hasNext()) {
+            NodeType nt = it.nextNodeType();
+            if (!testNt.isNodeType(nt.getName())) {
+                // perform test
+                Query q = qomFactory.createQuery(qomFactory.selector(nt.getName(), "s"),
+                        qomFactory.descendantNode("s", testRoot), null, null);
+                checkResult(q.execute(), new Node[]{});
+
+                // using default selector
+                q = qomFactory.createQuery(qomFactory.selector(nt.getName()),
+                        qomFactory.descendantNode(testRoot), null, null);
+                checkResult(q.execute(), new Node[]{});
+                return;
+            }
+        }
+        throw new NotExecutableException("No suitable node type found to " +
+                "perform test against '" + testNodeType + "' nodes");
+    }
+
+    public void testRelativePath() throws RepositoryException {
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                    qomFactory.descendantNode("s", testPath), null, null);
+            q.execute();
+            fail("DescendantNode with relative path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+
+        // using default selector
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                    qomFactory.descendantNode(testPath), null, null);
+            q.execute();
+            fail("DescendantNode with relative path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+    }
+
+    public void testSyntacticallyInvalidPath() throws RepositoryException {
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                    qomFactory.descendantNode("s", testRoot + "/" + nodeName1 +
+                    "["), null, null);
+            q.execute();
+            fail("DescendantNode with syntactically invalid path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+
+        // using default selector
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                    qomFactory.descendantNode(testRoot + "/" + nodeName1 +
+                    "["), null, null);
+            q.execute();
+            fail("DescendantNode with syntactically invalid path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+    }
+
+    public void testNotASelectorName() throws RepositoryException {
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                    qomFactory.descendantNode("x", testRoot), null, null);
+            q.execute();
+            fail("DescendantNode with an invalid selector name must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+
+        // using default selector
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                    qomFactory.descendantNode("x", testRoot), null, null);
+            q.execute();
+            fail("DescendantNode with an invalid selector name must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+    }
+
+    public void testDefaultSelector() throws RepositoryException {
+        Node n = testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.descendantNode(testRoot), null, null);
+        checkResult(q.execute(), new Node[]{n});
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/DescendantNodeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/SameNodeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/SameNodeTest.java?rev=633394&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/SameNodeTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/SameNodeTest.java Tue Mar  4 00:57:31 2008
@@ -0,0 +1,161 @@
+/*
+ * 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 org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.NodeTypeIterator;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.query.Query;
+import javax.jcr.query.InvalidQueryException;
+
+/**
+ * <code>SameNodeTest</code>...
+ */
+public class SameNodeTest extends AbstractQOMTest {
+
+    public void testSameNode() throws RepositoryException {
+        Node n = testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.sameNode("s", testRoot + "/" + nodeName1), null, null);
+        checkResult(q.execute(), new Node[]{n});
+
+        // using default selector
+        q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                qomFactory.sameNode(testRoot + "/" + nodeName1), null, null);
+        checkResult(q.execute(), new Node[]{n});
+    }
+
+    public void testPathDoesNotExist() throws RepositoryException {
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.sameNode("s", testRoot + "/" + nodeName1),
+                null, null);
+        checkResult(q.execute(), new Node[]{});
+
+        // default selector
+        q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                qomFactory.sameNode(testRoot + "/" + nodeName1),
+                null, null);
+        checkResult(q.execute(), new Node[]{});
+    }
+
+    public void testChildNodesDoNotMatchSelector()
+            throws RepositoryException, NotExecutableException {
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+
+        NodeTypeManager ntMgr = superuser.getWorkspace().getNodeTypeManager();
+        NodeTypeIterator it = ntMgr.getPrimaryNodeTypes();
+        NodeType testNt = ntMgr.getNodeType(testNodeType);
+        while (it.hasNext()) {
+            NodeType nt = it.nextNodeType();
+            if (!testNt.isNodeType(nt.getName())) {
+                // perform test
+                Query q = qomFactory.createQuery(qomFactory.selector(nt.getName(), "s"),
+                        qomFactory.sameNode("s", testRoot + "/" + nodeName1), null, null);
+                checkResult(q.execute(), new Node[]{});
+
+                // using default selector
+                q = qomFactory.createQuery(qomFactory.selector(nt.getName()),
+                        qomFactory.sameNode(testRoot + "/" + nodeName1), null, null);
+                checkResult(q.execute(), new Node[]{});
+                return;
+            }
+        }
+        throw new NotExecutableException("No suitable node type found to " +
+                "perform test against '" + testNodeType + "' nodes");
+    }
+
+    public void testRelativePath() throws RepositoryException {
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                    qomFactory.sameNode("s", testPath), null, null);
+            q.execute();
+            fail("SameNode with relative path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+
+        // using default selector
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                    qomFactory.sameNode(testPath), null, null);
+            q.execute();
+            fail("SameNode with relative path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+    }
+
+    public void testSyntacticallyInvalidPath() throws RepositoryException {
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                    qomFactory.sameNode("s", testRoot + "/" + nodeName1 + "["),
+                    null, null);
+            q.execute();
+            fail("SameNode with syntactically invalid path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+
+        // using default selector
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                    qomFactory.sameNode(testRoot + "/" + nodeName1 + "["),
+                    null, null);
+            q.execute();
+            fail("SameNode with syntactically invalid path argument must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+    }
+
+    public void testNotASelectorName() throws RepositoryException {
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                    qomFactory.sameNode("x", testRoot), null, null);
+            q.execute();
+            fail("SameNode with an invalid selector name must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+
+        // using default selector
+        try {
+            Query q = qomFactory.createQuery(qomFactory.selector(testNodeType),
+                    qomFactory.sameNode("x", testRoot), null, null);
+            q.execute();
+            fail("SameNode with an invalid selector name must throw InvalidQueryException");
+        } catch (InvalidQueryException e) {
+            // expected
+        }
+    }
+
+    public void testDefaultSelector() throws RepositoryException {
+        Node n = testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+
+        Query q = qomFactory.createQuery(qomFactory.selector(testNodeType, "s"),
+                qomFactory.sameNode(testRoot + "/" + nodeName1), null, null);
+        checkResult(q.execute(), new Node[]{n});
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/SameNodeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 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=633394&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/TestAll.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/TestAll.java Tue Mar  4 00:57:31 2008
@@ -0,0 +1,40 @@
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * <code>TestAll</code> includes tests that are related to the
+ * <code>QueryObjectModel</code>.
+ */
+public class TestAll extends TestCase {
+
+    public static Test suite() {
+        TestSuite suite = new TestSuite("QOM tests");
+
+        suite.addTestSuite(ChildNodeTest.class);
+        suite.addTestSuite(DescendantNodeTest.class);
+        suite.addTestSuite(QueryObjectModelFactoryTest.class);
+        suite.addTestSuite(SameNodeTest.class);
+        suite.addTestSuite(SelectorQueryTest.class);
+
+        return suite;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/qom/TestAll.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/ChildNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/ChildNodeImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/ChildNodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/ChildNodeImpl.java Tue Mar  4 00:57:31 2008
@@ -22,6 +22,9 @@
 
 import org.apache.jackrabbit.spi.commons.query.jsr283.qom.ChildNode;
 
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.RepositoryException;
+
 /**
  * <code>ChildNodeImpl</code>...
  */
@@ -37,10 +40,15 @@
      */
     private final Path path;
 
-    ChildNodeImpl(NamePathResolver resolver, Name selectorName, Path path) {
+    ChildNodeImpl(NamePathResolver resolver, Name selectorName, Path path)
+            throws InvalidQueryException, RepositoryException {
         super(resolver);
         this.selectorName = selectorName;
         this.path = path;
+        if (!path.isAbsolute()) {
+            throw new InvalidQueryException(resolver.getJCRPath(path) +
+                    " is not an absolute path");
+        }
     }
 
     /**
@@ -59,6 +67,24 @@
      */
     public String getPath() {
         return getJCRPath(path);
+    }
+
+    /**
+     * Gets the name of the selector against which to apply this constraint.
+     *
+     * @return the selector name; non-null
+     */
+    public Name getSelectorQName() {
+        return selectorName;
+    }
+
+    /**
+     * Gets the absolute path.
+     *
+     * @return the path; non-null
+     */
+    public Path getQPath() {
+        return path;
     }
 
     //------------------------< AbstractQOMNode >-------------------------------

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/DescendantNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/DescendantNodeImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/DescendantNodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/DescendantNodeImpl.java Tue Mar  4 00:57:31 2008
@@ -22,6 +22,9 @@
 
 import org.apache.jackrabbit.spi.commons.query.jsr283.qom.DescendantNode;
 
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.NamespaceException;
+
 /**
  * <code>DescendantNodeImpl</code>...
  */
@@ -41,10 +44,15 @@
 
     DescendantNodeImpl(NamePathResolver resolver,
                        Name selectorName,
-                       Path path) {
+                       Path path)
+            throws InvalidQueryException, NamespaceException {
         super(resolver);
         this.selectorName = selectorName;
         this.path = path;
+        if (!path.isAbsolute()) {
+            throw new InvalidQueryException(resolver.getJCRPath(path) +
+                    " is not an absolute path");
+        }
     }
 
     /**
@@ -63,6 +71,24 @@
      */
     public String getPath() {
         return getJCRPath(path);
+    }
+
+    /**
+     * Gets the name of the selector against which to apply this constraint.
+     *
+     * @return the selector name; non-null
+     */
+    public Name getSelectorQName() {
+        return selectorName;
+    }
+
+    /**
+     * Gets the absolute path.
+     *
+     * @return the path; non-null
+     */
+    public Path getQPath() {
+        return path;
     }
 
     //------------------------< AbstractQOMNode >-------------------------------

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/DynamicOperandImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/DynamicOperandImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/DynamicOperandImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/DynamicOperandImpl.java Tue Mar  4 00:57:31 2008
@@ -19,6 +19,7 @@
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 
 import org.apache.jackrabbit.spi.commons.query.jsr283.qom.DynamicOperand;
+import org.apache.jackrabbit.spi.Name;
 
 /**
  * <code>DynamicOperandImpl</code>...
@@ -27,7 +28,31 @@
         extends AbstractQOMNode
         implements DynamicOperand {
 
-    public DynamicOperandImpl(NamePathResolver resolver) {
+    /**
+     * The name of a selector.
+     */
+    private final Name selectorName;
+
+    public DynamicOperandImpl(NamePathResolver resolver, Name selectorName) {
         super(resolver);
+        this.selectorName = selectorName;
+    }
+
+    /**
+     * Gets the name of the selector against which to evaluate this operand.
+     *
+     * @return the selector name; non-null
+     */
+    public String getSelectorName() {
+        return getJCRName(selectorName);
+    }
+
+    /**
+     * Gets the name of the selector against which to evaluate this operand.
+     *
+     * @return the selector name; non-null
+     */
+    public Name getSelectorQName() {
+        return selectorName;
     }
 }

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/EquiJoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/EquiJoinConditionImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/EquiJoinConditionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/EquiJoinConditionImpl.java Tue Mar  4 00:57:31 2008
@@ -96,6 +96,24 @@
         return getJCRName(property2Name);
     }
 
+    /**
+     * Gets the name of the first selector.
+     *
+     * @return the selector name; non-null
+     */
+    public Name getSelector1QName() {
+        return selector1Name;
+    }
+
+    /**
+     * Gets the name of the second selector.
+     *
+     * @return the selector name; non-null
+     */
+    public Name getSelector2QName() {
+        return selector2Name;
+    }
+
     //------------------------< AbstractQOMNode >-------------------------------
 
     /**

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/FullTextSearchScoreImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/FullTextSearchScoreImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/FullTextSearchScoreImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/FullTextSearchScoreImpl.java Tue Mar  4 00:57:31 2008
@@ -28,23 +28,8 @@
         extends DynamicOperandImpl
         implements FullTextSearchScore {
 
-    /**
-     * Name of the selector against which to evaluate this operand.
-     */
-    private final Name selectorName;
-
     FullTextSearchScoreImpl(NamePathResolver resolver, Name selectorName) {
-        super(resolver);
-        this.selectorName = selectorName;
-    }
-
-    /**
-     * Gets the name of the selector against which to evaluate this operand.
-     *
-     * @return the selector name; non-null
-     */
-    public String getSelectorName() {
-        return getJCRName(selectorName);
+        super(resolver, selectorName);
     }
 
     //------------------------< AbstractQOMNode >-------------------------------

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/JoinImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/JoinImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/JoinImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/JoinImpl.java Tue Mar  4 00:57:31 2008
@@ -98,6 +98,21 @@
         return joinCondition;
     }
 
+    //---------------------------< SourceImpl >---------------------------------
+
+    /**
+     * {@inheritDoc}
+     */
+    public SelectorImpl[] getSelectors() {
+        SelectorImpl[] leftSelectors = left.getSelectors();
+        SelectorImpl[] rightSelectors = right.getSelectors();
+        SelectorImpl[] both =
+                new SelectorImpl[leftSelectors.length + rightSelectors.length];
+        System.arraycopy(leftSelectors, 0, both, 0, leftSelectors.length);
+        System.arraycopy(rightSelectors, 0, both, leftSelectors.length, rightSelectors.length);
+        return both;
+    }
+
     //------------------------< AbstractQOMNode >-------------------------------
 
     /**

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/LengthImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/LengthImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/LengthImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/LengthImpl.java Tue Mar  4 00:57:31 2008
@@ -32,7 +32,7 @@
     private final PropertyValueImpl propertyValue;
 
     LengthImpl(NamePathResolver resolver, PropertyValueImpl propertyValue) {
-        super(resolver);
+        super(resolver, propertyValue.getSelectorQName());
         this.propertyValue = propertyValue;
     }
 

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/LowerCaseImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/LowerCaseImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/LowerCaseImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/LowerCaseImpl.java Tue Mar  4 00:57:31 2008
@@ -32,7 +32,7 @@
     private final DynamicOperandImpl operand;
 
     LowerCaseImpl(NamePathResolver resolver, DynamicOperandImpl operand) {
-        super(resolver);
+        super(resolver, operand.getSelectorQName());
         this.operand = operand;
     }
 

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/NodeLocalNameImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/NodeLocalNameImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/NodeLocalNameImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/NodeLocalNameImpl.java Tue Mar  4 00:57:31 2008
@@ -28,23 +28,8 @@
         extends DynamicOperandImpl
         implements NodeLocalName {
 
-    /**
-     * The name of the selector against which to evaluate this operand.
-     */
-    private final Name selectorName;
-
     NodeLocalNameImpl(NamePathResolver resolver, Name selectorName) {
-        super(resolver);
-        this.selectorName = selectorName;
-    }
-
-    /**
-     * Gets the name of the selector against which to evaluate this operand.
-     *
-     * @return the selector name; non-null
-     */
-    public String getSelectorName() {
-        return getJCRName(selectorName);
+        super(resolver, selectorName);
     }
 
     //------------------------< AbstractQOMNode >-------------------------------

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/NodeNameImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/NodeNameImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/NodeNameImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/NodeNameImpl.java Tue Mar  4 00:57:31 2008
@@ -26,23 +26,8 @@
  */
 public class NodeNameImpl extends DynamicOperandImpl implements NodeName {
 
-    /**
-     * The name of the selector against which to evaluate this operand.
-     */
-    private final Name selectorName;
-
     NodeNameImpl(NamePathResolver resolver, Name selectorName) {
-        super(resolver);
-        this.selectorName = selectorName;
-    }
-
-    /**
-     * Gets the name of the selector against which to evaluate this operand.
-     *
-     * @return the selector name; non-null
-     */
-    public String getSelectorName() {
-        return getJCRName(selectorName);
+        super(resolver, selectorName);
     }
 
     //------------------------< AbstractQOMNode >-------------------------------

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/PropertyValueImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/PropertyValueImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/PropertyValueImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/PropertyValueImpl.java Tue Mar  4 00:57:31 2008
@@ -29,11 +29,6 @@
         implements PropertyValue {
 
     /**
-     * The name of the selector against which to apply this constraint.
-     */
-    private final Name selectorName;
-
-    /**
      * The name of the property.
      */
     private final Name propertyName;
@@ -41,21 +36,11 @@
     PropertyValueImpl(NamePathResolver resolver,
                       Name selectorName,
                       Name propertyName) {
-        super(resolver);
-        this.selectorName = selectorName;
+        super(resolver, selectorName);
         this.propertyName = propertyName;
     }
 
     /**
-     * Gets the name of the selector against which to evaluate this operand.
-     *
-     * @return the selector name; non-null
-     */
-    public Name getSelectorQName() {
-        return selectorName;
-    }
-
-    /**
      * Gets the name of the property.
      *
      * @return the property name; non-null
@@ -65,15 +50,6 @@
     }
 
     //------------------------------< PropertyValue >---------------------------
-
-    /**
-     * Gets the name of the selector against which to evaluate this operand.
-     *
-     * @return the selector name; non-null
-     */
-    public String getSelectorName() {
-        return getJCRName(selectorName);
-    }
 
     /**
      * Gets the name of the property.

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/QueryObjectModelTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/QueryObjectModelTree.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/QueryObjectModelTree.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/QueryObjectModelTree.java Tue Mar  4 00:57:31 2008
@@ -17,8 +17,13 @@
 package org.apache.jackrabbit.spi.commons.query.qom;
 
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.Name;
 
 import javax.jcr.query.InvalidQueryException;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.Iterator;
 
 /**
  * <code>QueryObjectModelTree</code> implements the root node of an object
@@ -46,6 +51,11 @@
      */
     private final ColumnImpl[] columns;
 
+    /**
+     * All selectors available in this query object model. Key=Name
+     */
+    private final Map selectors = new HashMap();
+
     public QueryObjectModelTree(NamePathResolver resolver,
                                 SourceImpl source,
                                 ConstraintImpl constraint,
@@ -57,6 +67,14 @@
         this.constraint = constraint;
         this.orderings = orderings;
         this.columns = columns;
+        for (Iterator it = Arrays.asList(source.getSelectors()).iterator(); it.hasNext(); ) {
+            SelectorImpl selector = (SelectorImpl) it.next();
+            selectors.put(selector.getSelectorQName(), selector);
+        }
+        if (selectors.size() == 1) {
+            // there is only one selector, which is also a default selector
+            selectors.put(null, selectors.values().iterator().next());
+        }
         checkQuery();
     }
 
@@ -100,6 +118,17 @@
         return temp;
     }
 
+    /**
+     * Returns the selector with the given <code>name</code> or
+     * <code>null</code> if there is no selector with this name.
+     *
+     * @param name the name of a selector.
+     * @return the selector or <code>null</code> if there is no such selector.
+     */
+    public SelectorImpl getSelector(Name name) {
+        return (SelectorImpl) selectors.get(name);
+    }
+
     //-----------------------< AbstractQOMNode >--------------------------------
 
     /**
@@ -118,6 +147,81 @@
      * @throws InvalidQueryException if the QOM is invalid.
      */
     private void checkQuery() throws InvalidQueryException {
-        // TODO: validate query
+        // TODO: validate query completely.
+        // checks currently implemented:
+        // - check for selector names
+        try {
+            accept(new DefaultTraversingQOMTreeVisitor() {
+                public Object visit(ChildNodeImpl node, Object data) throws Exception {
+                    return checkSelector(node.getSelectorQName());
+                }
+
+                public Object visit(ColumnImpl node, Object data) throws Exception {
+                    return checkSelector(node.getSelectorQName());
+                }
+
+                public Object visit(DescendantNodeImpl node, Object data) throws Exception {
+                    return checkSelector(node.getSelectorQName());
+                }
+
+                public Object visit(EquiJoinConditionImpl node, Object data)
+                        throws Exception {
+                    checkSelector(node.getSelector1QName());
+                    return checkSelector(node.getSelector2QName());
+                }
+
+                public Object visit(FullTextSearchImpl node, Object data) throws Exception {
+                    return checkSelector(node.getSelectorQName());
+                }
+
+                public Object visit(FullTextSearchScoreImpl node, Object data)
+                        throws Exception {
+                    return checkSelector(node.getSelectorQName());
+                }
+
+                public Object visit(NodeLocalNameImpl node, Object data) throws Exception {
+                    return checkSelector(node.getSelectorQName());
+                }
+
+                public Object visit(NodeNameImpl node, Object data) throws Exception {
+                    return checkSelector(node.getSelectorQName());
+                }
+
+                public Object visit(PropertyExistenceImpl node, Object data)
+                        throws Exception {
+                    return checkSelector(node.getSelectorQName());
+                }
+
+                public Object visit(PropertyValueImpl node, Object data) throws Exception {
+                    return checkSelector(node.getSelectorQName());
+                }
+
+                public Object visit(SameNodeImpl node, Object data) throws Exception {
+                    return checkSelector(node.getSelectorQName());
+                }
+
+                public Object visit(SameNodeJoinConditionImpl node, Object data)
+                        throws Exception {
+                    checkSelector(node.getSelector1QName());
+                    return checkSelector(node.getSelector2QName());
+                }
+
+                private Object checkSelector(Name selectorName)
+                        throws InvalidQueryException {
+                    if (!selectors.containsKey(selectorName)) {
+                        String msg = "Unknown selector: ";
+                        if (selectorName != null) {
+                            msg += QueryObjectModelTree.this.getJCRName(selectorName);
+                        } else {
+                            msg += "<default>";
+                        }
+                        throw new InvalidQueryException(msg);
+                    }
+                    return null;
+                }
+            }, null);
+        } catch (Exception e) {
+            throw new InvalidQueryException(e.getMessage());
+        }
     }
 }

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SameNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SameNodeImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SameNodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SameNodeImpl.java Tue Mar  4 00:57:31 2008
@@ -22,6 +22,9 @@
 
 import org.apache.jackrabbit.spi.commons.query.jsr283.qom.SameNode;
 
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.RepositoryException;
+
 /**
  * <code>SameNodeImpl</code>...
  */
@@ -39,10 +42,14 @@
 
     SameNodeImpl(NamePathResolver resolver,
                  Name selectorName,
-                 Path path) {
+                 Path path) throws InvalidQueryException, RepositoryException {
         super(resolver);
         this.selectorName = selectorName;
         this.path = path;
+        if (!path.isAbsolute()) {
+            throw new InvalidQueryException(resolver.getJCRPath(path) +
+                    " is not an absolute path");
+        }
     }
 
 
@@ -62,6 +69,15 @@
      */
     public String getPath() {
         return getJCRPath(path);
+    }
+
+    /**
+     * Gets the name of the selector against which to apply this constraint.
+     *
+     * @return the selector name; non-null
+     */
+    public Name getSelectorQName() {
+        return selectorName;
     }
 
     //------------------------< AbstractQOMNode >-------------------------------

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SameNodeJoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SameNodeJoinConditionImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SameNodeJoinConditionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SameNodeJoinConditionImpl.java Tue Mar  4 00:57:31 2008
@@ -81,6 +81,24 @@
         return getJCRPath(selector2Path);
     }
 
+    /**
+     * Gets the name of the first selector.
+     *
+     * @return the selector name; non-null
+     */
+    public Name getSelector1QName() {
+        return selector1Name;
+    }
+
+    /**
+     * Gets the name of the second selector.
+     *
+     * @return the selector name; non-null
+     */
+    public Name getSelector2QName() {
+        return selector2Name;
+    }
+
     //------------------------< AbstractQOMNode >-------------------------------
 
     /**

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SelectorImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SelectorImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SelectorImpl.java Tue Mar  4 00:57:31 2008
@@ -65,6 +65,15 @@
         return selectorName;
     }
 
+    //---------------------------< SourceImpl >---------------------------------
+
+    /**
+     * {@inheritDoc}
+     */ 
+    public SelectorImpl[] getSelectors() {
+        return new SelectorImpl[]{this};
+    }
+
     //-----------------------------< Selector >---------------------------------
 
     /**

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SourceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SourceImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SourceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/SourceImpl.java Tue Mar  4 00:57:31 2008
@@ -28,4 +28,9 @@
     public SourceImpl(NamePathResolver resolver) {
         super(resolver);
     }
+
+    /**
+     * @return the selectors that are contained in this source.
+     */
+    public abstract SelectorImpl[] getSelectors();
 }

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/UpperCaseImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/UpperCaseImpl.java?rev=633394&r1=633393&r2=633394&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/UpperCaseImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/UpperCaseImpl.java Tue Mar  4 00:57:31 2008
@@ -32,7 +32,7 @@
     private final DynamicOperandImpl operand;
 
     UpperCaseImpl(NamePathResolver resolver, DynamicOperandImpl operand) {
-        super(resolver);
+        super(resolver, operand.getSelectorQName());
         this.operand = operand;
     }