1. /*
  2. * @(#)IIOMetadataNode.java 1.36 02/03/21
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.imageio.metadata;
  8. import java.util.ArrayList;
  9. import java.util.Iterator;
  10. import java.util.List;
  11. import org.w3c.dom.Attr;
  12. import org.w3c.dom.Document;
  13. import org.w3c.dom.Element;
  14. import org.w3c.dom.DOMException;
  15. import org.w3c.dom.NamedNodeMap;
  16. import org.w3c.dom.Node;
  17. import org.w3c.dom.NodeList;
  18. import org.w3c.dom.TypeInfo;
  19. import org.w3c.dom.UserDataHandler;
  20. class IIODOMException extends DOMException {
  21. public IIODOMException(short code, String message) {
  22. super(code, message);
  23. }
  24. }
  25. class IIONamedNodeMap implements NamedNodeMap {
  26. List nodes;
  27. public IIONamedNodeMap(List nodes) {
  28. this.nodes = nodes;
  29. }
  30. public int getLength() {
  31. return nodes.size();
  32. }
  33. public Node getNamedItem(String name) {
  34. Iterator iter = nodes.iterator();
  35. while (iter.hasNext()) {
  36. Node node = (Node)iter.next();
  37. if (name.equals(node.getNodeName())) {
  38. return node;
  39. }
  40. }
  41. return null;
  42. }
  43. public Node item(int index) {
  44. Node node = (Node)nodes.get(index);
  45. return node;
  46. }
  47. public Node removeNamedItem(java.lang.String name) {
  48. throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
  49. "This NamedNodeMap is read-only!");
  50. }
  51. public Node setNamedItem(Node arg) {
  52. throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
  53. "This NamedNodeMap is read-only!");
  54. }
  55. /**
  56. * Equivalent to <code>getNamedItem(localName)</code>.
  57. */
  58. public Node getNamedItemNS(String namespaceURI, String localName) {
  59. return getNamedItem(localName);
  60. }
  61. /**
  62. * Equivalent to <code>setNamedItem(arg)</code>.
  63. */
  64. public Node setNamedItemNS(Node arg) {
  65. return setNamedItem(arg);
  66. }
  67. /**
  68. * Equivalent to <code>removeNamedItem(localName)</code>.
  69. */
  70. public Node removeNamedItemNS(String namespaceURI, String localName) {
  71. return removeNamedItem(localName);
  72. }
  73. }
  74. class IIONodeList implements NodeList {
  75. List nodes;
  76. public IIONodeList(List nodes) {
  77. this.nodes = nodes;
  78. }
  79. public int getLength() {
  80. return nodes.size();
  81. }
  82. public Node item(int index) {
  83. if (index < 0 || index > nodes.size()) {
  84. return null;
  85. }
  86. return (Node)nodes.get(index);
  87. }
  88. }
  89. class IIOAttr extends IIOMetadataNode implements Attr {
  90. boolean specified = true;
  91. Element owner;
  92. String name;
  93. String value;
  94. public IIOAttr(Element owner, String name, String value) {
  95. this.owner = owner;
  96. this.name = name;
  97. this.value = value;
  98. }
  99. public String getName() {
  100. return name;
  101. }
  102. public String getNodeName() {
  103. return name;
  104. }
  105. public short getNodeType() {
  106. return ATTRIBUTE_NODE;
  107. }
  108. public boolean getSpecified() {
  109. return specified;
  110. }
  111. public String getValue() {
  112. return value;
  113. }
  114. public String getNodeValue() {
  115. return value;
  116. }
  117. public void setValue(String value) {
  118. this.value = value;
  119. }
  120. public void setNodeValue(String value) {
  121. this.value = value;
  122. }
  123. public Element getOwnerElement() {
  124. return owner;
  125. }
  126. public void setOwnerElement(Element owner) {
  127. this.owner = owner;
  128. }
  129. // Start of dummy methods for DOM L3. PENDING: Please revisit
  130. public boolean isId( ) {
  131. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  132. }
  133. public TypeInfo getSchemaTypeInfo() {
  134. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  135. }
  136. public Object setUserData(String key,
  137. Object data,
  138. UserDataHandler handler) {
  139. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  140. }
  141. public Object getUserData ( String key ) {
  142. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  143. }
  144. public Object getFeature ( String feature, String version ) {
  145. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  146. }
  147. public boolean isEqualNode( Node node ) {
  148. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  149. }
  150. public boolean isSameNode( Node node ) {
  151. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  152. }
  153. public String lookupNamespaceURI( String prefix ) {
  154. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  155. }
  156. public boolean isDefaultNamespace(String namespaceURI) {
  157. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  158. }
  159. public String lookupPrefix(String namespaceURI) {
  160. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  161. }
  162. String textContent;
  163. public String getTextContent() throws DOMException {
  164. return textContent;
  165. }
  166. public void setTextContent(String textContent) throws DOMException{
  167. this.textContent = textContent; //PENDING
  168. }
  169. public short compareDocumentPosition(Node other)
  170. throws DOMException {
  171. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  172. }
  173. public String getBaseURI() {
  174. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  175. }
  176. // End of dummy methods for DOM L3. PENDING: Please revisit
  177. }
  178. /**
  179. * A class representing a node in a meta-data tree, which implements
  180. * the <a
  181. * href="../../../../api/org/w3c/dom/Element.html">
  182. * <code>org.w3c.dom.Element</code></a> interface and additionally allows
  183. * for the storage of non-textual objects via the
  184. * <code>getUserObject</code> and <code>setUserObject</code> methods.
  185. *
  186. * <p> This class is not intended to be used for general XML
  187. * processing. In particular, <code>Element</code> nodes created
  188. * within the Image I/O API are not compatible with those created by
  189. * Sun's standard implementation of the <code>org.w3.dom</code> API.
  190. * In particular, the implementation is tuned for simple uses and may
  191. * not perform well for intensive processing.
  192. *
  193. * <p> Namespaces are ignored in this implementation. The terms "tag
  194. * name" and "node name" are always considered to be synonymous.
  195. *
  196. * @see IIOMetadata#getAsTree
  197. * @see IIOMetadata#setFromTree
  198. * @see IIOMetadata#mergeTree
  199. *
  200. * @version 0.5
  201. */
  202. public class IIOMetadataNode implements Element, NodeList {
  203. /**
  204. * The name of the node as a <code>String</code>.
  205. */
  206. private String nodeName = null;
  207. /**
  208. * The value of the node as a <code>String</code>. The Image I/O
  209. * API typically does not make use of the node value.
  210. */
  211. private String nodeValue = null;
  212. /**
  213. * The <code>Object</code> value associated with this node.
  214. */
  215. private Object userObject = null;
  216. /**
  217. * The parent node of this node, or <code>null</code> if this node
  218. * forms the root of its own tree.
  219. */
  220. private IIOMetadataNode parent = null;
  221. /**
  222. * The number of child nodes.
  223. */
  224. private int numChildren = 0;
  225. /**
  226. * The first (leftmost) child node of this node, or
  227. * <code>null</code> if this node is a leaf node.
  228. */
  229. private IIOMetadataNode firstChild = null;
  230. /**
  231. * The last (rightmost) child node of this node, or
  232. * <code>null</code> if this node is a leaf node.
  233. */
  234. private IIOMetadataNode lastChild = null;
  235. /**
  236. * The next (right) sibling node of this node, or
  237. * <code>null</code> if this node is its parent's last child node.
  238. */
  239. private IIOMetadataNode nextSibling = null;
  240. /**
  241. * The previous (left) sibling node of this node, or
  242. * <code>null</code> if this node is its parent's first child node.
  243. */
  244. private IIOMetadataNode previousSibling = null;
  245. /**
  246. * A <code>List</code> of <code>IIOAttr</code> nodes representing
  247. * attributes.
  248. */
  249. private List attributes = new ArrayList();
  250. /**
  251. * Constructs an empty <code>IIOMetadataNode</code>.
  252. */
  253. public IIOMetadataNode() {}
  254. /**
  255. * Constructs an <code>IIOMetadataNode</code> with a given node
  256. * name.
  257. *
  258. * @param nodeName the name of the node, as a <code>String</code>.
  259. */
  260. public IIOMetadataNode(String nodeName) {
  261. this.nodeName = nodeName;
  262. }
  263. /**
  264. * Check that the node is either <code>null</code> or an
  265. * <code>IIOMetadataNode</code>.
  266. */
  267. private void checkNode(Node node) throws DOMException {
  268. if (node == null) {
  269. return;
  270. }
  271. if (!(node instanceof IIOMetadataNode)) {
  272. throw new IIODOMException(DOMException.WRONG_DOCUMENT_ERR,
  273. "Node not an IIOMetadataNode!");
  274. }
  275. }
  276. // Methods from Node
  277. /**
  278. * Returns the node name associated with this node.
  279. *
  280. * @return the node name, as a <code>String</code>.
  281. */
  282. public String getNodeName() {
  283. return nodeName;
  284. }
  285. public String getNodeValue() throws DOMException {
  286. return nodeValue;
  287. }
  288. public void setNodeValue(String nodeValue) throws DOMException {
  289. this.nodeValue = nodeValue;
  290. }
  291. /**
  292. * Returns the node type, which is always
  293. * <code>ELEMENT_NODE</code>.
  294. *
  295. * @return the <code>short</code> value <code>ELEMENT_NODE</code>.
  296. */
  297. public short getNodeType() {
  298. return ELEMENT_NODE;
  299. }
  300. /**
  301. * Returns the parent of this node. A <code>null</code> value
  302. * indicates that the node is the root of its own tree. To add a
  303. * node to an existing tree, use one of the
  304. * <code>insertBefore</code>, <code>replaceChild</code>, or
  305. * <code>appendChild</code> methods.
  306. *
  307. * @return the parent, as a <code>Node</code>.
  308. *
  309. * @see #insertBefore
  310. * @see #replaceChild
  311. * @see #appendChild
  312. */
  313. public Node getParentNode() {
  314. return parent;
  315. }
  316. public NodeList getChildNodes() {
  317. return this;
  318. }
  319. /**
  320. * Returns the first child of this node, or <code>null</code> if
  321. * the node has no children.
  322. *
  323. * @return the first child, as a <code>Node</code>, or
  324. * <code>null</code>
  325. */
  326. public Node getFirstChild() {
  327. return firstChild;
  328. }
  329. /**
  330. * Returns the last child of this node, or <code>null</code> if
  331. * the node has no children.
  332. *
  333. * @return the last child, as a <code>Node</code>, or
  334. * <code>null</code>.
  335. */
  336. public Node getLastChild() {
  337. return lastChild;
  338. }
  339. /**
  340. * Returns the previous sibling of this node, or <code>null</code>
  341. * if this node has no previous sibling.
  342. *
  343. * @return the previous sibling, as a <code>Node</code>, or
  344. * <code>null</code>.
  345. */
  346. public Node getPreviousSibling() {
  347. return previousSibling;
  348. }
  349. /**
  350. * Returns the next sibling of this node, or <code>null</code> if
  351. * the node has no next sibling.
  352. *
  353. * @return the next sibling, as a <code>Node</code>, or
  354. * <code>null</code>.
  355. */
  356. public Node getNextSibling() {
  357. return nextSibling;
  358. }
  359. public NamedNodeMap getAttributes() {
  360. return new IIONamedNodeMap(attributes);
  361. }
  362. /**
  363. * Returns <code>null</code>, since <code>IIOMetadataNode</code>s
  364. * do not belong to any <code>Document</code>.
  365. *
  366. * @return <code>null</code>.
  367. */
  368. public Document getOwnerDocument() {
  369. return null;
  370. }
  371. /**
  372. * Inserts the node <code>newChild</code> before the existing
  373. * child node <code>refChild</code>. If <code>refChild</code> is
  374. * <code>null</code>, insert <code>newChild</code> at the end of
  375. * the list of children.
  376. *
  377. * @param newChild the <code>Node</code> to insert.
  378. * @param refChild the reference <code>Node</code>.
  379. *
  380. * @return the node being inserted.
  381. *
  382. * @exception IllegalArgumentException if <code>newChild</code> is
  383. * <code>null</code>.
  384. */
  385. public Node insertBefore(Node newChild,
  386. Node refChild) {
  387. if (newChild == null) {
  388. throw new IllegalArgumentException("newChild == null!");
  389. }
  390. checkNode(newChild);
  391. checkNode(refChild);
  392. IIOMetadataNode newChildNode = (IIOMetadataNode)newChild;
  393. IIOMetadataNode refChildNode = (IIOMetadataNode)refChild;
  394. // Siblings, can be null.
  395. IIOMetadataNode previous = null;
  396. IIOMetadataNode next = null;
  397. if (refChild == null) {
  398. previous = this.lastChild;
  399. next = null;
  400. this.lastChild = newChildNode;
  401. } else {
  402. previous = refChildNode.previousSibling;
  403. next = refChildNode;
  404. }
  405. if (previous != null) {
  406. previous.nextSibling = newChildNode;
  407. }
  408. if (next != null) {
  409. next.previousSibling = newChildNode;
  410. }
  411. newChildNode.parent = this;
  412. newChildNode.previousSibling = previous;
  413. newChildNode.nextSibling = next;
  414. // N.B.: O.K. if refChild == null
  415. if (this.firstChild == refChildNode) {
  416. this.firstChild = newChildNode;
  417. }
  418. ++numChildren;
  419. return newChildNode;
  420. }
  421. /**
  422. * Replaces the child node <code>oldChild</code> with
  423. * <code>newChild</code> in the list of children, and returns the
  424. * <code>oldChild</code> node.
  425. *
  426. * @param newChild the <code>Node</code> to insert.
  427. * @param oldChild the <code>Node</code> to be replaced.
  428. *
  429. * @return the node replaced.
  430. *
  431. * @exception IllegalArgumentException if <code>newChild</code> is
  432. * <code>null</code>.
  433. */
  434. public Node replaceChild(Node newChild,
  435. Node oldChild) {
  436. if (newChild == null) {
  437. throw new IllegalArgumentException("newChild == null!");
  438. }
  439. checkNode(newChild);
  440. checkNode(oldChild);
  441. IIOMetadataNode newChildNode = (IIOMetadataNode)newChild;
  442. IIOMetadataNode oldChildNode = (IIOMetadataNode)oldChild;
  443. IIOMetadataNode previous = oldChildNode.previousSibling;
  444. IIOMetadataNode next = oldChildNode.nextSibling;
  445. if (previous != null) {
  446. previous.nextSibling = newChildNode;
  447. }
  448. if (next != null) {
  449. next.previousSibling = newChildNode;
  450. }
  451. newChildNode.parent = this;
  452. newChildNode.previousSibling = previous;
  453. newChildNode.nextSibling = next;
  454. if (firstChild == oldChildNode) {
  455. firstChild = newChildNode;
  456. }
  457. if (lastChild == oldChildNode) {
  458. lastChild = newChildNode;
  459. }
  460. oldChildNode.parent = null;
  461. oldChildNode.previousSibling = null;
  462. oldChildNode.nextSibling = null;
  463. return oldChildNode;
  464. }
  465. /**
  466. * Removes the child node indicated by <code>oldChild</code> from
  467. * the list of children, and returns it.
  468. *
  469. * @param oldChild the <code>Node</code> to be removed.
  470. *
  471. * @return the node removed.
  472. *
  473. * @exception IllegalArgumentException if <code>oldChild</code> is
  474. * <code>null</code>.
  475. */
  476. public Node removeChild(Node oldChild) {
  477. if (oldChild == null) {
  478. throw new IllegalArgumentException("oldChild == null!");
  479. }
  480. checkNode(oldChild);
  481. IIOMetadataNode oldChildNode = (IIOMetadataNode)oldChild;
  482. IIOMetadataNode previous = oldChildNode.previousSibling;
  483. IIOMetadataNode next = oldChildNode.nextSibling;
  484. if (previous != null) {
  485. previous.nextSibling = next;
  486. }
  487. if (next != null) {
  488. next.previousSibling = previous;
  489. }
  490. if (this.firstChild == oldChildNode) {
  491. this.firstChild = next;
  492. }
  493. if (this.lastChild == oldChildNode) {
  494. this.lastChild = previous;
  495. }
  496. oldChildNode.parent = null;
  497. oldChildNode.previousSibling = null;
  498. oldChildNode.nextSibling = null;
  499. --numChildren;
  500. return oldChildNode;
  501. }
  502. /**
  503. * Adds the node <code>newChild</code> to the end of the list of
  504. * children of this node.
  505. *
  506. * @param newChild the <code>Node</code> to insert.
  507. *
  508. * @return the node added.
  509. *
  510. * @exception IllegalArgumentException if <code>newChild</code> is
  511. * <code>null</code>.
  512. */
  513. public Node appendChild(Node newChild) {
  514. if (newChild == null) {
  515. throw new IllegalArgumentException("newChild == null!");
  516. }
  517. checkNode(newChild);
  518. // insertBefore will increment numChildren
  519. return insertBefore(newChild, null);
  520. }
  521. /**
  522. * Returns <code>true</code> if this node has child nodes.
  523. *
  524. * @return <code>true</code> if this node has children.
  525. */
  526. public boolean hasChildNodes() {
  527. return numChildren > 0;
  528. }
  529. /**
  530. * Returns a duplicate of this node. The duplicate node has no
  531. * parent (<code>getParentNode</code> returns <code>null</code>).
  532. * If a shallow clone is being performed (<code>deep</code> is
  533. * <code>false</code>), the new node will not have any children or
  534. * siblings. If a deep clone is being performed, the new node
  535. * will form the root of a complete cloned subtree.
  536. *
  537. * @param deep if <code>true</code>, recursively clone the subtree
  538. * under the specified node; if <code>false</code>, clone only the
  539. * node itself.
  540. *
  541. * @return the duplicate node.
  542. */
  543. public Node cloneNode(boolean deep) {
  544. IIOMetadataNode newNode = new IIOMetadataNode(this.nodeName);
  545. newNode.setUserObject(getUserObject());
  546. // Attributes
  547. if (deep) {
  548. for (IIOMetadataNode child = firstChild;
  549. child != null;
  550. child = child.nextSibling) {
  551. newNode.appendChild(child.cloneNode(true));
  552. }
  553. }
  554. return newNode;
  555. }
  556. /**
  557. * Does nothing, since <code>IIOMetadataNode</code>s do not
  558. * contain <code>Text</code> children.
  559. */
  560. public void normalize() {
  561. }
  562. /**
  563. * Returns <code>false</code> since DOM features are not
  564. * supported.
  565. *
  566. * @return <code>false</code>.
  567. *
  568. * @param feature a <code>String</code>, which is ignored.
  569. * @param version a <code>String</code>, which is ignored.
  570. */
  571. public boolean isSupported(String feature, String version) {
  572. return false;
  573. }
  574. /**
  575. * Returns <code>null</code>, since namespaces are not supported.
  576. */
  577. public String getNamespaceURI() throws DOMException {
  578. return null;
  579. }
  580. /**
  581. * Returns <code>null</code>, since namespaces are not supported.
  582. *
  583. * @return <code>null</code>.
  584. *
  585. * @see #setPrefix
  586. */
  587. public String getPrefix() {
  588. return null;
  589. }
  590. /**
  591. * Does nothing, since namespaces are not supported.
  592. *
  593. * @param prefix a <code>String</code>, which is ignored.
  594. *
  595. * @see #getPrefix
  596. */
  597. public void setPrefix(String prefix) {
  598. }
  599. /**
  600. * Equivalent to <code>getNodeName</code>.
  601. *
  602. * @return the node name, as a <code>String</code>.
  603. */
  604. public String getLocalName() {
  605. return nodeName;
  606. }
  607. // Methods from Element
  608. public String getTagName() {
  609. return nodeName;
  610. }
  611. public String getAttribute(String name) {
  612. Attr attr = getAttributeNode(name);
  613. if (attr == null) {
  614. return "";
  615. }
  616. return attr.getValue();
  617. }
  618. /**
  619. * Equivalent to <code>getAttribute(localName)</code>.
  620. *
  621. * @see #setAttributeNS
  622. */
  623. public String getAttributeNS(String namespaceURI, String localName) {
  624. return getAttribute(localName);
  625. }
  626. public void setAttribute(String name, String value) {
  627. // Note minor dependency on Crimson package
  628. // Steal the code if Crimson ever goes away
  629. if (!com.sun.imageio.metadata.XmlNames.isName(name)) {
  630. throw new IIODOMException(DOMException.INVALID_CHARACTER_ERR,
  631. "Attribute name is illegal!");
  632. }
  633. removeAttribute(name, false);
  634. attributes.add(new IIOAttr(this, name, value));
  635. }
  636. /**
  637. * Equivalent to <code>setAttribute(qualifiedName, value)</code>.
  638. *
  639. * @see #getAttributeNS
  640. */
  641. public void setAttributeNS(String namespaceURI,
  642. String qualifiedName, String value) {
  643. setAttribute(qualifiedName, value);
  644. }
  645. public void removeAttribute(String name) {
  646. removeAttribute(name, true);
  647. }
  648. private void removeAttribute(String name, boolean checkPresent) {
  649. int numAttributes = attributes.size();
  650. for (int i = 0; i < numAttributes; i++) {
  651. IIOAttr attr = (IIOAttr)attributes.get(i);
  652. if (name.equals(attr.getName())) {
  653. attr.setOwnerElement(null);
  654. attributes.remove(i);
  655. return;
  656. }
  657. }
  658. // If we get here, the attribute doesn't exist
  659. if (checkPresent) {
  660. throw new IIODOMException(DOMException.NOT_FOUND_ERR,
  661. "No such attribute!");
  662. }
  663. }
  664. /**
  665. * Equivalent to <code>removeAttribute(localName)</code>.
  666. */
  667. public void removeAttributeNS(String namespaceURI,
  668. String localName) {
  669. removeAttribute(localName);
  670. }
  671. public Attr getAttributeNode(String name) {
  672. Node node = getAttributes().getNamedItem(name);
  673. return (Attr)node;
  674. }
  675. /**
  676. * Equivalent to <code>getAttributeNode(localName)</code>.
  677. *
  678. * @see #setAttributeNodeNS
  679. */
  680. public Attr getAttributeNodeNS(String namespaceURI,
  681. String localName) {
  682. return getAttributeNode(localName);
  683. }
  684. public Attr setAttributeNode(Attr newAttr) throws DOMException {
  685. Element owner = newAttr.getOwnerElement();
  686. if (owner != null) {
  687. if (owner == this) {
  688. return null;
  689. } else {
  690. throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR,
  691. "Attribute is already in use");
  692. }
  693. }
  694. IIOAttr attr;
  695. if (newAttr instanceof IIOAttr) {
  696. attr = (IIOAttr)newAttr;
  697. attr.setOwnerElement(this);
  698. } else {
  699. attr = new IIOAttr(this,
  700. newAttr.getName(),
  701. newAttr.getValue());
  702. }
  703. Attr oldAttr = getAttributeNode(attr.getName());
  704. if (oldAttr != null) {
  705. removeAttributeNode(oldAttr);
  706. }
  707. attributes.add(attr);
  708. return oldAttr;
  709. }
  710. /**
  711. * Equivalent to <code>setAttributeNode(newAttr)</code>.
  712. *
  713. * @see #getAttributeNodeNS
  714. */
  715. public Attr setAttributeNodeNS(Attr newAttr) {
  716. return setAttributeNode(newAttr);
  717. }
  718. public Attr removeAttributeNode(Attr oldAttr) {
  719. removeAttribute(oldAttr.getName());
  720. return oldAttr;
  721. }
  722. public NodeList getElementsByTagName(String name) {
  723. List l = new ArrayList();
  724. getElementsByTagName(name, l);
  725. return new IIONodeList(l);
  726. }
  727. private void getElementsByTagName(String name, List l) {
  728. if (nodeName.equals(name)) {
  729. l.add(this);
  730. }
  731. Node child = getFirstChild();
  732. while (child != null) {
  733. ((IIOMetadataNode)child).getElementsByTagName(name, l);
  734. child = child.getNextSibling();
  735. }
  736. }
  737. /**
  738. * Equivalent to <code>getElementsByTagName(localName)</code>.
  739. */
  740. public NodeList getElementsByTagNameNS(String namespaceURI,
  741. String localName) {
  742. return getElementsByTagName(localName);
  743. }
  744. public boolean hasAttributes() {
  745. return attributes.size() > 0;
  746. }
  747. public boolean hasAttribute(String name) {
  748. return getAttributeNode(name) != null;
  749. }
  750. /**
  751. * Equivalent to <code>hasAttribute(localName)</code>.
  752. */
  753. public boolean hasAttributeNS(String namespaceURI,
  754. String localName) {
  755. return hasAttribute(localName);
  756. }
  757. // Methods from NodeList
  758. public int getLength() {
  759. return numChildren;
  760. }
  761. public Node item(int index) {
  762. if (index < 0) {
  763. return null;
  764. }
  765. Node child = getFirstChild();
  766. while (child != null && index-- > 0) {
  767. child = child.getNextSibling();
  768. }
  769. return child;
  770. }
  771. /**
  772. * Returns the <code>Object</code> value associated with this node.
  773. *
  774. * @return the user <code>Object</code>.
  775. *
  776. * @see #setUserObject
  777. */
  778. public Object getUserObject() {
  779. return userObject;
  780. }
  781. /**
  782. * Sets the value associated with this node.
  783. *
  784. * @param userObject the user <code>Object</code>.
  785. *
  786. * @see #getUserObject
  787. */
  788. public void setUserObject(Object userObject) {
  789. this.userObject = userObject;
  790. }
  791. // Start of dummy methods for DOM L3. PENDING: Please revisit
  792. public void setIdAttribute(String name,
  793. boolean isId)
  794. throws DOMException {
  795. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  796. }
  797. public void setIdAttributeNS(String namespaceURI,
  798. String localName,
  799. boolean isId)
  800. throws DOMException {
  801. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  802. }
  803. public void setIdAttributeNode(Attr idAttr,
  804. boolean isId)
  805. throws DOMException {
  806. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  807. }
  808. public TypeInfo getSchemaTypeInfo() {
  809. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  810. }
  811. public Object setUserData(String key,
  812. Object data,
  813. UserDataHandler handler) {
  814. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  815. }
  816. public Object getUserData ( String key ) {
  817. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  818. }
  819. public Object getFeature ( String feature, String version ) {
  820. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  821. }
  822. public boolean isSameNode( Node node ) {
  823. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  824. }
  825. public boolean isEqualNode( Node node ) {
  826. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  827. }
  828. public String lookupNamespaceURI( String prefix ) {
  829. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  830. }
  831. public boolean isDefaultNamespace(String namespaceURI) {
  832. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  833. }
  834. public String lookupPrefix(String namespaceURI) {
  835. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  836. }
  837. String textContent;
  838. public String getTextContent() throws DOMException {
  839. return textContent;
  840. }
  841. public void setTextContent(String textContent) throws DOMException{
  842. this.textContent = textContent; //PENDING
  843. }
  844. public short compareDocumentPosition(Node other)
  845. throws DOMException {
  846. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  847. }
  848. public String getBaseURI() {
  849. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
  850. }
  851. //End of dummy methods for DOM L3. Please revisit
  852. }