You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2012/03/16 14:19:34 UTC

svn commit: r1301486 - in /jackrabbit/sandbox/jackrabbit-microkernel/src: main/java/org/apache/jackrabbit/query/qom/ main/java/org/apache/jackrabbit/query/qom/tree/ main/java/org/apache/jackrabbit/query/reader/ test/java/org/apache/jackrabbit/query/rea...

Author: thomasm
Date: Fri Mar 16 13:19:33 2012
New Revision: 1301486

URL: http://svn.apache.org/viewvc?rev=1301486&view=rev
Log:
Query implementation (WIP)

Added:
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/FilterTest.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/LikePatternTest.java
Modified:
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelFactoryImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/AndImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ChildNodeImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ChildNodeJoinConditionImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ComparisonImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ConstraintImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DescendantNodeImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DescendantNodeJoinConditionImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DynamicOperandImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/EquiJoinConditionImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchScoreImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/JoinConditionImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LengthImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LowerCaseImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeLocalNameImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeNameImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NotImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/OrImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyExistenceImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyValueImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SameNodeImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SameNodeJoinConditionImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SelectorImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/UpperCaseImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/Filter.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/IndexReader.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/NodeReader.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingCursor.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingReader.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/TraversingCursorTest.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelFactoryImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelFactoryImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelFactoryImpl.java Fri Mar 16 13:19:33 2012
@@ -92,7 +92,7 @@ public class QueryObjectModelFactoryImpl
 
     @Override
     public OrderingImpl ascending(DynamicOperand operand) throws RepositoryException {
-        return new OrderingImpl((DynamicOperandImpl)operand, Order.ASCENDING);
+        return new OrderingImpl((DynamicOperandImpl) operand, Order.ASCENDING);
     }
 
     @Override
@@ -119,7 +119,7 @@ public class QueryObjectModelFactoryImpl
     @Override
     public Comparison comparison(DynamicOperand operand1, String operator, StaticOperand operand2)
             throws RepositoryException {
-        return new ComparisonImpl((DynamicOperandImpl)operand1, Operator.getOperatorByName(operator), (StaticOperandImpl)operand2);
+        return new ComparisonImpl((DynamicOperandImpl) operand1, Operator.getOperatorByName(operator), (StaticOperandImpl) operand2);
     }
 
     @Override
@@ -154,7 +154,7 @@ public class QueryObjectModelFactoryImpl
 
     @Override
     public Ordering descending(DynamicOperand operand) throws RepositoryException {
-        return new OrderingImpl((DynamicOperandImpl)operand, Order.DESCENDING);
+        return new OrderingImpl((DynamicOperandImpl) operand, Order.DESCENDING);
     }
 
     @Override
@@ -181,7 +181,7 @@ public class QueryObjectModelFactoryImpl
 
     @Override
     public Length length(PropertyValue propertyValue) throws  RepositoryException {
-        return new LengthImpl((PropertyValueImpl)propertyValue);
+        return new LengthImpl((PropertyValueImpl) propertyValue);
     }
 
     @Override
@@ -191,7 +191,7 @@ public class QueryObjectModelFactoryImpl
 
     @Override
     public LowerCase lowerCase(DynamicOperand operand) throws  RepositoryException {
-        return new LowerCaseImpl((DynamicOperandImpl)operand);
+        return new LowerCaseImpl((DynamicOperandImpl) operand);
     }
 
     @Override
@@ -206,12 +206,12 @@ public class QueryObjectModelFactoryImpl
 
     @Override
     public Not not(Constraint constraint) throws  RepositoryException {
-        return new NotImpl((ConstraintImpl)constraint);
+        return new NotImpl((ConstraintImpl) constraint);
     }
 
     @Override
     public Or or(Constraint constraint1, Constraint constraint2) throws  RepositoryException {
-        return new OrImpl((ConstraintImpl)constraint1, (ConstraintImpl)constraint2);
+        return new OrImpl((ConstraintImpl) constraint1, (ConstraintImpl) constraint2);
     }
 
     @Override
@@ -245,7 +245,7 @@ public class QueryObjectModelFactoryImpl
 
     @Override
     public UpperCase upperCase(DynamicOperand operand) throws  RepositoryException {
-        return new UpperCaseImpl((DynamicOperandImpl)operand);
+        return new UpperCaseImpl((DynamicOperandImpl) operand);
     }
 
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelImpl.java Fri Mar 16 13:19:33 2012
@@ -20,6 +20,7 @@ import org.apache.jackrabbit.query.qom.t
 import org.apache.jackrabbit.query.qom.tree.ChildNodeImpl;
 import org.apache.jackrabbit.query.qom.tree.ChildNodeJoinConditionImpl;
 import org.apache.jackrabbit.query.qom.tree.ColumnImpl;
+import org.apache.jackrabbit.query.qom.tree.ComparisonImpl;
 import org.apache.jackrabbit.query.qom.tree.ConstraintImpl;
 import org.apache.jackrabbit.query.qom.tree.DescendantNodeImpl;
 import org.apache.jackrabbit.query.qom.tree.DescendantNodeJoinConditionImpl;
@@ -60,13 +61,14 @@ import java.util.Iterator;
  */
 public class QueryObjectModelImpl implements QueryObjectModel {
 
-    private MicroKernel mk;
     final SourceImpl source;
     final ConstraintImpl constraint;
-    private final OrderingImpl[] orderings;
-    private final ColumnImpl[] columns;
     final HashMap<String, Value> bindVariableMap = new HashMap<String, Value>();
     final ArrayList<SelectorImpl> selectors = new ArrayList<SelectorImpl>();
+
+    private MicroKernel mk;
+    private final OrderingImpl[] orderings;
+    private final ColumnImpl[] columns;
     private boolean explain;
     private long limit;
     private long offset;
@@ -213,8 +215,15 @@ public class QueryObjectModelImpl implem
                 return super.visit(node);
             }
 
+            @Override
+            public boolean visit(ComparisonImpl node) {
+                node.setQuery(query);
+                return super.visit(node);
+            }
+
         }.visit(this);
         source.init(this);
+        source.setQueryConstraint(constraint);
         for (ColumnImpl column : columns) {
             column.bindSelector(source);
         }
