dmitri 2003/01/11 17:52:57
Modified: jxpath/src/java/org/apache/commons/jxpath/ri/model
VariablePointer.java
jxpath/src/java/org/apache/commons/jxpath/ri/compiler
CoreOperation.java
jxpath/src/test/org/apache/commons/jxpath/ri/model
BeanModelTestCase.java
Log:
Fixed bug in comparison implementations
Revision Changes Path
1.11 +16 -6
jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/VariablePointer.java
Index: VariablePointer.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/VariablePointer.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- VariablePointer.java 11 Jan 2003 05:41:24 -0000 1.10
+++ VariablePointer.java 12 Jan 2003 01:52:56 -0000 1.11
@@ -68,6 +68,7 @@
import org.apache.commons.jxpath.Variables;
import org.apache.commons.jxpath.ri.QName;
import org.apache.commons.jxpath.ri.compiler.NodeTest;
+import org.apache.commons.jxpath.ri.model.beans.NullPointer;
import org.apache.commons.jxpath.util.ValueUtils;
/**
@@ -128,7 +129,7 @@
}
return value;
}
-
+
public void setValue(Object value) {
if (!actual) {
throw new JXPathException("Cannot set undefined variable: " + name);
@@ -152,8 +153,17 @@
Object value = null;
if (actual) {
value = getImmediateNode();
+ valuePointer =
+ NodePointer.newChildNodePointer(this, null, value);
+ }
+ else {
+ return new NullPointer(this, getName()) {
+ public Object getImmediateNode() {
+ throw new JXPathException(
+ "Undefined variable: " + name);
+ }
+ };
}
- valuePointer = NodePointer.newChildNodePointer(this, null, value);
}
return valuePointer;
}
1.9 +137 -84
jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/compiler/CoreOperation.java
Index: CoreOperation.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/compiler/CoreOperation.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- CoreOperation.java 11 Jan 2003 05:41:23 -0000 1.8
+++ CoreOperation.java 12 Jan 2003 01:52:57 -0000 1.9
@@ -61,10 +61,8 @@
*/
package org.apache.commons.jxpath.ri.compiler;
-import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.Set;
import org.apache.commons.jxpath.Pointer;
import org.apache.commons.jxpath.ri.EvalContext;
@@ -72,7 +70,7 @@
import org.apache.commons.jxpath.ri.axes.InitialContext;
import org.apache.commons.jxpath.ri.axes.SelfContext;
import org.apache.commons.jxpath.ri.axes.UnionContext;
-import org.apache.commons.jxpath.ri.model.NodePointer;
+import org.apache.commons.jxpath.util.ValueUtils;
/**
* A compile tree element representing one of the core operations like "+",
@@ -264,9 +262,9 @@
Expression left,
Expression right)
{
- double l = InfoSetUtil.doubleValue(left.computeValue(context));
- double r = InfoSetUtil.doubleValue(right.computeValue(context));
- return l < r ? Boolean.TRUE : Boolean.FALSE;
+ return test(context, left, right, LT_TEST)
+ ? Boolean.TRUE
+ : Boolean.FALSE;
}
/**
@@ -277,9 +275,9 @@
Expression left,
Expression right)
{
- double l = InfoSetUtil.doubleValue(left.computeValue(context));
- double r = InfoSetUtil.doubleValue(right.computeValue(context));
- return l > r ? Boolean.TRUE : Boolean.FALSE;
+ return test(context, left, right, GT_TEST)
+ ? Boolean.TRUE
+ : Boolean.FALSE;
}
/**
@@ -290,9 +288,9 @@
Expression left,
Expression right)
{
- double l = InfoSetUtil.doubleValue(left.computeValue(context));
- double r = InfoSetUtil.doubleValue(right.computeValue(context));
- return l <= r ? Boolean.TRUE : Boolean.FALSE;
+ return test(context, left, right, LTE_TEST)
+ ? Boolean.TRUE
+ : Boolean.FALSE;
}
/**
@@ -303,9 +301,9 @@
Expression left,
Expression right)
{
- double l = InfoSetUtil.doubleValue(left.computeValue(context));
- double r = InfoSetUtil.doubleValue(right.computeValue(context));
- return l >= r ? Boolean.TRUE : Boolean.FALSE;
+ return test(context, left, right, GTE_TEST)
+ ? Boolean.TRUE
+ : Boolean.FALSE;
}
/**
@@ -316,7 +314,9 @@
Expression left,
Expression right)
{
- return equal(context, left, right) ? Boolean.TRUE : Boolean.FALSE;
+ return test(context, left, right, EQUAL_TEST)
+ ? Boolean.TRUE
+ : Boolean.FALSE;
}
/**
@@ -327,16 +327,22 @@
Expression left,
Expression right)
{
- return equal(context, left, right) ? Boolean.FALSE : Boolean.TRUE;
- }
-
- /**
- * Compares two values
- */
- protected boolean equal(
- EvalContext context,
- Expression left,
- Expression right)
+ return test(context, left, right, EQUAL_TEST)
+ ? Boolean.FALSE
+ : Boolean.TRUE;
+ }
+
+ /**
+ * When the left and/or right side of a comparisons like =, <, >,
+ * <= and >= is a NodeSet (i.e. a collection), we are supposed to
+ * perform a search for a pair of matching nodes. That's exactly what this
+ * method does. It takes a "PairTest" static object that implements the
+ * comparison of two nodes.
+ */
+ protected boolean test(EvalContext context,
+ Expression left,
+ Expression right,
+ NodeComparator pairTest)
{
Object l = left.compute(context);
Object r = right.compute(context);
@@ -346,105 +352,151 @@
// (r == null ? "null" : r.getClass().getName()));
if (l instanceof InitialContext || l instanceof SelfContext) {
- l = ((EvalContext) l).getSingleNodePointer();
+ l = ((EvalContext) l).getSingleNodePointer().getValue();
}
if (r instanceof InitialContext || r instanceof SelfContext) {
- r = ((EvalContext) r).getSingleNodePointer();
+ r = ((EvalContext) r).getSingleNodePointer().getValue();
}
- if (l instanceof Collection) {
- l = ((Collection) l).iterator();
+ if (ValueUtils.isCollection(l)) {
+ l = ValueUtils.iterate(l);
}
- if (r instanceof Collection) {
- r = ((Collection) r).iterator();
+ if (ValueUtils.isCollection(r)) {
+ r = ValueUtils.iterate(r);
}
if ((l instanceof Iterator) && !(r instanceof Iterator)) {
- return contains((Iterator) l, r);
+ return contains((Iterator) l, r, pairTest);
}
else if (!(l instanceof Iterator) && (r instanceof Iterator)) {
- return contains((Iterator) r, l);
+ Iterator it = (Iterator) r;
+ while (it.hasNext()) {
+ Object element = it.next();
+ if (pairTest.isTrue(element, l)) {
+ return true;
+ }
+ }
+ return false;
}
else if (l instanceof Iterator && r instanceof Iterator) {
- return findMatch((Iterator) l, (Iterator) r);
+ return findMatch((Iterator) l, (Iterator) r, pairTest);
}
- return equal(l, r);
+ return pairTest.isTrue(l, r);
}
- protected boolean contains(Iterator it, Object value) {
+ protected boolean contains(
+ Iterator it,
+ Object value,
+ NodeComparator pairTest)
+ {
while (it.hasNext()) {
Object element = it.next();
- if (equal(element, value)) {
+ if (pairTest.isTrue(element, value)) {
return true;
}
}
return false;
}
- protected boolean findMatch(Iterator lit, Iterator rit) {
+ protected boolean findMatch(Iterator lit, Iterator rit, NodeComparator
pairTest) {
HashSet left = new HashSet();
while (lit.hasNext()) {
left.add(lit.next());
}
while (rit.hasNext()) {
- if (contains(left.iterator(), rit.next())) {
+ if (contains(left.iterator(), rit.next(), pairTest)) {
return true;
}
}
return false;
}
- protected boolean equal(Object l, Object r) {
- if (l instanceof Pointer && r instanceof Pointer) {
- if (l.equals(r)) {
- return true;
+ private static abstract class NodeComparator {
+ abstract boolean compare(Object left, Object right);
+
+ boolean isTrue(Object left, Object right){
+ if (left instanceof Pointer) {
+ left = ((Pointer) left).getValue();
}
- }
- if (l instanceof Pointer) {
- l = ((Pointer) l).getValue();
+ if (right instanceof Pointer) {
+ right = ((Pointer) right).getValue();
+ }
+ return compare(left, right);
}
+ }
+
+ private static final NodeComparator EQUAL_TEST = new NodeComparator() {
+ public boolean isTrue(Object l, Object r) {
+ if (l instanceof Pointer && r instanceof Pointer) {
+ if (l.equals(r)) {
+ return true;
+ }
+ }
- if (r instanceof Pointer) {
- r = ((Pointer) r).getValue();
- }
+ if (l instanceof Pointer) {
+ l = ((Pointer) l).getValue();
+ }
- if (l == r) {
- return true;
- }
+ if (r instanceof Pointer) {
+ r = ((Pointer) r).getValue();
+ }
-// System.err.println("COMPARING VALUES: " + l + " " + r);
- if (l instanceof Boolean || r instanceof Boolean) {
- return (InfoSetUtil.booleanValue(l) == InfoSetUtil.booleanValue(r));
- }
- else if (l instanceof Number || r instanceof Number) {
- return (InfoSetUtil.doubleValue(l) == InfoSetUtil.doubleValue(r));
- }
- else if (l instanceof String || r instanceof String) {
- return (
- InfoSetUtil.stringValue(l).equals(InfoSetUtil.stringValue(r)));
- }
- else if (l == null) {
- return r == null;
- }
- return l.equals(r);
- }
+ if (l == r) {
+ return true;
+ }
- /**
- * Extracts all values from a context
- */
- private Set valueSet(EvalContext context) {
- HashSet set = new HashSet();
- while (context.hasNext()) {
- context.next();
- NodePointer pointer = context.getCurrentNodePointer();
- set.add(pointer.getValue());
+ if (l instanceof Boolean || r instanceof Boolean) {
+ return (
+ InfoSetUtil.booleanValue(l) == InfoSetUtil.booleanValue(r));
+ }
+ else if (l instanceof Number || r instanceof Number) {
+ return (
+ InfoSetUtil.doubleValue(l) == InfoSetUtil.doubleValue(r));
+ }
+ else if (l instanceof String || r instanceof String) {
+ return (
+ InfoSetUtil.stringValue(l).equals(
+ InfoSetUtil.stringValue(r)));
+ }
+ else if (l == null) {
+ return r == null;
+ }
+ return l.equals(r);
}
- return set;
- }
+
+ boolean compare(Object left, Object right){
+ // Not used
+ return false;
+ }
+ };
+
+ private static final NodeComparator LT_TEST = new NodeComparator() {
+ public boolean compare(Object l, Object r) {
+ return InfoSetUtil.doubleValue(l) < InfoSetUtil.doubleValue(r);
+ }
+ };
+
+ private static final NodeComparator GT_TEST = new NodeComparator() {
+ public boolean compare(Object l, Object r) {
+ return InfoSetUtil.doubleValue(l) > InfoSetUtil.doubleValue(r);
+ }
+ };
+
+ private static final NodeComparator LTE_TEST = new NodeComparator() {
+ public boolean compare(Object l, Object r) {
+ return InfoSetUtil.doubleValue(l) <= InfoSetUtil.doubleValue(r);
+ }
+ };
+
+ private static final NodeComparator GTE_TEST = new NodeComparator() {
+ public boolean compare(Object l, Object r) {
+ return InfoSetUtil.doubleValue(l) >= InfoSetUtil.doubleValue(r);
+ }
+ };
/**
* Computes <code>"left and right"<code>
@@ -469,4 +521,5 @@
}
return Boolean.FALSE;
}
+
}
1.7 +71 -4
jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/model/BeanModelTestCase.java
Index: BeanModelTestCase.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/model/BeanModelTestCase.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- BeanModelTestCase.java 11 Jan 2003 05:41:27 -0000 1.6
+++ BeanModelTestCase.java 12 Jan 2003 01:52:57 -0000 1.7
@@ -727,6 +727,73 @@
list(new Integer(1), new Integer(2)));
}
+ public void testBooleanPredicateWithSearch(){
+ context.getVariables().declareVariable(
+ "numbers",
+ new String[] { "2", "3" });
+
+ context.setValue("/beans[1]/strings", new String[] { "1", "2" });
+ context.setValue("/beans[2]/strings", new String[] { "3", "4" });
+
+ // Find beans with any string == 2
+ assertXPathValueIterator(context,
+ "/beans[strings = '2']/name",
+ list("Name 1")
+ );
+
+ // Find beans with any string in the variable $numbers
+ assertXPathValueIterator(context,
+ "/beans[strings = $numbers]/name",
+ list("Name 1", "Name 2")
+ );
+
+ // Find beans without any strings == 2
+ assertXPathValueIterator(context,
+ "/beans[strings != '2']/name",
+ list("Name 2")
+ );
+
+ assertXPathValueIterator(context,
+ "/beans[strings > '1']/name",
+ list("Name 1", "Name 2")
+ );
+
+ assertXPathValueIterator(context,
+ "/beans[strings > $numbers]/name",
+ list("Name 2")
+ );
+
+ assertXPathValueIterator(context,
+ "/beans[strings >= '2']/name",
+ list("Name 1", "Name 2")
+ );
+
+ assertXPathValueIterator(context,
+ "/beans[strings >= '3']/name",
+ list("Name 2")
+ );
+
+ assertXPathValueIterator(context,
+ "/beans[strings < '4']/name",
+ list("Name 1", "Name 2")
+ );
+
+ assertXPathValueIterator(context,
+ "/beans[strings < 3]/name",
+ list("Name 1")
+ );
+
+ assertXPathValueIterator(context,
+ "/beans[strings <= '3']/name",
+ list("Name 1", "Name 2")
+ );
+
+ assertXPathValueIterator(context,
+ "/beans[strings <= '2']/name",
+ list("Name 1")
+ );
+ }
+
public void testDocumentOrder(){
assertDocumentOrder(context,
"boolean", "int", -1);
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>