1 16 19 package org.apache.xpath; 20 21 import org.apache.xalan.res.XSLMessages; 22 import org.apache.xml.utils.DOM2Helper; 23 import org.apache.xpath.axes.ContextNodeList; 24 import org.apache.xpath.res.XPATHErrorResources; 25 26 import org.w3c.dom.DOMException ; 27 import org.w3c.dom.Node ; 28 import org.w3c.dom.NodeList ; 29 import org.w3c.dom.traversal.NodeFilter; 30 import org.w3c.dom.traversal.NodeIterator; 31 32 33 57 public class NodeSet 58 implements NodeList, NodeIterator, Cloneable , ContextNodeList 59 { 60 61 64 public NodeSet() 65 { 66 m_blocksize = 32; 67 m_mapSize = 0; 68 } 69 70 75 public NodeSet(int blocksize) 76 { 77 m_blocksize = blocksize; 78 m_mapSize = 0; 79 } 80 81 87 public NodeSet(NodeList nodelist) 88 { 89 90 this(32); 91 92 addNodes(nodelist); 93 } 94 95 101 public NodeSet(NodeSet nodelist) 102 { 103 104 this(32); 105 106 addNodes((NodeIterator) nodelist); 107 } 108 109 115 public NodeSet(NodeIterator ni) 116 { 117 118 this(32); 119 120 addNodes(ni); 121 } 122 123 128 public NodeSet(Node node) 129 { 130 131 this(32); 132 133 addNode(node); 134 } 135 136 140 public Node getRoot() 141 { 142 return null; 143 } 144 145 155 public NodeIterator cloneWithReset() throws CloneNotSupportedException 156 { 157 158 NodeSet clone = (NodeSet) clone(); 159 160 clone.reset(); 161 162 return clone; 163 } 164 165 168 public void reset() 169 { 170 m_next = 0; 171 } 172 173 185 public int getWhatToShow() 186 { 187 return NodeFilter.SHOW_ALL & ~NodeFilter.SHOW_ENTITY_REFERENCE; 188 } 189 190 203 public NodeFilter getFilter() 204 { 205 return null; 206 } 207 208 224 public boolean getExpandEntityReferences() 225 { 226 return true; 227 } 228 229 239 public Node nextNode() throws DOMException 240 { 241 242 if ((m_next) < this.size()) 243 { 244 Node next = this.elementAt(m_next); 245 246 m_next++; 247 248 return next; 249 } 250 else 251 return null; 252 } 253 254 265 public Node previousNode() throws DOMException 266 { 267 268 if (!m_cacheNodes) 269 throw new RuntimeException ( 270 XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_CANNOT_ITERATE, null)); 272 if ((m_next - 1) > 0) 273 { 274 m_next--; 275 276 return this.elementAt(m_next); 277 } 278 else 279 return null; 280 } 281 282 293 public void detach(){} 294 295 303 public boolean isFresh() 304 { 305 return (m_next == 0); 306 } 307 308 320 public void runTo(int index) 321 { 322 323 if (!m_cacheNodes) 324 throw new RuntimeException ( 325 XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_CANNOT_INDEX, null)); 327 if ((index >= 0) && (m_next < m_firstFree)) 328 m_next = index; 329 else 330 m_next = m_firstFree - 1; 331 } 332 333 345 public Node item(int index) 346 { 347 348 runTo(index); 349 350 return (Node ) this.elementAt(index); 351 } 352 353 361 public int getLength() 362 { 363 364 runTo(-1); 365 366 return this.size(); 367 } 368 369 377 public void addNode(Node n) 378 { 379 380 if (!m_mutable) 381 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 383 this.addElement(n); 384 } 385 386 395 public void insertNode(Node n, int pos) 396 { 397 398 if (!m_mutable) 399 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 401 insertElementAt(n, pos); 402 } 403 404 411 public void removeNode(Node n) 412 { 413 414 if (!m_mutable) 415 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 417 this.removeElement(n); 418 } 419 420 429 public void addNodes(NodeList nodelist) 430 { 431 432 if (!m_mutable) 433 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 435 if (null != nodelist) { 437 int nChildren = nodelist.getLength(); 438 439 for (int i = 0; i < nChildren; i++) 440 { 441 Node obj = nodelist.item(i); 442 443 if (null != obj) 444 { 445 addElement(obj); 446 } 447 } 448 } 449 450 } 452 453 469 public void addNodes(NodeSet ns) 470 { 471 472 if (!m_mutable) 473 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 475 addNodes((NodeIterator) ns); 476 } 477 478 486 public void addNodes(NodeIterator iterator) 487 { 488 489 if (!m_mutable) 490 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 492 if (null != iterator) { 494 Node obj; 495 496 while (null != (obj = iterator.nextNode())) 497 { 498 addElement(obj); 499 } 500 } 501 502 } 504 505 514 public void addNodesInDocOrder(NodeList nodelist, XPathContext support) 515 { 516 517 if (!m_mutable) 518 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 520 int nChildren = nodelist.getLength(); 521 522 for (int i = 0; i < nChildren; i++) 523 { 524 Node node = nodelist.item(i); 525 526 if (null != node) 527 { 528 addNodeInDocOrder(node, support); 529 } 530 } 531 } 532 533 542 public void addNodesInDocOrder(NodeIterator iterator, XPathContext support) 543 { 544 545 if (!m_mutable) 546 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 548 Node node; 549 550 while (null != (node = iterator.nextNode())) 551 { 552 addNodeInDocOrder(node, support); 553 } 554 } 555 556 569 private boolean addNodesInDocOrder(int start, int end, int testIndex, 570 NodeList nodelist, XPathContext support) 571 { 572 573 if (!m_mutable) 574 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 576 boolean foundit = false; 577 int i; 578 Node node = nodelist.item(testIndex); 579 580 for (i = end; i >= start; i--) 581 { 582 Node child = (Node ) elementAt(i); 583 584 if (child == node) 585 { 586 i = -2; 588 break; 589 } 590 591 if (!DOM2Helper.isNodeAfter(node, child)) 592 { 593 insertElementAt(node, i + 1); 594 595 testIndex--; 596 597 if (testIndex > 0) 598 { 599 boolean foundPrev = addNodesInDocOrder(0, i, testIndex, nodelist, 600 support); 601 602 if (!foundPrev) 603 { 604 addNodesInDocOrder(i, size() - 1, testIndex, nodelist, support); 605 } 606 } 607 608 break; 609 } 610 } 611 612 if (i == -1) 613 { 614 insertElementAt(node, 0); 615 } 616 617 return foundit; 618 } 619 620 633 public int addNodeInDocOrder(Node node, boolean test, XPathContext support) 634 { 635 636 if (!m_mutable) 637 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 639 int insertIndex = -1; 640 641 if (test) 642 { 643 644 int size = size(), i; 648 649 for (i = size - 1; i >= 0; i--) 650 { 651 Node child = (Node ) elementAt(i); 652 653 if (child == node) 654 { 655 i = -2; 657 break; 658 } 659 660 if (!DOM2Helper.isNodeAfter(node, child)) 661 { 662 break; 663 } 664 } 665 666 if (i != -2) 667 { 668 insertIndex = i + 1; 669 670 insertElementAt(node, insertIndex); 671 } 672 } 673 else 674 { 675 insertIndex = this.size(); 676 677 boolean foundit = false; 678 679 for (int i = 0; i < insertIndex; i++) 680 { 681 if (this.item(i).equals(node)) 682 { 683 foundit = true; 684 685 break; 686 } 687 } 688 689 if (!foundit) 690 addElement(node); 691 } 692 693 return insertIndex; 695 } 697 710 public int addNodeInDocOrder(Node node, XPathContext support) 711 { 712 713 if (!m_mutable) 714 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 716 return addNodeInDocOrder(node, true, support); 717 } 719 720 722 transient protected int m_next = 0; 723 724 732 public int getCurrentPos() 733 { 734 return m_next; 735 } 736 737 743 public void setCurrentPos(int i) 744 { 745 746 if (!m_cacheNodes) 747 throw new RuntimeException ( 748 XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_CANNOT_INDEX, null)); 750 m_next = i; 751 } 752 753 760 public Node getCurrentNode() 761 { 762 763 if (!m_cacheNodes) 764 throw new RuntimeException ( 765 XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_CANNOT_INDEX, null)); 767 int saved = m_next; 768 Node n = (m_next < m_firstFree) ? elementAt(m_next) : null; 769 m_next = saved; return n; 771 } 772 773 774 transient protected boolean m_mutable = true; 775 776 778 transient protected boolean m_cacheNodes = true; 779 780 786 public boolean getShouldCacheNodes() 787 { 788 return m_cacheNodes; 789 } 790 791 802 public void setShouldCacheNodes(boolean b) 803 { 804 805 if (!isFresh()) 806 throw new RuntimeException ( 807 XSLMessages.createXPATHMessage(XPATHErrorResources.ER_CANNOT_CALL_SETSHOULDCACHENODE, null)); 809 m_cacheNodes = b; 810 m_mutable = true; 811 } 812 813 814 transient private int m_last = 0; 815 816 public int getLast() 817 { 818 return m_last; 819 } 820 821 public void setLast(int last) 822 { 823 m_last = last; 824 } 825 826 828 private int m_blocksize; 829 830 832 Node m_map[]; 833 834 836 protected int m_firstFree = 0; 837 838 840 private int m_mapSize; 842 849 public Object clone() throws CloneNotSupportedException 850 { 851 852 NodeSet clone = (NodeSet) super.clone(); 853 854 if ((null != this.m_map) && (this.m_map == clone.m_map)) 855 { 856 clone.m_map = new Node [this.m_map.length]; 857 858 System.arraycopy(this.m_map, 0, clone.m_map, 0, this.m_map.length); 859 } 860 861 return clone; 862 } 863 864 869 public int size() 870 { 871 return m_firstFree; 872 } 873 874 879 public void addElement(Node value) 880 { 881 if (!m_mutable) 882 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 884 if ((m_firstFree + 1) >= m_mapSize) 885 { 886 if (null == m_map) 887 { 888 m_map = new Node [m_blocksize]; 889 m_mapSize = m_blocksize; 890 } 891 else 892 { 893 m_mapSize += m_blocksize; 894 895 Node newMap[] = new Node [m_mapSize]; 896 897 System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1); 898 899 m_map = newMap; 900 } 901 } 902 903 m_map[m_firstFree] = value; 904 905 m_firstFree++; 906 } 907 908 913 public final void push(Node value) 914 { 915 916 int ff = m_firstFree; 917 918 if ((ff + 1) >= m_mapSize) 919 { 920 if (null == m_map) 921 { 922 m_map = new Node [m_blocksize]; 923 m_mapSize = m_blocksize; 924 } 925 else 926 { 927 m_mapSize += m_blocksize; 928 929 Node newMap[] = new Node [m_mapSize]; 930 931 System.arraycopy(m_map, 0, newMap, 0, ff + 1); 932 933 m_map = newMap; 934 } 935 } 936 937 m_map[ff] = value; 938 939 ff++; 940 941 m_firstFree = ff; 942 } 943 944 949 public final Node pop() 950 { 951 952 m_firstFree--; 953 954 Node n = m_map[m_firstFree]; 955 956 m_map[m_firstFree] = null; 957 958 return n; 959 } 960 961 967 public final Node popAndTop() 968 { 969 970 m_firstFree--; 971 972 m_map[m_firstFree] = null; 973 974 return (m_firstFree == 0) ? null : m_map[m_firstFree - 1]; 975 } 976 977 980 public final void popQuick() 981 { 982 983 m_firstFree--; 984 985 m_map[m_firstFree] = null; 986 } 987 988 995 public final Node peepOrNull() 996 { 997 return ((null != m_map) && (m_firstFree > 0)) 998 ? m_map[m_firstFree - 1] : null; 999 } 1000 1001 1009 public final void pushPair(Node v1, Node v2) 1010 { 1011 1012 if (null == m_map) 1013 { 1014 m_map = new Node [m_blocksize]; 1015 m_mapSize = m_blocksize; 1016 } 1017 else 1018 { 1019 if ((m_firstFree + 2) >= m_mapSize) 1020 { 1021 m_mapSize += m_blocksize; 1022 1023 Node newMap[] = new Node [m_mapSize]; 1024 1025 System.arraycopy(m_map, 0, newMap, 0, m_firstFree); 1026 1027 m_map = newMap; 1028 } 1029 } 1030 1031 m_map[m_firstFree] = v1; 1032 m_map[m_firstFree + 1] = v2; 1033 m_firstFree += 2; 1034 } 1035 1036 1041 public final void popPair() 1042 { 1043 1044 m_firstFree -= 2; 1045 m_map[m_firstFree] = null; 1046 m_map[m_firstFree + 1] = null; 1047 } 1048 1049 1056 public final void setTail(Node n) 1057 { 1058 m_map[m_firstFree - 1] = n; 1059 } 1060 1061 1068 public final void setTailSub1(Node n) 1069 { 1070 m_map[m_firstFree - 2] = n; 1071 } 1072 1073 1080 public final Node peepTail() 1081 { 1082 return m_map[m_firstFree - 1]; 1083 } 1084 1085 1092 public final Node peepTailSub1() 1093 { 1094 return m_map[m_firstFree - 2]; 1095 } 1096 1097 1106 public void insertElementAt(Node value, int at) 1107 { 1108 if (!m_mutable) 1109 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 1111 if (null == m_map) 1112 { 1113 m_map = new Node [m_blocksize]; 1114 m_mapSize = m_blocksize; 1115 } 1116 else if ((m_firstFree + 1) >= m_mapSize) 1117 { 1118 m_mapSize += m_blocksize; 1119 1120 Node newMap[] = new Node [m_mapSize]; 1121 1122 System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1); 1123 1124 m_map = newMap; 1125 } 1126 1127 if (at <= (m_firstFree - 1)) 1128 { 1129 System.arraycopy(m_map, at, m_map, at + 1, m_firstFree - at); 1130 } 1131 1132 m_map[at] = value; 1133 1134 m_firstFree++; 1135 } 1136 1137 1142 public void appendNodes(NodeSet nodes) 1143 { 1144 1145 int nNodes = nodes.size(); 1146 1147 if (null == m_map) 1148 { 1149 m_mapSize = nNodes + m_blocksize; 1150 m_map = new Node [m_mapSize]; 1151 } 1152 else if ((m_firstFree + nNodes) >= m_mapSize) 1153 { 1154 m_mapSize += (nNodes + m_blocksize); 1155 1156 Node newMap[] = new Node [m_mapSize]; 1157 1158 System.arraycopy(m_map, 0, newMap, 0, m_firstFree + nNodes); 1159 1160 m_map = newMap; 1161 } 1162 1163 System.arraycopy(nodes.m_map, 0, m_map, m_firstFree, nNodes); 1164 1165 m_firstFree += nNodes; 1166 } 1167 1168 1174 public void removeAllElements() 1175 { 1176 1177 if (null == m_map) 1178 return; 1179 1180 for (int i = 0; i < m_firstFree; i++) 1181 { 1182 m_map[i] = null; 1183 } 1184 1185 m_firstFree = 0; 1186 } 1187 1188 1199 public boolean removeElement(Node s) 1200 { 1201 if (!m_mutable) 1202 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 1204 if (null == m_map) 1205 return false; 1206 1207 for (int i = 0; i < m_firstFree; i++) 1208 { 1209 Node node = m_map[i]; 1210 1211 if ((null != node) && node.equals(s)) 1212 { 1213 if (i < m_firstFree - 1) 1214 System.arraycopy(m_map, i + 1, m_map, i, m_firstFree - i - 1); 1215 1216 m_firstFree--; 1217 m_map[m_firstFree] = null; 1218 1219 return true; 1220 } 1221 } 1222 1223 return false; 1224 } 1225 1226 1234 public void removeElementAt(int i) 1235 { 1236 1237 if (null == m_map) 1238 return; 1239 1240 if (i >= m_firstFree) 1241 throw new ArrayIndexOutOfBoundsException (i + " >= " + m_firstFree); 1242 else if (i < 0) 1243 throw new ArrayIndexOutOfBoundsException (i); 1244 1245 if (i < m_firstFree - 1) 1246 System.arraycopy(m_map, i + 1, m_map, i, m_firstFree - i - 1); 1247 1248 m_firstFree--; 1249 m_map[m_firstFree] = null; 1250 } 1251 1252 1262 public void setElementAt(Node node, int index) 1263 { 1264 if (!m_mutable) 1265 throw new RuntimeException (XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); 1267 if (null == m_map) 1268 { 1269 m_map = new Node [m_blocksize]; 1270 m_mapSize = m_blocksize; 1271 } 1272 1273 m_map[index] = node; 1274 } 1275 1276 1283 public Node elementAt(int i) 1284 { 1285 1286 if (null == m_map) 1287 return null; 1288 1289 return m_map[i]; 1290 } 1291 1292 1299 public boolean contains(Node s) 1300 { 1301 runTo(-1); 1302 1303 if (null == m_map) 1304 return false; 1305 1306 for (int i = 0; i < m_firstFree; i++) 1307 { 1308 Node node = m_map[i]; 1309 1310 if ((null != node) && node.equals(s)) 1311 return true; 1312 } 1313 1314 return false; 1315 } 1316 1317 1328 public int indexOf(Node elem, int index) 1329 { 1330 runTo(-1); 1331 1332 if (null == m_map) 1333 return -1; 1334 1335 for (int i = index; i < m_firstFree; i++) 1336 { 1337 Node node = m_map[i]; 1338 1339 if ((null != node) && node.equals(elem)) 1340 return i; 1341 } 1342 1343 return -1; 1344 } 1345 1346 1356 public int indexOf(Node elem) 1357 { 1358 runTo(-1); 1359 1360 if (null == m_map) 1361 return -1; 1362 1363 for (int i = 0; i < m_firstFree; i++) 1364 { 1365 Node node = m_map[i]; 1366 1367 if ((null != node) && node.equals(elem)) 1368 return i; 1369 } 1370 1371 return -1; 1372 } 1373 1374} 1375 | Popular Tags |