KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jaxen > dom > NamespaceNode


1 /*
2  * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/dom/NamespaceNode.java,v 1.19 2005/06/26 16:13:33 elharo Exp $
3  * $Revision: 1.19 $
4  * $Date: 2005/06/26 16:13:33 $
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.19 2005/06/26 16:13:33 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 JavaDoc;
69
70 import org.jaxen.pattern.Pattern;
71 import org.w3c.dom.DOMException JavaDoc;
72 import org.w3c.dom.Document JavaDoc;
73 import org.w3c.dom.NamedNodeMap JavaDoc;
74 import org.w3c.dom.Node JavaDoc;
75 import org.w3c.dom.NodeList JavaDoc;
76 import org.w3c.dom.UserDataHandler JavaDoc;
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 JavaDoc
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 JavaDoc parent, String JavaDoc name, String JavaDoc value)
150     {
151         this.parent = parent;
152         this.name = name;
153         this.value = value;
154     }
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 JavaDoc parent, Node JavaDoc attribute)
165     {
166         String JavaDoc attributeName = attribute.getNodeName();
167     
168         if (attributeName.equals("xmlns")) {
169             this.name = "";
170         }
171         else if (attributeName.startsWith("xmlns:")) {
172             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
this.name = attributeName;
176         }
177         this.parent = parent;
178         this.value = attribute.getNodeValue();
179     }
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 JavaDoc getNodeName ()
194     {
195         return name;
196     }
197
198
199     /**
200      * Get the namespace URI.
201      *
202      * @return the namespace URI
203      */

204     public String JavaDoc getNodeValue ()
205     {
206         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 JavaDoc value) throws DOMException JavaDoc
217     {
218         disallowModification();
219     }
220
221
222     /**
223      * Get the node type.
224      *
225      * @return always {@link #NAMESPACE_NODE}.
226      */