@@ -326,7 +335,7 @@ public class QueryObjectModelImpl implem
 
     public int compareRows(Value[] orderValues, Value[] orderValues2) {
         int comp = 0;
-        for (int i=0, size = orderings.length; i < size; i++) {
+        for (int i = 0, size = orderings.length; i < size; i++) {
             Value a = orderValues[i];
             Value b = orderValues2[i];
             // TODO order by: currently use string compare
@@ -446,7 +455,7 @@ public class QueryObjectModelImpl implem
             } else {
                 int size = orderings.length;
                 orderValues = new Value[size];
-                for (int i=0; i<size; i++) {
+                for (int i = 0; i < size; i++) {
                     orderValues[i] = orderings[i].getOperand().currentValue();
                 }
             }
@@ -457,7 +466,7 @@ public class QueryObjectModelImpl implem
     }
 
     public int getSelectorIndex(String selectorName) throws RepositoryException {
-        for (int i=0, size = selectors.size(); i<size; i++) {
+        for (int i = 0, size = selectors.size(); i < size; i++) {
             if (selectors.get(i).getSelectorName().equals(selectorName)) {
                 return i;
             }
@@ -466,7 +475,7 @@ public class QueryObjectModelImpl implem
     }
 
     public int getColumnIndex(String columnName) throws RepositoryException {
-        for (int i=0, size = columns.length; i<size; i++) {
+        for (int i = 0, size = columns.length; i < size; i++) {
             ColumnImpl c = columns[i];
             if (c.getColumnName().equals(columnName)) {
                 return i;

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/AndImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/AndImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/AndImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/AndImpl.java Fri Mar 16 13:19:33 2012
@@ -19,6 +19,7 @@
 package org.apache.jackrabbit.query.qom.tree;
 
 import javax.jcr.query.qom.And;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -56,5 +57,11 @@ public class AndImpl extends ConstraintI
         return protect(constraint1) + " AND " + protect(constraint2);
     }
 
+    @Override
+    public void apply(Filter f) {
+        constraint1.apply(f);
+        constraint2.apply(f);
+    }
+
 }
 

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ChildNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ChildNodeImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ChildNodeImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ChildNodeImpl.java Fri Mar 16 13:19:33 2012
@@ -20,6 +20,8 @@ package org.apache.jackrabbit.query.qom.
 
 import javax.jcr.query.qom.ChildNode;
 import org.apache.jackrabbit.mk.util.PathUtils;
+import org.apache.jackrabbit.query.reader.Filter;
+import org.apache.jackrabbit.query.reader.Filter.PathRestriction;
 
 
 /**
@@ -70,4 +72,11 @@ public class ChildNodeImpl extends Const
         return !PathUtils.denotesRoot(p) && PathUtils.getParentPath(p).equals(parentPath);
     }
 
+    @Override
+    public void apply(Filter f) {
+        if (selector == f.getSelector()) {
+            f.restrictPath(parentPath, PathRestriction.DIRECT_CHILDREN);
+        }
+    }
+
 }
\ No newline at end of file

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ChildNodeJoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ChildNodeJoinConditionImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ChildNodeJoinConditionImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ChildNodeJoinConditionImpl.java Fri Mar 16 13:19:33 2012
@@ -20,6 +20,8 @@ package org.apache.jackrabbit.query.qom.
 
 import javax.jcr.query.qom.ChildNodeJoinCondition;
 import org.apache.jackrabbit.mk.util.PathUtils;
+import org.apache.jackrabbit.query.reader.Filter;
+import org.apache.jackrabbit.query.reader.Filter.PathRestriction;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -77,4 +79,16 @@ public class ChildNodeJoinConditionImpl 
         return !PathUtils.denotesRoot(c) && PathUtils.getParentPath(c).equals(p);
     }
 
+    @Override
+    public void apply(Filter f) {
+        String p = parentSelector.currentPath();
+        String c = childSelector.currentPath();
+        if (f.getSelector() == parentSelector && c != null) {
+            f.restrictPath(PathUtils.getParentPath(c), PathRestriction.EXACT);
+        }
+        if (f.getSelector() == childSelector && p != null) {
+            f.restrictPath(p, PathRestriction.DIRECT_CHILDREN);
+        }
+    }
+
 }
\ No newline at end of file

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ComparisonImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ComparisonImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ComparisonImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ComparisonImpl.java Fri Mar 16 13:19:33 2012
@@ -18,11 +18,11 @@
  */
 package org.apache.jackrabbit.query.qom.tree;
 
-import org.h2.message.DbException;
-
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
+import javax.jcr.ValueFactory;
 import javax.jcr.query.qom.Comparison;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -113,12 +113,14 @@ public class ComparisonImpl extends Cons
         private char[] patternChars;
         private int[] patternTypes;
         private int patternLength;
+        private String lowerBounds, upperBound;
 
-        LikePattern(String pattern) {
+        public LikePattern(String pattern) {
             initPattern(pattern);
+            initBounds();
         }
 
-        boolean matches(String value) {
+        public boolean matches(String value) {
             return !invalidPattern && compareAt(value, 0, 0, value.length(), patternChars, patternTypes);
         }
 
@@ -128,7 +130,8 @@ public class ComparisonImpl extends Cons
 
         private boolean compareAt(String s, int pi, int si, int sLen, char[] pattern, int[] types) {
             for (; pi < patternLength; pi++) {
-                switch (types[pi]) {
+                int type = types[pi];
+                switch (type) {
                 case MATCH:
                     if (si >= sLen || !compare(pattern, s, pi, si++)) {
                         return false;
@@ -151,7 +154,7 @@ public class ComparisonImpl extends Cons
                     }
                     return false;
                 default:
-                    DbException.throwInternalError();
+                    throw new RuntimeException("Internal error: " + type);
                 }
             }
             return si == sLen;
@@ -207,6 +210,90 @@ public class ComparisonImpl extends Cons
             return patternString;
         }
 
+        /**
+         * Get the lower bound if any.
+         *
+         * @return return the lower bound, or null if unbound
+         */
+        public String getLowerBound() {
+            return lowerBounds;
+        }
+
+        /**
+         * Get the upper bound if any.
+         *
+         * @return return the upper bound, or null if unbound
+         */
+        public String getUpperBound() {
+            return upperBound;
+        }
+
+        private void initBounds() {
+            if (invalidPattern) {
+                return;
+            }
+            if (patternLength <= 0 || patternTypes[0] != MATCH) {
+                // can't use an index
+                return;
+            }
+            int maxMatch = 0;
+            StringBuilder buff = new StringBuilder();
+            while (maxMatch < patternLength && patternTypes[maxMatch] == MATCH) {
+                buff.append(patternChars[maxMatch++]);
+            }
+            String lower = buff.toString();
+            if (lower.length() == 0) {
+                return;
+            }
+            if (maxMatch == patternLength) {
+                lowerBounds = upperBound = lower;
+                return;
+            }
+            lowerBounds = lower;
+            char next = lower.charAt(lower.length() - 1);
+            // search the 'next' unicode character (or at least a character
+            // that is higher)
+            for (int i = 1; i < 2000; i++) {
+                String upper = lower.substring(0, lower.length() - 1) + (char) (next + i);
+                if (upper.compareTo(lower) > 0) {
+                    upperBound = upper;
+                    return;
+                }
+            }
+        }
+
+    }
+
+    @Override
+    public void apply(Filter f) {
+        Value v = operand2.currentValue();
+        if (v != null) {
+            if (operator == Operator.LIKE) {
+                String pattern;
+                try {
+                    pattern = v.getString();
+                } catch (RepositoryException e) {
+                    // TODO exception handling
+                    throw new RuntimeException(e);
+                }
+                LikePattern p = new LikePattern(pattern);
+                String lowerBound = p.getLowerBound();
+                String upperBound = p.getUpperBound();
+                if (lowerBound == null && upperBound == null) {
+                    // ignore
+                } else {
+                    ValueFactory vf = query.getValueFactory();
+                    if (lowerBound != null) {
+                        operand1.apply(f, Operator.GE, vf.createValue(lowerBound));
+                    }
+                    if (upperBound != null) {
+                        operand1.apply(f, Operator.LE, vf.createValue(upperBound));
+                    }
+                }
+            } else {
+                operand1.apply(f, operator, v);
+            }
+        }
     }
 
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ConstraintImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ConstraintImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ConstraintImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ConstraintImpl.java Fri Mar 16 13:19:33 2012
@@ -17,12 +17,25 @@
 package org.apache.jackrabbit.query.qom.tree;
 
 import javax.jcr.query.qom.Constraint;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
  */
 public abstract class ConstraintImpl extends QOMNode implements Constraint {
 
+    /**
+     * Evaluate the result using the currently set values.
+     *
+     * @return true if the constraint matches
+     */
     public abstract boolean evaluate();
 
+    /**
+     * Apply the condition to the filter, further restricting the filter if possible.
+     *
+     * @param f the filter
+     */
+    public abstract void apply(Filter f);
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DescendantNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DescendantNodeImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DescendantNodeImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DescendantNodeImpl.java Fri Mar 16 13:19:33 2012
@@ -20,6 +20,8 @@ package org.apache.jackrabbit.query.qom.
 
 import javax.jcr.query.qom.DescendantNode;
 import org.apache.jackrabbit.mk.util.PathUtils;
+import org.apache.jackrabbit.query.reader.Filter;
+import org.apache.jackrabbit.query.reader.Filter.PathRestriction;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -67,4 +69,11 @@ public class DescendantNodeImpl extends 
         }
     }
 
+    @Override
+    public void apply(Filter f) {
+        if (f.getSelector() == selector) {
+            f.restrictPath(ancestorPath, PathRestriction.ALL_CHILDREN);
+        }
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DescendantNodeJoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DescendantNodeJoinConditionImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DescendantNodeJoinConditionImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DescendantNodeJoinConditionImpl.java Fri Mar 16 13:19:33 2012
@@ -20,6 +20,8 @@ package org.apache.jackrabbit.query.qom.
 
 import javax.jcr.query.qom.DescendantNodeJoinCondition;
 import org.apache.jackrabbit.mk.util.PathUtils;
+import org.apache.jackrabbit.query.reader.Filter;
+import org.apache.jackrabbit.query.reader.Filter.PathRestriction;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -77,4 +79,16 @@ public class DescendantNodeJoinCondition
         return PathUtils.isAncestor(a, d);
     }
 
+    @Override
+    public void apply(Filter f) {
+        String d = descendantSelector.currentPath();
+        String a = ancestorSelector.currentPath();
+        if (d != null && f.getSelector() == ancestorSelector) {
+            f.restrictPath(PathUtils.getParentPath(d), PathRestriction.PARENT);
+        }
+        if (a != null && f.getSelector() == descendantSelector) {
+            f.restrictPath(a, PathRestriction.DIRECT_CHILDREN);
+        }
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DynamicOperandImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DynamicOperandImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DynamicOperandImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DynamicOperandImpl.java Fri Mar 16 13:19:33 2012
@@ -19,9 +19,12 @@ package org.apache.jackrabbit.query.qom.
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.query.qom.DynamicOperand;
+import org.apache.jackrabbit.query.reader.Filter;
 
 public abstract class DynamicOperandImpl extends QOMNode implements DynamicOperand {
 
     public abstract Value currentValue() throws RepositoryException;
 
+    public abstract void apply(Filter f, Operator operator, Value v);
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/EquiJoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/EquiJoinConditionImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/EquiJoinConditionImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/EquiJoinConditionImpl.java Fri Mar 16 13:19:33 2012
@@ -20,6 +20,7 @@ package org.apache.jackrabbit.query.qom.
 
 import javax.jcr.Value;
 import javax.jcr.query.qom.EquiJoinCondition;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -94,4 +95,16 @@ public class EquiJoinConditionImpl exten
         return v2 != null && v1.equals(v2);
     }
 
+    @Override
+    public void apply(Filter f) {
+        Value v1 = selector1.currentProperty(property1Name);
+        Value v2 = selector2.currentProperty(property2Name);
+        if (f.getSelector() == selector1 && v2 != null) {
+            f.restrictProperty(property1Name, Operator.EQ, v2);
+        }
+        if (f.getSelector() == selector2 && v1 != null) {
+            f.restrictProperty(property2Name, Operator.EQ, v1);
+        }
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchImpl.java Fri Mar 16 13:19:33 2012
@@ -19,6 +19,7 @@
 package org.apache.jackrabbit.query.qom.tree;
 
 import javax.jcr.query.qom.FullTextSearch;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -75,8 +76,13 @@ public class FullTextSearchImpl extends 
 
     @Override
     public boolean evaluate() {
-        // TODO Auto-generated method stub
+        // TODO support evaluating fulltext conditions
         return false;
     }
 
+    @Override
+    public void apply(Filter f) {
+        // TODO support fulltext index conditions
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchScoreImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchScoreImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchScoreImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchScoreImpl.java Fri Mar 16 13:19:33 2012
@@ -20,6 +20,7 @@ package org.apache.jackrabbit.query.qom.
 
 import javax.jcr.Value;
 import javax.jcr.query.qom.FullTextSearchScore;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -48,8 +49,13 @@ public class FullTextSearchScoreImpl ext
 
     @Override
     public Value currentValue() {
-        // TODO Auto-generated method stub
+        // TODO support evaluating fulltext conditions (score)
         return null;
     }
 
+    @Override
+    public void apply(Filter f, Operator operator, Value v) {
+        // TODO support fulltext index conditions (score)
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/JoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/JoinConditionImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/JoinConditionImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/JoinConditionImpl.java Fri Mar 16 13:19:33 2012
@@ -14,9 +14,12 @@
 package org.apache.jackrabbit.query.qom.tree;
 
 import javax.jcr.query.qom.JoinCondition;
+import org.apache.jackrabbit.query.reader.Filter;
 
 public abstract class JoinConditionImpl extends QOMNode implements JoinCondition {
 
     public abstract boolean evaluate();
 
+    public abstract void apply(Filter f);
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LengthImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LengthImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LengthImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LengthImpl.java Fri Mar 16 13:19:33 2012
@@ -21,6 +21,7 @@ package org.apache.jackrabbit.query.qom.
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.query.qom.Length;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -57,4 +58,10 @@ public class LengthImpl extends DynamicO
         return query.getValueFactory().createValue(value.length());
     }
 
+    @Override
+    public void apply(Filter f, Operator operator, Value v) {
+        // ignore
+        // TODO LENGTH(x) conditions: can use IS NOT NULL?
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LowerCaseImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LowerCaseImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LowerCaseImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LowerCaseImpl.java Fri Mar 16 13:19:33 2012
@@ -21,6 +21,7 @@ package org.apache.jackrabbit.query.qom.
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.query.qom.LowerCase;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -57,4 +58,10 @@ public class LowerCaseImpl extends Dynam
         return query.getValueFactory().createValue(value.toLowerCase());
     }
 
+    @Override
+    public void apply(Filter f, Operator operator, Value v) {
+        // ignore
+        // TODO UPPER(x) conditions: can use IS NOT NULL?
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeLocalNameImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeLocalNameImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeLocalNameImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeLocalNameImpl.java Fri Mar 16 13:19:33 2012
@@ -21,6 +21,7 @@ package org.apache.jackrabbit.query.qom.
 import javax.jcr.Value;
 import javax.jcr.query.qom.NodeLocalName;
 import org.apache.jackrabbit.mk.util.PathUtils;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -64,4 +65,9 @@ public class NodeLocalNameImpl extends D
         return query.getValueFactory().createValue(localName);
     }
 
+    @Override
+    public void apply(Filter f, Operator operator, Value v) {
+        // TODO support LOCALNAME index conditions
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeNameImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeNameImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeNameImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeNameImpl.java Fri Mar 16 13:19:33 2012
@@ -21,6 +21,7 @@ package org.apache.jackrabbit.query.qom.
 import javax.jcr.Value;
 import javax.jcr.query.qom.NodeName;
 import org.apache.jackrabbit.mk.util.PathUtils;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -61,4 +62,9 @@ public class NodeNameImpl extends Dynami
         return query.getValueFactory().createValue(name);
     }
 
+    @Override
+    public void apply(Filter f, Operator operator, Value v) {
+        // TODO support NAME(..) index conditions
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NotImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NotImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NotImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NotImpl.java Fri Mar 16 13:19:33 2012
@@ -19,6 +19,7 @@
 package org.apache.jackrabbit.query.qom.tree;
 
 import javax.jcr.query.qom.Not;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -50,4 +51,10 @@ public class NotImpl extends ConstraintI
         return "NOT " + protect(constraint);
     }
 
+    @Override
+    public void apply(Filter f) {
+        // ignore
+        // TODO convert NOT conditions
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/OrImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/OrImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/OrImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/OrImpl.java Fri Mar 16 13:19:33 2012
@@ -19,6 +19,7 @@
 package org.apache.jackrabbit.query.qom.tree;
 
 import javax.jcr.query.qom.Or;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -57,4 +58,10 @@ public class OrImpl extends ConstraintIm
         return protect(constraint1) + " OR " + protect(constraint2);
     }
 
+    @Override
+    public void apply(Filter f) {
+        // ignore
+        // TODO convert OR conditions to UNION
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyExistenceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyExistenceImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyExistenceImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyExistenceImpl.java Fri Mar 16 13:19:33 2012
@@ -20,6 +20,7 @@ package org.apache.jackrabbit.query.qom.
 
 import javax.jcr.Value;
 import javax.jcr.query.qom.PropertyExistence;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -68,4 +69,11 @@ public class PropertyExistenceImpl exten
         }
     }
 
+    @Override
+    public void apply(Filter f) {
+        if (f.getSelector() == selector) {
+            f.restrictProperty(propertyName, Operator.NE, (Value) null);
+        }
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyValueImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyValueImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyValueImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyValueImpl.java Fri Mar 16 13:19:33 2012
@@ -20,6 +20,7 @@ package org.apache.jackrabbit.query.qom.
 
 import javax.jcr.Value;
 import javax.jcr.query.qom.PropertyValue;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -67,4 +68,11 @@ public class PropertyValueImpl extends D
         }
     }
 
+    @Override
+    public void apply(Filter f, Operator operator, Value v) {
+        if (f.getSelector() == selector) {
+            f.restrictProperty(propertyName, operator, v);
+        }
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SameNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SameNodeImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SameNodeImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SameNodeImpl.java Fri Mar 16 13:19:33 2012
@@ -19,6 +19,8 @@
 package org.apache.jackrabbit.query.qom.tree;
 
 import javax.jcr.query.qom.SameNode;
+import org.apache.jackrabbit.query.reader.Filter;
+import org.apache.jackrabbit.query.reader.Filter.PathRestriction;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -65,4 +67,11 @@ public class SameNodeImpl extends Constr
         }
     }
 
+    @Override
+    public void apply(Filter f) {
+        if (f.getSelector() == selector) {
+            f.restrictPath(path, PathRestriction.EXACT);
+        }
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SameNodeJoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SameNodeJoinConditionImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SameNodeJoinConditionImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SameNodeJoinConditionImpl.java Fri Mar 16 13:19:33 2012
@@ -19,6 +19,8 @@
 package org.apache.jackrabbit.query.qom.tree;
 
 import javax.jcr.query.qom.SameNodeJoinCondition;
+import org.apache.jackrabbit.query.reader.Filter;
+import org.apache.jackrabbit.query.reader.Filter.PathRestriction;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -90,4 +92,16 @@ public class SameNodeJoinConditionImpl e
         return p1.equals(p2);
     }
 
+    @Override
+    public void apply(Filter f) {
+        String p1 = selector1.currentPath();
+        String p2 = selector2.currentPath();
+        if (f.getSelector() == selector1) {
+            f.restrictPath(p2, PathRestriction.EXACT);
+        }
+        if (f.getSelector() == selector2) {
+            f.restrictPath(p1, PathRestriction.EXACT);
+        }
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SelectorImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SelectorImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/SelectorImpl.java Fri Mar 16 13:19:33 2012
@@ -37,8 +37,9 @@ public class SelectorImpl extends Source
 
     private static final String JCR_PATH = "jcr:path";
 
-    private final String nodeTypeName, selectorName;
     protected NodeReader reader;
+
+    private final String nodeTypeName, selectorName;
     private Cursor cursor;
 
     public SelectorImpl(String nodeTypeName, String selectorName) {
@@ -74,31 +75,42 @@ public class SelectorImpl extends Source
 
     @Override
     public void execute(String revisionId) {
-        cursor = reader.query(getFilter(), revisionId);
+        cursor = reader.query(createFilter(), revisionId);
     }
 
     @Override
     public String getPlan() {
-        return  nodeTypeName + " AS " + getSelectorName() + " /* " + reader.getPlan(getFilter()) + " */";
+        return  nodeTypeName + " AS " + getSelectorName() + " /* " + reader.getPlan(createFilter()) + " */";
     }
 
-    private static Filter getFilter() {
-        return new Filter();
+    private Filter createFilter() {
+        Filter f = new Filter(this);
+        if (joinCondition != null) {
+            joinCondition.apply(f);
+        }
+        if (!outerJoin) {
+            // for outer joins, query constraints can't be applied to the
+            // filter, because that would alter the result
+            if (queryConstraint != null) {
+                queryConstraint.apply(f);
+            }
+        }
+        return f;
     }
 
     @Override
     public boolean next() {
-        return cursor.next();
+        return cursor == null ? false : cursor.next();
     }
 
     @Override
     public String currentPath() {
-        return cursor.currentPath();
+        return cursor == null ? null : cursor.currentPath();
     }
 
     @Override
     public NodeImpl currentNode() {
-        return cursor.currentNode();
+        return cursor == null ? null : cursor.currentNode();
     }
 
     public Value currentProperty(String propertyName) {
@@ -121,8 +133,7 @@ public class SelectorImpl extends Source
 
     @Override
     public void init(QueryObjectModelImpl qom) {
-        // TODO Auto-generated method stub
-
+        // nothing to do
     }
 
     @Override

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/UpperCaseImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/UpperCaseImpl.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/UpperCaseImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/UpperCaseImpl.java Fri Mar 16 13:19:33 2012
@@ -21,6 +21,7 @@ package org.apache.jackrabbit.query.qom.
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.query.qom.UpperCase;
+import org.apache.jackrabbit.query.reader.Filter;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -57,4 +58,10 @@ public class UpperCaseImpl extends Dynam
         return query.getValueFactory().createValue(value.toUpperCase());
     }
 
+    @Override
+    public void apply(Filter f, Operator operator, Value v) {
+        // ignore
+        // TODO UPPER(x) conditions: can use IS NOT NULL?
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/Filter.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/Filter.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/Filter.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/Filter.java Fri Mar 16 13:19:33 2012
@@ -18,17 +18,73 @@
  */
 package org.apache.jackrabbit.query.reader;
 
+import java.util.HashMap;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import org.apache.jackrabbit.mk.util.PathUtils;
+import org.apache.jackrabbit.query.qom.tree.Operator;
+import org.apache.jackrabbit.query.qom.tree.SelectorImpl;
+
 /**
  * An index filter / lookup condition.
  */
 public class Filter {
 
     /**
+     * The selector this filter applies to.
+     */
+    private final SelectorImpl selector;
+
+    /**
+     * Whether the filter is always false.
+     */
+    private boolean alwaysFalse;
+
+    /**
      *  The path, or "/" (the root node, meaning no filter) if not set.
      */
     private String path = "/";
 
     /**
+     * The path restriction type.
+     */
+    public static enum PathRestriction {
+
+        /**
+         * A parent of this node
+         */
+        PARENT("/.."),
+
+        /**
+         * This exact node only.
+         */
+        EXACT(""),
+
+        /**
+         * All direct child nodes.
+         */
+        DIRECT_CHILDREN("/*"),
+
+        /**
+         * All direct and indirect child nodes.
+         */
+        ALL_CHILDREN("//*");
+
+        private String name;
+
+        PathRestriction(String name) {
+            this.name = name;
+        }
+
+        public String toString() {
+            return name;
+        }
+
+    }
+
+    private PathRestriction pathRestriction = PathRestriction.ALL_CHILDREN;
+
+    /**
      *  The node type, or null if not set.
      */
     private String nodeType;
@@ -38,29 +94,59 @@ public class Filter {
      */
     private String valuePrefix;
 
-    /**
-     * The first value to read, or null to read from the beginning.
-     */
-    private String first;
+    private HashMap<String, PropertyValueCondition> propertyRanges = new HashMap<String, PropertyValueCondition>();
 
-    private boolean firstExcluding;
+    static class PropertyValueCondition {
 
-    /**
-     * The last value to read, or null to read until the end.
-     */
-    private String last;
+        /**
+         * The name of the property.
+         */
+        public String propertyName;
+
+        /**
+         * The first value to read, or null to read from the beginning.
+         */
+        public String first;
+
+        /**
+         * Whether only values bigger than the first value should be returned.
+         */
+        public boolean firstExcluding;
+
+        /**
+         * The last value to read, or null to read until the end.
+         */
+        public String last;
+
+        /**
+         * Whether only values smaller than the last value should be returned.
+         */
+        public boolean lastExcluding;
 
-    private boolean lastExcluding;
+    }
 
     /**
      * Only return distinct values.
      */
     private boolean distinct;
 
+    // TODO support "order by"
+
+    public Filter(SelectorImpl selector) {
+        this.selector = selector;
+    }
+
+    /**
+     * Get the path.
+     */
     public String getPath() {
         return path;
     }
 
+    public PathRestriction getPathRestriction() {
+        return pathRestriction;
+    }
+
     public void setPath(String path) {
         this.path = path;
     }
@@ -81,38 +167,6 @@ public class Filter {
         this.valuePrefix = valuePrefix;
     }
 
-    public String getFirst() {
-        return first;
-    }
-
-    public void setFirst(String first) {
-        this.first = first;
-    }
-
-    public boolean isFirstExcluding() {
-        return firstExcluding;
-    }
-
-    public void setFirstExcluding(boolean firstExcluding) {
-        this.firstExcluding = firstExcluding;
-    }
-
-    public String getLast() {
-        return last;
-    }
-
-    public void setLast(String last) {
-        this.last = last;
-    }
-
-    public boolean isLastExcluding() {
-        return lastExcluding;
-    }
-
-    public void setLastExcluding(boolean lastExcluding) {
-        this.lastExcluding = lastExcluding;
-    }
-
     public boolean isDistinct() {
         return distinct;
     }
@@ -121,4 +175,201 @@ public class Filter {
         this.distinct = distinct;
     }
 
+    public void setAlwaysFalse() {
+        propertyRanges.clear();
+        valuePrefix = "none";
+        nodeType = "none";
+        path = "none";
+        pathRestriction = PathRestriction.EXACT;
+        alwaysFalse = true;
+    }
+
+    public boolean isAlwaysFalse() {
+        return alwaysFalse;
+    }
+
+    public SelectorImpl getSelector() {
+        return selector;
+    }
+
+    public void restrictProperty(String propertyName, Operator op, Value value) {
+        // TODO support QValue / Value
+        try {
+            restrictProperty(propertyName, op, value == null ? null : value.getString());
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+            // TODO exception handling
+        }
+    }
+
+    public boolean testPath(String path) {
+        if (isAlwaysFalse()) {
+            return false;
+        }
+        switch (pathRestriction) {
+        case EXACT:
+            return path.matches(this.path);
+        case PARENT:
+            return PathUtils.isAncestor(path, this.path);
+        case DIRECT_CHILDREN:
+            return PathUtils.getParentPath(path).equals(this.path);
+        case ALL_CHILDREN:
+            return PathUtils.isAncestor(this.path, path);
+        default:
+            throw new RuntimeException("Unknown path restriction: " + pathRestriction);
+        }
+    }
+
+    public void restrictProperty(String propertyName, Operator op, String value) {
+        PropertyValueCondition x = propertyRanges.get(propertyName);
+        if (x == null) {
+            x = new PropertyValueCondition();
+            x.propertyName = propertyName;
+            propertyRanges.put(propertyName, x);
+        }
+        String oldFirst = x.first, oldLast = x.last;
+        switch (op) {
+        case EQ:
+            x.first = maxValue(oldFirst, value);
+            x.firstExcluding = false;
+            x.last = minValue(oldLast, value);
+            x.lastExcluding = false;
+            break;
+        case NE:
+            // not null
+            break;
+        case GT:
+            x.first = maxValue(oldFirst, value);
+            x.firstExcluding = true;
+            break;
+        case GE:
+            x.first = maxValue(oldFirst, value);
+            x.firstExcluding = x.first == oldFirst ? x.firstExcluding : false;
+            break;
+        case LT:
+            x.last = minValue(oldLast, value);
+            x.lastExcluding = true;
+            break;
+        case LE:
+            x.last = minValue(oldLast, value);
+            x.lastExcluding = x.last == oldLast ? x.lastExcluding : false;
+            break;
+        case LIKE:
+            throw new RuntimeException("LIKE is not supported");
+        }
+    }
+
+    static String maxValue(String a, String b) {
+        if (a == null) {
+            return b;
+        }
+        return a.compareTo(b) < 0 ? b : a;
+    }
+
+    static String minValue(String a, String b) {
+        if (a == null) {
+            return b;
+        }
+        return a.compareTo(b) < 0 ? a : b;
+    }
+
+    public void restrictPath(String addedPath, PathRestriction addedPathRestriction) {
+        // calculating the intersection of path restrictions
+        // this is ugly code, but I don't currently see a radically simpler method
+        switch (addedPathRestriction) {
+        case PARENT:
+            switch (pathRestriction) {
+            case PARENT:
+                // ignore as it's fast anyway
+                // (would need to loop to find a common ancestor)
+                break;
+            case EXACT:
+            case ALL_CHILDREN:
+            case DIRECT_CHILDREN:
+                if (!PathUtils.isAncestor(path, addedPath)) {
+                    setAlwaysFalse();
+                }
+                break;
+            }
+            pathRestriction = PathRestriction.PARENT;
+            path = addedPath;
+            break;
+        case EXACT:
+            switch (pathRestriction) {
+            case PARENT:
+                if (!PathUtils.isAncestor(addedPath, path)) {
+                    setAlwaysFalse();
+                }
+                break;
+            case EXACT:
+                if (!addedPath.equals(path)) {
+                    setAlwaysFalse();
+                }
+                break;
+            case ALL_CHILDREN:
+                if (!PathUtils.isAncestor(path, addedPath)) {
+                    setAlwaysFalse();
+                }
+                break;
+            case DIRECT_CHILDREN:
+                if (!PathUtils.getParentPath(addedPath).equals(path)) {
+                    setAlwaysFalse();
+                }
+                break;
+            }
+            path = addedPath;
+            pathRestriction = PathRestriction.EXACT;
+            break;
+        case ALL_CHILDREN:
+            switch (pathRestriction) {
+            case PARENT:
+            case EXACT:
+                if (!PathUtils.isAncestor(addedPath, path)) {
+                    setAlwaysFalse();
+                }
+                break;
+            case ALL_CHILDREN:
+                if (PathUtils.isAncestor(path, addedPath)) {
+                    path = addedPath;
+                } else if (!path.equals(addedPath) && !PathUtils.isAncestor(addedPath, path)) {
+                    setAlwaysFalse();
+                }
+                break;
+            case DIRECT_CHILDREN:
+                if (!path.equals(addedPath) && !PathUtils.isAncestor(addedPath, path)) {
+                    setAlwaysFalse();
+                }
+                break;
+            }
+            break;
+        case DIRECT_CHILDREN:
+            switch (pathRestriction) {
+            case PARENT:
+                if (!PathUtils.isAncestor(addedPath, path)) {
+                    setAlwaysFalse();
+                }
+                break;
+            case EXACT:
+                if (!PathUtils.getParentPath(path).equals(addedPath)) {
+                    setAlwaysFalse();
+                }
+                break;
+            case ALL_CHILDREN:
+                if (!path.equals(addedPath) && !PathUtils.isAncestor(path, addedPath)) {
+                    setAlwaysFalse();
+                } else {
+                    path = addedPath;
+                    pathRestriction = PathRestriction.DIRECT_CHILDREN;
+                }
+                break;
+            case DIRECT_CHILDREN:
+                if (!path.equals(addedPath)) {
+                    setAlwaysFalse();
+                }
+                break;
+            }
+            break;
+        }
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/IndexReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/IndexReader.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/IndexReader.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/IndexReader.java Fri Mar 16 13:19:33 2012
@@ -18,6 +18,9 @@
  */
 package org.apache.jackrabbit.query.reader;
 
+/**
+ * A reader for indexed data.
+ */
 public class IndexReader {
 
     /**

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/NodeReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/NodeReader.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/NodeReader.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/NodeReader.java Fri Mar 16 13:19:33 2012
@@ -19,7 +19,8 @@
 package org.apache.jackrabbit.query.reader;
 
 /**
- * A node reader. The reader should use the data in the filter if possible to speed up reading.
+ * A node reader. The reader should use the data in the filter if possible to
+ * speed up reading.
  */
 public interface NodeReader {
 

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingCursor.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingCursor.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingCursor.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingCursor.java Fri Mar 16 13:19:33 2012
@@ -16,7 +16,6 @@ package org.apache.jackrabbit.query.read
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.simple.NodeImpl;
 import org.apache.jackrabbit.mk.util.PathUtils;
-
 import java.util.ArrayList;
 
 /**
@@ -104,7 +103,7 @@ public class TraversingCursor implements
                 currentPath = PathUtils.concat(currentPath, childName);
                 loadChildren(currentPath, 0);
                 return true;
-           }
+            }
         }
         nodes = null;
         currentPath = null;

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingReader.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingReader.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingReader.java Fri Mar 16 13:19:33 2012
@@ -55,7 +55,12 @@ public class TraversingReader implements
 
     @Override
     public String getPlan(Filter filter) {
-        return "traverse \"" + filter.getPath() + '"';
+        String p = filter.getPath();
+        String r = filter.getPathRestriction().toString();
+        if (PathUtils.denotesRoot(p)) {
+            p = "";
+        }
+        return "traverse \"" + p + r + '"';
     }
 
 }

Added: jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/FilterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/FilterTest.java?rev=1301486&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/FilterTest.java (added)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/FilterTest.java Fri Mar 16 13:19:33 2012
@@ -0,0 +1,210 @@
+/*
+ * 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.query.reader;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import java.util.ArrayList;
+import java.util.Random;
+import org.apache.jackrabbit.query.reader.Filter.PathRestriction;
+import org.junit.Test;
+
+/**
+ * Tests the Filter class.
+ */
+public class FilterTest {
+
+    @Test
+    public void pathRestrictionsRandomized() throws Exception {
+        ArrayList<String> paths = new ArrayList<String>();
+        // create paths /a, /b, /c, /a/a, /a/b, ... /c/c/c
+        paths.add("/");
+        for (int i = 'a'; i <= 'c'; i++) {
+            String p1 = "/" + (char) i;
+            paths.add(p1);
+            for (int j = 'a'; j <= 'c'; j++) {
+                String p2 = "/" + (char) j;
+                paths.add(p1 + p2);
+                for (int k = 'a'; k <= 'c'; k++) {
+                    String p3 = "/" + (char) k;
+                    paths.add(p1 + p2 + p3);
+                }
+            }
+        }
+        Random r = new Random(1);
+        for (int i = 0; i < 10000; i++) {
+            String p1 = paths.get(r.nextInt(paths.size()));
+            String p2 = paths.get(r.nextInt(paths.size()));
+            PathRestriction r1 = PathRestriction.values()[r.nextInt(PathRestriction.values().length)];
+            PathRestriction r2 = PathRestriction.values()[r.nextInt(PathRestriction.values().length)];
+            Filter f1 = new Filter(null);
+            f1.restrictPath(p1, r1);
+            Filter f2 = new Filter(null);
+            f2.restrictPath(p2, r2);
+            Filter fc = new Filter(null);
+            fc.restrictPath(p1, r1);
+            fc.restrictPath(p2, r2);
+            int tooMany = 0;
+            for (String p : paths) {
+                boolean expected = f1.testPath(p) && f2.testPath(p);
+                boolean got = fc.testPath(p);
+                if (expected == got) {
+                    // good
+                } else if (expected && !got) {
+                    fc = new Filter(null);
+                    fc.restrictPath(p1, r1);
+                    fc.restrictPath(p2, r2);
+                    fail("not matched: " + p1 + "/" + r1.name() + " && " + p2 + "/" + r2.name());
+                } else {
+                    // not great, but not a problem
+                    tooMany++;
+                }
+            }
+            if (tooMany > 3) {
+                fail("too many matches: " + p1 + "/" + r1.name() + " && " + p2 + "/" + r2.name() + " superfluous: " + tooMany);
+            }
+        }
+    }
+
+    @Test
+    public void pathRestrictions() throws Exception {
+        Filter f = new Filter(null);
+        assertEquals("/", f.getPath());
+        assertEquals(PathRestriction.ALL_CHILDREN, f.getPathRestriction());
+
+        f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+        f.restrictPath("/test2", PathRestriction.ALL_CHILDREN);
+        assertTrue(f.isAlwaysFalse());
+
+        f = new Filter(null);
+        f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+        assertEquals("/test", f.getPath());
+        assertEquals(PathRestriction.ALL_CHILDREN, f.getPathRestriction());
+        f.restrictPath("/test/x", PathRestriction.DIRECT_CHILDREN);
+        assertEquals("/test/x", f.getPath());
+        assertEquals(PathRestriction.DIRECT_CHILDREN, f.getPathRestriction());
+        f.restrictPath("/test/x/y", PathRestriction.PARENT);
+        assertEquals("/test/x/y", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+
+        f = new Filter(null);
+        f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+        f.restrictPath("/test/x/y", PathRestriction.PARENT);
+        assertEquals("/test/x/y", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+        f.restrictPath("/test/y", PathRestriction.DIRECT_CHILDREN);
+        assertTrue(f.isAlwaysFalse());
+
+        f = new Filter(null);
+        f.restrictPath("/test/x/y", PathRestriction.PARENT);
+        f.restrictPath("/test/x", PathRestriction.EXACT);
+        assertEquals("/test/x", f.getPath());
+        assertEquals(PathRestriction.EXACT, f.getPathRestriction());
+        f.restrictPath("/test/y", PathRestriction.EXACT);
+        assertTrue(f.isAlwaysFalse());
+
+        f = new Filter(null);
+        f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+        f.restrictPath("/test", PathRestriction.PARENT);
+        assertTrue(f.isAlwaysFalse());
+
+        f = new Filter(null);
+        f.restrictPath("/test/x", PathRestriction.PARENT);
+        f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+        assertEquals("/test/x", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+        f.restrictPath("/test/x", PathRestriction.ALL_CHILDREN);
+        assertTrue(f.isAlwaysFalse());
+
+        f = new Filter(null);
+        f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+        f.restrictPath("/test", PathRestriction.EXACT);
+        assertTrue(f.isAlwaysFalse());
+
+        f = new Filter(null);
+        f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+        f.restrictPath("/test/x", PathRestriction.EXACT);
+        assertEquals("/test/x", f.getPath());
+        assertEquals(PathRestriction.EXACT, f.getPathRestriction());
+
+        f = new Filter(null);
+        f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+        f.restrictPath("/test/x/y", PathRestriction.EXACT);
+        assertTrue(f.isAlwaysFalse());
+
+        f = new Filter(null);
+        f.restrictPath("/test/x", PathRestriction.PARENT);
+        f.restrictPath("/", PathRestriction.ALL_CHILDREN);
+        assertEquals("/test/x", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+        f.restrictPath("/test/y", PathRestriction.EXACT);
+        assertTrue(f.isAlwaysFalse());
+
+        f = new Filter(null);
+        f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+        assertEquals("/test", f.getPath());
+        assertEquals(PathRestriction.DIRECT_CHILDREN, f.getPathRestriction());
+        f.restrictPath("/", PathRestriction.ALL_CHILDREN);
+        assertEquals("/test", f.getPath());
+        assertEquals(PathRestriction.DIRECT_CHILDREN, f.getPathRestriction());
+        f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+        assertEquals("/test", f.getPath());
+        assertEquals(PathRestriction.DIRECT_CHILDREN, f.getPathRestriction());
+        f.restrictPath("/test/x/y", PathRestriction.PARENT);
+        assertEquals("/test/x/y", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+        f.restrictPath("/test2", PathRestriction.ALL_CHILDREN);
+        assertTrue(f.isAlwaysFalse());
+
+        f = new Filter(null);
+        f.restrictPath("/test/x", PathRestriction.EXACT);
+        assertEquals("/test/x", f.getPath());
+        assertEquals(PathRestriction.EXACT, f.getPathRestriction());
+        f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+        f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+        f.restrictPath("/test/x/y", PathRestriction.PARENT);
+        f.restrictPath("/test/y", PathRestriction.DIRECT_CHILDREN);
+        assertTrue(f.isAlwaysFalse());
+
+        f = new Filter(null);
+        f.restrictPath("/test/x/y", PathRestriction.PARENT);
+        assertEquals("/test/x/y", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+        f.restrictPath("/test/x", PathRestriction.PARENT);
+        assertEquals("/test/x", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+        f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+        assertEquals("/test/x", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+        f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+        assertEquals("/test/x", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+        f.restrictPath("/test/x", PathRestriction.PARENT);
+        assertEquals("/test/x", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+        f.restrictPath("/test", PathRestriction.PARENT);
+        assertEquals("/test", f.getPath());
+        assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+        f.restrictPath("/test2", PathRestriction.EXACT);
+        assertTrue(f.isAlwaysFalse());
+
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/LikePatternTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/LikePatternTest.java?rev=1301486&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/LikePatternTest.java (added)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/LikePatternTest.java Fri Mar 16 13:19:33 2012
@@ -0,0 +1,49 @@
+/*
+ * 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.query.reader;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import org.apache.jackrabbit.query.qom.tree.ComparisonImpl;
+import org.junit.Test;
+
+public class LikePatternTest {
+
+    @Test
+    public void pattern() {
+        pattern("%_", "X", "", null, null);
+        pattern("A%", "A", "X", "A", "B");
+        pattern("A%%", "A", "X", "A", "B");
+        pattern("%\\_%", "A_A", "AAA", null, null);
+    }
+
+    private void pattern(String pattern, String match, String noMatch, String lower, String upper) {
+        ComparisonImpl.LikePattern p = new ComparisonImpl.LikePattern(pattern);
+        if (match != null) {
+            assertTrue(p.matches(match));
+        }
+        if (noMatch != null) {
+            assertFalse(p.matches(noMatch));
+        }
+        assertEquals(lower, p.getLowerBound());
+        assertEquals(upper, p.getUpperBound());
+    }
+
+}

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/TraversingCursorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/TraversingCursorTest.java?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/TraversingCursorTest.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/reader/TraversingCursorTest.java Fri Mar 16 13:19:33 2012
@@ -4,14 +4,14 @@
  * 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
+ * "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
+ * "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.
@@ -62,7 +62,7 @@ public class TraversingCursorTest {
     private void traverse(TraversingReader r) {
         head = mk.commit("/", "+ \"parents\": { \"p0\": {\"id\": \"0\"}, \"p1\": {\"id\": \"1\"}, \"p2\": {\"id\": \"2\"}}", head, "");
         head = mk.commit("/", "+ \"children\": { \"c1\": {\"p\": \"1\"}, \"c2\": {\"p\": \"1\"}, \"c3\": {\"p\": \"2\"}, \"c4\": {\"p\": \"3\"}}", head, "");
-        Filter f = new Filter();
+        Filter f = new Filter(null);
         Cursor c;
         f.setPath("/");
         c = r.query(f, head);

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt?rev=1301486&r1=1301485&r2=1301486&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt Fri Mar 16 13:19:33 2012
@@ -8,6 +8,12 @@
 
 + "test": { "jcr:resource": {}, "resource": { "x" : {}}}
 
+explain select * from [nt:base] as b where ischildnode(b, '/test')
+nt:base AS b /* traverse "/test/*" */
+
+explain select * from [nt:base] as b where isdescendantnode(b, '/test')
+nt:base AS b /* traverse "/test//*" */
+
 select * from [nt:base] as b where ischildnode(b, '/test')
 /test/jcr:resource
 /test/resource
@@ -85,7 +91,7 @@ select * from [nt:base] as p inner join 
 /parents/p2, /children/c3
 
 explain select * from [nt:base] as p inner join [nt:base] as c on p.id = c.p
-nt:base AS p /* traverse "/" */ INNER JOIN nt:base AS c /* traverse "/" */
+nt:base AS p /* traverse "//*" */ INNER JOIN nt:base AS c /* traverse "//*" */
 
 - "parents"
 - "children"