1 18 package org.apache.batik.dom; 19 20 import java.io.Serializable ; 21 22 import org.w3c.dom.DOMException ; 23 import org.w3c.dom.Node ; 24 import org.w3c.dom.NodeList ; 25 import org.w3c.dom.events.DocumentEvent ; 26 import org.w3c.dom.events.MutationEvent ; 27 28 34 35 public abstract class AbstractParentNode extends AbstractNode { 36 37 40 protected ChildNodes childNodes; 41 42 46 public NodeList getChildNodes() { 47 return (childNodes == null) 48 ? childNodes = new ChildNodes() 49 : childNodes; 50 } 51 52 56 public Node getFirstChild() { 57 return (childNodes == null) ? null : childNodes.firstChild; 58 } 59 60 64 public Node getLastChild() { 65 return (childNodes == null) ? null : childNodes.lastChild; 66 } 67 68 72 public Node insertBefore(Node newChild, Node refChild) 73 throws DOMException { 74 if ((refChild != null) && ((childNodes == null) || 75 (refChild.getParentNode() != this))) 76 throw createDOMException 77 (DOMException.NOT_FOUND_ERR, 78 "child.missing", 79 new Object [] { new Integer (refChild.getNodeType()), 80 refChild.getNodeName() }); 81 82 checkAndRemove(newChild, false); 83 84 if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) { 85 Node n = newChild.getFirstChild(); 86 while (n != null) { 87 Node ns = n.getNextSibling(); 88 insertBefore(n, refChild); 89 n = ns; 90 } 91 return newChild; 92 } else { 93 if (childNodes == null) { 95 childNodes = new ChildNodes(); 96 } 97 ExtendedNode n = childNodes.insert((ExtendedNode)newChild, 98 (ExtendedNode)refChild); 99 n.setParentNode(this); 100 101 nodeAdded(n); 102 103 fireDOMNodeInsertedEvent(n); 105 fireDOMSubtreeModifiedEvent(); 106 return n; 107 } 108 } 109 110 114 public Node replaceChild(Node newChild, Node oldChild) 115 throws DOMException { 116 if ((childNodes == null) || (oldChild.getParentNode() != this) ) 117 throw createDOMException 118 (DOMException.NOT_FOUND_ERR, 119 "child.missing", 120 new Object [] { new Integer (oldChild.getNodeType()), 121 oldChild.getNodeName() }); 122 123 checkAndRemove(newChild, true); 124 125 if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) { 126 Node n = newChild.getLastChild(); 127 if (n == null) 128 return newChild; 129 130 Node ps = n.getPreviousSibling(); 131 replaceChild(n, oldChild); 132 Node ns = n; 133 n = ps; 134 while (n != null) { 135 ps = n.getPreviousSibling(); 136 insertBefore(n, ns); 137 ns = n; 138 n = ps; 139 } 140 141 return newChild; 142 } 143 144 fireDOMNodeRemovedEvent(oldChild); 146 147 getCurrentDocument().nodeToBeRemoved(oldChild); 148 nodeToBeRemoved(oldChild); 149 150 ExtendedNode n = (ExtendedNode)newChild; 152 ExtendedNode o = childNodes.replace(n, (ExtendedNode)oldChild); 153 n.setParentNode(this); 154 o.setParentNode(null); 155 156 nodeAdded(n); 157 158 fireDOMNodeInsertedEvent(n); 160 fireDOMSubtreeModifiedEvent(); 161 return n; 162 } 163 164 167 public Node removeChild(Node oldChild) throws DOMException { 168 if (childNodes == null || oldChild.getParentNode() != this) { 169 throw createDOMException 170 (DOMException.NOT_FOUND_ERR, 171 "child.missing", 172 new Object [] { new Integer (oldChild.getNodeType()), 173 oldChild.getNodeName() }); 174 } 175 if (isReadonly()) { 176 throw createDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 177 "readonly.node", 178 new Object [] { new Integer (getNodeType()), 179 getNodeName() }); 180 } 181 182 fireDOMNodeRemovedEvent(oldChild); 184 185 getCurrentDocument().nodeToBeRemoved(oldChild); 186 nodeToBeRemoved(oldChild); 187 188 ExtendedNode result = childNodes.remove((ExtendedNode)oldChild); 190 result.setParentNode(null); 191 192 fireDOMSubtreeModifiedEvent(); 194 return result; 195 } 196 197 200 public Node appendChild(Node newChild) throws DOMException { 201 checkAndRemove(newChild, false); 202 203 if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) { 204 Node n = newChild.getFirstChild(); 205 while (n != null) { 206 Node ns = n.getNextSibling(); 207 appendChild(n); 208 n = ns; 209 } 210 return newChild; 211 } else { 212 if (childNodes == null) 213 childNodes = new ChildNodes(); 214 215 ExtendedNode n = childNodes.append((ExtendedNode)newChild); 217 n.setParentNode(this); 218 219 nodeAdded(n); 220 221 fireDOMNodeInsertedEvent(n); 223 fireDOMSubtreeModifiedEvent(); 224 return n; 225 } 226 } 227 228 232 public boolean hasChildNodes() { 233 return childNodes != null && childNodes.getLength() != 0; 234 } 235 236 239 public void normalize() { 240 Node p = getFirstChild(); 241 if (p != null) { 242 p.normalize(); 243 Node n = p.getNextSibling(); 244 while (n != null) { 245 if (p.getNodeType() == TEXT_NODE && 246 n.getNodeType() == TEXT_NODE) { 247 String s = p.getNodeValue() + n.getNodeValue(); 248 AbstractText at = (AbstractText)p; 249 at.setNodeValue(s); 250 removeChild(n); 251 n = p.getNextSibling(); 252 } else { 253 n.normalize(); 254 p = n; 255 n = n.getNextSibling(); 256 } 257 } 258 } 259 } 260 261 265 public NodeList getElementsByTagName(String name) { 266 if (name == null) { 267 return EMPTY_NODE_LIST; 268 } 269 AbstractDocument ad = getCurrentDocument(); 270 ElementsByTagName result = ad.getElementsByTagName(this, name); 271 if (result == null) { 272 result = new ElementsByTagName(name); 273 ad.putElementsByTagName(this, name, result); 274 } 275 return result; 276 } 277 278 282 public NodeList getElementsByTagNameNS(String namespaceURI, 283 String localName) { 284 if (localName == null) { 285 return EMPTY_NODE_LIST; 286 } 287 AbstractDocument ad = getCurrentDocument(); 288 ElementsByTagNameNS result = 289 ad.getElementsByTagNameNS(this, namespaceURI, 290 localName); 291 if (result == null) { 292 result = new ElementsByTagNameNS(namespaceURI, localName); 293 ad.putElementsByTagNameNS(this, namespaceURI, localName, result); 294 } 295 return result; 296 } 297 298 301 public void fireDOMNodeInsertedIntoDocumentEvent() { 302 AbstractDocument doc = getCurrentDocument(); 303 if (doc.getEventsEnabled()) { 304 super.fireDOMNodeInsertedIntoDocumentEvent(); 305 for (Node n = getFirstChild(); n != null; n = n.getNextSibling()) { 306 ((AbstractNode)n).fireDOMNodeInsertedIntoDocumentEvent(); 307 } 308 } 309 } 310 311 314 public void fireDOMNodeRemovedFromDocumentEvent() { 315 AbstractDocument doc = getCurrentDocument(); 316 if (doc.getEventsEnabled()) { 317 super.fireDOMNodeRemovedFromDocumentEvent(); 318 for (Node n = getFirstChild(); n != null; n = n.getNextSibling()) { 319 ((AbstractNode)n).fireDOMNodeRemovedFromDocumentEvent(); 320 } 321 } 322 } 323 324 327 protected void nodeAdded(Node n) { 328 } 329 330 333 protected void nodeToBeRemoved(Node n) { 334 } 335 336 339 protected Node deepExport(Node n, AbstractDocument d) { 340 super.deepExport(n, d); 341 for (Node p = getFirstChild(); p != null; p = p.getNextSibling()) { 342 Node t = ((AbstractNode)p).deepExport(p.cloneNode(false), d); 343 n.appendChild(t); 344 } 345 return n; 346 } 347 348 352 protected Node deepCopyInto(Node n) { 353 super.deepCopyInto(n); 354 for (Node p = getFirstChild(); p != null; p = p.getNextSibling()) { 355 Node t = p.cloneNode(true); 356 n.appendChild(t); 357 } 358 return n; 359 } 360 361 364 protected void fireDOMSubtreeModifiedEvent() { 365 AbstractDocument doc = getCurrentDocument(); 366 if (doc.getEventsEnabled()) { 367 DocumentEvent de = (DocumentEvent )doc; 368 MutationEvent ev = (MutationEvent )de.createEvent("MutationEvents"); 369 ev.initMutationEvent("DOMSubtreeModified", 370 true, false, null, null, null, null, MutationEvent.MODIFICATION); 377 dispatchEvent(ev); 378 } 379 } 380 381 384 protected void fireDOMNodeInsertedEvent(Node node) { 385 AbstractDocument doc = getCurrentDocument(); 386 if (doc.getEventsEnabled()) { 387 DocumentEvent de = (DocumentEvent )doc; 388 MutationEvent ev = (MutationEvent )de.createEvent("MutationEvents"); 389 ev.initMutationEvent("DOMNodeInserted", 390 true, false, this, null, null, null, MutationEvent.ADDITION); 397 AbstractNode n = (AbstractNode)node; 398 n.dispatchEvent(ev); 399 n.fireDOMNodeInsertedIntoDocumentEvent(); 400 } 401 } 402 403 406 protected void fireDOMNodeRemovedEvent(Node node) { 407 AbstractDocument doc = getCurrentDocument(); 408 if (doc.getEventsEnabled()) { 409 DocumentEvent de = (DocumentEvent )doc; 410 MutationEvent ev = (MutationEvent )de.createEvent("MutationEvents"); 411 ev.initMutationEvent("DOMNodeRemoved", 412 true, false, this, null, null, null, MutationEvent.REMOVAL); 419 AbstractNode n = (AbstractNode)node; 420 n.dispatchEvent(ev); 421 n.fireDOMNodeRemovedFromDocumentEvent(); 422 } 423 } 424 425 429 protected void checkAndRemove(Node n, boolean replace) { 430 checkChildType(n, replace); 431 432 if (isReadonly()) 433 throw createDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 434 "readonly.node", 435 new Object [] { new Integer (getNodeType()), 436 getNodeName() }); 437 438 if (n.getOwnerDocument() != getCurrentDocument()) 439 throw createDOMException(DOMException.WRONG_DOCUMENT_ERR, 440 "node.from.wrong.document", 441 new Object [] { new Integer (getNodeType()), 442 getNodeName() }); 443 if (this == n) 444 throw createDOMException 445 (DOMException.HIERARCHY_REQUEST_ERR, 446 "add.self", new Object [] { getNodeName() }); 447 448 Node np = n.getParentNode(); 449 if (np == null) 450 return; 452 for (Node pn = getParentNode(); pn != null; pn = pn.getParentNode()) { 453 if (pn == n) 454 throw createDOMException 455 (DOMException.HIERARCHY_REQUEST_ERR, 456 "add.ancestor", 457 new Object [] { new Integer (getNodeType()), 458 getNodeName() }); 459 } 460 461 np.removeChild(n); 463 } 464 465 468 protected class ElementsByTagName implements NodeList { 469 470 473 protected Node [] table; 474 475 478 protected int size = -1; 479 480 483 protected String name; 484 485 488 public ElementsByTagName(String n) { 489 name = n; 490 } 491 492 495 public Node item(int index) { 496 if (size == -1) { 497 initialize(); 498 } 499 if (table == null || index < 0 || index >= size) { 500 return null; 501 } 502 return table[index]; 503 } 504 505 509 public int getLength() { 510 if (size == -1) { 511 initialize(); 512 } 513 return size; 514 } 515 516 519 public void invalidate() { 520 size = -1; 521 } 522 523 526 protected void append(Node n) { 527 if (table == null) { 528 table = new Node [11]; 529 } else if (size == table.length - 1) { 530 Node [] t = new Node [table.length * 2 + 1]; 531 for (int i = 0; i < size; i++) { 532 t[i] = table[i]; 533 } 534 table = t; 535 } 536 table[size++] = n; 537 } 538 539 542 protected void initialize() { 543 size = 0; 544 for (Node n = AbstractParentNode.this.getFirstChild(); 545 n != null; 546 n = n.getNextSibling()) { 547 initialize(n); 548 } 549 } 550 551 private void initialize(Node node) { 552 if (node.getNodeType() == ELEMENT_NODE) { 553 String nm = node.getNodeName(); 554 if (name.equals("*") || name.equals(nm)) { 555 append(node); 556 } 557 } 558 for (Node n = node.getFirstChild(); 559 n != null; 560 n = n.getNextSibling()) { 561 initialize(n); 562 } 563 } 564 } 565 566 569 protected class ElementsByTagNameNS implements NodeList { 570 571 574 protected Node [] table; 575 576 579 protected int size = -1; 580 581 584 protected String namespaceURI; 585 586 589 protected String localName; 590 591 594 public ElementsByTagNameNS(String ns, String ln) { 595 namespaceURI = ns; 596 localName = ln; 597 } 598 599 602 public Node item(int index) { 603 if (size == -1) { 604 initialize(); 605 } 606 if (table == null || index < 0 || index > size) { 607 return null; 608 } 609 return table[index]; 610 } 611 612 616 public int getLength() { 617 if (size == -1) { 618 initialize(); 619 } 620 return size; 621 } 622 623 626 public void invalidate() { 627 size = -1; 628 } 629 630 633 protected void append(Node n) { 634 if (table == null) { 635 table = new Node [11]; 636 } else if (size == table.length - 1) { 637 Node [] t = new Node [table.length * 2 + 1]; 638 for (int i = 0; i < size; i++) { 639 t[i] = table[i]; 640 } 641 table = t; 642 } 643 table[size++] = n; 644 } 645 646 649 protected void initialize() { 650 size = 0; 651 for (Node n = AbstractParentNode.this.getFirstChild(); 652 n != null; 653 n = n.getNextSibling()) { 654 initialize(n); 655 } 656 } 657 658 private void initialize(Node node) { 659 if (node.getNodeType() == ELEMENT_NODE) { 660 String ns = node.getNamespaceURI(); 661 String nm = (ns == null) 662 ? node.getNodeName() 663 : node.getLocalName(); 664 if (nsMatch(namespaceURI, node.getNamespaceURI()) && 665 (localName.equals("*") || localName.equals(nm))) { 666 append(node); 667 } 668 } 669 for (Node n = node.getFirstChild(); 670 n != null; 671 n = n.getNextSibling()) { 672 initialize(n); 673 } 674 } 675 676 private boolean nsMatch(String s1, String s2) { 677 if (s1 == null && s2 == null) { 678 return true; 679 } 680 if (s1 == null || s2 == null) { 681 return false; 682 } 683 if (s1.equals("*")) { 684 return true; 685 } 686 return s1.equals(s2); 687 } 688 } 689 690 693 protected class ChildNodes implements NodeList , Serializable { 694 697 protected ExtendedNode firstChild; 698 699 702 protected ExtendedNode lastChild; 703 704 707 protected int children; 708 709 712 public ChildNodes() { 713 } 714 715 718 public Node item(int index) { 719 if (index < 0 || index >= children) { 720 return null; 721 } 722 if (index < (children >> 1)) { 723 Node n = firstChild; 724 for (int i = 0; i < index; i++) { 725 n = n.getNextSibling(); 726 } 727 return n; 728 } else { 729 Node n = lastChild; 730 for (int i = children - 1; i > index; i--) { 731 n = n.getPreviousSibling(); 732 } 733 return n; 734 } 735 } 736 737 741 public int getLength() { 742 return children; 743 } 744 745 749 public ExtendedNode append(ExtendedNode n) { 750 if (lastChild == null) { 751 firstChild = n; 752 } else { 753 lastChild.setNextSibling(n); 754 n.setPreviousSibling(lastChild); 755 } 756 lastChild = n; 757 children++; 758 return n; 759 } 760 761 764 public ExtendedNode insert(ExtendedNode n, ExtendedNode r) { 765 if (r == null) { 766 return append(n); 767 } 768 769 if (r == firstChild) { 770 firstChild.setPreviousSibling(n); 771 n.setNextSibling(firstChild); 772 firstChild = n; 773 children++; 774 return n; 775 } 776 if (r == lastChild) { 777 ExtendedNode ps = (ExtendedNode)r.getPreviousSibling(); 778 ps.setNextSibling(n); 779 r.setPreviousSibling(n); 780 n.setNextSibling(r); 781 n.setPreviousSibling(ps); 782 children++; 783 return n; 784 } 785 786 ExtendedNode ps = (ExtendedNode)r.getPreviousSibling(); 787 if ((ps.getNextSibling() == r) && 788 (ps.getParentNode() == r.getParentNode())) { 789 ps.setNextSibling(n); 790 n.setPreviousSibling(ps); 791 n.setNextSibling(r); 792 r.setPreviousSibling(n); 793 children++; 794 return n; 795 } 796 797 throw createDOMException 798 (DOMException.NOT_FOUND_ERR, 799 "child.missing", 800 new Object [] { new Integer (r.getNodeType()), 801 r.getNodeName() }); 802 } 803 804 807 public ExtendedNode replace(ExtendedNode n, ExtendedNode o) { 808 if (o == firstChild) { 809 ExtendedNode t = (ExtendedNode)firstChild.getNextSibling(); 810 n.setNextSibling(t); 811 if (o == lastChild) { 812 lastChild = n; 813 } else { 814 t.setPreviousSibling(n); 815 } 816 firstChild.setNextSibling(null); 817 firstChild = n; 818 return o; 819 } 820 821 if (o == lastChild) { 822 ExtendedNode t = (ExtendedNode)lastChild.getPreviousSibling(); 823 n.setPreviousSibling(t); 824 t.setNextSibling(n); 825 lastChild.setPreviousSibling(null); 826 lastChild = n; 827 return o; 828 } 829 830 ExtendedNode ps = (ExtendedNode)o.getPreviousSibling(); 831 ExtendedNode ns = (ExtendedNode)o.getNextSibling(); 832 if ((ps.getNextSibling() == o) && 833 (ns.getPreviousSibling() == o) && 834 (ps.getParentNode() == o.getParentNode()) && 835 (ns.getParentNode() == o.getParentNode())) { 836 837 ps.setNextSibling(n); 838 n.setPreviousSibling(ps); 839 n.setNextSibling(ns); 840 ns.setPreviousSibling(n); 841 o.setPreviousSibling(null); 842 o.setNextSibling(null); 843 return o; 844 } 845 throw createDOMException 846 (DOMException.NOT_FOUND_ERR, 847 "child.missing", 848 new Object [] { new Integer (o.getNodeType()), 849 o.getNodeName() }); 850 } 851 852 855 public ExtendedNode remove(ExtendedNode n) { 856 if (n == firstChild) { 857 if (n == lastChild) { 858 firstChild = null; 859 lastChild = null; 860 children--; 861 return n; 862 } 863 firstChild = (ExtendedNode)firstChild.getNextSibling(); 864 firstChild.setPreviousSibling(null); 865 n.setNextSibling(null); 866 children--; 867 return n; 868 } 869 870 if (n == lastChild) { 871 lastChild = (ExtendedNode)lastChild.getPreviousSibling(); 872 lastChild.setNextSibling(null); 873 n.setPreviousSibling(null); 874 children--; 875 return n; 876 } 877 878 ExtendedNode ps = (ExtendedNode)n.getPreviousSibling(); 879 ExtendedNode ns = (ExtendedNode)n.getNextSibling(); 880 if ((ps.getNextSibling() == n) && 881 (ns.getPreviousSibling() == n) && 882 (ps.getParentNode() == n.getParentNode()) && 883 (ns.getParentNode() == n.getParentNode())) { 884 ps.setNextSibling(ns); 885 ns.setPreviousSibling(ps); 886 n.setPreviousSibling(null); 887 n.setNextSibling(null); 888 children--; 889 return n; 890 } 891 throw createDOMException 892 (DOMException.NOT_FOUND_ERR, 893 "child.missing", 894 new Object [] { new Integer (n.getNodeType()), 895 n.getNodeName() }); 896 } 897 } 898 } 899 | Popular Tags |