Coverage Report - org.jaxen.dom.NamespaceNode

Classes in this File Line Coverage Branch Coverage Complexity
NamespaceNode
40% 
59% 
1.565

 1  
 /*
 2  
  * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/dom/NamespaceNode.java,v 1.20 2005/06/28 13:44:46 elharo Exp $
 3  
  * $Revision: 1.20 $
 4  
  * $Date: 2005/06/28 13:44:46 $
 5  
  *
 6  
  * ====================================================================
 7  
  *
 8  
  * Copyright (C) 2000-2002 bob mcwhirter & James Strachan.
 9  
  * All rights reserved.
 10  
  *
 11  
  * Redistribution and use in source and binary forms, with or without
 12  
  * modification, are permitted provided that the following conditions
 13  
  * are met:
 14  
  * 
 15  
  * 1. Redistributions of source code must retain the above copyright
 16  
  *    notice, this list of conditions, and the following disclaimer.
 17  
  *
 18  
  * 2. Redistributions in binary form must reproduce the above copyright
 19  
  *    notice, this list of conditions, and the disclaimer that follows 
 20  
  *    these conditions in the documentation and/or other materials 
 21  
  *    provided with the distribution.
 22  
  *
 23  
  * 3. The name "Jaxen" must not be used to endorse or promote products
 24  
  *    derived from this software without prior written permission.  For
 25  
  *    written permission, please contact license@jaxen.org.
 26  
  * 
 27  
  * 4. Products derived from this software may not be called "Jaxen", nor
 28  
  *    may "Jaxen" appear in their name, without prior written permission
 29  
  *    from the Jaxen Project Management (pm@jaxen.org).
 30  
  * 
 31  
  * In addition, we request (but do not require) that you include in the 
 32  
  * end-user documentation provided with the redistribution and/or in the 
 33  
  * software itself an acknowledgement equivalent to the following:
 34  
  *     "This product includes software developed by the
 35  
  *      Jaxen Project <http://www.jaxen.org/>."
 36  
  * Alternatively, the acknowledgment may be graphical using the logos 
 37  
  * available at http://www.jaxen.org/
 38  
  *
 39  
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 40  
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 41  
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 42  
  * DISCLAIMED.  IN NO EVENT SHALL THE Jaxen AUTHORS OR THE PROJECT
 43  
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 44  
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 45  
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 46  
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 47  
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 48  
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 49  
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 50  
  * SUCH DAMAGE.
 51  
  *
 52  
  * ====================================================================
 53  
  * This software consists of voluntary contributions made by many 
 54  
  * individuals on behalf of the Jaxen Project and was originally 
 55  
  * created by bob mcwhirter <bob@werken.com> and 
 56  
  * James Strachan <jstrachan@apache.org>.  For more information on the 
 57  
  * Jaxen Project, please see <http://www.jaxen.org/>.
 58  
  * 
 59  
  * $Id: NamespaceNode.java,v 1.20 2005/06/28 13:44:46 elharo Exp $
 60  
  */
 61  
 
 62  
 ////////////////////////////////////////////////////////////////////
 63  
 // Inner class for a Namespace node.
 64  
 ////////////////////////////////////////////////////////////////////
 65  
 
 66  
 package org.jaxen.dom;
 67  
 
 68  
 import java.util.HashMap;
 69  
 
 70  
 import org.jaxen.pattern.Pattern;
 71  
 import org.w3c.dom.DOMException;
 72  
 import org.w3c.dom.Document;
 73  
 import org.w3c.dom.NamedNodeMap;
 74  
 import org.w3c.dom.Node;
 75  
 import org.w3c.dom.NodeList;
 76  
 import org.w3c.dom.UserDataHandler;
 77  
 
 78  
 
 79  
 /**
 80  
  * Extension DOM2/DOm3 node type for a namespace node.
 81  
  *
 82  
  * <p>This class implements the DOM2 and DOM3 {@link Node} interface
 83  
  * to allow namespace nodes to be included in the result
 84  
  * set of an XPath selectNodes operation, even though DOM does
 85  
  * not model namespaces in scope as separate nodes.</p>
 86  
  *
 87  
  * <p>
 88  
  * While all of the DOM2 methods are implemented with reasonable
 89  
  * defaults, there will be some unexpected surprises, so users are
 90  
  * advised to test for NamespaceNodes and filter them out from the
 91  
  * result sets as early as possible.
 92  
   * </p>
 93  
  *
 94  
  * <ol>
 95  
  *
 96  
  * <li>The {@link #getNodeType} method returns {@link #NAMESPACE_NODE},
 97  
  * which is not one of the usual DOM2 node types.  Generic code may
 98  
  * fall unexpectedly out of switch statements, for example.</li>
 99  
  *
 100  
  * <li>The {@link #getOwnerDocument} method returns the owner document
 101  
  * of the parent node, but that owner document will know nothing about
 102  
  * the namespace node.</p>
 103  
  *
 104  
  * <li>The {@link #isSupported} method always returns false.</li>
 105  
  *
 106  
  * <li> The DOM3 methods sometimes throw UnsupportedOperationException.
 107  
  *      They're here only to allow this class to be compiled with Java 1.5.
 108  
  *       Do not call or rely on them.</li>
 109  
  * </ol>
 110  
  *
 111  
  * <p>All attempts to modify a <code>NamespaceNode</code> will fail with a {@link
 112  
  * DOMException} ({@link
 113  
  * DOMException#NO_MODIFICATION_ALLOWED_ERR}).</p>
 114  
  *
 115  
  * @author David Megginson
 116  
  * @author Elliotte Rusty Harold
 117  
  * @see DocumentNavigator
 118  
  */
 119  
 public class NamespaceNode implements Node
 120  
 {
 121  
 
 122  
 
 123  
     ////////////////////////////////////////////////////////////////////
 124  
     // Constants.
 125  
     ////////////////////////////////////////////////////////////////////
 126  
 
 127  
     /**
 128  
      * Constant: this is a NamespaceNode.
 129  
      *
 130  
      * @see #getNodeType
 131  
      */
 132  
     public final static short NAMESPACE_NODE = Pattern.NAMESPACE_NODE;
 133  
 
 134  
     // FIXME "Note: Numeric codes up to 200 are reserved to W3C for possible future use."
 135  
     // Ww should be using higher codes.
 136  
 
 137  
     ////////////////////////////////////////////////////////////////////
 138  
     // Protected Constructors.
 139  
     ////////////////////////////////////////////////////////////////////
 140  
 
 141  
 
 142  
     /**
 143  
      * Create a new NamespaceNode.
 144  
      *
 145  
      * @param parent the DOM node to which the namespace is attached
 146  
      * @param name the namespace prefix
 147  
      * @param value the namespace URI
 148  
      */
 149  
     public NamespaceNode (Node parent, String name, String value)
 150  768
     {
 151  768
         this.parent = parent;
 152  768
         this.name = name;
 153  768
         this.value = value;
 154  768
     }
 155  
 
 156  
 
 157  
     /**
 158  
      * Constructor.
 159  
      *
 160  
      * @param parent the DOM node to which the namespace is attached
 161  
      * @param attribute the DOM attribute object containing the
 162  
      *        namespace declaration
 163  
      */
 164  
     NamespaceNode (Node parent, Node attribute)
 165  582
     {
 166  582
         String attributeName = attribute.getNodeName();
 167  
     
 168  582
         if (attributeName.equals("xmlns")) {
 169  0
             this.name = "";
 170  
         }
 171  582
         else if (attributeName.startsWith("xmlns:")) {
 172  582
             this.name = attributeName.substring(6); // the part after "xmlns:"
 173  
         }
 174  
         else { // workaround for Crimson bug; Crimson incorrectly reports the prefix as the node name
 175  0
             this.name = attributeName;
 176  
         }
 177  582
         this.parent = parent;
 178  582
         this.value = attribute.getNodeValue();
 179  582
     }
 180  
 
 181  
 
 182  
 
 183  
     ////////////////////////////////////////////////////////////////////
 184  
     // Implementation of org.w3c.dom.Node.
 185  
     ////////////////////////////////////////////////////////////////////
 186  
 
 187  
 
 188  
     /**
 189  
      * Get the namespace prefix.
 190  
      *
 191  
      * @return the namespace prefix, or "" for the default namespace
 192  
      */
 193  
     public String getNodeName ()
 194  
     {
 195  606
         return name;
 196  
     }
 197  
 
 198  
 
 199  
     /**
 200  
      * Get the namespace URI.
 201  
      *
 202  
      * @return the namespace URI
 203  
      */
 204  
     public String getNodeValue ()
 205  
     {
 206  66
         return value;
 207  
     }
 208  
 
 209  
 
 210  
     /**
 211  
      * Change the namespace URI (always fails).
 212  
      *
 213  
      * @param value the new URI
 214  
      * @throws DOMException always
 215  
      */
 216  
     public void setNodeValue (String value) throws DOMException
 217  
     {
 218  0
         disallowModification();
 219  0
     }
 220  
 
 221  
 
 222  
     /**
 223  
      * Get the node type.
 224  
      *
 225  
      * @return always {@link #NAMESPACE_NODE}.
 226  
      */
 227  
     public short getNodeType ()
 228  
     {
 229  9276
         return NAMESPACE_NODE;
 230  
     }
 231  
 
 232  
 
 233  
     /**
 234  
      * Get the parent node.
 235  
      *
 236  
      * <p>This method returns the element that was queried for Namespaces
 237  
      * in effect, <em>not</em> necessarily the actual element containing
 238  
      * the Namespace declaration.</p>
 239  
      *
 240  
      * @return the parent node (not null)
 241  
      */
 242  
     public Node getParentNode ()
 243  
     {
 244  2238
         return parent;
 245  
     }
 246  
 
 247  
 
 248  
     /**
 249  
      * Get the list of child nodes.
 250  
      *
 251  
      * @return an empty node list
 252  
      */
 253  
     public NodeList getChildNodes ()
 254  
     {
 255  0
         return new EmptyNodeList();
 256  
     }
 257  
 
 258  
 
 259  
     /**
 260  
      * Get the first child node.
 261  
      *
 262  
      * @return null
 263  
      */
 264  
     public Node getFirstChild ()
 265  
     {
 266  0
         return null;
 267  
     }
 268  
 
 269  
 
 270  
     /**
 271  
      * Get the last child node.
 272  
      *
 273  
      * @return null
 274  
      */
 275  
     public Node getLastChild ()
 276  
     {
 277  0
         return null;
 278  
     }
 279  
 
 280  
 
 281  
     /**
 282  
      * Get the previous sibling node.
 283  
      *
 284  
      * @return null
 285  
      */
 286  
     public Node getPreviousSibling ()
 287  
     {
 288  0
         return null;
 289  
     }
 290  
 
 291  
 
 292  
     /**
 293  
      * Get the next sibling node.
 294  
      *
 295  
      * @return null
 296  
      */
 297  
     public Node getNextSibling ()
 298  
     {
 299  0
         return null;
 300  
     }
 301  
 
 302  
 
 303  
     /**
 304  
      * Get the attribute nodes.
 305  
      *
 306  
      * @return null
 307  
      */
 308  
     public NamedNodeMap getAttributes ()
 309  
     {
 310  0
         return null;
 311  
     }
 312  
 
 313  
 
 314  
     /**
 315  
      * Get the owner document.
 316  
      *
 317  
      * @return the owner document <em>of the parent node</em>
 318  
      */
 319  
     public Document getOwnerDocument ()
 320  
     {
 321  0
         if (parent == null) return null;
 322  0
         return parent.getOwnerDocument();
 323  
     }
 324  
 
 325  
 
 326  
     /**
 327  
      * Insert a new child node (always fails).
 328  
      * 
 329  
      * @param newChild the node to add
 330  
      * @param refChild ignored
 331  
      * @return never
 332  
      * @throws DOMException always
 333  
      * @see Node#insertBefore
 334  
      */
 335  
     public Node insertBefore (Node newChild, Node refChild)
 336  
     throws DOMException
 337  
     {
 338  0
         disallowModification();
 339  0
         return null;
 340  
     }
 341  
 
 342  
 
 343  
     /**
 344  
      * Replace a child node (always fails).
 345  
      *
 346  
      * @param newChild the node to add
 347  
      * @param oldChild the child node to replace
 348  
      * @return never
 349  
      * @throws DOMException always
 350  
      * @see Node#replaceChild
 351  
      */
 352  
     public Node replaceChild (Node newChild, Node oldChild)
 353  
     throws DOMException
 354  
     {
 355  0
         disallowModification();
 356  0
         return null;
 357  
     }
 358  
 
 359  
 
 360  
     /**
 361  
      * Remove a child node (always fails).
 362  
      *
 363  
      * @param oldChild the child node to remove
 364  
      * @return never
 365  
      * @throws DOMException always
 366  
      * @see Node#removeChild
 367  
      */
 368  
     public Node removeChild (Node oldChild)
 369  
     throws DOMException
 370  
     {
 371  0
         disallowModification();
 372  0
         return null;
 373  
     }
 374  
 
 375  
 
 376  
     /**
 377  
      * Append a new child node (always fails).
 378  
      *
 379  
      * @param newChild the node to add
 380  
      * @return never
 381  
      * @throws DOMException always
 382  
      * @see Node#appendChild
 383  
      */
 384  
     public Node appendChild (Node newChild)
 385  
     throws DOMException
 386  
     {
 387  0
         disallowModification();
 388  0
         return null;
 389  
     }
 390  
 
 391  
 
 392  
     /**
 393  
      * Test for child nodes.
 394  
      *
 395  
      * @return false
 396  
      */
 397  
     public boolean hasChildNodes ()
 398  
     {
 399  0
         return false;
 400  
     }
 401  
 
 402  
 
 403  
     /**
 404  
      * Create a copy of this node.
 405  
      *
 406  
      * @param deep make a deep copy (no effect, since namespace nodes
 407  
      *        don't have children).
 408  
      * @return a new copy of this namespace node
 409  
      */
 410  
     public Node cloneNode (boolean deep)
 411  
     {
 412  0
         return new NamespaceNode(parent, name, value);
 413  
     }
 414  
 
 415  
 
 416  
     /**
 417  
      * Normalize the text descendants of this node.
 418  
      *
 419  
      * <p>This method has no effect, since namespace nodes have no
 420  
      * descendants.</p>
 421  
      */
 422  
     public void normalize ()
 423  
     {
 424  
     // no op
 425  0
     }
 426  
 
 427  
 
 428  
     /**
 429  
      * Test if a DOM2 feature is supported.
 430  
      *
 431  
      * @param feature the feature name
 432  
      * @param version the feature version
 433  
      * @return false
 434  
      */
 435  
     public boolean isSupported (String feature, String version)
 436  
     {
 437  0
         return false;
 438  
     }
 439  
 
 440  
 
 441  
     /**
 442  
      * Get the namespace URI of this node.
 443  
      *
 444  
      * <p>Namespace declarations are not themselves
 445  
      * Namespace-qualified.</p>
 446  
      *
 447  
      * @return null
 448  
      */
 449  
     public String getNamespaceURI ()
 450  
     {
 451  0
        return null;
 452  
     }
 453  
 
 454  
 
 455  
     /**
 456  
      * Get the namespace prefix of this node.
 457  
      *
 458  
      * <p>Namespace declarations are not themselves
 459  
      * namespace-qualified.</p>
 460  
      *
 461  
      * @return null
 462  
      * @see #getLocalName
 463  
      */
 464  
     public String getPrefix ()
 465  
     {
 466  0
         return null;
 467  
     }
 468  
 
 469  
 
 470  
     /**
 471  
      * Change the namespace prefix of this node (always fails).
 472  
      *
 473  
      * @param prefix the new prefix
 474  
      * @throws DOMException always thrown
 475  
      */
 476  
     public void setPrefix (String prefix)
 477  
     throws DOMException
 478  
     {
 479  0
         disallowModification();
 480  0
     }
 481  
 
 482  
 
 483  
     /**
 484  
      * Get the XPath name of the namespace node;; i.e. the
 485  
      * namespace prefix.
 486  
      *
 487  
      * @return the namespace prefix
 488  
      */
 489  
     public String getLocalName ()
 490  
     {
 491  942
         return name;
 492  
     }
 493  
 
 494  
 
 495  
     /**
 496  
      * Test if this node has attributes.
 497  
      *
 498  
      * @return false
 499  
      */
 500  
     public boolean hasAttributes ()
 501  
     {
 502  0
         return false;
 503  
     }
 504  
 
 505  
 
 506  
     /**
 507  
      * Throw a NO_MODIFICATION_ALLOWED_ERR DOMException.
 508  
      *
 509  
      * @throws DOMException always thrown
 510  
      */
 511  
     private void disallowModification () throws DOMException
 512  
     {
 513  6
         throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
 514  
                    "Namespace node may not be modified");
 515  
     }
 516  
 
 517  
 
 518  
 
 519  
     ////////////////////////////////////////////////////////////////////
 520  
     // Override default methods from java.lang.Object.
 521  
     ////////////////////////////////////////////////////////////////////
 522  
 
 523  
 
 524  
     /**
 525  
      * Generate a hash code for a namespace node.
 526  
      *
 527  
      * @return a hash code for this node
 528  
      */
 529  
     public int hashCode ()
 530  
     {
 531  48
     return hashCode(parent) + hashCode(name) + hashCode(value);
 532  
     }
 533  
 
 534  
 
 535  
     /**
 536  
      * Test for equivalence with another object.
 537  
      *
 538  
      * <p>Two Namespace nodes are considered equivalent if their parents,
 539  
      * names, and values are equal.</p>
 540  
      *
 541  
      * @param o the object to test for equality
 542  
      * @return true if the object is equivalent to this node, false
 543  
      *         otherwise
 544  
      */
 545  
     public boolean equals (Object o)
 546  
     {
 547  0
         if (o == this) return true;
 548  0
         else if (o == null) return false;
 549  0
         else if (o instanceof NamespaceNode) {
 550  0
             NamespaceNode ns = (NamespaceNode)o;
 551  0
             return (equals(parent, ns.getParentNode()) &&
 552  
                 equals(name, ns.getNodeName()) &&
 553  
                 equals(value, ns.getNodeValue()));
 554  
         } else {
 555  0
             return false;
 556  
         }
 557  
     }
 558  
 
 559  
 
 560  
     /**
 561  
      * Helper method for generating a hash code.
 562  
      *
 563  
      * @param o the object for generating a hash code (possibly null)
 564  
      * @return the object's hash code, or 0 if the object is null
 565  
      * @see java.lang.Object#hashCode
 566  
      */
 567  
     private int hashCode (Object o)
 568  
     {
 569  144
     return (o == null ? 0 : o.hashCode());
 570  
     }
 571  
 
 572  
 
 573  
     /**
 574  
      * Helper method for comparing two objects.
 575  
      *
 576  
      * @param a the first object to compare (possibly null)
 577  
      * @param b the second object to compare (possibly null)
 578  
      * @return true if the objects are equivalent or are both null
 579  
      * @see java.lang.Object#equals
 580  
      */
 581  
     private boolean equals (Object a, Object b)
 582  
     {
 583  0
         return ((a == null && b == null) ||
 584  
           (a != null && a.equals(b)));
 585  
     }
 586  
 
 587  
 
 588  
     ////////////////////////////////////////////////////////////////////
 589  
     // Internal state.
 590  
     ////////////////////////////////////////////////////////////////////
 591  
 
 592  
     private Node parent;
 593  
     private String name;
 594  
     private String value;
 595  
 
 596  
 
 597  
 
 598  
     ////////////////////////////////////////////////////////////////////
 599  
     // Inner class: empty node list.
 600  
     ////////////////////////////////////////////////////////////////////
 601  
 
 602  
 
 603  
     /**
 604  
      * A node list with no members.
 605  
      *
 606  
      * <p>This class is necessary for the {@link Node#getChildNodes}
 607  
      * method, which must return an empty node list rather than
 608  
      * null when there are no children.</p>
 609  
      */
 610  0
     private static class EmptyNodeList implements NodeList
 611  
     {
 612  
 
 613  
         /**
 614  
          * @see NodeList#getLength
 615  
          */
 616  
         public int getLength ()
 617  
         {
 618  0
             return 0;
 619  
         }
 620  
     
 621  
     
 622  
         /**
 623  
          * @see NodeList#item
 624  
          */
 625  
         public Node item(int index)
 626  
         {
 627  0
             return null;
 628  
         }
 629  
     
 630  
     }
 631  
 
 632  
     ////////////////////////////////////////////////////////////////////
 633  
     // DOM Level 3 methods
 634  
     ////////////////////////////////////////////////////////////////////
 635  
 
 636  
     /**
 637  
      * Return the base URI of the document containing this node (always fails).
 638  
      *
 639  
      * @return null
 640  
      */
 641  
     public String getBaseURI() {
 642  
         // XXX we could use reflection in DOM Level 3 to get this value
 643  0
         return null;
 644  
     }
 645  
 
 646  
 
 647  
     /**
 648  
      * Compare relative position of this node to another nbode. (Always fails).
 649  
      *
 650  
      * @return never
 651  
      * @throws DOMException NOT_SUPPORTED_ERR
 652  
      */
 653  
     public short compareDocumentPosition(Node other) throws DOMException {
 654  0
         DOMException ex = new DOMException(
 655  
           DOMException.NOT_SUPPORTED_ERR,
 656  
           "DOM level 3 interfaces are not fully implemented in Jaxen's NamespaceNode class"
 657  
         );
 658  0
         throw ex;
 659  
     }
 660  
 
 661  
 
 662  
     /**
 663  
      * Return the namespace URI.
 664  
      *
 665  
      * @return the namespace URI
 666  
      * @see #getNodeValue
 667  
      */
 668  
     public String getTextContent() {
 669  6
         return value;
 670  
     }
 671  
 
 672  
 
 673  
     /**
 674  
      * Change the value of this node (always fails).
 675  
      *
 676  
      * @param textContent the new content
 677  
      * @throws DOMException always
 678  
      */
 679  
     public void setTextContent(String textContent) throws DOMException {
 680  6
         disallowModification();
 681  0
     }
 682  
 
 683  
 
 684  
     /**
 685  
      * Returns true if and only if this object represents the same XPath namespace node
 686  
      * as the argument; that is, they have the same parent, the same prefix, and the
 687  
      * same URI.
 688  
      * 
 689  
      * @param other the node to compare to
 690  
      * @return true if this object represents the same XPath namespace node
 691  
      *     as other; false otherwise
 692  
      */
 693  
     public boolean isSameNode(Node other) {
 694  12
         return this.isEqualNode(other) 
 695  
           // a bit flaky (should really be this.getParentNode().isEqual(other.getParentNode())
 696  
           // but we want this to compile in Java 1.4 without problems
 697  
           && this.getParentNode() == other.getParentNode();
 698  
     }
 699  
 
 700  
 
 701  
     /**
 702  
      * Return the prefix bound to this namespace URI within the scope
 703  
      * of this node (always fails).
 704  
      *
 705  
      * @return never
 706  
      * @throws UnsupportedOperationException always
 707  
      */
 708  
     public String lookupPrefix(String namespaceURI) {
 709  
         // XXX This could be implemented. See
 710  
         // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo
 711  
         // It hardly seems worth the effort though.
 712  0
         throw new UnsupportedOperationException("Changing interfaces in a JDK blows chunks!");
 713  
     }
 714  
 
 715  
 
 716  
     /**
 717  
      * Return true if the specified URI is the default namespace in
 718  
      * scope (always fails).
 719  
      *
 720  
      * @return never
 721  
      * @throws UnsupportedOperationException always
 722  
      */
 723  
     public boolean isDefaultNamespace(String namespaceURI) {
 724  0
         return namespaceURI.equals(this.lookupNamespaceURI(null));
 725  
     }
 726  
 
 727  
 
 728  
     /**
 729  
      * Return the namespace URI mapped to the specified
 730  
      * prefix within the scope of this namespace node (always fails).
 731  
      *
 732  
      * @return never
 733  
      * @throws UnsupportedOperationException always
 734  
      */
 735  
     public String lookupNamespaceURI(String prefix) {
 736  
         // XXX This could be implemented. See
 737  
         // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo
 738  
         // It hardly seems worth the effort though.
 739  0
         throw new UnsupportedOperationException("Changing interfaces in a JDK blows chunks!");
 740  
     }
 741  
 
 742  
 
 743  
     /**
 744  
      * Returns true if this object binds the same prefix to the same URI.
 745  
      * That is, this object has the same prefix and URI as the argument.
 746  
      * 
 747  
      * @param arg the node to compare to
 748  
      * @return true if this object has the same prefix and URI as the argument; false otherwise
 749  
      */
 750  
     public boolean isEqualNode(Node arg) {
 751  24
         if (arg.getNodeType() == this.getNodeType()) {
 752  24
             NamespaceNode other = (NamespaceNode) arg;
 753  24
             if (other.name == null && this.name != null) return false;
 754  24
             else if (other.name != null && this.name == null) return false;
 755  12
             else if (other.value == null && this.value != null) return false;
 756  12
             else if (other.value != null && this.value == null) return false;
 757  12
             else if (other.name == null && this.name == null) {
 758  12
                 return other.value.equals(this.value);
 759  
             }
 760  
 
 761  0
             return other.name.equals(this.name) && other.value.equals(this.value);
 762  
         }
 763  0
         return false;
 764  
     }
 765  
 
 766  
 
 767  
     /**
 768  
      * Returns the value of the requested feature. Always returns null.
 769  
      * 
 770  
      * @return null
 771  
      */
 772  
     public Object getFeature(String feature, String version) {
 773  6
         return null;
 774  
     }
 775  
 
 776  
     
 777  
     // XXX userdata needs testing
 778  1350
     private HashMap userData = new HashMap();
 779  
 
 780  
     /**
 781  
      * Associates an object with a key. 
 782  
      * 
 783  
      * @param key the key by which the data will be retrieved
 784  
      * @param data the object to store with the key
 785  
      * @param handler ignored since nnamespace ndoes cannot be imported, cloned, or renamed
 786  
      * 
 787  
      * @return the value previously associated with this key; or null
 788  
      *     if there isn't any such previous value
 789  
      */
 790  
     public Object setUserData(String key, Object data, UserDataHandler handler) {
 791  0
         Object oldValue = getUserData(key);
 792  0
         userData.put(key, data);
 793  0
         return oldValue;
 794  
     }
 795  
 
 796  
 
 797  
     /**
 798  
      * Returns the user data associated with the given key. 
 799  
      * 
 800  
      * @return the object associated with the key; or null if no such object is available
 801  
      */
 802  
     public Object getUserData(String key) {
 803  0
         return userData.get(key);
 804  
     }
 805  
     
 806  
 }
 807  
 
 808  
 // end of Namespace.java