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 2006/03/10 15:31:07 UTC

svn commit: r384804 - in /incubator/jackrabbit/trunk/jackrabbit/src: main/java/org/apache/jackrabbit/core/query/lucene/ main/java/org/apache/jackrabbit/core/query/xpath/ test/java/org/apache/jackrabbit/core/query/

Author: mreutegg
Date: Fri Mar 10 06:31:05 2006
New Revision: 384804

URL: http://svn.apache.org/viewcvs?rev=384804&view=rev
Log:
JCR-338: Query Builder and jcr:deref problem. Can't add predicate after jcr:deref

Added:
    incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/query/DerefTest.java   (with props)
Modified:
    incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/DerefQuery.java
    incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java
    incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/xpath/SimpleNode.java
    incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/xpath/XPathQueryBuilder.java
    incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/query/TestAll.java

Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/DerefQuery.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/DerefQuery.java?rev=384804&r1=384803&r2=384804&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/DerefQuery.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/DerefQuery.java Fri Mar 10 06:31:05 2006
@@ -275,9 +275,13 @@
                 }
 
                 // retrieve uuids of target nodes
+                String prefix = FieldNames.createNamedValue(refProperty, "");
                 for (int i = hits.nextSetBit(0); i >= 0; i = hits.nextSetBit(i + 1)) {
                     String[] values = reader.document(i).getValues(FieldNames.PROPERTIES);
-                    String prefix = FieldNames.createNamedValue(refProperty, "");
+                    if (values == null) {
+                        // no reference properties at all on this node
+                        continue;
+                    }
                     for (int v = 0; v < values.length; v++) {
                         if (values[v].startsWith(prefix)) {
                             uuids.add(values[v].substring(prefix.length()));

Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java?rev=384804&r1=384803&r2=384804&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java Fri Mar 10 06:31:05 2006
@@ -508,18 +508,37 @@
         if (context == null) {
             exceptions.add(new IllegalArgumentException("Unsupported query"));
         }
+
         try {
             String refProperty = node.getRefProperty().toJCRName(nsMappings);
             String nameTest = null;
             if (node.getNameTest() != null) {
                 nameTest = node.getNameTest().toJCRName(nsMappings);
             }
-            return new DerefQuery(context, refProperty, nameTest);
+
+            if (node.getIncludeDescendants()) {
+                Query refPropQuery = new MatchAllQuery(refProperty);
+                context = new DescendantSelfAxisQuery(context, refPropQuery, false);
+            }
+
+            context = new DerefQuery(context, refProperty, nameTest);
+
+            // attach predicates
+            Object[] predicates = node.acceptOperands(this, data);
+            if (predicates.length > 0) {
+                BooleanQuery andQuery = new BooleanQuery();
+                for (int i = 0; i < predicates.length; i++) {
+                    andQuery.add((Query) predicates[i], true, false);
+                }
+                andQuery.add(context, true, false);
+                context = andQuery;
+            }
+
         } catch (NoPrefixDeclaredException e) {
             // should never happen
             exceptions.add(e);
         }
-        // fallback in case of exception
+
         return context;
     }
 

Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/xpath/SimpleNode.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/xpath/SimpleNode.java?rev=384804&r1=384803&r2=384804&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/xpath/SimpleNode.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/xpath/SimpleNode.java Fri Mar 10 06:31:05 2006
@@ -86,7 +86,7 @@
     public Object childrenAccept(XPathVisitor visitor, Object data) {
         if (children != null) {
             for (int i = 0; i < children.length; ++i) {
-                children[i].jjtAccept(visitor, data);
+                data = children[i].jjtAccept(visitor, data);
             }
         }
         return data;

Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/xpath/XPathQueryBuilder.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/xpath/XPathQueryBuilder.java?rev=384804&r1=384803&r2=384804&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/xpath/XPathQueryBuilder.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/xpath/XPathQueryBuilder.java Fri Mar 10 06:31:05 2006
@@ -324,7 +324,7 @@
             case JJTSTEPEXPR:
                 if (isAttributeAxis(node)) {
                     if (queryNode.getType() == QueryNode.TYPE_RELATION
-                            || queryNode.getType() == QueryNode.TYPE_DEREF
+                            || (queryNode.getType() == QueryNode.TYPE_DEREF && ((DerefQueryNode) queryNode).getRefProperty() == null)
                             || queryNode.getType() == QueryNode.TYPE_ORDER
                             || queryNode.getType() == QueryNode.TYPE_PATH
                             || queryNode.getType() == QueryNode.TYPE_TEXTSEARCH) {
@@ -350,7 +350,7 @@
                     }
                 } else {
                     if (queryNode.getType() == QueryNode.TYPE_PATH) {
-                        queryNode = createLocationStep(node, (NAryQueryNode) queryNode);
+                        createLocationStep(node, (NAryQueryNode) queryNode);
                     } else if (queryNode.getType() == QueryNode.TYPE_TEXTSEARCH) {
                         // ignore
                     } else {
@@ -457,6 +457,14 @@
                     specs[specs.length - 1].setAscending(false);
                 }
                 break;
+            case JJTPREDICATELIST:
+                if (queryNode.getType() == QueryNode.TYPE_PATH) {
+                    // switch to last location
+                    QueryNode[] operands = ((PathQueryNode) queryNode).getOperands();
+                    queryNode = operands[operands.length - 1];
+                }
+                node.childrenAccept(this, queryNode);
+                break;
             default:
                 // per default traverse
                 node.childrenAccept(this, queryNode);
@@ -476,16 +484,16 @@
      */
     private LocationStepQueryNode createLocationStep(SimpleNode node, NAryQueryNode parent) {
         LocationStepQueryNode queryNode = null;
-        boolean descenant = false;
+        boolean descendant = false;
         Node p = node.jjtGetParent();
         for (int i = 0; i < p.jjtGetNumChildren(); i++) {
             SimpleNode c = (SimpleNode) p.jjtGetChild(i);
             if (c == node) {
-                queryNode = new LocationStepQueryNode(parent, null, descenant);
+                queryNode = new LocationStepQueryNode(parent, null, descendant);
                 parent.addOperand(queryNode);
                 break;
             }
-            descenant = (c.getId() == JJTSLASHSLASH
+            descendant = (c.getId() == JJTSLASHSLASH
                     || c.getId() == JJTROOTDESCENDANTS);
         }
 
@@ -781,6 +789,14 @@
             } else if (JCR_DEREF.toJCRName(resolver).equals(fName)) {
                 // check number of arguments
                 if (node.jjtGetNumChildren() == 3) {
+                    boolean descendant = false;
+                    if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
+                        LocationStepQueryNode loc = (LocationStepQueryNode) queryNode;
+                        // remember if descendant axis
+                        descendant = loc.getIncludeDescendants();
+                        queryNode = loc.getParent();
+                        ((NAryQueryNode) queryNode).removeOperand(loc);
+                    }
                     if (queryNode.getType() == QueryNode.TYPE_PATH) {
                         PathQueryNode pathNode = (PathQueryNode) queryNode;
                         DerefQueryNode derefNode = new DerefQueryNode(pathNode, null, false);
@@ -811,6 +827,20 @@
                         } else {
                             exceptions.add(new InvalidQueryException("Wrong second argument type for jcr:like"));
                         }
+
+                        // check if descendant
+                        if (!descendant) {
+                            Node p = node.jjtGetParent();
+                            for (int i = 0; i < p.jjtGetNumChildren(); i++) {
+                                SimpleNode c = (SimpleNode) p.jjtGetChild(i);
+                                if (c == node) {
+                                    break;
+                                }
+                                descendant = (c.getId() == JJTSLASHSLASH
+                                        || c.getId() == JJTROOTDESCENDANTS);
+                            }
+                        }
+                        derefNode.setIncludeDescendants(descendant);
                         pathNode.addPathStep(derefNode);
                     } else {
                         exceptions.add(new InvalidQueryException("Unsupported location for jcr:deref()"));

Added: incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/query/DerefTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/query/DerefTest.java?rev=384804&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/query/DerefTest.java (added)
+++ incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/query/DerefTest.java Fri Mar 10 06:31:05 2006
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+/**
+ * Tests the jcr:deref() function.
+ */
+public class DerefTest extends AbstractQueryTest {
+
+    /**
+     * Test nodes.
+     */
+    private Node andrew, bill, carl, daren, eric, frank;
+
+    /**
+     * Test nodes.
+     */
+    private Node sun, microsoft, ibm;
+
+    /**
+     * Sets up the following structure:
+     * <pre>
+     *   + people
+     *      + andrew (worksfor -> company/sun)
+     *         + bill (worksfor -> company/ibm)
+     *      + carl (worksfor -> company/microsoft)
+     *         + daren (worksfor -> company/ibm)
+     *            + eric (worksfor -> company/sun)
+     *      + frank (worksfor -> company/microsoft)
+     *   + company
+     *      + sun
+     *      + microsoft
+     *      + ibm
+     * </pre>
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        Node people = testRootNode.addNode("people");
+        Node company = testRootNode.addNode("company");
+
+        sun = company.addNode("sun");
+        sun.addMixin(mixReferenceable);
+        sun.setProperty("ceo", "McNealy");
+        microsoft = company.addNode("microsoft");
+        microsoft.addMixin(mixReferenceable);
+        microsoft.setProperty("ceo", "Ballmer");
+        ibm = company.addNode("ibm");
+        ibm.addMixin(mixReferenceable);
+        ibm.setProperty("ceo", "Palmisano");
+
+        andrew = people.addNode("andrew");
+        andrew.setProperty("worksfor", sun);
+        bill = andrew.addNode("bill");
+        bill.setProperty("worksfor", ibm);
+        carl = people.addNode("carl");
+        carl.setProperty("worksfor", microsoft);
+        daren = carl.addNode("daren");
+        daren.setProperty("worksfor", ibm);
+        eric = daren.addNode("eric");
+        eric.setProperty("worksfor", sun);
+        frank = people.addNode("frank");
+        frank.setProperty("worksfor", microsoft);
+
+        testRootNode.save();
+    }
+
+    /**
+     * Tests various XPath queries with jcr:deref() function.
+     */
+    public void testDeref() throws RepositoryException {
+        executeXPathQuery(testPath + "/people/jcr:deref(@worksfor, '*')",
+                new Node[]{});
+
+        executeXPathQuery(testPath + "/people/*/jcr:deref(@worksfor, '*')",
+                new Node[]{sun, microsoft});
+
+        executeXPathQuery(testPath + "/people/*/*/jcr:deref(@worksfor, '*')",
+                new Node[]{ibm});
+
+        executeXPathQuery(testPath + "/people//jcr:deref(@worksfor, '*')",
+                new Node[]{sun, ibm, microsoft});
+
+        executeXPathQuery(testPath + "/people/carl//jcr:deref(@worksfor, '*')",
+                new Node[]{sun, ibm});
+
+        executeXPathQuery(testPath + "/people//jcr:deref(@worksfor, 'sun')",
+                new Node[]{sun});
+
+        executeXPathQuery(testPath + "/people//jcr:deref(@worksfor, '*')[@ceo = 'McNealy']",
+                new Node[]{sun});
+
+        executeXPathQuery(testPath + "/people/*/jcr:deref(@worksfor, '*')[jcr:contains(.,'ballmer')]",
+                new Node[]{microsoft});
+    }
+}

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

Modified: incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/query/TestAll.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/query/TestAll.java?rev=384804&r1=384803&r2=384804&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/query/TestAll.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/query/TestAll.java Fri Mar 10 06:31:05 2006
@@ -43,6 +43,7 @@
         suite.addTestSuite(XPathAxisTest.class);
         suite.addTestSuite(SkipDeletedNodesTest.class);
         suite.addTestSuite(MixinTest.class);
+        suite.addTestSuite(DerefTest.class);
 
         // exclude long running tests per default
         //suite.addTestSuite(MassiveRangeTest.class);