1 16 19 package org.apache.xpath.patterns; 20 21 import org.apache.xml.dtm.Axis; 22 import org.apache.xml.dtm.DTM; 23 import org.apache.xml.dtm.DTMAxisTraverser; 24 import org.apache.xml.dtm.DTMFilter; 25 import org.apache.xpath.Expression; 26 import org.apache.xpath.ExpressionOwner; 27 import org.apache.xpath.XPathContext; 28 import org.apache.xpath.XPathVisitor; 29 import org.apache.xpath.axes.SubContextList; 30 import org.apache.xpath.compiler.PsuedoNames; 31 import org.apache.xpath.objects.XObject; 32 33 37 public class StepPattern extends NodeTest implements SubContextList, ExpressionOwner 38 { 39 40 41 protected int m_axis; 42 43 53 public StepPattern(int whatToShow, String namespace, String name, int axis, 54 int axisForPredicate) 55 { 56 57 super(whatToShow, namespace, name); 58 59 m_axis = axis; 60 } 61 62 70 public StepPattern(int whatToShow, int axis, int axisForPredicate) 71 { 72 73 super(whatToShow); 74 75 m_axis = axis; 76 } 77 78 82 String m_targetString; 84 90 public void calcTargetString() 91 { 92 93 int whatToShow = getWhatToShow(); 94 95 switch (whatToShow) 96 { 97 case DTMFilter.SHOW_COMMENT : 98 m_targetString = PsuedoNames.PSEUDONAME_COMMENT; 99 break; 100 case DTMFilter.SHOW_TEXT : 101 case DTMFilter.SHOW_CDATA_SECTION : 102 case (DTMFilter.SHOW_TEXT | DTMFilter.SHOW_CDATA_SECTION) : 103 m_targetString = PsuedoNames.PSEUDONAME_TEXT; 104 break; 105 case DTMFilter.SHOW_ALL : 106 m_targetString = PsuedoNames.PSEUDONAME_ANY; 107 break; 108 case DTMFilter.SHOW_DOCUMENT : 109 case DTMFilter.SHOW_DOCUMENT | DTMFilter.SHOW_DOCUMENT_FRAGMENT : 110 m_targetString = PsuedoNames.PSEUDONAME_ROOT; 111 break; 112 case DTMFilter.SHOW_ELEMENT : 113 if (this.WILD == m_name) 114 m_targetString = PsuedoNames.PSEUDONAME_ANY; 115 else 116 m_targetString = m_name; 117 break; 118 default : 119 m_targetString = PsuedoNames.PSEUDONAME_ANY; 120 break; 121 } 122 } 123 124 132 public String getTargetString() 133 { 134 return m_targetString; 135 } 136 137 142 StepPattern m_relativePathPattern; 143 144 155 public void fixupVariables(java.util.Vector vars, int globalsSize) 156 { 157 158 super.fixupVariables(vars, globalsSize); 159 160 if (null != m_predicates) 161 { 162 for (int i = 0; i < m_predicates.length; i++) 163 { 164 m_predicates[i].fixupVariables(vars, globalsSize); 165 } 166 } 167 168 if (null != m_relativePathPattern) 169 { 170 m_relativePathPattern.fixupVariables(vars, globalsSize); 171 } 172 } 173 174 181 public void setRelativePathPattern(StepPattern expr) 182 { 183 184 m_relativePathPattern = expr; 185 expr.exprSetParent(this); 186 187 calcScore(); 188 } 189 190 197 public StepPattern getRelativePathPattern() 198 { 199 return m_relativePathPattern; 200 } 201 202 211 215 public Expression[] getPredicates() 216 { 217 return m_predicates; 218 } 219 220 224 Expression[] m_predicates; 225 226 235 public boolean canTraverseOutsideSubtree() 236 { 237 238 int n = getPredicateCount(); 239 240 for (int i = 0; i < n; i++) 241 { 242 if (getPredicate(i).canTraverseOutsideSubtree()) 243 return true; 244 } 245 246 return false; 247 } 248 249 257 public Expression getPredicate(int i) 258 { 259 return m_predicates[i]; 260 } 261 262 268 public final int getPredicateCount() 269 { 270 return (null == m_predicates) ? 0 : m_predicates.length; 271 } 272 273 280 public void setPredicates(Expression[] predicates) 281 { 282 283 m_predicates = predicates; 284 if(null != predicates) 285 { 286 for(int i = 0; i < predicates.length; i++) 287 { 288 predicates[i].exprSetParent(this); 289 } 290 } 291 292 calcScore(); 293 } 294 295 298 public void calcScore() 299 { 300 301 if ((getPredicateCount() > 0) || (null != m_relativePathPattern)) 302 { 303 m_score = SCORE_OTHER; 304 } 305 else 306 super.calcScore(); 307 308 if (null == m_targetString) 309 calcTargetString(); 310 } 311 312 327 public XObject execute(XPathContext xctxt, int currentNode) 328 throws javax.xml.transform.TransformerException 329 { 330 331 DTM dtm = xctxt.getDTM(currentNode); 332 333 if (dtm != null) 334 { 335 int expType = dtm.getExpandedTypeID(currentNode); 336 337 return execute(xctxt, currentNode, dtm, expType); 338 } 339 340 return NodeTest.SCORE_NONE; 341 } 342 343 357 public XObject execute(XPathContext xctxt) 358 throws javax.xml.transform.TransformerException 359 { 360 return execute(xctxt, xctxt.getCurrentNode()); 361 } 362 363 378 public XObject execute( 379 XPathContext xctxt, int currentNode, DTM dtm, int expType) 380 throws javax.xml.transform.TransformerException 381 { 382 383 if (m_whatToShow == NodeTest.SHOW_BYFUNCTION) 384 { 385 if (null != m_relativePathPattern) 386 { 387 return m_relativePathPattern.execute(xctxt); 388 } 389 else 390 return NodeTest.SCORE_NONE; 391 } 392 393 XObject score; 394 395 score = super.execute(xctxt, currentNode, dtm, expType); 396 397 if (score == NodeTest.SCORE_NONE) 398 return NodeTest.SCORE_NONE; 399 400 if (getPredicateCount() != 0) 401 { 402 if (!executePredicates(xctxt, dtm, currentNode)) 403 return NodeTest.SCORE_NONE; 404 } 405 406 if (null != m_relativePathPattern) 407 return m_relativePathPattern.executeRelativePathPattern(xctxt, dtm, 408 currentNode); 409 410 return score; 411 } 412 413 425 private final boolean checkProximityPosition(XPathContext xctxt, 426 int predPos, DTM dtm, int context, int pos) 427 { 428 429 try 430 { 431 DTMAxisTraverser traverser = 432 dtm.getAxisTraverser(Axis.PRECEDINGSIBLING); 433 434 for (int child = traverser.first(context); DTM.NULL != child; 435 child = traverser.next(context, child)) 436 { 437 try 438 { 439 xctxt.pushCurrentNode(child); 440 441 if (NodeTest.SCORE_NONE != super.execute(xctxt, child)) 442 { 443 boolean pass = true; 444 445 try 446 { 447 xctxt.pushSubContextList(this); 448 449 for (int i = 0; i < predPos; i++) 450 { 451 xctxt.pushPredicatePos(i); 452 try 453 { 454 XObject pred = m_predicates[i].execute(xctxt); 455 456 try 457 { 458 if (XObject.CLASS_NUMBER == pred.getType()) 459 { 460 throw new Error ("Why: Should never have been called"); 461 } 462 else if (!pred.boolWithSideEffects()) 463 { 464 pass = false; 465 466 break; 467 } 468 } 469 finally 470 { 471 pred.detach(); 472 } 473 } 474 finally 475 { 476 xctxt.popPredicatePos(); 477 } 478 } 479 } 480 finally 481 { 482 xctxt.popSubContextList(); 483 } 484 485 if (pass) 486 pos--; 487 488 if (pos < 1) 489 return false; 490 } 491 } 492 finally 493 { 494 xctxt.popCurrentNode(); 495 } 496 } 497 } 498 catch (javax.xml.transform.TransformerException se) 499 { 500 501 throw new java.lang.RuntimeException (se.getMessage()); 503 } 504 505 return (pos == 1); 506 } 507 508 520 private final int getProximityPosition(XPathContext xctxt, int predPos, 521 boolean findLast) 522 { 523 524 int pos = 0; 525 int context = xctxt.getCurrentNode(); 526 DTM dtm = xctxt.getDTM(context); 527 int parent = dtm.getParent(context); 528 529 try 530 { 531 DTMAxisTraverser traverser = dtm.getAxisTraverser(Axis.CHILD); 532 533 for (int child = traverser.first(parent); DTM.NULL != child; 534 child = traverser.next(parent, child)) 535 { 536 try 537 { 538 xctxt.pushCurrentNode(child); 539 540 if (NodeTest.SCORE_NONE != super.execute(xctxt, child)) 541 { 542 boolean pass = true; 543 544 try 545 { 546 xctxt.pushSubContextList(this); 547 548 for (int i = 0; i < predPos; i++) 549 { 550 xctxt.pushPredicatePos(i); 551 try 552 { 553 XObject pred = m_predicates[i].execute(xctxt); 554 555 try 556 { 557 if (XObject.CLASS_NUMBER == pred.getType()) 558 { 559 if ((pos + 1) != (int) pred.numWithSideEffects()) 560 { 561 pass = false; 562 563 break; 564 } 565 } 566 else if (!pred.boolWithSideEffects()) 567 { 568 pass = false; 569 570 break; 571 } 572 } 573 finally 574 { 575 pred.detach(); 576 } 577 } 578 finally 579 { 580 xctxt.popPredicatePos(); 581 } 582 } 583 } 584 finally 585 { 586 xctxt.popSubContextList(); 587 } 588 589 if (pass) 590 pos++; 591 592 if (!findLast && child == context) 593 { 594 return pos; 595 } 596 } 597 } 598 finally 599 { 600 xctxt.popCurrentNode(); 601 } 602 } 603 } 604 catch (javax.xml.transform.TransformerException se) 605 { 606 607 throw new java.lang.RuntimeException (se.getMessage()); 609 } 610 611 return pos; 612 } 613 614 624 public int getProximityPosition(XPathContext xctxt) 625 { 626 return getProximityPosition(xctxt, xctxt.getPredicatePos(), false); 627 } 628 629 640 public int getLastPos(XPathContext xctxt) 641 { 642 return getProximityPosition(xctxt, xctxt.getPredicatePos(), true); 643 } 644 645 661 protected final XObject executeRelativePathPattern( 662 XPathContext xctxt, DTM dtm, int currentNode) 663 throws javax.xml.transform.TransformerException 664 { 665 666 XObject score = NodeTest.SCORE_NONE; 667 int context = currentNode; 668 DTMAxisTraverser traverser; 669 670 traverser = dtm.getAxisTraverser(m_axis); 671 672 for (int relative = traverser.first(context); DTM.NULL != relative; 673 relative = traverser.next(context, relative)) 674 { 675 try 676 { 677 xctxt.pushCurrentNode(relative); 678 679 score = execute(xctxt); 680 681 if (score != NodeTest.SCORE_NONE) 682 break; 683 } 684 finally 685 { 686 xctxt.popCurrentNode(); 687 } 688 } 689 690 return score; 691 } 692 693 705 protected final boolean executePredicates( 706 XPathContext xctxt, DTM dtm, int currentNode) 707 throws javax.xml.transform.TransformerException 708 { 709 710 boolean result = true; 711 boolean positionAlreadySeen = false; 712 int n = getPredicateCount(); 713 714 try 715 { 716 xctxt.pushSubContextList(this); 717 718 for (int i = 0; i < n; i++) 719 { 720 xctxt.pushPredicatePos(i); 721 722 try 723 { 724 XObject pred = m_predicates[i].execute(xctxt); 725 726 try 727 { 728 if (XObject.CLASS_NUMBER == pred.getType()) 729 { 730 int pos = (int) pred.num(); 731 732 if (positionAlreadySeen) 733 { 734 result = (pos == 1); 735 736 break; 737 } 738 else 739 { 740 positionAlreadySeen = true; 741 742 if (!checkProximityPosition(xctxt, i, dtm, currentNode, pos)) 743 { 744 result = false; 745 746 break; 747 } 748 } 749 750 } 751 else if (!pred.boolWithSideEffects()) 752 { 753 result = false; 754 755 break; 756 } 757 } 758 finally 759 { 760 pred.detach(); 761 } 762 } 763 finally 764 { 765 xctxt.popPredicatePos(); 766 } 767 } 768 } 769 finally 770 { 771 xctxt.popSubContextList(); 772 } 773 774 return result; 775 } 776 777 784 public String toString() 785 { 786 787 StringBuffer buf = new StringBuffer (); 788 789 for (StepPattern pat = this; pat != null; pat = pat.m_relativePathPattern) 790 { 791 if (pat != this) 792 buf.append("/"); 793 794 buf.append(Axis.names[pat.m_axis]); 795 buf.append("::"); 796 797 if (0x000005000 == pat.m_whatToShow) 798 { 799 buf.append("doc()"); 800 } 801 else if (DTMFilter.SHOW_BYFUNCTION == pat.m_whatToShow) 802 { 803 buf.append("function()"); 804 } 805 else if (DTMFilter.SHOW_ALL == pat.m_whatToShow) 806 { 807 buf.append("node()"); 808 } 809 else if (DTMFilter.SHOW_TEXT == pat.m_whatToShow) 810 { 811 buf.append("text()"); 812 } 813 else if (DTMFilter.SHOW_PROCESSING_INSTRUCTION == pat.m_whatToShow) 814 { 815 buf.append("processing-instruction("); 816 817 if (null != pat.m_name) 818 { 819 buf.append(pat.m_name); 820 } 821 822 buf.append(")"); 823 } 824 else if (DTMFilter.SHOW_COMMENT == pat.m_whatToShow) 825 { 826 buf.append("comment()"); 827 } 828 else if (null != pat.m_name) 829 { 830 if (DTMFilter.SHOW_ATTRIBUTE == pat.m_whatToShow) 831 { 832 buf.append("@"); 833 } 834 835 if (null != pat.m_namespace) 836 { 837 buf.append("{"); 838 buf.append(pat.m_namespace); 839 buf.append("}"); 840 } 841 842 buf.append(pat.m_name); 843 } 844 else if (DTMFilter.SHOW_ATTRIBUTE == pat.m_whatToShow) 845 { 846 buf.append("@"); 847 } 848 else if ((DTMFilter.SHOW_DOCUMENT | DTMFilter.SHOW_DOCUMENT_FRAGMENT) 849 == pat.m_whatToShow) 850 { 851 buf.append("doc-root()"); 852 } 853 else 854 { 855 buf.append("?" + Integer.toHexString(pat.m_whatToShow)); 856 } 857 858 if (null != pat.m_predicates) 859 { 860 for (int i = 0; i < pat.m_predicates.length; i++) 861 { 862 buf.append("["); 863 buf.append(pat.m_predicates[i]); 864 buf.append("]"); 865 } 866 } 867 } 868 869 return buf.toString(); 870 } 871 872 873 private static final boolean DEBUG_MATCHES = false; 874 875 889 public double getMatchScore(XPathContext xctxt, int context) 890 throws javax.xml.transform.TransformerException 891 { 892 893 xctxt.pushCurrentNode(context); 894 xctxt.pushCurrentExpressionNode(context); 895 896 try 897 { 898 XObject score = execute(xctxt); 899 900 return score.num(); 901 } 902 finally 903 { 904 xctxt.popCurrentNode(); 905 xctxt.popCurrentExpressionNode(); 906 } 907 908 } 910 911 917 public void setAxis(int axis) 918 { 919 m_axis = axis; 920 } 921 922 928 public int getAxis() 929 { 930 return m_axis; 931 } 932 933 class PredOwner implements ExpressionOwner 934 { 935 int m_index; 936 937 PredOwner(int index) 938 { 939 m_index = index; 940 } 941 942 945 public Expression getExpression() 946 { 947 return m_predicates[m_index]; 948 } 949 950 951 954 public void setExpression(Expression exp) 955 { 956 exp.exprSetParent(StepPattern.this); 957 m_predicates[m_index] = exp; 958 } 959 } 960 961 964 public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) 965 { 966 if(visitor.visitMatchPattern(owner, this)) 967 { 968 callSubtreeVisitors(visitor); 969 } 970 } 971 972 976 protected void callSubtreeVisitors(XPathVisitor visitor) 977 { 978 if (null != m_predicates) 979 { 980 int n = m_predicates.length; 981 for (int i = 0; i < n; i++) 982 { 983 ExpressionOwner predOwner = new PredOwner(i); 984 if (visitor.visitPredicate(predOwner, m_predicates[i])) 985 { 986 m_predicates[i].callVisitors(predOwner, visitor); 987 } 988 } 989 } 990 if (null != m_relativePathPattern) 991 { 992 m_relativePathPattern.callVisitors(this, visitor); 993 } 994 } 995 996 997 1000 public Expression getExpression() 1001 { 1002 return m_relativePathPattern; 1003 } 1004 1005 1008 public void setExpression(Expression exp) 1009 { 1010 exp.exprSetParent(this); 1011 m_relativePathPattern = (StepPattern)exp; 1012 } 1013 1014 1017 public boolean deepEquals(Expression expr) 1018 { 1019 if(!super.deepEquals(expr)) 1020 return false; 1021 1022 StepPattern sp = (StepPattern)expr; 1023 1024 if (null != m_predicates) 1025 { 1026 int n = m_predicates.length; 1027 if ((null == sp.m_predicates) || (sp.m_predicates.length != n)) 1028 return false; 1029 for (int i = 0; i < n; i++) 1030 { 1031 if (!m_predicates[i].deepEquals(sp.m_predicates[i])) 1032 return false; 1033 } 1034 } 1035 else if (null != sp.m_predicates) 1036 return false; 1037 1038 if(null != m_relativePathPattern) 1039 { 1040 if(!m_relativePathPattern.deepEquals(sp.m_relativePathPattern)) 1041 return false; 1042 } 1043 else if(sp.m_relativePathPattern != null) 1044 return false; 1045 1046 return true; 1047 } 1048 1049 1050} 1051 | Popular Tags |