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