1 28 29 package com.caucho.xpath.expr; 30 31 import com.caucho.xpath.Expr; 32 import com.caucho.xpath.ExprEnvironment; 33 import com.caucho.xpath.XPathException; 34 import com.caucho.xpath.pattern.NodeIterator; 35 36 import org.w3c.dom.Element ; 37 import org.w3c.dom.Node ; 38 import org.w3c.dom.NodeList ; 39 40 import java.util.ArrayList ; 41 import java.util.Iterator ; 42 43 public class BooleanExpr extends Expr { 44 private int _code; 45 private Expr _left; 46 private Expr _right; 47 private boolean _value; 48 private ArrayList _args; 49 50 public BooleanExpr(int code, Expr left, Expr right) 51 { 52 _code = code; 53 _left = left; 54 _right = right; 55 56 if (code == Expr.EQ) { 57 if (_left.isNodeSet() || _right.isNodeSet()) 58 _code = Expr.EQ; 59 else if (_left.isBoolean() || _right.isBoolean()) 60 _code = Expr.BOOLEAN_EQ; 61 else if (left.isNumber() || right.isNumber()) 62 _code = Expr.NUMBER_EQ; 63 else if (left.isString() && right.isString()) 64 _code = Expr.STRING_EQ; 65 else 66 _code = Expr.EQ; 67 } 68 else if (code == Expr.NEQ) { 69 if (left.isNodeSet() || right.isNodeSet()) 70 _code = Expr.NEQ; 71 else if (left.isBoolean() || right.isBoolean()) 72 _code = Expr.BOOLEAN_NEQ; 73 else if (left.isNumber() || right.isNumber()) 74 _code = Expr.NUMBER_NEQ; 75 else if (left.isString() && right.isString()) 76 _code = Expr.STRING_NEQ; 77 else 78 _code = Expr.NEQ; 79 } 80 else if (code == Expr.LT) { 81 if (left.isNodeSet() || right.isNodeSet()) 82 _code = Expr.LT; 83 else if (left.isNumber() || right.isNumber()) 84 _code = Expr.NUMBER_LT; 85 else 86 _code = Expr.LT; 87 } 88 else if (code == Expr.LE) { 89 if (left.isNodeSet() || right.isNodeSet()) 90 _code = Expr.LE; 91 else if (left.isNumber() || right.isNumber()) 92 _code = Expr.NUMBER_LE; 93 else 94 _code = Expr.LE; 95 } 96 else if (code == Expr.GT) { 97 if (left.isNodeSet() || right.isNodeSet()) 98 _code = Expr.GT; 99 else if (left.isNumber() || right.isNumber()) 100 _code = Expr.NUMBER_GT; 101 else 102 _code = Expr.GT; 103 } 104 else if (code == Expr.GE) { 105 if (left.isNodeSet() || right.isNodeSet()) 106 _code = Expr.GE; 107 else if (left.isNumber() || right.isNumber()) 108 _code = Expr.NUMBER_GE; 109 else 110 _code = Expr.GE; 111 } 112 } 113 114 public BooleanExpr(int code, Expr expr) 115 { 116 _code = code; 117 _left = expr; 118 } 119 120 public BooleanExpr(boolean value) 121 { 122 _code = CONST; 123 _value = value; 124 } 125 126 public BooleanExpr(int code, ArrayList args) 127 { 128 _code = code; 129 _args = args; 130 131 if (args.size() > 0) 132 _left = (Expr) args.get(0); 133 if (args.size() > 1) 134 _right = (Expr) args.get(1); 135 } 136 137 public boolean isBoolean() { return true; } 138 139 147 public boolean evalBoolean(Node node, ExprEnvironment env) 148 throws XPathException 149 { 150 switch (_code) { 151 case CONST: 152 return _value; 153 154 case BOOLEAN_EQ: 155 return (_left.evalBoolean(node, env) == _right.evalBoolean(node, env)); 156 157 case NUMBER_EQ: 158 return (_left.evalNumber(node, env) == _right.evalNumber(node, env)); 159 160 case STRING_EQ: 161 String lstr = _left.evalString(node, env); 162 String rstr = _right.evalString(node, env); 163 return lstr.equals(rstr); 164 165 case EQ: 166 Object lobj = _left.evalObject(node, env); 167 Object robj = _right.evalObject(node, env); 168 169 if (lobj == robj) 170 return true; 171 172 return cmp(P_EQ, lobj, robj); 173 174 case BOOLEAN_NEQ: 175 return (_left.evalBoolean(node, env) != _right.evalBoolean(node, env)); 176 177 case NUMBER_NEQ: 178 return (_left.evalNumber(node, env) != _right.evalNumber(node, env)); 179 180 case STRING_NEQ: 181 lstr = _left.evalString(node, env); 182 rstr = _right.evalString(node, env); 183 return ! lstr.equals(rstr); 184 185 case NEQ: 186 lobj = _left.evalObject(node, env); 187 robj = _right.evalObject(node, env); 188 189 if (lobj == robj) 190 return false; 191 192 return cmp(P_NEQ, lobj, robj); 193 194 case LT: 195 return cmp(P_LT, 196 _left.evalObject(node, env), 197 _right.evalObject(node, env)); 198 199 case LE: 200 return cmp(P_LE, 201 _left.evalObject(node, env), 202 _right.evalObject(node, env)); 203 204 case GT: 205 return cmp(P_GT, 206 _left.evalObject(node, env), 207 _right.evalObject(node, env)); 208 209 case GE: 210 return cmp(P_GE, 211 _left.evalObject(node, env), 212 _right.evalObject(node, env)); 213 214 case NUMBER_LT: 215 return (_left.evalNumber(node, env) < _right.evalNumber(node, env)); 216 217 case NUMBER_LE: 218 return (_left.evalNumber(node, env) <= _right.evalNumber(node, env)); 219 220 case NUMBER_GT: 221 return (_left.evalNumber(node, env) > _right.evalNumber(node, env)); 222 223 case NUMBER_GE: 224 return (_left.evalNumber(node, env) >= _right.evalNumber(node, env)); 225 226 case OR: 227 return (_left.evalBoolean(node, env) || _right.evalBoolean(node, env)); 228 229 case AND: 230 return (_left.evalBoolean(node, env) && _right.evalBoolean(node, env)); 231 232 case TRUE: 233 return true; 234 235 case FALSE: 236 return false; 237 238 case NOT: 239 return ! _left.evalBoolean(node, env); 240 241 case BOOLEAN: 242 return _left.evalBoolean(node, env); 243 244 case STARTS_WITH: 245 lstr = _left.evalString(node, env); 246 rstr = _right.evalString(node, env); 247 return lstr.startsWith(rstr); 248 249 case CONTAINS: 250 lstr = _left.evalString(node, env); 251 rstr = _right.evalString(node, env); 252 return lstr.indexOf(rstr) >= 0; 253 254 case LANG: 255 lstr = _left.evalString(node, env); 256 for (; node != null; node = node.getParentNode()) { 257 if (! (node instanceof Element )) 258 continue; 259 String lang = ((Element ) node).getAttribute("xml:lang"); 260 if (lang != null && lang.equals(lstr)) 261 return true; 262 } 263 return false; 264 265 case FUNCTION_AVAILABLE: 266 return false; 267 268 default: 269 throw new RuntimeException ("unknown code: " + _code); 270 } 271 } 272 273 private boolean cmp(Predicate test, Object lobj, Object robj) 274 throws XPathException 275 { 276 if (lobj instanceof NodeList ) { 277 NodeList list = (NodeList ) lobj; 278 279 int length = list.getLength(); 280 for (int i = 0; i < length; i++) { 281 if (cmp(test, list.item(i), robj)) 282 return true; 283 } 284 285 return false; 286 } 287 else if (lobj instanceof ArrayList ) { 288 ArrayList list = (ArrayList ) lobj; 289 290 for (int i = 0; i < list.size(); i++) { 291 if (cmp(test, list.get(i), robj)) 292 return true; 293 } 294 295 return false; 296 } 297 else if (lobj instanceof Iterator) { 298 Iterator iter = (Iterator) lobj; 299 300 while (iter.hasNext()) { 301 if (cmp(test, iter.next(), robj)) 302 return true; 303 } 304 305 return false; 306 } 307 308 if (robj instanceof NodeList ) { 309 NodeList list = (NodeList ) robj; 310 311 int length = list.getLength(); 312 for (int i = 0; i < length; i++) { 313 if (cmp(test, lobj, list.item(i))) 314 return true; 315 } 316 317 return false; 318 } 319 else if (robj instanceof ArrayList ) { 320 ArrayList list = (ArrayList ) robj; 321 322 for (int i = 0; i < list.size(); i++) { 323 if (cmp(test, lobj, list.get(i))) 324 return true; 325 } 326 327 return false; 328 } 329 else if (robj instanceof NodeIterator) { 330 Iterator iter = null; 331 332 iter = (Iterator) ((NodeIterator) robj).clone(); 333 334 while (iter.hasNext()) { 335 if (cmp(test, lobj, iter.next())) 336 return true; 337 } 338 return false; 339 } 340 341 return test.test(lobj, robj); 342 } 343 344 352 public double evalNumber(Node node, ExprEnvironment env) 353 throws XPathException 354 { 355 if (evalBoolean(node, env)) 356 return 1.0; 357 else 358 return 0.0; 359 } 360 361 369 public String evalString(Node node, ExprEnvironment env) 370 throws XPathException 371 { 372 if (evalBoolean(node, env)) 373 return "true"; 374 else 375 return "false"; 376 } 377 378 386 public Object evalObject(Node node, ExprEnvironment env) 387 throws XPathException 388 { 389 return new Boolean (evalBoolean(node, env)); 390 } 391 392 public String toString() 393 { 394 switch (_code) { 395 case CONST: 396 return String.valueOf(_value); 397 398 case BOOLEAN_EQ: 399 case NUMBER_EQ: 400 case STRING_EQ: 401 case EQ: 402 return "(" + _left.toString() + " = " + _right.toString() + ")"; 403 404 case BOOLEAN_NEQ: 405 case NUMBER_NEQ: 406 case STRING_NEQ: 407 case NEQ: 408 return "(" + _left.toString() + " != " + _right.toString() + ")"; 409 410 case LT: 411 case NUMBER_LT: 412 return "(" + _left.toString() + " < " + _right.toString() + ")"; 413 414 case LE: 415 case NUMBER_LE: 416 return "(" + _left.toString() + " <= " + _right.toString() + ")"; 417 418 case GT: 419 case NUMBER_GT: 420 return "(" + _left.toString() + " > " + _right.toString() + ")"; 421 422 case GE: 423 case NUMBER_GE: 424 return "(" + _left.toString() + " >= " + _right.toString() + ")"; 425 426 case OR: 427 return "(" + _left.toString() + " or " + _right.toString() + ")"; 428 429 case AND: 430 return "(" + _left.toString() + " and " + _right.toString() + ")"; 431 432 case TRUE: 433 return "true()"; 434 435 case FALSE: 436 return "false()"; 437 438 case NOT: 439 return "not(" + _left.toString() + ")"; 440 441 case BOOLEAN: 442 return "boolean(" + _left.toString() + ")"; 443 444 case STARTS_WITH: 445 return "starts-with(" + _left + ", " + _right + ")"; 446 447 case CONTAINS: 448 return "contains(" + _left + ", " + _right + ")"; 449 450 case LANG: 451 return "lang(" + _left + ")"; 452 453 case FUNCTION_AVAILABLE: 454 return "function-available(" + _left + ")"; 455 456 default: return super.toString(); 457 } 458 } 459 460 abstract static class Predicate { 461 abstract public boolean test(Object l, Object r) 462 throws XPathException; 463 } 464 465 final static Predicate P_EQ = new Predicate() { 466 public boolean test(Object lobj, Object robj) 467 throws XPathException 468 { 469 if (lobj instanceof Boolean || robj instanceof Boolean ) 470 return toBoolean(lobj) == toBoolean(robj); 471 else if (lobj instanceof Double || robj instanceof Double ) 472 return toDouble(lobj) == toDouble(robj); 473 else 474 return BooleanExpr.toString(lobj).equals(BooleanExpr.toString(robj)); 475 } 476 }; 477 478 final static Predicate P_NEQ = new Predicate() { 479 public boolean test(Object lobj, Object robj) 480 throws XPathException 481 { 482 if (lobj instanceof Boolean || robj instanceof Boolean ) 483 return toBoolean(lobj) != toBoolean(robj); 484 else if (lobj instanceof Double || robj instanceof Double ) 485 return toDouble(lobj) != toDouble(robj); 486 else 487 return ! BooleanExpr.toString(lobj).equals(BooleanExpr.toString(robj)); 488 } 489 }; 490 491 final static Predicate P_LT = new Predicate() { 492 public boolean test(Object lobj, Object robj) 493 throws XPathException 494 { 495 return toDouble(lobj) < toDouble(robj); 496 } 497 }; 498 499 final static Predicate P_LE = new Predicate() { 500 public boolean test(Object lobj, Object robj) 501 throws XPathException 502 { 503 return toDouble(lobj) <= toDouble(robj); 504 } 505 }; 506 507 final static Predicate P_GT = new Predicate() { 508 public boolean test(Object lobj, Object robj) 509 throws XPathException 510 { 511 return toDouble(lobj) > toDouble(robj); 512 } 513 }; 514 515 final static Predicate P_GE = new Predicate() { 516 public boolean test(Object lobj, Object robj) 517 throws XPathException 518 { 519 return toDouble(lobj) >= toDouble(robj); 520 } 521 }; 522 } 523 | Popular Tags |