View Javadoc
1 /* 2 * @(#)ElementImpl.java 1.36 02/03/21 3 * 4 * Copyright 2002 Sun Microsystems, Inc. All rights reserved. 5 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 6 */ 7 package org.enhydra.xml; 8 9 import java.io.File; 10 import java.io.FileOutputStream; 11 import java.util.ArrayList; 12 import java.util.Iterator; 13 import java.util.List; 14 import java.util.HashMap; 15 import java.util.HashMap; 16 17 import org.w3c.dom.Attr; 18 import org.w3c.dom.Document; 19 import org.w3c.dom.Element; 20 import org.w3c.dom.DOMException; 21 import org.w3c.dom.NamedNodeMap; 22 import org.w3c.dom.Node; 23 import org.w3c.dom.NodeList; 24 25 /*** 26 * @author Tweety 27 * 28 * A class representing a node in a meta-data tree, which implements 29 * the <a href="../../../../api/org/w3c/dom/Element.html"> 30 * 31 * <p> Namespaces are ignored in this implementation. The terms "tag 32 * name" and "node name" are always considered to be synonymous. 33 * 34 * @version 1.0 35 */ 36 public class ElementImpl extends NodeImpl implements Element { 37 38 /*** 39 * A <code>HashMap</code> of <code>AttrImpl</code> nodes representing 40 * attributes. 41 */ 42 protected HashMap attributes = null; 43 44 45 /*** 46 * Constructs an empty <code>ElementImpl</code>. 47 */ 48 public ElementImpl() { 49 attributes = new HashMap(); 50 type = ELEMENT_NODE; 51 } 52 53 54 /*** 55 * Constructs a <code>ElementImpl</code> from the given node, 56 * without creating entire children subtree. 57 * 58 * @param element, as a <code>ElementImpl</code>. 59 */ 60 public ElementImpl(ElementImpl element) { 61 super(element); 62 attributes = element.attributes; 63 type = ELEMENT_NODE; 64 } 65 66 67 /*** 68 * Constructs an <code>ElementImpl</code> with the given 69 * document owner and node name. 70 * 71 * @param ownerDoc the document owner of the node, as a <code>Document</code>. 72 * @param nodeName the name of the node, as a <code>String</code>. 73 */ 74 public ElementImpl(Document ownerDoc, String name) { 75 super(ownerDoc,name,ELEMENT_NODE); 76 this.attributes = new HashMap(); 77 } 78 79 80 /*** 81 * Constructs an <code>ElementImpl</code> with the given 82 * document owner, node name, node type and node value. 83 * 84 * @param ownerDoc the document owner of the node, as a <code>Document</code>. 85 * @param nodeName the name of the node, as a <code>String</code>. 86 * @param type the type of the node, as a <code>short</code>. 87 * @param value the value of the node, as a <code>String</code>. 88 */ 89 protected ElementImpl(Document ownerDoc, String nodeName, short type, String value) { 90 super(ownerDoc, nodeName, type, value); 91 } 92 93 94 /*** 95 * Constructs an <code>ElementImpl</code> from a given node (creates the children subtree too), 96 * as a <code>Node</code> 97 * 98 * @param node, as a <code>Node</code>. 99 */ 100 public ElementImpl(Node node) { 101 this(node,true); 102 } 103 104 105 /*** 106 * Constructs an <code>ElementImpl</code> from a given node, as a <code>Node</code>, 107 * and deep as <code>boolean</code>. 108 * 109 * @param node, as a <code>Node</code>. 110 * @param deep if <code>true</code>, recursively clone the subtree 111 * under the specified node; if <code>false</code>, clone only the 112 * node itself. 113 */ 114 public ElementImpl(Node node, boolean deep) { 115 super(node,false); 116 attributes = new HashMap(); 117 NamedNodeMap attrs = node.getAttributes(); 118 if (attrs != null) { 119 for (int i = 0; i < attrs.getLength(); i++) { 120 Attr attr = new AttrImpl((Attr) attrs.item(i)); 121 attributes.put(attr.getName(), attr); 122 } 123 } 124 if (deep) 125 initNodeImplChildren(node); 126 } 127 128 129 /*** 130 * Creates new instance of <code>ElementImpl</code> from a given document 131 * as a <code>Document</code>. 132 * 133 * @param document document. 134 * 135 * @return new <code>Element</code> node as a root of the <code>Document</code>. 136 */ 137 public static Element newInstance(Document document) { 138 Node root = document.getDocumentElement(); 139 return new ElementImpl(root); 140 } 141 142 143 /*** 144 * Inserts the node <code>newChild</code> before the existing 145 * child node <code>refChild</code>. If <code>refChild</code> is 146 * <code>null</code>, insert <code>newChild</code> at the end of 147 * the list of children. 148 * 149 * @param newChild the <code>Node</code> to insert. 150 * @param refChild the reference <code>Node</code>. 151 * 152 * @return the node being inserted. 153 * 154 * @exception IllegalArgumentException if <code>newChild</code> is 155 * <code>null</code>. 156 */ 157 public Node insertBefore(Node newChild, Node refChild) { 158 super.insertBefore(newChild,refChild); 159 return newChild; 160 } 161 162 163 /*** 164 * Replaces the child node <code>oldChild</code> with 165 * <code>newChild</code> in the list of children, and returns the 166 * <code>oldChild</code> node. 167 * 168 * @param newChild the <code>Node</code> to insert. 169 * @param oldChild the <code>Node</code> to be replaced. 170 * 171 * @return the node replaced. 172 * 173 * @exception IllegalArgumentException if <code>newChild</code> is 174 * <code>null</code>. 175 */ 176 public Node replaceChild(Node newChild, Node oldChild) { 177 super.replaceChild(newChild,oldChild); 178 return oldChild; 179 } 180 181 182 /*** 183 * Removes the child node indicated by <code>oldChild</code> from 184 * the list of children, and returns it. 185 * 186 * @param oldChild the <code>Node</code> to be removed. 187 * 188 * @return the node removed. 189 * 190 * @exception IllegalArgumentException if <code>oldChild</code> is 191 * <code>null</code>. 192 */ 193 public Node removeChild(Node oldChild) { 194 super.removeChild(oldChild); 195 return oldChild; 196 } 197 198 199 /*** 200 * Returns a duplicate of this node. The duplicate node has no 201 * parent (<code>getParentNode</code> returns <code>null</code>). 202 * If a shallow clone is being performed (<code>deep</code> is 203 * <code>false</code>), the new node will not have any children or 204 * siblings. If a deep clone is being performed, the new node 205 * will form the root of a complete cloned subtree. 206 * 207 * @param deep if <code>true</code>, recursively clone the subtree 208 * under the specified node; if <code>false</code>, clone only the 209 * node itself. 210 * 211 * @return the duplicate node. 212 */ 213 public Node cloneNode(boolean deep) { 214 return new ElementImpl(this,deep); 215 } 216 217 218 219 220 221 // Methods from Element 222 223 224 /*** 225 * Returns tag name of this node. 226 * 227 * @return tag name of this node as a <code>String</code>. 228 */ 229 public String getTagName() { 230 return nodeName; 231 } 232 233 234 /*** 235 * Returns all attribute nodes of this node. 236 * 237 * @return all attribute nodes of this node as a <code>NamedNodeMap</code>. 238 */ 239 public NamedNodeMap getAttributes() { 240 return new HashMapNamedNodeMap(attributes); 241 } 242 243 244 /*** 245 * Returns the value of the attribute with given name. 246 * 247 * @param name name of attribute. 248 * 249 * @return value of attribute. 250 */ 251 public String getAttribute(String name) { 252 Attr attr = getAttributeNode(name); 253 if (attr == null) { 254 return ""; 255 } 256 return attr.getValue(); 257 } 258 259 260 /*** 261 * Equivalent to <code>getAttribute(localName)</code>. 262 * 263 * @see #setAttributeNS 264 */ 265 public String getAttributeNS(String namespaceURI, String localName) { 266 return getAttribute(localName); 267 } 268 269 270 /*** 271 * To the <code>name</code> attribute set value to <code>value</code>. 272 * 273 * @param name attribute value. 274 * @param value new attribute value. 275 */ 276 public void setAttribute(String name, String value) { 277 // Note minor dependency on Crimson package 278 // Steal the code if Crimson ever goes away 279 if (!org.apache.crimson.util.XmlNames.isName(name)) { 280 throw new NodeDOMException( 281 DOMException.INVALID_CHARACTER_ERR, 282 "Attribute name is illegal!"); 283 } 284 attributes.put(name, new AttrImpl(this, name, value)); 285 } 286 287 288 /*** 289 * Equivalent to <code>setAttribute(qualifiedName, value)</code>. 290 * 291 * @see #getAttributeNS 292 */ 293 public void setAttributeNS(String namespaceURI, String qualifiedName, String value) { 294 setAttribute(qualifiedName, value); 295 } 296 297 298 /*** 299 * Removes attribute with the given name. 300 * 301 * @param name attribute name. 302 */ 303 public void removeAttribute(String name) { 304 if (type != ELEMENT_NODE) 305 throw new NodeDOMException( 306 DOMException.NOT_SUPPORTED_ERR, 307 "Node doesn't have attributes"); 308 removeAttribute(name, true); 309 } 310 311 312 private void removeAttribute(String name, boolean checkPresent) { 313 if (attributes.remove(name) != null) 314 return; 315 // If we get here, the attribute doesn't exist 316 if (checkPresent) { 317 throw new NodeDOMException( 318 DOMException.NOT_FOUND_ERR, 319 "No such attribute!"); 320 } 321 } 322 323 324 /*** 325 * Returns <code>true</code>, if this node has attributes, otherwise 326 * <code>false</code>. 327 * 328 * @return <code>true</code> if node has attributes, otherwise <code>false</code>.. 329 */ 330 public boolean hasAttributes() { 331 return attributes.size() > 0; 332 } 333 334 335 /*** 336 * Returns <code>true</code>, if this node has attribute with given name, 337 * otherwise <code>false</code>. 338 * 339 * @return <code>true</code> if node has given attribute, otherwise <code>false</code>.. 340 */ 341 public boolean hasAttribute(String name) { 342 return getAttributeNode(name) != null; 343 } 344 345 346 /*** 347 * Equivalent to <code>removeAttribute(localName)</code>. 348 */ 349 public void removeAttributeNS(String namespaceURI, String localName) { 350 removeAttribute(localName); 351 } 352 353 354 /*** 355 * Returns attribute value with given name of this node. 356 * 357 * @param name name of attribute. 358 * 359 * @return value of attribute. 360 */ 361 public Attr getAttributeNode(String name) { 362 return (Attr) attributes.get(name); 363 } 364 365 366 /*** 367 * Equivalent to <code>getAttributeNode(localName)</code>. 368 * 369 * @see #setAttributeNodeNS 370 */ 371 public Attr getAttributeNodeNS(String namespaceURI, String localName) { 372 return getAttributeNode(localName); 373 } 374 375 376 /*** 377 * Add new attribute to this node. 378 * 379 * @param newAttr new attribute. 380 * 381 * @return new attribute as <code>AttrImpl</code>. 382 */ 383 public Attr setAttributeNode(Attr newAttr) throws DOMException { 384 AttrImpl attr; 385 if (newAttr instanceof AttrImpl) { 386 attr = (AttrImpl) newAttr; 387 } else { 388 attr = new AttrImpl(newAttr); 389 } 390 attributes.put(attr.getName(), attr); 391 return attr; 392 } 393 394 395 /*** 396 * Equivalent to <code>setAttributeNode(newAttr)</code>. 397 * 398 * @see #getAttributeNodeNS 399 */ 400 public Attr setAttributeNodeNS(Attr newAttr) { 401 return setAttributeNode(newAttr); 402 } 403 404 405 /*** 406 * Remove attribute from this node. 407 * 408 * @param oldAttr attribute that will be removed. 409 * 410 * @return old attribute as <code>AttrImpl</code>. 411 */ 412 public Attr removeAttributeNode(Attr oldAttr) { 413 removeAttribute(oldAttr.getName()); 414 return oldAttr; 415 } 416 417 418 /*** 419 * Equivalent to <code>hasAttribute(localName)</code>. 420 */ 421 public boolean hasAttributeNS(String namespaceURI, String localName) { 422 return hasAttribute(localName); 423 } 424 425 426 /*** 427 * Returns all <code>Element</code> nodes with given name, 428 * searching by all sub nodes from this node. 429 * 430 * @param name tag name. 431 * 432 * @return all <code>Element</code> vith given name as <code>NodeList</code>. 433 */ 434 public NodeList getElementsByTagName(String name) { 435 List list = new ArrayList(); 436 getElementsByTagName(name, list); 437 return new NodeListImpl(list); 438 } 439 440 441 private void getElementsByTagName(String name, List list) { 442 if (nodeName.equals(name)) { 443 list.add(this); 444 } 445 446 Node child = getFirstChild(); 447 while (child != null) { 448 if (child.getNodeType() == Node.ELEMENT_NODE) 449 ((ElementImpl)child).getElementsByTagName(name, list); 450 child = child.getNextSibling(); 451 } 452 } 453 454 455 /*** 456 * Equivalent to <code>getElementsByTagName(localName)</code>. 457 */ 458 public NodeList getElementsByTagNameNS(String namespaceURI, String localName) { 459 return getElementsByTagName(localName); 460 } 461 462 463 /*** 464 * Returns <code>true</code> if this node has children nodes. 465 * 466 * @return <code>true</code> if this node has children. 467 */ 468 public boolean hasElementChildNodes() { 469 Node child = getFirstChild(); 470 while (child != null) { 471 if (child.getNodeType() == Node.ELEMENT_NODE) 472 return true; 473 child = child.getNextSibling(); 474 } 475 return false; 476 } 477 478 479 /*** 480 * Method beginToString for this class writes the xml 481 * begining tag string and all attributes. 482 * 483 * @param sb string buffer to add resulting string. 484 * @param indent used in formating the output. 485 */ 486 protected void beginToString(StringBuffer sb, Indent indent) { 487 sb.append("\n" + indent + "<" + this.nodeName); 488 489 for (Iterator iter = attributes.values().iterator(); iter.hasNext();) { 490 Attr attr = (Attr) iter.next(); 491 sb.append(" " + attr.getNodeName() + "=\"" + attr.getNodeValue() + "\""); 492 } 493 // if (hasChildNodes()) { 494 sb.append(">"); 495 indent.increment(); 496 // } else 497 // sb.append("/>"); 498 } 499 500 501 /*** 502 * Method endToString for this class writes the xml 503 * ending tag string. 504 * 505 * @param sb string buffer to add resulting string. 506 * @param indent used in formating the output. 507 */ 508 protected void endToString(StringBuffer sb, Indent indent) { 509 // if (hasChildNodes()) { 510 indent.decrement(); 511 if (hasElementChildNodes()) 512 sb.append("\n" + indent + "</" + this.nodeName + ">"); 513 else 514 sb.append("</" + this.nodeName + ">"); 515 // } 516 } 517 }

This page automatically generated by Maven