227     public short getNodeType ()
228     {
229         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 JavaDoc getParentNode ()
243     {
244         return parent;
245     }
246
247
248     /**
249      * Get the list of child nodes.
250      *
251      * @return an empty node list
252      */

253     public NodeList JavaDoc getChildNodes ()
254     {
255         return new EmptyNodeList();
256     }
257
258
259     /**
260      * Get the first child node.
261      *
262      * @return null
263      */

264     public Node JavaDoc getFirstChild ()
265     {
266         return null;
267     }
268
269
270     /**
271      * Get the last child node.
272      *
273      * @return null
274      */

275     public Node JavaDoc getLastChild ()
276     {
277         return null;
278     }
279
280
281     /**
282      * Get the previous sibling node.
283      *
284      * @return null
285      */

286     public Node JavaDoc getPreviousSibling ()
287     {
288         return null;
289     }
290
291
292     /**
293      * Get the next sibling node.
294      *
295      * @return null
296      */

297     public Node JavaDoc getNextSibling ()
298     {
299         return null;
300     }
301
302
303     /**
304      * Get the attribute nodes.
305      *
306      * @return null
307      */

308     public NamedNodeMap JavaDoc getAttributes ()
309     {
310         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 JavaDoc getOwnerDocument ()
320     {
321         if (parent == null) return null;
322         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 JavaDoc insertBefore (Node JavaDoc newChild, Node JavaDoc refChild)
336     throws DOMException JavaDoc
337     {
338         disallowModification();
339         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 JavaDoc replaceChild (Node JavaDoc newChild, Node JavaDoc oldChild)
353     throws DOMException JavaDoc
354     {
355         disallowModification();
356         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 JavaDoc removeChild (Node JavaDoc oldChild)
369     throws DOMException JavaDoc
370     {
371         disallowModification();
372         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 JavaDoc appendChild (Node JavaDoc newChild)
385     throws DOMException JavaDoc
386     {
387         disallowModification();
388         return null;
389     }
390
391
392     /**
393      * Test for child nodes.
394      *
395      * @return false
396      */

397     public boolean hasChildNodes ()
398     {
399         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 JavaDoc cloneNode (boolean deep)
411     {
412         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
}
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 JavaDoc feature, String JavaDoc version)
436     {
437         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 JavaDoc getNamespaceURI ()
450     {
451        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 JavaDoc getPrefix ()
465     {
466         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 JavaDoc prefix)
477     throws DOMException JavaDoc
478     {
479         disallowModification();
480     }
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 JavaDoc getLocalName ()
490     {
491         return name;
492     }
493
494
495     /**
496      * Test if this node has attributes.
497      *
498      * @return false
499      */

500     public boolean hasAttributes ()
501     {
502         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 JavaDoc
512     {
513         throw new DOMException JavaDoc(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     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 JavaDoc o)
546     {
547         if (o == this) return true;
548         else if (o == null) return false;
549         else if (o instanceof NamespaceNode) {
550             NamespaceNode ns = (NamespaceNode)o;
551             return (equals(parent, ns.getParentNode()) &&
552                 equals(name, ns.getNodeName()) &&
553                 equals(value, ns.getNodeValue()));
554         } else {
555             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 JavaDoc o)
568     {
569     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 JavaDoc a, Object JavaDoc b)
582     {
583         return ((a == null && b == null) ||
584           (a != null && a.equals(b)));
585     }
586
587
588     ////////////////////////////////////////////////////////////////////
589
// Internal state.
590
////////////////////////////////////////////////////////////////////
591

592     private Node JavaDoc parent;
593     private String JavaDoc name;
594     private String JavaDoc 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     private static class EmptyNodeList implements NodeList JavaDoc
611     {
612
613         /**
614          * @see NodeList#getLength
615          */

616         public int getLength ()
617         {
618             return 0;
619         }
620     
621     
622         /**
623          * @see NodeList#item
624          */

625         public Node JavaDoc item(int index)
626         {
627             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 JavaDoc getBaseURI() {
642         // XXX we could use reflection in DOM Level 3 to get this value
643
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 JavaDoc other) throws DOMException JavaDoc {
654         DOMException JavaDoc ex = new DOMException JavaDoc(
655           DOMException.NOT_SUPPORTED_ERR,
656           "DOM level 3 interfaces are not fully implemented in Jaxen's NamespaceNode class"
657         );
658         throw ex;
659     }
660
661
662     /**
663      * Return the namespace URI.
664      *
665      * @return the namespace URI
666      * @see #getNodeValue
667      */

668     public String JavaDoc getTextContent() {
669         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 JavaDoc textContent) throws DOMException JavaDoc {
680         disallowModification();
681     }
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 JavaDoc other) {
694         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 JavaDoc lookupPrefix(String JavaDoc 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
throw new UnsupportedOperationException JavaDoc("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 JavaDoc namespaceURI) {
724         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 JavaDoc lookupNamespaceURI(String JavaDoc 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
throw new UnsupportedOperationException JavaDoc("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 JavaDoc arg) {
751         if (arg.getNodeType() == this.getNodeType()) {
752             NamespaceNode other = (NamespaceNode) arg;
753             if (other.name == null && this.name != null) return false;
754             else if (other.name != null && this.name == null) return false;
755             else if (other.value == null && this.value != null) return false;
756             else if (other.value != null && this.value == null) return false;
757             else if (other.name == null && this.name == null) {
758                 return other.value.equals(this.value);
759             }
760
761             return other.name.equals(this.name) && other.value.equals(this.value);
762         }
763         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 JavaDoc getFeature(String JavaDoc feature, String JavaDoc version) {
773         return null;
774     }
775
776     
777     // XXX userdata needs testing
778
private HashMap JavaDoc userData = new HashMap JavaDoc();
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 JavaDoc setUserData(String JavaDoc key, Object JavaDoc data, UserDataHandler JavaDoc handler) {
791         Object JavaDoc oldValue = getUserData(key);
792         userData.put(key, data);
793         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 JavaDoc getUserData(String JavaDoc key) {
803         return userData.get(key);
804     }
805     
806 }
807
808 // end of Namespace.java
809
Popular Tags