1 package net.sf.saxon.expr; 2 import net.sf.saxon.om.*; 3 import net.sf.saxon.trans.XPathException; 4 import net.sf.saxon.type.ItemType; 5 import net.sf.saxon.type.Type; 6 import net.sf.saxon.value.*; 7 8 16 17 public class RangeExpression extends BinaryExpression { 18 19 22 23 public RangeExpression(Expression start, int op, Expression end) { 24 super(start, op, end); 25 } 26 27 30 31 public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 32 operand0 = operand0.typeCheck(env, contextItemType); 33 operand1 = operand1.typeCheck(env, contextItemType); 34 35 RoleLocator role0 = new RoleLocator(RoleLocator.BINARY_EXPR, "to", 0, null); 36 role0.setSourceLocator(this); 37 operand0 = TypeChecker.staticTypeCheck( 38 operand0, SequenceType.OPTIONAL_INTEGER, false, role0, env); 39 40 RoleLocator role1 = new RoleLocator(RoleLocator.BINARY_EXPR, "to", 1, null); 41 role1.setSourceLocator(this); 42 operand1 = TypeChecker.staticTypeCheck( 43 operand1, SequenceType.OPTIONAL_INTEGER, false, role1, env); 44 45 return this; 46 } 47 48 65 66 public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException { 67 operand0 = operand0.optimize(opt, env, contextItemType); 68 operand1 = operand1.optimize(opt, env, contextItemType); 69 70 if (operand0 instanceof IntegerValue && operand1 instanceof IntegerValue) { 71 long i0 = ((IntegerValue)operand0).longValue(); 72 long i1 = ((IntegerValue)operand1).longValue(); 73 if (i0 > i1) { 74 return EmptySequence.getInstance(); 75 } else { 76 return new IntegerRange(i0, i1); 77 } 78 } 79 return this; 80 81 } 82 83 84 87 88 public ItemType getItemType() { 89 return Type.INTEGER_TYPE; 90 } 91 92 95 96 public int computeCardinality() { 97 return StaticProperty.ALLOWS_ZERO_OR_MORE; 98 } 99 100 103 104 public SequenceIterator iterate(XPathContext context) throws XPathException { 105 AtomicValue av1 = (AtomicValue)operand0.evaluateItem(context); 106 if (av1 == null) { 107 return new EmptyIterator(); 108 } 109 NumericValue v1 = (NumericValue)av1.getPrimitiveValue(); 110 111 AtomicValue av2 = (AtomicValue)operand1.evaluateItem(context); 112 if (av2 == null) { 113 return new EmptyIterator(); 114 } 115 NumericValue v2 = (NumericValue)av2.getPrimitiveValue(); 116 117 if (v1.compareTo(v2) > 0) { 118 return new EmptyIterator(); 119 } 120 return new RangeIterator(v1.longValue(), v2.longValue()); 121 } 122 123 129 130 public static class RangeIterator implements SequenceIterator, 131 ReversibleIterator, 132 LastPositionFinder, 133 LookaheadIterator, 134 GroundedIterator { 135 136 long start; 137 long currentValue; 138 int increment; long limit; 140 141 public RangeIterator(long start, long end) { 142 this.start = start; 143 increment = (start <= end ? +1 : -1); 144 currentValue = start; 145 limit = end; 146 } 147 148 public boolean hasNext() { 149 if (increment>0) { 150 return currentValue <= limit; 151 } else if (increment<0) { 152 return currentValue >= limit; 153 } else { 154 return false; 155 } 156 } 157 158 public Item next() { 159 if (!hasNext()) { 160 increment = 0; 161 return null; 162 } 163 long d = currentValue; 164 currentValue += increment; 165 return new IntegerValue(d); 166 } 167 168 public Item current() { 169 if (increment == 0) { 170 return null; 171 } else { 172 return new IntegerValue(currentValue - increment); 173 } 174 } 175 176 public int position() { 177 if (increment > 0) { 178 return (int)(currentValue - start); 179 } else if (increment < 0) { 180 return (int)(start - currentValue); 181 } else { 182 return -1; 183 } 184 } 185 186 public int getLastPosition() { 187 return (int)((limit - start) * increment + 1); 188 } 189 190 public SequenceIterator getAnother() throws XPathException { 191 return new RangeIterator(start, limit); 192 } 193 194 203 204 public int getProperties() { 205 int props = LOOKAHEAD | LAST_POSITION_FINDER; 206 if (increment == 1) { 207 props |= GROUNDED; 208 } 209 return props; 210 } 211 212 public SequenceIterator getReverseIterator() { 213 return new RangeIterator(limit, start); 214 } 215 216 222 223 public Value materialize() throws XPathException { 224 if (increment == 1) { 225 return new IntegerRange(start, limit); 226 } else { 227 return new SequenceExtent(getAnother()); 228 } 229 } 230 } 231 } 232 233 | Popular Tags |