1 package com.icl.saxon.jdom; 2 import com.icl.saxon.om.NodeInfo; 3 import com.icl.saxon.om.DocumentInfo; 4 import com.icl.saxon.om.AxisEnumeration; 5 import com.icl.saxon.om.NamePool; 6 import com.icl.saxon.om.Axis; 7 import com.icl.saxon.pattern.NodeTest; 8 import com.icl.saxon.pattern.AnyNodeTest; 9 import com.icl.saxon.output.Outputter; 10 import com.icl.saxon.om.EmptyEnumeration; 11 import com.icl.saxon.om.SingletonEnumeration; 12 import org.jdom.*; 13 import javax.xml.transform.TransformerException; 14 15 17 import java.util.List; 18 import java.util.Iterator; 19 import java.util.ListIterator; 20 import java.util.Stack; 21 import java.util.HashMap; 22 23 29 30 public class NodeWrapper implements NodeInfo { 31 32 protected Object node; 33 protected short nodeType; 34 protected NodeWrapper parent; 35 protected DocumentWrapper docWrapper; 36 protected int index; 37 40 public NodeWrapper(Object node, NodeWrapper parent, int index) { 41 this.node = node; 42 this.parent = parent; 43 this.index = index; 44 } 45 46 public NodeWrapper makeWrapper(Object node, NodeWrapper parent, int index) { 47 NodeWrapper wrapper; 48 if (node instanceof Document) { 49 return docWrapper; 50 } else if (node instanceof Element) { 51 wrapper = new NodeWrapper(node, parent, index); 52 wrapper.nodeType = NodeInfo.ELEMENT; 53 } else if (node instanceof Attribute) { 54 wrapper = new NodeWrapper(node, parent, index); 55 wrapper.nodeType = NodeInfo.ATTRIBUTE; 56 } else if (node instanceof String || node instanceof Text) { wrapper = new NodeWrapper(node, parent, index); 58 wrapper.nodeType = NodeInfo.TEXT; 59 } else if (node instanceof CDATA) { 60 wrapper = new NodeWrapper(node, parent, index); 61 wrapper.nodeType = NodeInfo.TEXT; 62 } else if (node instanceof Comment) { 63 wrapper = new NodeWrapper(node, parent, index); 64 wrapper.nodeType = NodeInfo.COMMENT; 65 } else if (node instanceof ProcessingInstruction) { 66 wrapper = new NodeWrapper(node, parent, index); 67 wrapper.nodeType = NodeInfo.PI; 68 } else { 69 throw new IllegalArgumentException("Bad node type in JDOM! " + node.getClass() + " instance " + node.toString()); 70 } 71 wrapper.docWrapper = parent.docWrapper; 72 return wrapper; 73 } 74 75 78 79 public Object getNode() { 80 return node; 81 } 82 83 87 88 public short getNodeType() { 89 return nodeType; 90 } 91 92 98 99 public boolean isSameNode(NodeInfo other) { 100 if (!(other instanceof NodeWrapper)) { 101 return false; 102 } 103 NodeWrapper ow = (NodeWrapper)other; 104 if (nodeType != ow.getNodeType()) { 105 return false; 106 } 107 if (index != ow.index) { 108 return false; 109 } 110 if (node instanceof String) { 111 return parent.isSameNode(ow.parent); 112 } else { 113 return node.equals(ow.node); } 116 } 117 118 124 125 public String getSystemId() { 126 return docWrapper.baseURI; 127 } 128 129 public void setSystemId(String uri) { 130 docWrapper.baseURI = uri; 131 } 132 133 137 138 public String getBaseURI() { 139 return docWrapper.baseURI; 140 } 141 142 146 147 public int getLineNumber() { 148 return -1; 149 } 150 151 159 160 public int compareOrder(NodeInfo other) { 161 162 NodeWrapper ow = (NodeWrapper)other; 163 164 if (this.isSameNode(other)) { 166 return 0; 167 } 168 169 if (this.getParent().isSameNode(other.getParent())) { 171 return this.index - ow.index; 172 } 173 174 176 int depth1 = 0; 177 int depth2 = 0; 178 NodeInfo p1 = this; 179 NodeInfo p2 = other; 180 while (p1 != null) { 181 depth1++; 182 p1 = p1.getParent(); 183 } 184 while (p2 != null) { 185 depth2++; 186 p2 = p2.getParent(); 187 } 188 189 191 p1 = this; 192 while (depth1>depth2) { 193 p1 = p1.getParent(); 194 if (p1.isSameNode(ow)) { 195 return +1; 196 } 197 depth1--; 198 } 199 200 p2 = ow; 201 while (depth2>depth1) { 202 p2 = p2.getParent(); 203 if (p2.isSameNode(this)) { 204 return -1; 205 } 206 depth2--; 207 } 208 209 while (true) { 211 NodeInfo par1 = p1.getParent(); 212 NodeInfo par2 = p2.getParent(); 213 if (par1==null || par2==null) { 214 throw new NullPointerException("JDOM tree compare - internal error"); 215 } 216 if (par1.isSameNode(par2)) { 217 return ((NodeWrapper)p1).index - ((NodeWrapper)p2).index; 218 } 219 p1 = par1; 220 p2 = par2; 221 } 222 } 223 224 230 231 public String getStringValue() { 232 switch (nodeType) { 233 case NodeInfo.ROOT: 234 List children1 = ((Document)node).getContent(); 235 StringBuffer sb1 = new StringBuffer(); 236 expandStringValue(children1, sb1); 237 return sb1.toString(); 238 239 case NodeInfo.ELEMENT: 240 List children2 = ((Element)node).getContent(); 241 StringBuffer sb2 = new StringBuffer(); 242 expandStringValue(children2, sb2); 243 return sb2.toString(); 244 245 case NodeInfo.ATTRIBUTE: 246 return ((Attribute)node).getValue(); 247 248 case NodeInfo.TEXT: 249 if (node instanceof String) return (String)node; 250 if (node instanceof Text) return ((Text)node).getText(); 251 if (node instanceof CDATA) return ((CDATA)node).getText(); 252 return ""; 253 254 case NodeInfo.COMMENT: 255 return ((Comment)node).getText(); 256 257 case NodeInfo.PI: 258 return ((ProcessingInstruction)node).getData(); 259 260 case NodeInfo.NAMESPACE: 261 return ((Namespace)node).getURI(); 262 263 default: 264 return ""; 265 } 266 } 267 268 private static void expandStringValue(List list, StringBuffer sb) { 269 Iterator iter = list.iterator(); 270 while (iter.hasNext()) { 271 Object obj = iter.next(); 272 if (obj instanceof Element) { 273 expandStringValue(((Element)obj).getContent(), sb); 274 } else if (obj instanceof String) { sb.append((String)obj); 276 } else if (obj instanceof Text) { sb.append(((Text)obj).getText()); 278 } else if (obj instanceof CDATA) { 279 sb.append(((CDATA)obj).getText()); 280 } else if (obj instanceof EntityRef) { 281 throw new IllegalStateException("Unexpanded entity in JDOM tree"); 282 } 283 } 284 } 285 286 294 295 public int getNameCode() { 296 switch (nodeType) { 297 case ELEMENT: 298 case ATTRIBUTE: 299 case PI: 300 return docWrapper.namePool.allocate(getPrefix(), 301 getURI(), 302 getLocalName()); 303 default: 304 return -1; 305 } 306 } 307 308 314 315 public int getFingerprint() { 316 return getNameCode()&0xfffff; 317 } 318 319 323 324 public String getLocalName() { 325 switch (nodeType) { 326 case NodeInfo.ELEMENT: 327 return ((Element)node).getName(); 328 case NodeInfo.ATTRIBUTE: 329 return ((Attribute)node).getName(); 330 case NodeInfo.TEXT: 331 case NodeInfo.COMMENT: 332 case NodeInfo.ROOT: 333 return ""; 334 case NodeInfo.PI: 335 return ((ProcessingInstruction)node).getTarget(); 336 case NodeInfo.NAMESPACE: 337 return ((Namespace)node).getPrefix(); 338 default: 339 return ""; 340 } 341 } 342 343 347 348 public String getPrefix() { 349 switch (nodeType) { 350 case NodeInfo.ELEMENT: 351 return ((Element)node).getNamespacePrefix(); 352 case NodeInfo.ATTRIBUTE: 353 return ((Attribute)node).getNamespacePrefix(); 354 default: 355 return ""; 356 } 357 } 358 359 365 366 public String getURI() { 367 switch (nodeType) { 368 case NodeInfo.ELEMENT: 369 return ((Element)node).getNamespaceURI(); 370 case NodeInfo.ATTRIBUTE: 371 return ((Attribute)node).getNamespaceURI(); 372 default: 373 return ""; 374 } 375 } 376 377 383 384 public String getDisplayName() { 385 switch (nodeType) { 386 case NodeInfo.ELEMENT: 387 return ((Element)node).getQualifiedName(); 388 case NodeInfo.ATTRIBUTE: 389 return ((Attribute)node).getQualifiedName(); 390 case NodeInfo.PI: 391 case NodeInfo.NAMESPACE: 392 return getLocalName(); 393 default: 394 return ""; 395 396 } 397 } 398 399 402 403 public NodeInfo getParent() { 404 return parent; 405 } 406 407 414 415 public AxisEnumeration getEnumeration(byte axisNumber, NodeTest nodeTest) { 416 switch (axisNumber) { 417 case Axis.ANCESTOR: 418 if (nodeType==ROOT) return EmptyEnumeration.getInstance(); 419 return new FilterEnumeration( 420 new AncestorEnumeration(this, false), 421 nodeTest); 422 423 case Axis.ANCESTOR_OR_SELF: 424 if (nodeType==ROOT) return EmptyEnumeration.getInstance(); 425 return new FilterEnumeration( 426 new AncestorEnumeration(this, true), 427 nodeTest); 428 429 case Axis.ATTRIBUTE: 430 if (nodeType!=ELEMENT) return EmptyEnumeration.getInstance(); 431 return new FilterEnumeration( 432 new AttributeEnumeration(this), 433 nodeTest); 434 435 case Axis.CHILD: 436 if (hasChildNodes()) { 437 return new FilterEnumeration( 438 new ChildEnumeration(this, true, true), 439 nodeTest); 440 } else { 441 return EmptyEnumeration.getInstance(); 442 } 443 444 case Axis.DESCENDANT: 445 if (hasChildNodes()) { 446 return new FilterEnumeration( 447 new DescendantEnumeration(this, false, true), 448 nodeTest); 449 } else { 450 return EmptyEnumeration.getInstance(); 451 } 452 453 case Axis.DESCENDANT_OR_SELF: 454 return new FilterEnumeration( 455 new DescendantEnumeration(this, true, true), 456 nodeTest); 457 458 case Axis.FOLLOWING: 459 return new FilterEnumeration( 460 new FollowingEnumeration(this), 461 nodeTest); 462 463 case Axis.FOLLOWING_SIBLING: 464 switch (nodeType) { 465 case ROOT: 466 case ATTRIBUTE: 467 case NAMESPACE: 468 return EmptyEnumeration.getInstance(); 469 default: 470 return new FilterEnumeration( 471 new ChildEnumeration(this, false, true), 472 nodeTest); 473 } 474 475 case Axis.NAMESPACE: 476 if (nodeType!=ELEMENT) return EmptyEnumeration.getInstance(); 477 return new FilterEnumeration( 478 new NamespaceEnumeration(this), 479 nodeTest); 480 483 case Axis.PARENT: 484 if (parent==null) return EmptyEnumeration.getInstance(); 485 if (nodeTest.matches(parent)) return new SingletonEnumeration(parent); 486 return EmptyEnumeration.getInstance(); 487 488 case Axis.PRECEDING: 489 return new FilterEnumeration( 490 new PrecedingEnumeration(this, false), 491 nodeTest); 492 493 case Axis.PRECEDING_SIBLING: 494 switch (nodeType) { 495 case ROOT: 496 case ATTRIBUTE: 497 case NAMESPACE: 498 return EmptyEnumeration.getInstance(); 499 default: 500 return new FilterEnumeration( 501 new ChildEnumeration(this, false, false), 502 nodeTest); 503 } 504 505 case Axis.SELF: 506 if (nodeTest.matches(this)) return new SingletonEnumeration(this); 507 return EmptyEnumeration.getInstance(); 508 509 case Axis.PRECEDING_OR_ANCESTOR: 510 return new FilterEnumeration( 511 new PrecedingEnumeration(this, true), 512 nodeTest); 513 514 default: 515 throw new IllegalArgumentException("Unknown axis number " + axisNumber); 516 } 517 } 518 519 527 528 public String getAttributeValue(String uri, String localName) { 529 if (nodeType==NodeInfo.ELEMENT) { 530 Namespace ns = Namespace.getNamespace(uri); 531 return ((Element)node).getAttributeValue(localName, ns); 532 } else { 533 return ""; 534 } 535 } 536 537 542 543 public String getAttributeValue(int fingerprint) { 544 if (nodeType==NodeInfo.ELEMENT) { 545 Iterator list = ((Element)node).getAttributes().iterator(); 546 NamePool pool = docWrapper.getNamePool(); 547 while (list.hasNext()) { 548 Attribute att = (Attribute)list.next(); 549 int nameCode = pool.allocate(att.getNamespacePrefix(), 550 att.getNamespaceURI(), 551 att.getName()); 552 if (fingerprint == (nameCode & 0xfffff)) { 553 return att.getValue(); 554 } 555 } 556 } 557 return null; 558 } 559 560 564 565 public DocumentInfo getDocumentRoot() { 566 return docWrapper; 567 } 568 569 574 575 public boolean hasChildNodes() { 576 switch (nodeType) { 577 case NodeInfo.ROOT: 578 return true; 579 case NodeInfo.ELEMENT: 580 return !((Element)node).getContent().isEmpty(); 581 default: 582 return false; 583 } 584 } 585 592 593 public String generateId() { 594 if (node instanceof String || node instanceof Text) { 595 return parent.generateId() + "text" + index; 596 } else { 597 return "j" + node.hashCode(); 598 } 599 } 600 601 604 605 public void copy(Outputter out) throws TransformerException { 606 607 610 switch (nodeType) { 611 case NodeInfo.ROOT: 612 AxisEnumeration children0 = getEnumeration(Axis.CHILD, new AnyNodeTest()); 613 while (children0.hasMoreElements()) { 614 children0.nextElement().copy(out); 615 } 616 return; 617 618 case NodeInfo.ELEMENT: 619 int nc = getNameCode(); 620 out.writeStartTag(nc); 621 622 624 outputNamespaceNodes(out, true); 625 626 628 AxisEnumeration attributes = getEnumeration(Axis.ATTRIBUTE, new AnyNodeTest()); 629 while (attributes.hasMoreElements()) { 630 attributes.nextElement().copy(out); 631 } 632 633 635 AxisEnumeration children = getEnumeration(Axis.CHILD, new AnyNodeTest()); 636 while (children.hasMoreElements()) { 637 children.nextElement().copy(out); 638 } 639 640 642 out.writeEndTag(nc); 643 return; 644 645 case NodeInfo.ATTRIBUTE: 646 out.writeAttribute(getNameCode(), getStringValue()); 647 return; 648 649 case NodeInfo.TEXT: 650 out.writeContent(getStringValue()); 651 return; 652 653 case NodeInfo.COMMENT: 654 out.writeComment(getStringValue()); 655 return; 656 657 case NodeInfo.PI: 658 out.writePI(getLocalName(), getStringValue()); 659 return; 660 661 case NodeInfo.NAMESPACE: 662 throw new IllegalArgumentException("Copying Namespace node!"); 663 664 default: 665 666 } 667 } 668 669 672 673 public void copyStringValue(Outputter out) throws TransformerException { 674 out.writeContent(getStringValue()); 675 } 676 677 684 685 public void outputNamespaceNodes(Outputter out, boolean includeAncestors) 686 throws TransformerException { 687 if (nodeType==ELEMENT) { 689 NamePool pool = docWrapper.getNamePool(); 690 AxisEnumeration enum = getEnumeration(Axis.NAMESPACE, 691 AnyNodeTest.getInstance()); 692 while (enum.hasMoreElements()) { 693 Namespace ns = (Namespace)((NodeWrapper)enum.nextElement()).node; 694 int nscode = pool.allocateNamespaceCode( 695 ns.getPrefix(), 696 ns.getURI()); 697 out.writeNamespaceDeclaration(nscode); 698 } 699 } 700 } 701 702 706 private class FilterEnumeration implements AxisEnumeration { 707 private BaseEnumeration base; 708 private NodeTest nodeTest; 709 private NodeInfo next; 710 private int last = -1; 711 712 public FilterEnumeration(BaseEnumeration base, NodeTest test) { 713 this.base = base; 714 this.nodeTest = test; 715 advance(); 716 } 717 718 public void advance() { 719 while (base.hasMoreElements()) { 720 next = base.nextElement(); 721 if (nodeTest.matches(next)) return; 722 } 723 next = null; 724 } 725 726 public NodeInfo nextElement() { 727 NodeInfo n = next; 728 advance(); 729 return n; 730 } 731 732 public boolean hasMoreElements() { 733 return next!=null; 734 } 735 736 public int getLastPosition() { 737 738 742 if (last>=0) { 743 return last; 744 } 745 last = 0; 746 BaseEnumeration b = base.copy(); 747 while (b.hasMoreElements()) { 748 NodeInfo n = b.nextElement(); 749 if (nodeTest.matches(n)) { 750 last++; 751 } 752 } 753 return last; 754 } 755 756 public boolean isSorted() { 757 return base.isSorted(); 758 } 759 760 public boolean isReverseSorted() { 761 return base.isReverseSorted(); 762 } 763 764 public boolean isPeer() { 765 return base.isPeer(); 766 } 767 } 768 769 private abstract class BaseEnumeration implements AxisEnumeration { 770 771 protected NodeWrapper next; 772 773 public final boolean hasMoreElements() { 774 return next!=null; 775 } 776 777 public final NodeInfo nextElement() { 778 NodeInfo n = next; 779 advance(); 780 return n; 781 } 782 783 public abstract void advance(); 784 785 public abstract BaseEnumeration copy(); 786 787 public final int getLastPosition() { return 1; 789 } 790 791 public boolean isSorted() { 792 return true; 793 } 794 795 public final boolean isReverseSorted() { 796 return !isSorted(); 797 } 798 799 public boolean isPeer() { 800 return false; 801 } 802 } 803 804 805 final class AncestorEnumeration extends BaseEnumeration { 806 807 private boolean includeSelf; 808 private NodeWrapper start; 809 810 public AncestorEnumeration(NodeWrapper start, boolean includeSelf) { 811 this.start = start; 812 this.includeSelf = includeSelf; 813 this.next = start; 814 if (!includeSelf) { 815 advance(); 816 } 817 } 818 819 public void advance() { 820 next=(NodeWrapper)next.getParent(); 821 } 822 823 public boolean isSorted() { 824 return false; 825 } 826 827 public boolean isPeer() { 828 return false; 829 } 830 831 public BaseEnumeration copy() { 832 return new AncestorEnumeration(start, includeSelf); 833 } 834 835 } 837 private final class AttributeEnumeration extends BaseEnumeration { 838 839 private Iterator atts; 840 private int ix = 0; 841 private NodeWrapper start; 842 843 public AttributeEnumeration(NodeWrapper start) { 844 this.start = start; 845 atts = ((Element)start.node).getAttributes().iterator(); 846 advance(); 847 } 848 849 public void advance() { 850 if (atts.hasNext()) { 851 next = makeWrapper(atts.next(), start, ix++); 852 } else { 853 next = null; 854 } 855 } 856 857 public boolean isPeer() { 858 return true; 859 } 860 861 public BaseEnumeration copy() { 862 return new AttributeEnumeration(start); 863 } 864 865 } 867 private final class NamespaceEnumeration extends BaseEnumeration { 868 869 private HashMap nslist = new HashMap(); 870 private Iterator prefixes; 871 private int ix = 0; 872 private NodeWrapper start; 873 874 public NamespaceEnumeration(NodeWrapper start) { 875 this.start = start; 876 NodeWrapper curr = start; 877 878 880 do { 881 Element elem = (Element)curr.node; 882 Namespace ns = elem.getNamespace(); 883 if (nslist.containsKey(ns.getPrefix())) { 884 nslist.put(ns.getPrefix(), ns); 885 } 886 List addl = elem.getAdditionalNamespaces(); 887 if (addl.size() > 0) { 888 Iterator itr = addl.iterator(); 889 while (itr.hasNext()) { 890 ns = (Namespace) itr.next(); 891 if (nslist.containsKey(ns.getPrefix())) { 892 nslist.put(ns.getPrefix(), ns); 893 } 894 } 895 } 896 curr = (NodeWrapper)curr.getParent(); 897 } while (curr.getNodeType()==ELEMENT); 898 899 nslist.put("xml", Namespace.XML_NAMESPACE); 900 prefixes = nslist.keySet().iterator(); 901 } 902 903 public void advance() { 904 if (prefixes.hasNext()) { 905 String prefix = (String)prefixes.next(); 906 Namespace ns = (Namespace)nslist.get(prefix); 907 next = makeWrapper(ns, start, ix++); 908 } else { 909 next = null; 910 } 911 } 912 913 public boolean isPeer() { 914 return true; 915 } 916 917 public BaseEnumeration copy() { 918 return new NamespaceEnumeration(start); 919 } 920 921 } 923 924 930 931 private class ChildEnumeration extends BaseEnumeration { 932 933 private NodeWrapper start; 934 private NodeWrapper commonParent; 935 private ListIterator children; 936 private int ix = 0; 937 private boolean downwards; private boolean forwards; 940 public ChildEnumeration(NodeWrapper start, 941 boolean downwards, boolean forwards) { 942 this.start = start; 943 this.downwards = downwards; 944 this.forwards = forwards; 945 946 if (downwards) { 947 commonParent = start; 948 } else { 949 commonParent = (NodeWrapper)start.getParent(); 950 } 951 952 if (commonParent.getNodeType()==ROOT) { 953 children = ((Document)commonParent.node).getContent().listIterator(); 954 } else { 955 children = ((Element)commonParent.node).getContent().listIterator(); 956 } 957 958 if (downwards) { 959 if (!forwards) { 960 while (children.hasNext()) { 962 children.next(); 963 ix++; 964 } 965 } 966 } else { 967 ix = start.index; 968 if (forwards) { 970 for (int i=0; i<=ix; i++) { 971 children.next(); 972 } 973 ix++; 974 } else { 975 for (int i=0; i<ix; i++) { 976 children.next(); 977 } 978 ix--; 979 } 980 } 981 advance(); 982 } 983 984 985 986 public void advance() { 987 if (forwards) { 988 if (children.hasNext()) { 989 Object nextChild = children.next(); 990 if (nextChild instanceof EntityRef) { 991 throw new IllegalStateException("Unexpanded entity in JDOM tree"); 992 } else { 993 next = makeWrapper(nextChild, commonParent, ix++); 994 } 995 } else { 996 next = null; 997 } 998 } else { if (children.hasPrevious()) { 1000 Object nextChild = children.previous(); 1001 if (nextChild instanceof EntityRef) { 1002 throw new IllegalStateException("Unexpanded entity in JDOM tree"); 1003 } else { 1004 next = makeWrapper(nextChild, commonParent, ix--); 1005 } 1006 } else { 1007 next = null; 1008 } 1009 } 1010 } 1011 1012 public boolean isSorted() { 1013 return forwards; 1014 } 1015 1016 public boolean isPeer() { 1017 return true; 1018 } 1019 1020 public BaseEnumeration copy() { 1021 return new ChildEnumeration(start, downwards, forwards); 1022 } 1023 1024 } 1026 1033 1034 private final class DescendantEnumeration extends BaseEnumeration { 1035 1036 private AxisEnumeration children = null; 1037 private AxisEnumeration descendants = null; 1038 private NodeWrapper start; 1039 private boolean includeSelf; 1040 private boolean forwards; 1041 private boolean atEnd = false; 1042 1043 public DescendantEnumeration(NodeWrapper start, 1044 boolean includeSelf, boolean forwards) { 1045 this.start = start; 1046 this.includeSelf = includeSelf; 1047 this.forwards = forwards; 1048 advance(); 1049 } 1050 1051 public void advance() { 1052 if (descendants!=null) { 1053 if (descendants.hasMoreElements()) { 1054 next = (NodeWrapper)descendants.nextElement(); 1055 return; 1056 } else { 1057 descendants = null; 1058 } 1059 } 1060 if (children!=null) { 1061 if (children.hasMoreElements()) { 1062 NodeWrapper n = (NodeWrapper)children.nextElement(); 1063 if (n.hasChildNodes()) { 1064 if (forwards) { 1065 descendants = new DescendantEnumeration(n, 1066 false, forwards); 1067 next = n; 1068 } else { 1069 descendants = new DescendantEnumeration(n, true, forwards); 1070 advance(); 1071 } 1072 } else { 1073 next = n; 1074 } 1075 } else { 1076 if (forwards || !includeSelf) { 1077 next = null; 1078 } else { 1079 atEnd = true; 1080 children = null; 1081 next = start; 1082 } 1083 } 1084 } else if (atEnd) { 1085 next = null; 1087 } else { 1088 if (start.hasChildNodes()) { 1090 children = new ChildEnumeration(start, true, forwards); 1091 } else { 1092 children = EmptyEnumeration.getInstance(); 1093 } 1094 if (forwards && includeSelf) { 1095 next = start; 1096 } else { 1097 advance(); 1098 } 1099 } 1100 } 1101 1102 public boolean isSorted() { 1103 return forwards; 1104 } 1105 1106 public boolean isPeer() { 1107 return false; 1108 } 1109 1110 public BaseEnumeration copy() { 1111 return new DescendantEnumeration(start, includeSelf, forwards); 1112 } 1113 1114 } 1116 private class FollowingEnumeration extends BaseEnumeration { 1117 1118 private NodeWrapper start; 1119 private AxisEnumeration ancestorEnum = null; 1120 private AxisEnumeration siblingEnum = null; 1121 private AxisEnumeration descendEnum = null; 1122 1123 public FollowingEnumeration(NodeWrapper start) { 1124 this.start = start; 1125 ancestorEnum = new AncestorEnumeration(start, false); 1126 switch (start.getNodeType()) { 1127 case ELEMENT: 1128 case TEXT: 1129 case COMMENT: 1130 case PI: 1131 siblingEnum = new ChildEnumeration(start, false, true); 1132 break; 1133 case ATTRIBUTE: 1134 case NAMESPACE: 1135 siblingEnum = new ChildEnumeration((NodeWrapper)start.getParent(), true, true); 1136 break; 1138 default: 1139 siblingEnum = EmptyEnumeration.getInstance(); 1140 } 1141 advance(); 1142 } 1143 1144 public void advance() { 1145 if (descendEnum!=null) { 1146 if (descendEnum.hasMoreElements()) { 1147 next = (NodeWrapper)descendEnum.nextElement(); 1148 return; 1149 } else { 1150 descendEnum = null; 1151 } 1152 } 1153 if (siblingEnum!=null) { 1154 if (siblingEnum.hasMoreElements()) { 1155 next = (NodeWrapper)siblingEnum.nextElement(); 1156 if (next.hasChildNodes()) { 1157 descendEnum = new DescendantEnumeration(next, false, true); 1158 } else { 1159 descendEnum = null; 1160 } 1161 return; 1162 } else { 1163 descendEnum = null; 1164 siblingEnum = null; 1165 } 1166 } 1167 if (ancestorEnum.hasMoreElements()) { 1168 next = (NodeWrapper)ancestorEnum.nextElement(); 1169 if (next.getNodeType() == ROOT) { 1170 siblingEnum = EmptyEnumeration.getInstance(); 1171 } else { 1172 siblingEnum = new ChildEnumeration(next, false, true); 1173 } 1174 advance(); 1175 } else { 1176 next = null; 1177 } 1178 } 1179 1180 public boolean isSorted() { 1181 return true; 1182 } 1183 1184 public boolean isPeer() { 1185 return false; 1186 } 1187 1188 public BaseEnumeration copy() { 1189 return new FollowingEnumeration(start); 1190 } 1191 1192 } 1194 private class PrecedingEnumeration extends BaseEnumeration { 1195 1196 private NodeWrapper start; 1197 private AxisEnumeration ancestorEnum = null; 1198 private AxisEnumeration siblingEnum = null; 1199 private AxisEnumeration descendEnum = null; 1200 private boolean includeAncestors; 1201 1202 public PrecedingEnumeration(NodeWrapper start, boolean includeAncestors) { 1203 this.start = start; 1204 this.includeAncestors = includeAncestors; 1205 ancestorEnum = new AncestorEnumeration(start, false); 1206 switch (start.getNodeType()) { 1207 case ELEMENT: 1208 case TEXT: 1209 case COMMENT: 1210 case PI: 1211 siblingEnum = new ChildEnumeration(start, false, false); 1213 break; 1214 default: 1215 siblingEnum = EmptyEnumeration.getInstance(); 1216 } 1217 advance(); 1218 } 1219 1220 public void advance() { 1221 if (descendEnum!=null) { 1222 if (descendEnum.hasMoreElements()) { 1223 next = (NodeWrapper)descendEnum.nextElement(); 1224 return; 1225 } else { 1226 descendEnum = null; 1227 } 1228 } 1229 if (siblingEnum!=null) { 1230 if (siblingEnum.hasMoreElements()) { 1231 NodeWrapper sib = (NodeWrapper)siblingEnum.nextElement(); 1232 if (sib.hasChildNodes()) { 1233 descendEnum = new DescendantEnumeration(sib, true, false); 1234 advance(); 1235 } else { 1236 descendEnum = null; 1237 next = sib; 1238 } 1239 return; 1240 } else { 1241 descendEnum = null; 1242 siblingEnum = null; 1243 } 1244 } 1245 if (ancestorEnum.hasMoreElements()) { 1246 next = (NodeWrapper)ancestorEnum.nextElement(); 1247 if (next.getNodeType() == ROOT) { 1248 siblingEnum = EmptyEnumeration.getInstance(); 1249 } else { 1250 siblingEnum = new ChildEnumeration(next, false, false); 1251 } 1252 if (!includeAncestors) { 1253 advance(); 1254 } 1255 } else { 1256 next = null; 1257 } 1258 } 1259 1260 public boolean isSorted() { 1261 return false; 1262 } 1263 1264 public boolean isPeer() { 1265 return false; 1266 } 1267 1268 public BaseEnumeration copy() { 1269 return new PrecedingEnumeration(start, includeAncestors); 1270 } 1271 1272 } 1274} 1275 1276 | Popular Tags |