1 /* 2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.imageio.metadata; 27 28 import java.util.ArrayList; 29 import java.util.Iterator; 30 import java.util.List; 31 32 import org.w3c.dom.Attr; 33 import org.w3c.dom.Document; 34 import org.w3c.dom.Element; 35 import org.w3c.dom.DOMException; 36 import org.w3c.dom.NamedNodeMap; 37 import org.w3c.dom.Node; 38 import org.w3c.dom.NodeList; 39 import org.w3c.dom.TypeInfo; 40 import org.w3c.dom.UserDataHandler; 41 42 43 class IIODOMException extends DOMException { 44 45 public IIODOMException(short code, String message) { 46 super(code, message); 47 } 48 } 49 50 class IIONamedNodeMap implements NamedNodeMap { 51 52 List nodes; 53 54 public IIONamedNodeMap(List nodes) { 55 this.nodes = nodes; 56 } 57 58 public int getLength() { 59 return nodes.size(); 60 } 61 62 public Node getNamedItem(String name) { 63 Iterator iter = nodes.iterator(); 64 while (iter.hasNext()) { 65 Node node = (Node)iter.next(); 66 if (name.equals(node.getNodeName())) { 67 return node; 68 } 69 } 70 71 return null; 72 } 73 74 public Node item(int index) { 75 Node node = (Node)nodes.get(index); 76 return node; 77 } 78 79 public Node removeNamedItem(java.lang.String name) { 80 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 81 "This NamedNodeMap is read-only!"); 82 } 83 84 public Node setNamedItem(Node arg) { 85 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 86 "This NamedNodeMap is read-only!"); 87 } 88 89 /** 90 * Equivalent to <code>getNamedItem(localName)</code>. 91 */ 92 public Node getNamedItemNS(String namespaceURI, String localName) { 93 return getNamedItem(localName); 94 } 95 96 /** 97 * Equivalent to <code>setNamedItem(arg)</code>. 98 */ 99 public Node setNamedItemNS(Node arg) { 100 return setNamedItem(arg); 101 } 102 103 /** 104 * Equivalent to <code>removeNamedItem(localName)</code>. 105 */ 106 public Node removeNamedItemNS(String namespaceURI, String localName) { 107 return removeNamedItem(localName); 108 } 109 } 110 111 class IIONodeList implements NodeList { 112 113 List nodes; 114 115 public IIONodeList(List nodes) { 116 this.nodes = nodes; 117 } 118 119 public int getLength() { 120 return nodes.size(); 121 } 122 123 public Node item(int index) { 124 if (index < 0 || index > nodes.size()) { 125 return null; 126 } 127 return (Node)nodes.get(index); 128 } 129 } 130 131 class IIOAttr extends IIOMetadataNode implements Attr { 132 133 Element owner; 134 String name; 135 String value; 136 137 public IIOAttr(Element owner, String name, String value) { 138 this.owner = owner; 139 this.name = name; 140 this.value = value; 141 } 142 143 public String getName() { 144 return name; 145 } 146 147 public String getNodeName() { 148 return name; 149 } 150 151 public short getNodeType() { 152 return ATTRIBUTE_NODE; 153 } 154 155 public boolean getSpecified() { 156 return true; 157 } 158 159 public String getValue() { 160 return value; 161 } 162 163 public String getNodeValue() { 164 return value; 165 } 166 167 public void setValue(String value) { 168 this.value = value; 169 } 170 171 public void setNodeValue(String value) { 172 this.value = value; 173 } 174 175 public Element getOwnerElement() { 176 return owner; 177 } 178 179 public void setOwnerElement(Element owner) { 180 this.owner = owner; 181 } 182 183 /** This method is new in the DOM L3 for Attr interface. 184 * Could throw DOMException here, but its probably OK 185 * to always return false. One reason for this, is we have no good 186 * way to document this exception, since this class, IIOAttr, 187 * is not a public class. The rest of the methods that throw 188 * DOMException are publically documented as such on IIOMetadataNode. 189 * @return false 190 */ 191 public boolean isId() { 192 return false; 193 } 194 195 196 } 197 198 /** 199 * A class representing a node in a meta-data tree, which implements 200 * the <a 201 * href="../../../../api/org/w3c/dom/Element.html"> 202 * <code>org.w3c.dom.Element</code></a> interface and additionally allows 203 * for the storage of non-textual objects via the 204 * <code>getUserObject</code> and <code>setUserObject</code> methods. 205 * 206 * <p> This class is not intended to be used for general XML 207 * processing. In particular, <code>Element</code> nodes created 208 * within the Image I/O API are not compatible with those created by 209 * Sun's standard implementation of the <code>org.w3.dom</code> API. 210 * In particular, the implementation is tuned for simple uses and may 211 * not perform well for intensive processing. 212 * 213 * <p> Namespaces are ignored in this implementation. The terms "tag 214 * name" and "node name" are always considered to be synonymous. 215 * 216 * <em>Note:</em> 217 * The DOM Level 3 specification added a number of new methods to the 218 * {@code Node}, {@code Element} and {@code Attr} interfaces that are not 219 * of value to the {@code IIOMetadataNode} implementation or specification. 220 * 221 * Calling such methods on an {@code IIOMetadataNode}, or an {@code Attr} 222 * instance returned from an {@code IIOMetadataNode} will result in a 223 * {@code DOMException} being thrown. 224 * 225 * @see IIOMetadata#getAsTree 226 * @see IIOMetadata#setFromTree 227 * @see IIOMetadata#mergeTree 228 * 229 */ 230 public class IIOMetadataNode implements Element, NodeList { 231 232 /** 233 * The name of the node as a <code>String</code>. 234 */ 235 private String nodeName = null; 236 237 /** 238 * The value of the node as a <code>String</code>. The Image I/O 239 * API typically does not make use of the node value. 240 */ 241 private String nodeValue = null; 242 243 /** 244 * The <code>Object</code> value associated with this node. 245 */ 246 private Object userObject = null; 247 248 /** 249 * The parent node of this node, or <code>null</code> if this node 250 * forms the root of its own tree. 251 */ 252 private IIOMetadataNode parent = null; 253 254 /** 255 * The number of child nodes. 256 */ 257 private int numChildren = 0; 258 259 /** 260 * The first (leftmost) child node of this node, or 261 * <code>null</code> if this node is a leaf node. 262 */ 263 private IIOMetadataNode firstChild = null; 264 265 /** 266 * The last (rightmost) child node of this node, or 267 * <code>null</code> if this node is a leaf node. 268 */ 269 private IIOMetadataNode lastChild = null; 270 271 /** 272 * The next (right) sibling node of this node, or 273 * <code>null</code> if this node is its parent's last child node. 274 */ 275 private IIOMetadataNode nextSibling = null; 276 277 /** 278 * The previous (left) sibling node of this node, or 279 * <code>null</code> if this node is its parent's first child node. 280 */ 281 private IIOMetadataNode previousSibling = null; 282 283 /** 284 * A <code>List</code> of <code>IIOAttr</code> nodes representing 285 * attributes. 286 */ 287 private List attributes = new ArrayList(); 288 289 /** 290 * Constructs an empty <code>IIOMetadataNode</code>. 291 */ 292 public IIOMetadataNode() {} 293 294 /** 295 * Constructs an <code>IIOMetadataNode</code> with a given node 296 * name. 297 * 298 * @param nodeName the name of the node, as a <code>String</code>. 299 */ 300 public IIOMetadataNode(String nodeName) { 301 this.nodeName = nodeName; 302 } 303 304 /** 305 * Check that the node is either <code>null</code> or an 306 * <code>IIOMetadataNode</code>. 307 */ 308 private void checkNode(Node node) throws DOMException { 309 if (node == null) { 310 return; 311 } 312 if (!(node instanceof IIOMetadataNode)) { 313 throw new IIODOMException(DOMException.WRONG_DOCUMENT_ERR, 314 "Node not an IIOMetadataNode!"); 315 } 316 } 317 318 // Methods from Node 319 320 /** 321 * Returns the node name associated with this node. 322 * 323 * @return the node name, as a <code>String</code>. 324 */ 325 public String getNodeName() { 326 return nodeName; 327 } 328 329 /** 330 * Returns the value associated with this node. 331 * 332 * @return the node value, as a <code>String</code>. 333 */ 334 public String getNodeValue(){ 335 return nodeValue; 336 } 337 338 /** 339 * Sets the <code>String</code> value associated with this node. 340 */ 341 public void setNodeValue(String nodeValue) { 342 this.nodeValue = nodeValue; 343 } 344 345 /** 346 * Returns the node type, which is always 347 * <code>ELEMENT_NODE</code>. 348 * 349 * @return the <code>short</code> value <code>ELEMENT_NODE</code>. 350 */ 351 public short getNodeType() { 352 return ELEMENT_NODE; 353 } 354 355 /** 356 * Returns the parent of this node. A <code>null</code> value 357 * indicates that the node is the root of its own tree. To add a 358 * node to an existing tree, use one of the 359 * <code>insertBefore</code>, <code>replaceChild</code>, or 360 * <code>appendChild</code> methods. 361 * 362 * @return the parent, as a <code>Node</code>. 363 * 364 * @see #insertBefore 365 * @see #replaceChild 366 * @see #appendChild 367 */ 368 public Node getParentNode() { 369 return parent; 370 } 371 372 /** 373 * Returns a <code>NodeList</code> that contains all children of this node. 374 * If there are no children, this is a <code>NodeList</code> containing 375 * no nodes. 376 * 377 * @return the children as a <code>NodeList</code> 378 */ 379 public NodeList getChildNodes() { 380 return this; 381 } 382 383 /** 384 * Returns the first child of this node, or <code>null</code> if 385 * the node has no children. 386 * 387 * @return the first child, as a <code>Node</code>, or 388 * <code>null</code> 389 */ 390 public Node getFirstChild() { 391 return firstChild; 392 } 393 394 /** 395 * Returns the last child of this node, or <code>null</code> if 396 * the node has no children. 397 * 398 * @return the last child, as a <code>Node</code>, or 399 * <code>null</code>. 400 */ 401 public Node getLastChild() { 402 return lastChild; 403 } 404 405 /** 406 * Returns the previous sibling of this node, or <code>null</code> 407 * if this node has no previous sibling. 408 * 409 * @return the previous sibling, as a <code>Node</code>, or 410 * <code>null</code>. 411 */ 412 public Node getPreviousSibling() { 413 return previousSibling; 414 } 415 416 /** 417 * Returns the next sibling of this node, or <code>null</code> if 418 * the node has no next sibling. 419 * 420 * @return the next sibling, as a <code>Node</code>, or 421 * <code>null</code>. 422 */ 423 public Node getNextSibling() { 424 return nextSibling; 425 } 426 427 /** 428 * Returns a <code>NamedNodeMap</code> containing the attributes of 429 * this node. 430 * 431 * @return a <code>NamedNodeMap</code> containing the attributes of 432 * this node. 433 */ 434 public NamedNodeMap getAttributes() { 435 return new IIONamedNodeMap(attributes); 436 } 437 438 /** 439 * Returns <code>null</code>, since <code>IIOMetadataNode</code>s 440 * do not belong to any <code>Document</code>. 441 * 442 * @return <code>null</code>. 443 */ 444 public Document getOwnerDocument() { 445 return null; 446 } 447 448 /** 449 * Inserts the node <code>newChild</code> before the existing 450 * child node <code>refChild</code>. If <code>refChild</code> is 451 * <code>null</code>, insert <code>newChild</code> at the end of 452 * the list of children. 453 * 454 * @param newChild the <code>Node</code> to insert. 455 * @param refChild the reference <code>Node</code>. 456 * 457 * @return the node being inserted. 458 * 459 * @exception IllegalArgumentException if <code>newChild</code> is 460 * <code>null</code>. 461 */ 462 public Node insertBefore(Node newChild, 463 Node refChild) { 464 if (newChild == null) { 465 throw new IllegalArgumentException("newChild == null!"); 466 } 467 468 checkNode(newChild); 469 checkNode(refChild); 470 471 IIOMetadataNode newChildNode = (IIOMetadataNode)newChild; 472 IIOMetadataNode refChildNode = (IIOMetadataNode)refChild; 473 474 // Siblings, can be null. 475 IIOMetadataNode previous = null; 476 IIOMetadataNode next = null; 477 478 if (refChild == null) { 479 previous = this.lastChild; 480 next = null; 481 this.lastChild = newChildNode; 482 } else { 483 previous = refChildNode.previousSibling; 484 next = refChildNode; 485 } 486 487 if (previous != null) { 488 previous.nextSibling = newChildNode; 489 } 490 if (next != null) { 491 next.previousSibling = newChildNode; 492 } 493 494 newChildNode.parent = this; 495 newChildNode.previousSibling = previous; 496 newChildNode.nextSibling = next; 497 498 // N.B.: O.K. if refChild == null 499 if (this.firstChild == refChildNode) { 500 this.firstChild = newChildNode; 501 } 502 503 ++numChildren; 504 return newChildNode; 505 } 506 507 /** 508 * Replaces the child node <code>oldChild</code> with 509 * <code>newChild</code> in the list of children, and returns the 510 * <code>oldChild</code> node. 511 * 512 * @param newChild the <code>Node</code> to insert. 513 * @param oldChild the <code>Node</code> to be replaced. 514 * 515 * @return the node replaced. 516 * 517 * @exception IllegalArgumentException if <code>newChild</code> is 518 * <code>null</code>. 519 */ 520 public Node replaceChild(Node newChild, 521 Node oldChild) { 522 if (newChild == null) { 523 throw new IllegalArgumentException("newChild == null!"); 524 } 525 526 checkNode(newChild); 527 checkNode(oldChild); 528 529 IIOMetadataNode newChildNode = (IIOMetadataNode)newChild; 530 IIOMetadataNode oldChildNode = (IIOMetadataNode)oldChild; 531 532 IIOMetadataNode previous = oldChildNode.previousSibling; 533 IIOMetadataNode next = oldChildNode.nextSibling; 534 535 if (previous != null) { 536 previous.nextSibling = newChildNode; 537 } 538 if (next != null) { 539 next.previousSibling = newChildNode; 540 } 541 542 newChildNode.parent = this; 543 newChildNode.previousSibling = previous; 544 newChildNode.nextSibling = next; 545 546 if (firstChild == oldChildNode) { 547 firstChild = newChildNode; 548 } 549 if (lastChild == oldChildNode) { 550 lastChild = newChildNode; 551 } 552 553 oldChildNode.parent = null; 554 oldChildNode.previousSibling = null; 555 oldChildNode.nextSibling = null; 556 557 return oldChildNode; 558 } 559 560 /** 561 * Removes the child node indicated by <code>oldChild</code> from 562 * the list of children, and returns it. 563 * 564 * @param oldChild the <code>Node</code> to be removed. 565 * 566 * @return the node removed. 567 * 568 * @exception IllegalArgumentException if <code>oldChild</code> is 569 * <code>null</code>. 570 */ 571 public Node removeChild(Node oldChild) { 572 if (oldChild == null) { 573 throw new IllegalArgumentException("oldChild == null!"); 574 } 575 checkNode(oldChild); 576 577 IIOMetadataNode oldChildNode = (IIOMetadataNode)oldChild; 578 579 IIOMetadataNode previous = oldChildNode.previousSibling; 580 IIOMetadataNode next = oldChildNode.nextSibling; 581 582 if (previous != null) { 583 previous.nextSibling = next; 584 } 585 if (next != null) { 586 next.previousSibling = previous; 587 } 588 589 if (this.firstChild == oldChildNode) { 590 this.firstChild = next; 591 } 592 if (this.lastChild == oldChildNode) { 593 this.lastChild = previous; 594 } 595 596 oldChildNode.parent = null; 597 oldChildNode.previousSibling = null; 598 oldChildNode.nextSibling = null; 599 600 --numChildren; 601 return oldChildNode; 602 } 603 604 /** 605 * Adds the node <code>newChild</code> to the end of the list of 606 * children of this node. 607 * 608 * @param newChild the <code>Node</code> to insert. 609 * 610 * @return the node added. 611 * 612 * @exception IllegalArgumentException if <code>newChild</code> is 613 * <code>null</code>. 614 */ 615 public Node appendChild(Node newChild) { 616 if (newChild == null) { 617 throw new IllegalArgumentException("newChild == null!"); 618 } 619 checkNode(newChild); 620 621 // insertBefore will increment numChildren 622 return insertBefore(newChild, null); 623 } 624 625 /** 626 * Returns <code>true</code> if this node has child nodes. 627 * 628 * @return <code>true</code> if this node has children. 629 */ 630 public boolean hasChildNodes() { 631 return numChildren > 0; 632 } 633 634 /** 635 * Returns a duplicate of this node. The duplicate node has no 636 * parent (<code>getParentNode</code> returns <code>null</code>). 637 * If a shallow clone is being performed (<code>deep</code> is 638 * <code>false</code>), the new node will not have any children or 639 * siblings. If a deep clone is being performed, the new node 640 * will form the root of a complete cloned subtree. 641 * 642 * @param deep if <code>true</code>, recursively clone the subtree 643 * under the specified node; if <code>false</code>, clone only the 644 * node itself. 645 * 646 * @return the duplicate node. 647 */ 648 public Node cloneNode(boolean deep) { 649 IIOMetadataNode newNode = new IIOMetadataNode(this.nodeName); 650 newNode.setUserObject(getUserObject()); 651 // Attributes 652 653 if (deep) { 654 for (IIOMetadataNode child = firstChild; 655 child != null; 656 child = child.nextSibling) { 657 newNode.appendChild(child.cloneNode(true)); 658 } 659 } 660 661 return newNode; 662 } 663 664 /** 665 * Does nothing, since <code>IIOMetadataNode</code>s do not 666 * contain <code>Text</code> children. 667 */ 668 public void normalize() { 669 } 670 671 /** 672 * Returns <code>false</code> since DOM features are not 673 * supported. 674 * 675 * @return <code>false</code>. 676 * 677 * @param feature a <code>String</code>, which is ignored. 678 * @param version a <code>String</code>, which is ignored. 679 */ 680 public boolean isSupported(String feature, String version) { 681 return false; 682 } 683 684 /** 685 * Returns <code>null</code>, since namespaces are not supported. 686 */ 687 public String getNamespaceURI() throws DOMException { 688 return null; 689 } 690 691 /** 692 * Returns <code>null</code>, since namespaces are not supported. 693 * 694 * @return <code>null</code>. 695 * 696 * @see #setPrefix 697 */ 698 public String getPrefix() { 699 return null; 700 } 701 702 /** 703 * Does nothing, since namespaces are not supported. 704 * 705 * @param prefix a <code>String</code>, which is ignored. 706 * 707 * @see #getPrefix 708 */ 709 public void setPrefix(String prefix) { 710 } 711 712 /** 713 * Equivalent to <code>getNodeName</code>. 714 * 715 * @return the node name, as a <code>String</code>. 716 */ 717 public String getLocalName() { 718 return nodeName; 719 } 720 721 // Methods from Element 722 723 724 /** 725 * Equivalent to <code>getNodeName</code>. 726 * 727 * @return the node name, as a <code>String</code> 728 */ 729 public String getTagName() { 730 return nodeName; 731 } 732 733 /** 734 * Retrieves an attribute value by name. 735 * @param name The name of the attribute to retrieve. 736 * @return The <code>Attr</code> value as a string, or the empty string 737 * if that attribute does not have a specified or default value. 738 */ 739 public String getAttribute(String name) { 740 Attr attr = getAttributeNode(name); 741 if (attr == null) { 742 return ""; 743 } 744 return attr.getValue(); 745 } 746 747 /** 748 * Equivalent to <code>getAttribute(localName)</code>. 749 * 750 * @see #setAttributeNS 751 */ 752 public String getAttributeNS(String namespaceURI, String localName) { 753 return getAttribute(localName); 754 } 755 756 public void setAttribute(String name, String value) { 757 // Name must be valid unicode chars 758 boolean valid = true; 759 char[] chs = name.toCharArray(); 760 for (int i=0;i<chs.length;i++) { 761 if (chs[i] >= 0xfffe) { 762 valid = false; 763 break; 764 } 765 } 766 if (!valid) { 767 throw new IIODOMException(DOMException.INVALID_CHARACTER_ERR, 768 "Attribute name is illegal!"); 769 } 770 removeAttribute(name, false); 771 attributes.add(new IIOAttr(this, name, value)); 772 } 773 774 /** 775 * Equivalent to <code>setAttribute(qualifiedName, value)</code>. 776 * 777 * @see #getAttributeNS 778 */ 779 public void setAttributeNS(String namespaceURI, 780 String qualifiedName, String value) { 781 setAttribute(qualifiedName, value); 782 } 783 784 public void removeAttribute(String name) { 785 removeAttribute(name, true); 786 } 787 788 private void removeAttribute(String name, boolean checkPresent) { 789 int numAttributes = attributes.size(); 790 for (int i = 0; i < numAttributes; i++) { 791 IIOAttr attr = (IIOAttr)attributes.get(i); 792 if (name.equals(attr.getName())) { 793 attr.setOwnerElement(null); 794 attributes.remove(i); 795 return; 796 } 797 } 798 799 // If we get here, the attribute doesn't exist 800 if (checkPresent) { 801 throw new IIODOMException(DOMException.NOT_FOUND_ERR, 802 "No such attribute!"); 803 } 804 } 805 806 /** 807 * Equivalent to <code>removeAttribute(localName)</code>. 808 */ 809 public void removeAttributeNS(String namespaceURI, 810 String localName) { 811 removeAttribute(localName); 812 } 813 814 public Attr getAttributeNode(String name) { 815 Node node = getAttributes().getNamedItem(name); 816 return (Attr)node; 817 } 818 819 /** 820 * Equivalent to <code>getAttributeNode(localName)</code>. 821 * 822 * @see #setAttributeNodeNS 823 */ 824 public Attr getAttributeNodeNS(String namespaceURI, 825 String localName) { 826 return getAttributeNode(localName); 827 } 828 829 public Attr setAttributeNode(Attr newAttr) throws DOMException { 830 Element owner = newAttr.getOwnerElement(); 831 if (owner != null) { 832 if (owner == this) { 833 return null; 834 } else { 835 throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, 836 "Attribute is already in use"); 837 } 838 } 839 840 IIOAttr attr; 841 if (newAttr instanceof IIOAttr) { 842 attr = (IIOAttr)newAttr; 843 attr.setOwnerElement(this); 844 } else { 845 attr = new IIOAttr(this, 846 newAttr.getName(), 847 newAttr.getValue()); 848 } 849 850 Attr oldAttr = getAttributeNode(attr.getName()); 851 if (oldAttr != null) { 852 removeAttributeNode(oldAttr); 853 } 854 855 attributes.add(attr); 856 857 return oldAttr; 858 } 859 860 /** 861 * Equivalent to <code>setAttributeNode(newAttr)</code>. 862 * 863 * @see #getAttributeNodeNS 864 */ 865 public Attr setAttributeNodeNS(Attr newAttr) { 866 return setAttributeNode(newAttr); 867 } 868 869 public Attr removeAttributeNode(Attr oldAttr) { 870 removeAttribute(oldAttr.getName()); 871 return oldAttr; 872 } 873 874 public NodeList getElementsByTagName(String name) { 875 List l = new ArrayList(); 876 getElementsByTagName(name, l); 877 return new IIONodeList(l); 878 } 879 880 private void getElementsByTagName(String name, List l) { 881 if (nodeName.equals(name)) { 882 l.add(this); 883 } 884 885 Node child = getFirstChild(); 886 while (child != null) { 887 ((IIOMetadataNode)child).getElementsByTagName(name, l); 888 child = child.getNextSibling(); 889 } 890 } 891 892 /** 893 * Equivalent to <code>getElementsByTagName(localName)</code>. 894 */ 895 public NodeList getElementsByTagNameNS(String namespaceURI, 896 String localName) { 897 return getElementsByTagName(localName); 898 } 899 900 public boolean hasAttributes() { 901 return attributes.size() > 0; 902 } 903 904 public boolean hasAttribute(String name) { 905 return getAttributeNode(name) != null; 906 } 907 908 /** 909 * Equivalent to <code>hasAttribute(localName)</code>. 910 */ 911 public boolean hasAttributeNS(String namespaceURI, 912 String localName) { 913 return hasAttribute(localName); 914 } 915 916 // Methods from NodeList 917 918 public int getLength() { 919 return numChildren; 920 } 921 922 public Node item(int index) { 923 if (index < 0) { 924 return null; 925 } 926 927 Node child = getFirstChild(); 928 while (child != null && index-- > 0) { 929 child = child.getNextSibling(); 930 } 931 return child; 932 } 933 934 /** 935 * Returns the <code>Object</code> value associated with this node. 936 * 937 * @return the user <code>Object</code>. 938 * 939 * @see #setUserObject 940 */ 941 public Object getUserObject() { 942 return userObject; 943 } 944 945 /** 946 * Sets the value associated with this node. 947 * 948 * @param userObject the user <code>Object</code>. 949 * 950 * @see #getUserObject 951 */ 952 public void setUserObject(Object userObject) { 953 this.userObject = userObject; 954 } 955 956 // Start of dummy methods for DOM L3. 957 958 /** 959 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 960 * and will throw a {@code DOMException}. 961 * @throws DOMException - always. 962 */ 963 public void setIdAttribute(String name, 964 boolean isId) 965 throws DOMException { 966 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 967 "Method not supported"); 968 } 969 970 /** 971 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 972 * and will throw a {@code DOMException}. 973 * @throws DOMException - always. 974 */ 975 public void setIdAttributeNS(String namespaceURI, 976 String localName, 977 boolean isId) 978 throws DOMException { 979 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 980 "Method not supported"); 981 } 982 983 /** 984 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 985 * and will throw a {@code DOMException}. 986 * @throws DOMException - always. 987 */ 988 public void setIdAttributeNode(Attr idAttr, 989 boolean isId) 990 throws DOMException { 991 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 992 "Method not supported"); 993 } 994 995 /** 996 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 997 * and will throw a {@code DOMException}. 998 * @throws DOMException - always. 999 */ 1000 public TypeInfo getSchemaTypeInfo() throws DOMException { 1001 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1002 "Method not supported"); 1003 } 1004 1005 /** 1006 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1007 * and will throw a {@code DOMException}. 1008 * @throws DOMException - always. 1009 */ 1010 public Object setUserData(String key, 1011 Object data, 1012 UserDataHandler handler) throws DOMException { 1013 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1014 "Method not supported"); 1015 } 1016 1017 /** 1018 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1019 * and will throw a {@code DOMException}. 1020 * @throws DOMException - always. 1021 */ 1022 public Object getUserData(String key) throws DOMException { 1023 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1024 "Method not supported"); 1025 } 1026 1027 /** 1028 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1029 * and will throw a {@code DOMException}. 1030 * @throws DOMException - always. 1031 */ 1032 public Object getFeature(String feature, String version) 1033 throws DOMException { 1034 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1035 "Method not supported"); 1036 } 1037 1038 /** 1039 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1040 * and will throw a {@code DOMException}. 1041 * @throws DOMException - always. 1042 */ 1043 public boolean isSameNode(Node node) throws DOMException { 1044 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1045 "Method not supported"); 1046 } 1047 1048 /** 1049 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1050 * and will throw a {@code DOMException}. 1051 * @throws DOMException - always. 1052 */ 1053 public boolean isEqualNode(Node node) throws DOMException { 1054 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1055 "Method not supported"); 1056 } 1057 1058 /** 1059 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1060 * and will throw a {@code DOMException}. 1061 * @throws DOMException - always. 1062 */ 1063 public String lookupNamespaceURI(String prefix) throws DOMException { 1064 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1065 "Method not supported"); 1066 } 1067 1068 /** 1069 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1070 * and will throw a {@code DOMException}. 1071 * @throws DOMException - always. 1072 */ 1073 public boolean isDefaultNamespace(String namespaceURI) 1074 throws DOMException { 1075 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1076 "Method not supported"); 1077 } 1078 1079 /** 1080 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1081 * and will throw a {@code DOMException}. 1082 * @throws DOMException - always. 1083 */ 1084 public String lookupPrefix(String namespaceURI) throws DOMException { 1085 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1086 "Method not supported"); 1087 } 1088 1089 /** 1090 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1091 * and will throw a {@code DOMException}. 1092 * @throws DOMException - always. 1093 */ 1094 public String getTextContent() throws DOMException { 1095 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1096 "Method not supported"); 1097 } 1098 1099 /** 1100 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1101 * and will throw a {@code DOMException}. 1102 * @throws DOMException - always. 1103 */ 1104 public void setTextContent(String textContent) throws DOMException { 1105 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1106 "Method not supported"); 1107 } 1108 1109 /** 1110 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1111 * and will throw a {@code DOMException}. 1112 * @throws DOMException - always. 1113 */ 1114 public short compareDocumentPosition(Node other) 1115 throws DOMException { 1116 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1117 "Method not supported"); 1118 } 1119 1120 /** 1121 * This DOM Level 3 method is not supported for {@code IIOMetadataNode} 1122 * and will throw a {@code DOMException}. 1123 * @throws DOMException - always. 1124 */ 1125 public String getBaseURI() throws DOMException { 1126 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 1127 "Method not supported"); 1128 } 1129 //End of dummy methods for DOM L3. 1130 1131 1132 }