1 package net.sf.saxon.expr; 2 import net.sf.saxon.om.Item; 3 import net.sf.saxon.om.SequenceIterator; 4 import net.sf.saxon.trans.XPathException; 5 import net.sf.saxon.type.ItemType; 6 import net.sf.saxon.type.Type; 7 import net.sf.saxon.value.BooleanValue; 8 import net.sf.saxon.value.NumericValue; 9 import net.sf.saxon.value.Value; 10 import net.sf.saxon.value.AtomicValue; 11 12 13 19 20 public class MinimaxComparison extends BinaryExpression { 21 22 public MinimaxComparison(Expression p0, int operator, Expression p1) { 23 super(p0, operator, p1); 24 } 25 26 29 30 public int computeCardinality() { 31 return StaticProperty.EXACTLY_ONE; 32 } 33 34 37 38 public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException { 39 operand0 = operand0.optimize(opt, env, contextItemType); 40 operand1 = operand1.optimize(opt, env, contextItemType); 41 42 45 if (operand0 instanceof Value) { 46 NumericValue[] range = getRange(operand0.iterate(null)); 47 if (range==null) { 48 return BooleanValue.FALSE; 49 } 50 if (operator == Token.LT || operator == Token.LE) { 51 operand0 = range[0]; 52 } else { 53 operand0 = range[1]; 54 } 55 } 56 if (operand1 instanceof Value) { 57 NumericValue[] range = getRange(operand1.iterate(null)); 58 if (range==null) { 59 return BooleanValue.FALSE; 60 } 61 if (operator == Token.GT || operator == Token.GE) { 62 operand1 = range[0]; 63 } else { 64 operand1 = range[1]; 65 } 66 } 67 return this; 68 } 69 70 74 75 public ItemType getItemType() { 76 return Type.BOOLEAN_TYPE; 77 } 78 79 84 85 public Item evaluateItem(XPathContext context) throws XPathException { 86 return BooleanValue.get(effectiveBooleanValue(context)); 87 } 88 89 94 95 public boolean effectiveBooleanValue(XPathContext context) throws XPathException { 96 97 NumericValue[] range1 = getRange(operand0.iterate(context)); 98 NumericValue[] range2 = getRange(operand1.iterate(context)); 99 100 if (range1==null) return false; 101 if (range2==null) return false; 102 103 switch(operator) { 105 case Token.LT: 106 return range1[0].compareTo( range2[1] ) < 0; 107 case Token.LE: 108 return range1[0].compareTo( range2[1] ) <= 0; 109 case Token.GT: 110 return range1[1].compareTo( range2[0] ) > 0; 111 case Token.GE: 112 return range1[1].compareTo( range2[0] ) >= 0; 113 default: 114 throw new UnsupportedOperationException ("Unknown operator " + operator); 115 } 116 } 117 118 123 124 private static NumericValue[] getRange(SequenceIterator iter) throws XPathException { 125 NumericValue[] range = null; 126 while (true) { 127 AtomicValue av = (AtomicValue)iter.next(); 128 if (av == null) break; 129 NumericValue val = (NumericValue)av.getPrimitiveValue(); 130 131 if (val.isNaN()) continue; 132 133 if (range == null) { 134 range = new NumericValue[2]; 135 range[0] = val; 136 range[1] = val; 137 } else { 138 if (val.compareTo(range[0]) < 0) { 139 range[0] = val; 140 } 141 if (val.compareTo(range[1]) > 0) { 142 range[1] = val; 143 } 144 } 145 } 146 return range; 147 } 148 149 } 150 151 | Popular Tags |