1 package net.sf.saxon.expr; 2 import net.sf.saxon.functions.NumberFn; 3 import net.sf.saxon.om.Item; 4 import net.sf.saxon.om.SequenceIterator; 5 import net.sf.saxon.sort.AtomicComparer; 6 import net.sf.saxon.sort.CodepointCollator; 7 import net.sf.saxon.trans.DynamicError; 8 import net.sf.saxon.trans.XPathException; 9 import net.sf.saxon.type.AtomicType; 10 import net.sf.saxon.type.ItemType; 11 import net.sf.saxon.type.Type; 12 import net.sf.saxon.value.*; 13 14 import java.util.ArrayList ; 15 import java.util.Comparator ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 19 26 27 public class GeneralComparison10 extends BinaryExpression { 28 29 protected int singletonOperator; 30 protected AtomicComparer comparer; 31 private boolean atomize0 = true; 32 private boolean atomize1 = true; 33 private boolean maybeBoolean0 = true; 34 private boolean maybeBoolean1 = true; 35 36 42 43 public GeneralComparison10(Expression p0, int op, Expression p1) { 44 super(p0, op, p1); 45 singletonOperator = getSingletonOperator(op); 46 } 47 48 51 52 public int computeCardinality() { 53 return StaticProperty.EXACTLY_ONE; 54 } 55 56 60 61 public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 62 63 operand0 = operand0.typeCheck(env, contextItemType); 64 operand1 = operand1.typeCheck(env, contextItemType); 65 66 Comparator comp = env.getCollation(env.getDefaultCollationName()); 67 if (comp==null) comp = CodepointCollator.getInstance(); 68 comparer = new AtomicComparer(comp, env.getConfiguration()); 69 70 return this; 71 } 72 73 77 78 public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException { 79 80 operand0 = operand0.optimize(opt, env, contextItemType); 81 operand1 = operand1.optimize(opt, env, contextItemType); 82 83 85 operand0 = ExpressionTool.unsorted(opt, operand0, false); 86 operand1 = ExpressionTool.unsorted(opt, operand1, false); 87 88 90 if ((operand0 instanceof Value) && (operand1 instanceof Value)) { 91 return (AtomicValue)evaluateItem(null); 92 } 93 94 ItemType type0 = operand0.getItemType(); 95 ItemType type1 = operand1.getItemType(); 96 97 if (type0 instanceof AtomicType) { 98 atomize0 = false; 99 } 100 if (type1 instanceof AtomicType) { 101 atomize1 = false; 102 } 103 104 if (Type.relationship(type0, Type.BOOLEAN_TYPE) == Type.DISJOINT) { 105 maybeBoolean0 = false; 106 } 107 if (Type.relationship(type1, Type.BOOLEAN_TYPE) == Type.DISJOINT) { 108 maybeBoolean1 = false; 109 } 110 111 if (!maybeBoolean0 && !maybeBoolean1) { 112 int n0 = Type.relationship(type0, Type.NUMBER_TYPE); 113 int n1 = Type.relationship(type1, Type.NUMBER_TYPE); 114 boolean maybeNumeric0 = (n0 != Type.DISJOINT); 115 boolean maybeNumeric1 = (n1 != Type.DISJOINT); 116 boolean numeric0 = (n0 == Type.SUBSUMED_BY || n0 == Type.SAME_TYPE); 117 boolean numeric1 = (n1 == Type.SUBSUMED_BY || n1 == Type.SAME_TYPE); 118 119 if (!maybeNumeric0 && !maybeNumeric1) { 122 return new GeneralComparison(operand0, operator, operand1) 123 .typeCheck(env, contextItemType).optimize(opt, env, contextItemType); 124 } 125 if (numeric0 && numeric1) { 126 return new GeneralComparison(operand0, operator, operand1) 127 .typeCheck(env, contextItemType).optimize(opt, env, contextItemType); 128 } 129 } 130 131 return this; 132 } 133 134 135 136 141 142 public Item evaluateItem(XPathContext context) throws XPathException { 143 return BooleanValue.get(effectiveBooleanValue(context)); 144 } 145 146 151 152 public boolean effectiveBooleanValue(XPathContext context) throws XPathException { 153 154 157 SequenceIterator iter0 = null; 158 159 if (maybeBoolean0) { 160 iter0 = operand0.iterate(context); 161 Item i01 = iter0.next(); 162 Item i02 = (i01 == null ? null : iter0.next()); 163 if (i01 instanceof BooleanValue && i02 == null) { 164 boolean b = operand1.effectiveBooleanValue(context); 165 return compare((BooleanValue)i01, singletonOperator, BooleanValue.get(b), comparer, context); 166 } 167 if (i01 == null && !maybeBoolean1) { 168 return false; 169 } 170 } 171 172 175 SequenceIterator iter1 = null; 176 177 if (maybeBoolean1) { 178 iter1 = operand1.iterate(context); 179 Item i11 = iter1.next(); 180 Item i12 = (i11 == null ? null : iter1.next()); 181 if (i11 instanceof BooleanValue && i12 == null) { 182 boolean b = operand0.effectiveBooleanValue(context); 183 return compare(BooleanValue.get(b), singletonOperator, (BooleanValue)i11, comparer, context); 184 } 185 if (i11 == null && !maybeBoolean0) { 186 return false; 187 } 188 } 189 190 192 if (iter0 == null) { 193 iter0 = operand0.iterate(context); 194 } else { 195 iter0 = iter0.getAnother(); 196 } 197 198 if (iter1 == null) { 199 iter1 = operand1.iterate(context); 200 } else { 201 iter1 = iter1.getAnother(); 202 } 203 204 if (atomize0) { 205 iter0 = Atomizer.AtomizingFunction.getAtomizingIterator(iter0); 206 } 207 208 if (atomize1) { 209 iter1 = Atomizer.AtomizingFunction.getAtomizingIterator(iter1); 210 } 211 212 215 if (operator == Token.LT || operator == Token.LE || operator == Token.GT || operator == Token.GE) { 216 iter0 = new MappingIterator(iter0, new NumberFn(), null); 217 iter1 = new MappingIterator(iter1, new NumberFn(), null); 218 } 219 220 222 List seq1 = null; 223 while (true) { 224 AtomicValue item0 = (AtomicValue)iter0.next(); 225 if (item0 == null) { 226 return false; 227 } 228 if (iter1 != null) { 229 while (true) { 230 AtomicValue item1 = (AtomicValue)iter1.next(); 231 if (item1 == null) { 232 iter1 = null; 233 if (seq1 == null) { 234 return false; 236 } 237 break; 238 } 239 try { 240 if (compare(item0, singletonOperator, item1, comparer, context)) { 241 return true; 242 } 243 if (seq1 == null) { 244 seq1 = new ArrayList (40); 245 } 246 seq1.add(item1); 247 } catch (DynamicError e) { 248 if (e.getXPathContext() == null) { 250 e.setXPathContext(context); 251 } 252 if (e.getLocator() == null) { 253 e.setLocator(this); 254 } 255 throw e; 256 } 257 } 258 } else { 259 Iterator listIter1 = seq1.iterator(); 260 while (listIter1.hasNext()) { 261 AtomicValue item1 = (AtomicValue)listIter1.next(); 262 if (compare(item0, singletonOperator, item1, comparer, context)) { 263 return true; 264 } 265 } 266 } 267 } 268 } 269 270 273 274 protected static boolean compare(AtomicValue a0, 275 int operator, 276 AtomicValue a1, 277 AtomicComparer comparer, 278 XPathContext context) throws XPathException { 279 280 AtomicType t0 = (AtomicType)a0.getItemType().getPrimitiveItemType(); 281 AtomicType t1 = (AtomicType)a1.getItemType().getPrimitiveItemType(); 282 283 286 if (Type.isNumericPrimitiveType(t0) || Type.isNumericPrimitiveType(t1)) { 287 DoubleValue v0 = NumberFn.convert(a0); 288 DoubleValue v1 = NumberFn.convert(a1); 289 return ValueComparison.compare(v0, operator, v1, comparer); 290 } 291 292 295 if (t0 == Type.STRING_TYPE || t1 == Type.STRING_TYPE || 296 (t0 == Type.UNTYPED_ATOMIC_TYPE && t1 == Type.UNTYPED_ATOMIC_TYPE)) { 297 StringValue s0 = (StringValue)a0.convert(Type.STRING, context); 298 StringValue s1 = (StringValue)a1.convert(Type.STRING, context); 299 return ValueComparison.compare(s0, operator, s1, comparer); 300 } 301 302 305 if (t0 == Type.UNTYPED_ATOMIC_TYPE) { 306 a0 = a0.convert(t1, context, true); 307 if (a0 instanceof ValidationErrorValue) { 308 throw ((ValidationErrorValue)a0).getException(); 309 } 310 } 311 312 if (t1 == Type.UNTYPED_ATOMIC_TYPE) { 313 a1 = a1.convert(t0, context, true); 314 if (a1 instanceof ValidationErrorValue) { 315 throw ((ValidationErrorValue)a1).getException(); 316 } 317 } 318 319 return ValueComparison.compare(a0, operator, a1, comparer); 320 } 321 322 326 327 public ItemType getItemType() { 328 return Type.BOOLEAN_TYPE; 329 } 330 331 334 335 private static int getSingletonOperator(int op) { 336 switch (op) { 337 case Token.EQUALS: 338 return Token.FEQ; 339 case Token.GE: 340 return Token.FGE; 341 case Token.NE: 342 return Token.FNE; 343 case Token.LT: 344 return Token.FLT; 345 case Token.GT: 346 return Token.FGT; 347 case Token.LE: 348 return Token.FLE; 349 default: 350 return op; 351 } 352 } 353 354 protected String displayOperator() { 355 return "many-to-many (1.0) " + super.displayOperator(); 356 } 357 358 } 359 360 | Popular Tags |