1 28 29 package com.caucho.xpath; 30 31 import com.caucho.util.CharBuffer; 32 import com.caucho.xml.XmlChar; 33 import com.caucho.xml.XmlUtil; 34 import com.caucho.xpath.expr.ObjectVar; 35 import com.caucho.xpath.expr.Var; 36 import com.caucho.xpath.pattern.AbstractPattern; 37 import com.caucho.xpath.pattern.FromExpr; 38 import com.caucho.xpath.pattern.NodeArrayListIterator; 39 import com.caucho.xpath.pattern.NodeIterator; 40 import com.caucho.xpath.pattern.NodeListIterator; 41 import com.caucho.xpath.pattern.SingleNodeIterator; 42 43 import org.w3c.dom.Node ; 44 import org.w3c.dom.NodeList ; 45 46 import java.util.ArrayList ; 47 import java.util.Iterator ; 48 49 54 abstract public class Expr { 55 protected static final int CONST = 0; 56 57 protected static final int NODE_SET = CONST + 1; 58 protected static final int ID = NODE_SET + 1; 59 60 protected static final int OR = ID + 1; 61 protected static final int AND = OR + 1; 62 63 protected static final int EQ = AND + 1; 64 protected static final int NEQ = EQ + 1; 65 protected static final int LT = NEQ + 1; 66 protected static final int LE = LT + 1; 67 protected static final int GT = LE + 1; 68 protected static final int GE = GT + 1; 69 70 protected static final int BOOLEAN_EQ = GE + 1; 71 protected static final int BOOLEAN_NEQ = BOOLEAN_EQ + 1; 72 73 protected static final int NUMBER_EQ = BOOLEAN_NEQ + 1; 74 protected static final int NUMBER_NEQ = NUMBER_EQ + 1; 75 protected static final int NUMBER_LT = NUMBER_NEQ + 1; 76 protected static final int NUMBER_LE = NUMBER_LT + 1; 77 protected static final int NUMBER_GT = NUMBER_LE + 1; 78 protected static final int NUMBER_GE = NUMBER_GT + 1; 79 80 protected static final int STRING_EQ = NUMBER_GE + 1; 81 protected static final int STRING_NEQ = STRING_EQ + 1; 82 83 protected static final int NEG = STRING_NEQ + 1; 84 protected static final int ADD = NEG + 1; 85 protected static final int SUB = ADD + 1; 86 protected static final int MUL = SUB + 1; 87 protected static final int DIV = MUL + 1; 88 protected static final int QUO = DIV + 1; 89 protected static final int MOD = QUO + 1; 90 91 protected static final int TRUE = MOD + 1; 92 protected static final int FALSE = TRUE + 1; 93 protected static final int NOT = FALSE + 1; 94 protected static final int BOOLEAN = NOT + 1; 95 protected static final int LANG = BOOLEAN + 1; 96 97 protected static final int NUMBER = LANG + 1; 98 protected static final int SUM = NUMBER + 1; 99 protected static final int FLOOR = SUM + 1; 100 protected static final int CEILING = FLOOR + 1; 101 protected static final int ROUND = CEILING + 1; 102 public static final int POSITION = ROUND + 1; 103 protected static final int COUNT = POSITION + 1; 104 protected static final int LAST = COUNT + 1; 105 106 protected static final int STRING = LAST + 1; 107 protected static final int CONCAT = STRING + 1; 108 protected static final int STARTS_WITH = CONCAT + 1; 109 protected static final int CONTAINS = STARTS_WITH + 1; 110 protected static final int SUBSTRING = CONTAINS + 1; 111 protected static final int SUBSTRING_BEFORE = SUBSTRING + 1; 112 protected static final int SUBSTRING_AFTER = SUBSTRING_BEFORE + 1; 113 protected static final int STRING_LENGTH = SUBSTRING_AFTER + 1; 114 protected static final int NORMALIZE = STRING_LENGTH + 1; 115 protected static final int TRANSLATE = NORMALIZE + 1; 116 protected static final int FORMAT_NUMBER = TRANSLATE + 1; 117 118 protected static final int LOCAL_PART = FORMAT_NUMBER + 1; 119 protected static final int NAMESPACE = LOCAL_PART + 1; 120 protected static final int QNAME = NAMESPACE + 1; 121 protected static final int GENERATE_ID = QNAME + 1; 122 123 protected static final int FUNCTION_AVAILABLE = GENERATE_ID + 1; 124 protected static final int SYSTEM_PROPERTY = FUNCTION_AVAILABLE + 1; 125 126 protected static final int IF = SYSTEM_PROPERTY + 1; 127 128 protected static final int SELF = IF + 1; 129 protected static final int SELF_NAME = SELF + 1; 130 protected static final int ATTRIBUTE = SELF_NAME + 1; 131 protected static final int ELEMENT = ATTRIBUTE + 1; 132 133 protected static final int BASE_URI = ELEMENT + 1; 134 protected static final int LAST_FUN = BASE_URI + 1; 135 136 private AbstractPattern listContext; 137 138 protected Expr() {} 139 140 public void setListContext(AbstractPattern listContext) 141 { 142 this.listContext = listContext; 143 } 144 145 public AbstractPattern getListContext() 146 { 147 return listContext; 148 } 149 150 153 public boolean isNumber() 154 { 155 return false; 156 } 157 158 165 public double evalNumber(Node node) 166 throws XPathException 167 { 168 Env env = XPath.createEnv(); 169 env.setCurrentNode(node); 170 env.setContextNode(node); 171 172 double result = evalNumber(node, env); 173 174 XPath.freeEnv(env); 175 176 return result; 177 } 178 179 187 public abstract double evalNumber(Node node, ExprEnvironment env) 188 throws XPathException; 189 190 193 public boolean isBoolean() 194 { 195 return false; 196 } 197 198 205 public boolean evalBoolean(Node node) 206 throws XPathException 207 { 208 Env env = XPath.createEnv(); 209 env.setCurrentNode(node); 210 env.setContextNode(node); 211 212 boolean result = evalBoolean(node, env); 213 214 XPath.freeEnv(env); 215 216 return result; 217 } 218 219 227 public abstract boolean evalBoolean(Node node, ExprEnvironment env) 228 throws XPathException; 229 230 237 public String evalString(Node node) 238 throws XPathException 239 { 240 Env env = XPath.createEnv(); 241 env.setCurrentNode(node); 242 env.setContextNode(node); 243 244 String result = evalString(node, env); 245 246 XPath.freeEnv(env); 247 248 return result; 249 } 250 251 254 public boolean isString() 255 { 256 return false; 257 } 258 259 265 public abstract String evalString(Node node, ExprEnvironment env) 266 throws XPathException; 267 268 274 public void evalString(CharBuffer cb, Node node) 275 throws XPathException 276 { 277 Env env = XPath.createEnv(); 278 env.setCurrentNode(node); 279 env.setContextNode(node); 280 281 evalString(cb, node, env); 282 283 XPath.freeEnv(env); 284 } 285 286 293 public void evalString(CharBuffer cb, Node node, ExprEnvironment env) 294 throws XPathException 295 { 296 cb.append(evalString(node, env)); 297 } 298 299 302 public boolean isNodeSet() 303 { 304 return false; 305 } 306 307 314 public NodeIterator evalNodeSet(Node node) 315 throws XPathException 316 { 317 Env env = XPath.createEnv(); 318 env.setCurrentNode(node); 319 env.setContextNode(node); 320 321 NodeIterator result = evalNodeSet(node, env); 322 323 XPath.freeEnv(env); 324 325 return result; 326 } 327 328 336 public NodeIterator evalNodeSet(Node node, ExprEnvironment env) 337 throws XPathException 338 { 339 Object obj = evalObject(node, env); 340 341 if (obj instanceof Node ) 342 return new SingleNodeIterator(env, (Node ) obj); 343 344 else if (obj instanceof NodeList ) 345 return new NodeListIterator(env, (NodeList ) obj); 346 347 else if (obj instanceof NodeIterator) 348 return (NodeIterator) obj; 349 350 else if (obj instanceof ArrayList ) 351 return new NodeArrayListIterator(env, (ArrayList ) obj); 352 353 else { 354 return new SingleNodeIterator(env, null); 355 } 356 } 357 358 363 public Object evalObject(Node node) 364 throws XPathException 365 { 366 Env env = XPath.createEnv(); 367 env.setCurrentNode(node); 368 env.setContextNode(node); 369 370 Object result = evalObject(node, env); 371 372 XPath.freeEnv(env); 373 374 return result; 375 } 376 377 383 public abstract Object evalObject(Node node, ExprEnvironment env) 384 throws XPathException; 385 386 394 public Var evalVar(Node node, ExprEnvironment env) 395 throws XPathException 396 { 397 Object obj = evalObject(node, env); 398 399 return new ObjectVar(obj); 400 } 401 402 405 public void addVar(Env newEnv, String name, Node node, Env env) 406 throws XPathException 407 { 408 Var var = evalVar(node, env); 409 410 newEnv.addVar(name, var); 411 } 412 413 416 public void setVar(String name, Node node, Env env) 417 throws XPathException 418 { 419 env.setVar(name, evalVar(node, env)); 420 } 421 422 425 public void addParam(Env newEnv, String name, 426 Node node, Env env) 427 throws XPathException 428 { 429 Var var = env.getVar(name); 430 431 if (var == null) 432 newEnv.addVar(name, evalVar(node, env)); 433 else 434 newEnv.addVar(name, var); 435 } 436 437 440 public static boolean toBoolean(Object value) 441 throws XPathException 442 { 443 if (value instanceof Node ) 444 value = XmlUtil.textValue((Node ) value); 445 else if (value instanceof NodeList ) { 446 NodeList list = (NodeList ) value; 447 448 return list.item(0) != null; 449 } 450 else if (value instanceof ArrayList ) { 451 ArrayList list = (ArrayList ) value; 452 return list.size() > 0; 453 } 454 else if (value instanceof Iterator) { 455 return ((Iterator) value).hasNext(); 456 } 457 458 if (value == null) 459 return false; 460 461 else if (value instanceof Double ) { 462 Double d = (Double ) value; 463 464 return d.doubleValue() != 0; 465 } 466 else if (value instanceof Boolean ) { 467 Boolean b = (Boolean ) value; 468 return b.booleanValue(); 469 } 470 else if (value instanceof String ) { 471 String string = (String ) value; 472 return string != null && string.length() > 0; 473 } 474 else 475 return true; 476 } 477 478 481 public static double toDouble(Object value) 482 throws XPathException 483 { 484 if (value instanceof Node ) { 485 String string = XmlUtil.textValue((Node ) value); 486 487 if (string == null) 488 return 0; 489 else 490 return stringToNumber(string); 491 } 492 else if (value instanceof NodeList ) { 493 NodeList list = (NodeList ) value; 494 495 value = list.item(0); 496 } 497 else if (value instanceof ArrayList ) { 498 ArrayList list = (ArrayList ) value; 499 if (list.size() > 0) 500 value = list.get(0); 501 else 502 value = null; 503 } 504 else if (value instanceof NodeIterator) { 505 value = ((NodeIterator) value).nextNode(); 506 } 507 508 if (value instanceof Node ) 509 value = XmlUtil.textValue((Node ) value); 510 511 if (value == null) 512 return 0; 513 514 if (value instanceof Number ) { 515 Number d = (Number ) value; 516 517 return d.doubleValue(); 518 } 519 else if (value instanceof Boolean ) { 520 Boolean b = (Boolean ) value; 521 return b.booleanValue() ? 1 : 0; 522 } 523 else if (value instanceof String ) { 524 return stringToNumber((String ) value); 525 } 526 else 527 return 0; 528 } 529 530 533 public static String toString(Object value) 534 throws XPathException 535 { 536 if (value instanceof Node ) { 537 String s = XmlUtil.textValue((Node ) value); 538 539 if (s == null) 540 return ""; 541 else 542 return s; 543 } 544 else if (value instanceof NodeList ) { 545 NodeList list = (NodeList ) value; 546 547 value = list.item(0); 548 } 549 else if (value instanceof ArrayList ) { 550 ArrayList list = (ArrayList ) value; 551 if (list.size() > 0) 552 value = list.get(0); 553 else 554 value = null; 555 } 556 else if (value instanceof Iterator) { 557 value = ((Iterator) value).next(); 558 } 559 560 if (value instanceof Node ) 561 value = XmlUtil.textValue((Node ) value); 562 else if (value instanceof Double ) { 563 double d = ((Double ) value).doubleValue(); 564 565 if ((int) d == d) 566 return String.valueOf((int) d); 567 else 568 return String.valueOf(d); 569 } 570 571 if (value == null) 572 return ""; 573 else 574 return value.toString(); 575 } 576 577 580 public static Node toNode(Object value) 581 throws XPathException 582 { 583 if (value instanceof Node ) 584 return (Node ) value; 585 else if (value instanceof NodeList ) { 586 NodeList list = (NodeList ) value; 587 value = list.item(0); 588 } 589 else if (value instanceof ArrayList ) { 590 ArrayList list = (ArrayList ) value; 591 if (list.size() > 0) 592 value = list.get(0); 593 else 594 value = null; 595 } 596 else if (value instanceof NodeIterator) { 597 value = ((NodeIterator) value).nextNode(); 598 } 599 600 if (value instanceof Node ) 601 return (Node ) value; 602 else 603 return null; 604 } 605 606 612 static protected double stringToNumber(String string) 613 throws XPathException 614 { 615 int i = 0; 616 int length = string.length(); 617 boolean isNumber = false; 618 for (; i < length && XmlChar.isWhitespace(string.charAt(i)); i++) { 619 } 620 621 if (i >= length) 622 return 0; 623 624 int ch = string.charAt(i);; 625 int sign = 1; 626 if (ch == '-') { 627 sign = -1; 628 for (i++; i < length && XmlChar.isWhitespace(string.charAt(i)); i++) { 629 } 630 } 631 632 double value = 0; 633 double exp = 1; 634 for (; i < length && (ch = string.charAt(i)) >= '0' && ch <= '9'; i++) { 635 value = 10 * value + ch - '0'; 636 isNumber = true; 637 } 638 639 if (ch == '.') { 640 for (i++; 641 i < length && (ch = string.charAt(i)) >= '0' && ch <= '9'; 642 i++) { 643 value = 10 * value + ch - '0'; 644 isNumber = true; 645 exp = 10 * exp; 646 } 647 } 648 649 double pexp = 1.0; 650 if (ch == 'e' || ch == 'E') { 651 int eSign = 1; 652 i++; 653 654 if (i >= length) 655 return Double.NaN; 656 657 if (string.charAt(i) == '-') { 658 eSign = -1; 659 i++; 660 } 661 else if (string.charAt(i) == '+') { 662 i++; 663 } 664 665 int v = 0; 666 for (; i < length && (ch = string.charAt(i)) >= '0' && ch <= '9'; i++) { 667 v = v * 10 + ch - '0'; 668 } 669 670 pexp = Math.pow(10, eSign * v); 671 } 672 673 for (; i < length && XmlChar.isWhitespace(string.charAt(i)); i++) { 674 } 675 676 if (i < length || ! isNumber) 677 return Double.NaN; 678 else 679 return sign * value * pexp / exp; 680 } 681 682 685 protected AbstractPattern toNodeList() 686 { 687 return new FromExpr(null, this); 688 } 689 } 690 | Popular Tags |