~ubuntu-branches/ubuntu/karmic/libxerces2-java/karmic

« back to all changes in this revision

Viewing changes to src/org/apache/xerces/dom/NodeImpl.java

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Gybas
  • Date: 2004-06-06 18:00:26 UTC
  • Revision ID: james.westby@ubuntu.com-20040606180026-a3vh56uc95hjbyfh
Tags: upstream-2.6.2
ImportĀ upstreamĀ versionĀ 2.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 /*
 
2
 * The Apache Software License, Version 1.1
 
3
 *
 
4
 *
 
5
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights 
 
6
 * reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions
 
10
 * are met:
 
11
 *
 
12
 * 1. Redistributions of source code must retain the above copyright
 
13
 *    notice, this list of conditions and the following disclaimer. 
 
14
 *
 
15
 * 2. Redistributions in binary form must reproduce the above copyright
 
16
 *    notice, this list of conditions and the following disclaimer in
 
17
 *    the documentation and/or other materials provided with the
 
18
 *    distribution.
 
19
 *
 
20
 * 3. The end-user documentation included with the redistribution,
 
21
 *    if any, must include the following acknowledgment:  
 
22
 *       "This product includes software developed by the
 
23
 *        Apache Software Foundation (http://www.apache.org/)."
 
24
 *    Alternately, this acknowledgment may appear in the software itself,
 
25
 *    if and wherever such third-party acknowledgments normally appear.
 
26
 *
 
27
 * 4. The names "Xerces" and "Apache Software Foundation" must
 
28
 *    not be used to endorse or promote products derived from this
 
29
 *    software without prior written permission. For written 
 
30
 *    permission, please contact apache@apache.org.
 
31
 *
 
32
 * 5. Products derived from this software may not be called "Apache",
 
33
 *    nor may "Apache" appear in their name, without prior written
 
34
 *    permission of the Apache Software Foundation.
 
35
 *
 
36
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 
37
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
38
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
39
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 
40
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
41
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
42
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 
43
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
44
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
45
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 
46
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
47
 * SUCH DAMAGE.
 
48
 * ====================================================================
 
49
 *
 
50
 * This software consists of voluntary contributions made by many
 
51
 * individuals on behalf of the Apache Software Foundation and was
 
52
 * originally based on software copyright (c) 1999, International
 
53
 * Business Machines, Inc., http://www.apache.org.  For more
 
54
 * information on the Apache Software Foundation, please see
 
55
 * <http://www.apache.org/>.
 
56
 */
 
57
 
 
58
package org.apache.xerces.dom;
 
59
 
 
60
import java.io.IOException;
 
61
import java.io.ObjectOutputStream;
 
62
import java.io.Serializable;
 
63
 
 
64
import org.apache.xerces.dom3.UserDataHandler;
 
65
import org.w3c.dom.DOMException;
 
66
import org.w3c.dom.Document;
 
67
import org.w3c.dom.DocumentType;
 
68
import org.w3c.dom.NamedNodeMap;
 
69
import org.w3c.dom.Node;
 
70
import org.w3c.dom.NodeList;
 
71
import org.w3c.dom.events.Event;
 
72
import org.w3c.dom.events.EventListener;
 
73
import org.w3c.dom.events.EventTarget;
 
74
 
 
75
/**
 
76
 * NodeImpl provides the basic structure of a DOM tree. It is never used
 
77
 * directly, but instead is subclassed to add type and data
 
78
 * information, and additional methods, appropriate to each node of
 
79
 * the tree. Only its subclasses should be instantiated -- and those,
 
80
 * with the exception of Document itself, only through a specific
 
81
 * Document's factory methods.
 
82
 * <P>
 
83
 * The Node interface provides shared behaviors such as siblings and
 
84
 * children, both for consistancy and so that the most common tree
 
85
 * operations may be performed without constantly having to downcast
 
86
 * to specific node types. When there is no obvious mapping for one of
 
87
 * these queries, it will respond with null.
 
88
 * Note that the default behavior is that children are forbidden. To
 
89
 * permit them, the subclass ParentNode overrides several methods.
 
90
 * <P>
 
91
 * NodeImpl also implements NodeList, so it can return itself in
 
92
 * response to the getChildNodes() query. This eliminiates the need
 
93
 * for a separate ChildNodeList object. Note that this is an
 
94
 * IMPLEMENTATION DETAIL; applications should _never_ assume that
 
95
 * this identity exists.
 
96
 * <P>
 
97
 * All nodes in a single document must originate
 
98
 * in that document. (Note that this is much tighter than "must be
 
99
 * same implementation") Nodes are all aware of their ownerDocument,
 
100
 * and attempts to mismatch will throw WRONG_DOCUMENT_ERR.
 
101
 * <P>
 
102
 * However, to save memory not all nodes always have a direct reference
 
103
 * to their ownerDocument. When a node is owned by another node it relies
 
104
 * on its owner to store its ownerDocument. Parent nodes always store it
 
105
 * though, so there is never more than one level of indirection.
 
106
 * And when a node doesn't have an owner, ownerNode refers to its
 
107
 * ownerDocument.
 
108
 * <p>
 
109
 * This class doesn't directly support mutation events, however, it still
 
110
 * implements the EventTarget interface and forward all related calls to the
 
111
 * document so that the document class do so.
 
112
 *
 
113
 * @author Arnaud  Le Hors, IBM
 
114
 * @author Joe Kesselman, IBM
 
115
 * @version $Id: NodeImpl.java,v 1.71 2004/01/16 16:23:50 elena Exp $
 
116
 * @since  PR-DOM-Level-1-19980818.
 
117
 */
 
118
public abstract class NodeImpl
 
119
    implements Node, NodeList, EventTarget, Cloneable, Serializable{
 
120
 
 
121
    //
 
122
    // Constants
 
123
    //
 
124
 
 
125
 
 
126
    // TreePosition Constants.
 
127
    // Taken from DOM L3 Node interface.
 
128
    /**
 
129
     * The node precedes the reference node.
 
130
     */
 
131
    public static final short TREE_POSITION_PRECEDING   = 0x01;
 
132
    /**
 
133
     * The node follows the reference node.
 
134
     */
 
135
    public static final short TREE_POSITION_FOLLOWING   = 0x02;
 
136
    /**
 
137
     * The node is an ancestor of the reference node.
 
138
     */
 
139
    public static final short TREE_POSITION_ANCESTOR    = 0x04;
 
140
    /**
 
141
     * The node is a descendant of the reference node.
 
142
     */
 
143
    public static final short TREE_POSITION_DESCENDANT  = 0x08;
 
144
    /**
 
145
     * The two nodes have an equivalent position. This is the case of two 
 
146
     * attributes that have the same <code>ownerElement</code>, and two 
 
147
     * nodes that are the same.
 
148
     */
 
149
    public static final short TREE_POSITION_EQUIVALENT  = 0x10;
 
150
    /**
 
151
     * The two nodes are the same. Two nodes that are the same have an 
 
152
     * equivalent position, though the reverse may not be true.
 
153
     */
 
154
    public static final short TREE_POSITION_SAME_NODE   = 0x20;
 
155
    /**
 
156
     * The two nodes are disconnected, they do not have any common ancestor. 
 
157
     * This is the case of two nodes that are not in the same document.
 
158
     */
 
159
    public static final short TREE_POSITION_DISCONNECTED = 0x00;
 
160
 
 
161
 
 
162
    // DocumentPosition
 
163
    public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
 
164
    public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
 
165
    public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
 
166
    public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
 
167
    public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
 
168
    public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
 
169
 
 
170
    /** Serialization version. */
 
171
    static final long serialVersionUID = -6316591992167219696L;
 
172
 
 
173
    // public
 
174
 
 
175
    /** Element definition node type. */
 
176
    public static final short ELEMENT_DEFINITION_NODE = 21;
 
177
 
 
178
    //
 
179
    // Data
 
180
    //
 
181
 
 
182
    // links
 
183
 
 
184
    protected NodeImpl ownerNode; // typically the parent but not always!
 
185
 
 
186
    // data
 
187
 
 
188
    protected short flags;
 
189
 
 
190
    protected final static short READONLY     = 0x1<<0;
 
191
    protected final static short SYNCDATA     = 0x1<<1;
 
192
    protected final static short SYNCCHILDREN = 0x1<<2;
 
193
    protected final static short OWNED        = 0x1<<3;
 
194
    protected final static short FIRSTCHILD   = 0x1<<4;
 
195
    protected final static short SPECIFIED    = 0x1<<5;
 
196
    protected final static short IGNORABLEWS  = 0x1<<6;
 
197
    protected final static short HASSTRING    = 0x1<<7;
 
198
    protected final static short NORMALIZED = 0x1<<8;
 
199
    protected final static short ID           = 0x1<<9;
 
200
 
 
201
    //
 
202
    // Constructors
 
203
    //
 
204
 
 
205
    /**
 
206
     * No public constructor; only subclasses of Node should be
 
207
     * instantiated, and those normally via a Document's factory methods
 
208
     * <p>
 
209
     * Every Node knows what Document it belongs to.
 
210
     */
 
211
    protected NodeImpl(CoreDocumentImpl ownerDocument) {
 
212
        // as long as we do not have any owner, ownerNode is our ownerDocument
 
213
        ownerNode = ownerDocument;
 
214
    } // <init>(CoreDocumentImpl)
 
215
 
 
216
    /** Constructor for serialization. */
 
217
    public NodeImpl() {}
 
218
 
 
219
    //
 
220
    // Node methods
 
221
    //
 
222
 
 
223
    /**
 
224
     * A short integer indicating what type of node this is. The named
 
225
     * constants for this value are defined in the org.w3c.dom.Node interface.
 
226
     */
 
227
    public abstract short getNodeType();
 
228
 
 
229
    /**
 
230
     * the name of this node.
 
231
     */
 
232
    public abstract String getNodeName();
 
233
    
 
234
    /**
 
235
     * Returns the node value.
 
236
     * @throws DOMException(DOMSTRING_SIZE_ERR)
 
237
     */
 
238
    public String getNodeValue()
 
239
        throws DOMException {
 
240
        return null;            // overridden in some subclasses
 
241
    }
 
242
 
 
243
    /**
 
244
     * Sets the node value.
 
245
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR)
 
246
     */
 
247
    public void setNodeValue(String x) 
 
248
        throws DOMException {
 
249
        // Default behavior is to do nothing, overridden in some subclasses
 
250
    }
 
251
 
 
252
    /**
 
253
     * Adds a child node to the end of the list of children for this node.
 
254
     * Convenience shorthand for insertBefore(newChild,null).
 
255
     * @see #insertBefore(Node, Node)
 
256
     * <P>
 
257
     * By default we do not accept any children, ParentNode overrides this.
 
258
     * @see ParentNode
 
259
     *
 
260
     * @return newChild, in its new state (relocated, or emptied in the case of
 
261
     * DocumentNode.)
 
262
     *
 
263
     * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
 
264
     * type that shouldn't be a child of this node.
 
265
     *
 
266
     * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
 
267
     * different owner document than we do.
 
268
     *
 
269
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
 
270
     * read-only.
 
271
     */
 
272
    public Node appendChild(Node newChild) throws DOMException {
 
273
        return insertBefore(newChild, null);
 
274
    }
 
275
 
 
276
    /**
 
277
     * Returns a duplicate of a given node. You can consider this a
 
278
     * generic "copy constructor" for nodes. The newly returned object should
 
279
     * be completely independent of the source object's subtree, so changes
 
280
     * in one after the clone has been made will not affect the other.
 
281
     * <P>
 
282
     * Note: since we never have any children deep is meaningless here,
 
283
     * ParentNode overrides this behavior.
 
284
     * @see ParentNode
 
285
     *
 
286
     * <p>
 
287
     * Example: Cloning a Text node will copy both the node and the text it
 
288
     * contains.
 
289
     * <p>
 
290
     * Example: Cloning something that has children -- Element or Attr, for
 
291
     * example -- will _not_ clone those children unless a "deep clone"
 
292
     * has been requested. A shallow clone of an Attr node will yield an
 
293
     * empty Attr of the same name.
 
294
     * <p>
 
295
     * NOTE: Clones will always be read/write, even if the node being cloned
 
296
     * is read-only, to permit applications using only the DOM API to obtain
 
297
     * editable copies of locked portions of the tree.
 
298
     */
 
299
    public Node cloneNode(boolean deep) {
 
300
 
 
301
        if (needsSyncData()) {
 
302
            synchronizeData();
 
303
        }
 
304
        
 
305
        NodeImpl newnode;
 
306
        try {
 
307
            newnode = (NodeImpl)clone();
 
308
        }
 
309
        catch (CloneNotSupportedException e) {
 
310
            // if we get here we have an error in our program we may as well
 
311
            // be vocal about it, so that people can take appropriate action.
 
312
            throw new RuntimeException("**Internal Error**" + e);
 
313
        }
 
314
        
 
315
        // Need to break the association w/ original kids
 
316
        newnode.ownerNode      = ownerDocument();
 
317
        newnode.isOwned(false);
 
318
 
 
319
        // By default we make all clones readwrite,
 
320
        // this is overriden in readonly subclasses
 
321
        newnode.isReadOnly(false);
 
322
 
 
323
        ownerDocument().callUserDataHandlers(this, newnode,
 
324
                                             UserDataHandler.NODE_CLONED);
 
325
 
 
326
        return newnode;
 
327
 
 
328
    } // cloneNode(boolean):Node
 
329
 
 
330
    /**
 
331
     * Find the Document that this Node belongs to (the document in
 
332
     * whose context the Node was created). The Node may or may not
 
333
     * currently be part of that Document's actual contents.
 
334
     */
 
335
    public Document getOwnerDocument() {
 
336
        // if we have an owner simply forward the request
 
337
        // otherwise ownerNode is our ownerDocument
 
338
        if (isOwned()) {
 
339
            return ownerNode.ownerDocument();
 
340
        } else {
 
341
            return (Document) ownerNode;
 
342
        }
 
343
    }
 
344
 
 
345
    /**
 
346
     * same as above but returns internal type and this one is not overridden
 
347
     * by CoreDocumentImpl to return null 
 
348
     */
 
349
    CoreDocumentImpl ownerDocument() {
 
350
        // if we have an owner simply forward the request
 
351
        // otherwise ownerNode is our ownerDocument
 
352
        if (isOwned()) {
 
353
            return ownerNode.ownerDocument();
 
354
        } else {
 
355
            return (CoreDocumentImpl) ownerNode;
 
356
        }
 
357
    }
 
358
 
 
359
    /**
 
360
     * NON-DOM
 
361
     * set the ownerDocument of this node
 
362
     */
 
363
    void setOwnerDocument(CoreDocumentImpl doc) {
 
364
        if (needsSyncData()) {
 
365
            synchronizeData();
 
366
        }
 
367
        // if we have an owner we rely on it to have it right
 
368
        // otherwise ownerNode is our ownerDocument
 
369
        if (!isOwned()) {
 
370
            ownerNode = doc;
 
371
        }
 
372
    }
 
373
 
 
374
    /**
 
375
     * Returns the node number
 
376
     */
 
377
    protected int getNodeNumber() {
 
378
        int nodeNumber;
 
379
        CoreDocumentImpl cd = (CoreDocumentImpl)(this.getOwnerDocument());
 
380
        nodeNumber = cd.getNodeNumber(this);   
 
381
        return nodeNumber;
 
382
    }
 
383
 
 
384
    /**
 
385
     * Obtain the DOM-tree parent of this node, or null if it is not
 
386
     * currently active in the DOM tree (perhaps because it has just been
 
387
     * created or removed). Note that Document, DocumentFragment, and
 
388
     * Attribute will never have parents.
 
389
     */
 
390
    public Node getParentNode() {
 
391
        return null;            // overriden by ChildNode
 
392
    }
 
393
 
 
394
    /*
 
395
     * same as above but returns internal type
 
396
     */
 
397
    NodeImpl parentNode() {
 
398
        return null;
 
399
    }
 
400
 
 
401
    /** The next child of this node's parent, or null if none */
 
402
    public Node getNextSibling() {
 
403
        return null;            // default behavior, overriden in ChildNode
 
404
    }
 
405
 
 
406
    /** The previous child of this node's parent, or null if none */
 
407
    public Node getPreviousSibling() {
 
408
        return null;            // default behavior, overriden in ChildNode
 
409
    }
 
410
 
 
411
    ChildNode previousSibling() {
 
412
        return null;            // default behavior, overriden in ChildNode
 
413
    }
 
414
 
 
415
    /**
 
416
     * Return the collection of attributes associated with this node,
 
417
     * or null if none. At this writing, Element is the only type of node
 
418
     * which will ever have attributes.
 
419
     *
 
420
     * @see ElementImpl
 
421
     */
 
422
    public NamedNodeMap getAttributes() {
 
423
        return null; // overridden in ElementImpl
 
424
    }
 
425
 
 
426
    /**
 
427
     *  Returns whether this node (if it is an element) has any attributes.
 
428
     * @return <code>true</code> if this node has any attributes, 
 
429
     *   <code>false</code> otherwise.
 
430
     * @since DOM Level 2
 
431
     * @see ElementImpl
 
432
     */
 
433
    public boolean hasAttributes() {
 
434
        return false;           // overridden in ElementImpl
 
435
    }
 
436
 
 
437
    /**
 
438
     * Test whether this node has any children. Convenience shorthand
 
439
     * for (Node.getFirstChild()!=null)
 
440
     * <P>
 
441
     * By default we do not have any children, ParentNode overrides this.
 
442
     * @see ParentNode
 
443
     */
 
444
    public boolean hasChildNodes() {
 
445
        return false;
 
446
    }
 
447
 
 
448
    /**
 
449
     * Obtain a NodeList enumerating all children of this node. If there
 
450
     * are none, an (initially) empty NodeList is returned.
 
451
     * <p>
 
452
     * NodeLists are "live"; as children are added/removed the NodeList
 
453
     * will immediately reflect those changes. Also, the NodeList refers
 
454
     * to the actual nodes, so changes to those nodes made via the DOM tree
 
455
     * will be reflected in the NodeList and vice versa.
 
456
     * <p>
 
457
     * In this implementation, Nodes implement the NodeList interface and
 
458
     * provide their own getChildNodes() support. Other DOMs may solve this
 
459
     * differently.
 
460
     */
 
461
    public NodeList getChildNodes() {
 
462
        return this;
 
463
    }
 
464
 
 
465
    /** The first child of this Node, or null if none.
 
466
     * <P>
 
467
     * By default we do not have any children, ParentNode overrides this.
 
468
     * @see ParentNode
 
469
     */
 
470
    public Node getFirstChild() {
 
471
        return null;
 
472
    }
 
473
 
 
474
    /** The first child of this Node, or null if none.
 
475
     * <P>
 
476
     * By default we do not have any children, ParentNode overrides this.
 
477
     * @see ParentNode
 
478
     */
 
479
    public Node getLastChild() {
 
480
        return null;
 
481
    }
 
482
 
 
483
    /**
 
484
     * Move one or more node(s) to our list of children. Note that this
 
485
     * implicitly removes them from their previous parent.
 
486
     * <P>
 
487
     * By default we do not accept any children, ParentNode overrides this.
 
488
     * @see ParentNode
 
489
     *
 
490
     * @param newChild The Node to be moved to our subtree. As a
 
491
     * convenience feature, inserting a DocumentNode will instead insert
 
492
     * all its children.
 
493
     *
 
494
     * @param refChild Current child which newChild should be placed
 
495
     * immediately before. If refChild is null, the insertion occurs
 
496
     * after all existing Nodes, like appendChild().
 
497
     *
 
498
     * @return newChild, in its new state (relocated, or emptied in the case of
 
499
     * DocumentNode.)
 
500
     *
 
501
     * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
 
502
     * type that shouldn't be a child of this node, or if newChild is an
 
503
     * ancestor of this node.
 
504
     *
 
505
     * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
 
506
     * different owner document than we do.
 
507
     *
 
508
     * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
 
509
     * this node.
 
510
     *
 
511
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
 
512
     * read-only.
 
513
     */
 
514
    public Node insertBefore(Node newChild, Node refChild) 
 
515
        throws DOMException {
 
516
        throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 
 
517
              DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
 
518
                 "HIERARCHY_REQUEST_ERR", null));
 
519
    }
 
520
 
 
521
    /**
 
522
     * Remove a child from this Node. The removed child's subtree
 
523
     * remains intact so it may be re-inserted elsewhere.
 
524
     * <P>
 
525
     * By default we do not have any children, ParentNode overrides this.
 
526
     * @see ParentNode
 
527
     *
 
528
     * @return oldChild, in its new state (removed).
 
529
     *
 
530
     * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
 
531
     * this node.
 
532
     *
 
533
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
 
534
     * read-only.
 
535
     */
 
536
    public Node removeChild(Node oldChild) 
 
537
                throws DOMException {
 
538
        throw new DOMException(DOMException.NOT_FOUND_ERR, 
 
539
              DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
 
540
                 "NOT_FOUND_ERR", null));
 
541
    }
 
542
 
 
543
    /**
 
544
     * Make newChild occupy the location that oldChild used to
 
545
     * have. Note that newChild will first be removed from its previous
 
546
     * parent, if any. Equivalent to inserting newChild before oldChild,
 
547
     * then removing oldChild.
 
548
     * <P>
 
549
     * By default we do not have any children, ParentNode overrides this.
 
550
     * @see ParentNode
 
551
     *
 
552
     * @return oldChild, in its new state (removed).
 
553
     *
 
554
     * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
 
555
     * type that shouldn't be a child of this node, or if newChild is
 
556
     * one of our ancestors.
 
557
     *
 
558
     * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
 
559
     * different owner document than we do.
 
560
     *
 
561
     * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
 
562
     * this node.
 
563
     *
 
564
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
 
565
     * read-only.
 
566
     */
 
567
    public Node replaceChild(Node newChild, Node oldChild)
 
568
        throws DOMException {
 
569
        throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 
 
570
              DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
 
571
                 "HIERARCHY_REQUEST_ERR", null));
 
572
    }
 
573
 
 
574
    //
 
575
    // NodeList methods
 
576
    //
 
577
 
 
578
    /**
 
579
     * NodeList method: Count the immediate children of this node
 
580
     * <P>
 
581
     * By default we do not have any children, ParentNode overrides this.
 
582
     * @see ParentNode
 
583
     *
 
584
     * @return int
 
585
     */
 
586
    public int getLength() {
 
587
        return 0;
 
588
    }
 
589
 
 
590
    /**
 
591
     * NodeList method: Return the Nth immediate child of this node, or
 
592
     * null if the index is out of bounds.
 
593
     * <P>
 
594
     * By default we do not have any children, ParentNode overrides this.
 
595
     * @see ParentNode
 
596
     *
 
597
     * @return org.w3c.dom.Node
 
598
     * @param Index int
 
599
     */
 
600
    public Node item(int index) {
 
601
        return null;
 
602
    }
 
603
 
 
604
    //
 
605
    // DOM2: methods, getters, setters
 
606
    //
 
607
 
 
608
    /**
 
609
     * Puts all <code>Text</code> nodes in the full depth of the sub-tree 
 
610
     * underneath this <code>Node</code>, including attribute nodes, into a 
 
611
     * "normal" form where only markup (e.g., tags, comments, processing 
 
612
     * instructions, CDATA sections, and entity references) separates 
 
613
     * <code>Text</code> nodes, i.e., there are no adjacent <code>Text</code> 
 
614
     * nodes.  This can be used to ensure that the DOM view of a document is 
 
615
     * the same as if it were saved and re-loaded, and is useful when 
 
616
     * operations (such as XPointer lookups) that depend on a particular 
 
617
     * document tree structure are to be used.In cases where the document 
 
618
     * contains <code>CDATASections</code>, the normalize operation alone may 
 
619
     * not be sufficient, since XPointers do not differentiate between 
 
620
     * <code>Text</code> nodes and <code>CDATASection</code> nodes.
 
621
     * <p>
 
622
     * Note that this implementation simply calls normalize() on this Node's
 
623
     * children. It is up to implementors or Node to override normalize()
 
624
     * to take action.
 
625
     */
 
626
    public void normalize() {
 
627
        /* by default we do not have any children,
 
628
           ParentNode overrides this behavior */
 
629
    }
 
630
 
 
631
    /**
 
632
     * Introduced in DOM Level 2. <p>
 
633
     * Tests whether the DOM implementation implements a specific feature and
 
634
     * that feature is supported by this node.
 
635
     * @param feature The package name of the feature to test. This is the same
 
636
     * name as what can be passed to the method hasFeature on
 
637
     * DOMImplementation.
 
638
     * @param version This is the version number of the package name to
 
639
     * test. In Level 2, version 1, this is the string "2.0". If the version is
 
640
     * not specified, supporting any version of the feature will cause the
 
641
     * method to return true.
 
642
     * @return boolean Returns true if this node defines a subtree within which
 
643
     * the specified feature is supported, false otherwise.
 
644
     * @since WD-DOM-Level-2-19990923
 
645
     */
 
646
    public boolean isSupported(String feature, String version)
 
647
    {
 
648
        return ownerDocument().getImplementation().hasFeature(feature,
 
649
                                                              version);
 
650
    }
 
651
 
 
652
    /**
 
653
     * Introduced in DOM Level 2. <p>
 
654
     *
 
655
     * The namespace URI of this node, or null if it is unspecified. When this
 
656
     * node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE, this is
 
657
     * always null and setting it has no effect. <p>
 
658
     *
 
659
     * This is not a computed value that is the result of a namespace lookup
 
660
     * based on an examination of the namespace declarations in scope. It is
 
661
     * merely the namespace URI given at creation time.<p>
 
662
     *
 
663
     * For nodes created with a DOM Level 1 method, such as createElement
 
664
     * from the Document interface, this is null.
 
665
     * @since WD-DOM-Level-2-19990923
 
666
     * @see AttrNSImpl
 
667
     * @see ElementNSImpl
 
668
     */
 
669
    public String getNamespaceURI()
 
670
    {
 
671
        return null;
 
672
    }
 
673
 
 
674
    /**
 
675
     * Introduced in DOM Level 2. <p>
 
676
     *
 
677
     * The namespace prefix of this node, or null if it is unspecified. When
 
678
     * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE this
 
679
     * is always null and setting it has no effect.<p>
 
680
     *
 
681
     * For nodes created with a DOM Level 1 method, such as createElement
 
682
     * from the Document interface, this is null. <p>
 
683
     *
 
684
     * @since WD-DOM-Level-2-19990923
 
685
     * @see AttrNSImpl
 
686
     * @see ElementNSImpl
 
687
     */
 
688
    public String getPrefix()
 
689
    {
 
690
        return null;
 
691
    }
 
692
 
 
693
    /**
 
694
     *  Introduced in DOM Level 2. <p>
 
695
     *
 
696
     *  The namespace prefix of this node, or null if it is unspecified. When
 
697
     *  this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE
 
698
     *  this is always null and setting it has no effect.<p>
 
699
     *
 
700
     *  For nodes created with a DOM Level 1 method, such as createElement from
 
701
     *  the Document interface, this is null.<p>
 
702
     *
 
703
     *  Note that setting this attribute changes the nodeName attribute, which
 
704
     *  holds the qualified name, as well as the tagName and name attributes of
 
705
     *  the Element and Attr interfaces, when applicable.<p>
 
706
     *
 
707
     * @throws INVALID_CHARACTER_ERR Raised if the specified
 
708
     *  prefix contains an invalid character.
 
709
     *
 
710
     * @since WD-DOM-Level-2-19990923
 
711
     * @see AttrNSImpl
 
712
     * @see ElementNSImpl
 
713
     */
 
714
    public void setPrefix(String prefix)
 
715
        throws DOMException
 
716
    {
 
717
        throw new DOMException(DOMException.NAMESPACE_ERR, 
 
718
              DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
 
719
                 "NAMESPACE_ERR", null));
 
720
    }
 
721
 
 
722
    /**
 
723
     * Introduced in DOM Level 2. <p>
 
724
     *
 
725
     * Returns the local part of the qualified name of this node.
 
726
     * For nodes created with a DOM Level 1 method, such as createElement
 
727
     * from the Document interface, and for nodes of any type other than
 
728
     * ELEMENT_NODE and ATTRIBUTE_NODE this is the same as the nodeName
 
729
     * attribute.
 
730
     * @since WD-DOM-Level-2-19990923
 
731
     * @see AttrNSImpl
 
732
     * @see ElementNSImpl
 
733
     */
 
734
    public String             getLocalName()
 
735
    {
 
736
        return null;
 
737
    }
 
738
    
 
739
    //
 
740
    // EventTarget support
 
741
    //
 
742
 
 
743
    public void addEventListener(String type, EventListener listener,
 
744
                                 boolean useCapture) {
 
745
        // simply forward to Document
 
746
        ownerDocument().addEventListener(this, type, listener, useCapture);
 
747
    }
 
748
 
 
749
    public void removeEventListener(String type, EventListener listener,
 
750
                                    boolean useCapture) {
 
751
        // simply forward to Document
 
752
        ownerDocument().removeEventListener(this, type, listener, useCapture);
 
753
    }
 
754
 
 
755
    public boolean dispatchEvent(Event event) {
 
756
        // simply forward to Document
 
757
        return ownerDocument().dispatchEvent(this, event);
 
758
    }
 
759
 
 
760
    //
 
761
    // Public DOM Level 3 methods
 
762
    //
 
763
 
 
764
    /**
 
765
     * The absolute base URI of this node or <code>null</code> if undefined. 
 
766
     * This value is computed according to . However, when the 
 
767
     * <code>Document</code> supports the feature "HTML" , the base URI is 
 
768
     * computed using first the value of the href attribute of the HTML BASE 
 
769
     * element if any, and the value of the <code>documentURI</code> 
 
770
     * attribute from the <code>Document</code> interface otherwise.
 
771
     * <br> When the node is an <code>Element</code>, a <code>Document</code> 
 
772
     * or a a <code>ProcessingInstruction</code>, this attribute represents 
 
773
     * the properties [base URI] defined in . When the node is a 
 
774
     * <code>Notation</code>, an <code>Entity</code>, or an 
 
775
     * <code>EntityReference</code>, this attribute represents the 
 
776
     * properties [declaration base URI] in the . How will this be affected 
 
777
     * by resolution of relative namespace URIs issue?It's not.Should this 
 
778
     * only be on Document, Element, ProcessingInstruction, Entity, and 
 
779
     * Notation nodes, according to the infoset? If not, what is it equal to 
 
780
     * on other nodes? Null? An empty string? I think it should be the 
 
781
     * parent's.No.Should this be read-only and computed or and actual 
 
782
     * read-write attribute?Read-only and computed (F2F 19 Jun 2000 and 
 
783
     * teleconference 30 May 2001).If the base HTML element is not yet 
 
784
     * attached to a document, does the insert change the Document.baseURI?
 
785
     * Yes. (F2F 26 Sep 2001)
 
786
     * @since DOM Level 3
 
787
     */
 
788
    public String getBaseURI() {
 
789
        return null;
 
790
    }
 
791
 
 
792
    /**
 
793
     * Compares a node with this node with regard to their position in the 
 
794
     * tree and according to the document order. This order can be extended 
 
795
     * by module that define additional types of nodes.
 
796
     * @param other The node to compare against this node.
 
797
     * @return Returns how the given node is positioned relatively to this 
 
798
     *   node.
 
799
     * @since DOM Level 3
 
800
     * @deprecated
 
801
     */
 
802
    public short compareTreePosition(Node other) {
 
803
        // Questions of clarification for this method - to be answered by the
 
804
        // DOM WG.   Current assumptions listed - LM
 
805
        // 
 
806
        // 1. How do ENTITY nodes compare?  
 
807
        //    Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes 
 
808
        //    aren't really 'in the tree'
 
809
        //
 
810
        // 2. How do NOTATION nodes compare?
 
811
        //    Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes
 
812
        //    aren't really 'in the tree'
 
813
        //
 
814
        // 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT     
 
815
        //    only relevant for nodes that are "part of the document tree"?   
 
816
        //     <outer>
 
817
        //         <inner  myattr="true"/>
 
818
        //     </outer>
 
819
        //    Is the element node "outer" considered an ancestor of "myattr"?
 
820
        //    Current assumption: No.                                     
 
821
        //
 
822
        // 4. How do children of ATTRIBUTE nodes compare (with eachother, or  
 
823
        //    with children of other attribute nodes with the same element)    
 
824
        //    Current assumption: Children of ATTRIBUTE nodes are treated as if 
 
825
        //    they they are the attribute node itself, unless the 2 nodes 
 
826
        //    are both children of the same attribute. 
 
827
        //
 
828
        // 5. How does an ENTITY_REFERENCE node compare with it's children? 
 
829
        //    Given the DOM, it should precede its children as an ancestor. 
 
830
        //    Given "document order",  does it represent the same position?     
 
831
        //    Current assumption: An ENTITY_REFERENCE node is an ancestor of its
 
832
        //    children.
 
833
        //
 
834
        // 6. How do children of a DocumentFragment compare?   
 
835
        //    Current assumption: If both nodes are part of the same document 
 
836
        //    fragment, there are compared as if they were part of a document. 
 
837
 
 
838
        
 
839
        // If the nodes are the same...
 
840
        if (this==other) 
 
841
          return (TREE_POSITION_SAME_NODE | TREE_POSITION_EQUIVALENT);
 
842
        
 
843
        // If either node is of type ENTITY or NOTATION, compare as disconnected
 
844
        short thisType = this.getNodeType();
 
845
        short otherType = other.getNodeType();
 
846
 
 
847
        // If either node is of type ENTITY or NOTATION, compare as disconnected
 
848
        if (thisType == Node.ENTITY_NODE || 
 
849
            thisType == Node.NOTATION_NODE ||
 
850
            otherType == Node.ENTITY_NODE ||
 
851
            otherType == Node.NOTATION_NODE ) {
 
852
          return TREE_POSITION_DISCONNECTED; 
 
853
        }
 
854
 
 
855
        // Find the ancestor of each node, and the distance each node is from 
 
856
        // its ancestor.
 
857
        // During this traversal, look for ancestor/descendent relationships 
 
858
        // between the 2 nodes in question. 
 
859
        // We do this now, so that we get this info correct for attribute nodes 
 
860
        // and their children. 
 
861
 
 
862
        Node node; 
 
863
        Node thisAncestor = this;
 
864
        Node otherAncestor = other;
 
865
        int thisDepth=0;
 
866
        int otherDepth=0;
 
867
        for (node=this; node != null; node = node.getParentNode()) {
 
868
            thisDepth +=1;
 
869
            if (node == other) 
 
870
              // The other node is an ancestor of this one.
 
871
              return (TREE_POSITION_ANCESTOR | TREE_POSITION_PRECEDING);
 
872
            thisAncestor = node;
 
873
        }
 
874
 
 
875
        for (node=other; node!=null; node=node.getParentNode()) {
 
876
            otherDepth +=1;
 
877
            if (node == this) 
 
878
              // The other node is a descendent of the reference node.
 
879
              return (TREE_POSITION_DESCENDANT | TREE_POSITION_FOLLOWING);
 
880
            otherAncestor = node;
 
881
        }
 
882
        
 
883
       
 
884
        Node thisNode = this;
 
885
        Node otherNode = other;
 
886
 
 
887
        int thisAncestorType = thisAncestor.getNodeType();
 
888
        int otherAncestorType = otherAncestor.getNodeType();
 
889
 
 
890
        // if the ancestor is an attribute, get owning element. 
 
891
        // we are now interested in the owner to determine position.
 
892
 
 
893
        if (thisAncestorType == Node.ATTRIBUTE_NODE)  {
 
894
           thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
 
895
        }
 
896
        if (otherAncestorType == Node.ATTRIBUTE_NODE) {
 
897
           otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
 
898
        }
 
899
 
 
900
        // Before proceeding, we should check if both ancestor nodes turned
 
901
        // out to be attributes for the same element
 
902
        if (thisAncestorType == Node.ATTRIBUTE_NODE &&  
 
903
            otherAncestorType == Node.ATTRIBUTE_NODE &&  
 
904
            thisNode==otherNode)              
 
905
            return TREE_POSITION_EQUIVALENT;
 
906
 
 
907
        // Now, find the ancestor of the owning element, if the original
 
908
        // ancestor was an attribute
 
909
 
 
910
        // Note:  the following 2 loops are quite close to the ones above.
 
911
        // May want to common them up.  LM.
 
912
        if (thisAncestorType == Node.ATTRIBUTE_NODE) {
 
913
            thisDepth=0;
 
914
            for (node=thisNode; node != null; node=node.getParentNode()) {
 
915
                thisDepth +=1;
 
916
                if (node == otherNode) 
 
917
                  // The other node is an ancestor of the owning element
 
918
                  {
 
919
                  return TREE_POSITION_PRECEDING;
 
920
                  }
 
921
                thisAncestor = node;
 
922
            }
 
923
        }
 
924
 
 
925
        // Now, find the ancestor of the owning element, if the original
 
926
        // ancestor was an attribute
 
927
        if (otherAncestorType == Node.ATTRIBUTE_NODE) {
 
928
            otherDepth=0;
 
929
            for (node=otherNode; node != null; node=node.getParentNode()) {
 
930
                otherDepth +=1;
 
931
                if (node == thisNode) 
 
932
                  // The other node is a descendent of the reference 
 
933
                  // node's element
 
934
                  return TREE_POSITION_FOLLOWING;
 
935
                otherAncestor = node;
 
936
            }
 
937
        }
 
938
 
 
939
        // thisAncestor and otherAncestor must be the same at this point,  
 
940
        // otherwise, we are not in the same tree or document fragment
 
941
        if (thisAncestor != otherAncestor) 
 
942
          return TREE_POSITION_DISCONNECTED; 
 
943
 
 
944
      
 
945
        // Go up the parent chain of the deeper node, until we find a node 
 
946
        // with the same depth as the shallower node
 
947
 
 
948
        if (thisDepth > otherDepth) {
 
949
          for (int i=0; i<thisDepth - otherDepth; i++)
 
950
            thisNode = thisNode.getParentNode();
 
951
          // Check if the node we have reached is in fact "otherNode". This can
 
952
          // happen in the case of attributes.  In this case, otherNode 
 
953
          // "precedes" this.
 
954
          if (thisNode == otherNode) 
 
955
            return TREE_POSITION_PRECEDING;
 
956
        }
 
957
 
 
958
        else {
 
959
          for (int i=0; i<otherDepth - thisDepth; i++)
 
960
            otherNode = otherNode.getParentNode();
 
961
          // Check if the node we have reached is in fact "thisNode".  This can
 
962
          // happen in the case of attributes.  In this case, otherNode 
 
963
          // "follows" this.
 
964
          if (otherNode == thisNode) 
 
965
            return TREE_POSITION_FOLLOWING;
 
966
        }
 
967
             
 
968
        // We now have nodes at the same depth in the tree.  Find a common 
 
969
        // ancestor.                                   
 
970
        Node thisNodeP, otherNodeP;
 
971
        for (thisNodeP=thisNode.getParentNode(),
 
972
                  otherNodeP=otherNode.getParentNode();
 
973
             thisNodeP!=otherNodeP;) {
 
974
             thisNode = thisNodeP;
 
975
             otherNode = otherNodeP;
 
976
             thisNodeP = thisNodeP.getParentNode();
 
977
             otherNodeP = otherNodeP.getParentNode();
 
978
        }
 
979
 
 
980
        // At this point, thisNode and otherNode are direct children of 
 
981
        // the common ancestor.  
 
982
        // See whether thisNode or otherNode is the leftmost
 
983
 
 
984
        for (Node current=thisNodeP.getFirstChild(); 
 
985
                  current!=null;
 
986
                  current=current.getNextSibling()) {
 
987
               if (current==otherNode) {
 
988
                 return TREE_POSITION_PRECEDING;
 
989
               }
 
990
               else if (current==thisNode) {
 
991
                 return TREE_POSITION_FOLLOWING;
 
992
               }
 
993
        }
 
994
        // REVISIT:  shouldn't get here.   Should probably throw an 
 
995
        // exception
 
996
        return 0;
 
997
 
 
998
    }
 
999
    /**
 
1000
     * Compares a node with this node with regard to their position in the 
 
1001
     * document. 
 
1002
     * @param other The node to compare against this node.
 
1003
     * @return Returns how the given node is positioned relatively to this 
 
1004
     *   node.
 
1005
     * @since DOM Level 3
 
1006
     */
 
1007
    public short compareDocumentPosition(Node other) throws DOMException {
 
1008
 
 
1009
        // If the nodes are the same, no flags should be set
 
1010
        if (this==other) 
 
1011
          return 0; 
 
1012
 
 
1013
        // check if other is from a different implementation
 
1014
        try {
 
1015
            NodeImpl node = (NodeImpl) other;
 
1016
        } catch (ClassCastException e) {
 
1017
            // other comes from a different implementation
 
1018
            String msg = DOMMessageFormatter.formatMessage(
 
1019
               DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
 
1020
            throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 
1021
        }
 
1022
 
 
1023
        Document thisOwnerDoc, otherOwnerDoc;
 
1024
        // get the respective Document owners.  
 
1025
        if (this.getNodeType() == Node.DOCUMENT_NODE) 
 
1026
          thisOwnerDoc = (Document)this;
 
1027
        else
 
1028
          thisOwnerDoc = this.getOwnerDocument();
 
1029
        if (other.getNodeType() == Node.DOCUMENT_NODE) 
 
1030
          otherOwnerDoc = (Document)other;
 
1031
        else
 
1032
          otherOwnerDoc = other.getOwnerDocument();
 
1033
 
 
1034
        // If from different documents, we know they are disconnected. 
 
1035
        // and have an implementation dependent order 
 
1036
        if (thisOwnerDoc != otherOwnerDoc && 
 
1037
            thisOwnerDoc !=null && 
 
1038
            otherOwnerDoc !=null) 
 
1039
 {
 
1040
          int otherDocNum = ((CoreDocumentImpl)otherOwnerDoc).getNodeNumber();
 
1041
          int thisDocNum = ((CoreDocumentImpl)thisOwnerDoc).getNodeNumber();
 
1042
          if (otherDocNum > thisDocNum)  
 
1043
            return DOCUMENT_POSITION_DISCONNECTED | 
 
1044
                   DOCUMENT_POSITION_FOLLOWING | 
 
1045
                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
 
1046
          else
 
1047
            return DOCUMENT_POSITION_DISCONNECTED | 
 
1048
                   DOCUMENT_POSITION_PRECEDING | 
 
1049
                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
 
1050
                  
 
1051
        }
 
1052
     
 
1053
        // Find the ancestor of each node, and the distance each node is from 
 
1054
        // its ancestor.
 
1055
        // During this traversal, look for ancestor/descendent relationships 
 
1056
        // between the 2 nodes in question. 
 
1057
        // We do this now, so that we get this info correct for attribute nodes 
 
1058
        // and their children. 
 
1059
 
 
1060
        Node node; 
 
1061
        Node thisAncestor = this;
 
1062
        Node otherAncestor = other;
 
1063
       
 
1064
        int thisDepth=0;
 
1065
        int otherDepth=0;
 
1066
        for (node=this; node != null; node = node.getParentNode()) {
 
1067
            thisDepth +=1;
 
1068
            if (node == other) 
 
1069
              // The other node is an ancestor of this one.
 
1070
              return (DOCUMENT_POSITION_CONTAINS | 
 
1071
                      DOCUMENT_POSITION_PRECEDING);
 
1072
            thisAncestor = node;
 
1073
        }
 
1074
 
 
1075
        for (node=other; node!=null; node=node.getParentNode()) {
 
1076
            otherDepth +=1;
 
1077
            if (node == this) 
 
1078
              // The other node is a descendent of the reference node.
 
1079
              return (DOCUMENT_POSITION_IS_CONTAINED | 
 
1080
                      DOCUMENT_POSITION_FOLLOWING);
 
1081
            otherAncestor = node;
 
1082
        }
 
1083
        
 
1084
       
 
1085
 
 
1086
        int thisAncestorType = thisAncestor.getNodeType();
 
1087
        int otherAncestorType = otherAncestor.getNodeType();
 
1088
        Node thisNode = this;
 
1089
        Node otherNode = other;
 
1090
 
 
1091
        // Special casing for ENTITY, NOTATION, DOCTYPE and ATTRIBUTES
 
1092
        // LM:  should rewrite this.                                          
 
1093
        switch (thisAncestorType) {
 
1094
          case Node.NOTATION_NODE:
 
1095
          case Node.ENTITY_NODE: {
 
1096
            DocumentType container = thisOwnerDoc.getDoctype();
 
1097
            if (container == otherAncestor) return 
 
1098
                   (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
 
1099
            switch (otherAncestorType) {
 
1100
              case Node.NOTATION_NODE: 
 
1101
              case Node.ENTITY_NODE:  {
 
1102
                if (thisAncestorType != otherAncestorType) 
 
1103
                 // the nodes are of different types
 
1104
                 return ((thisAncestorType>otherAncestorType) ? 
 
1105
                    DOCUMENT_POSITION_PRECEDING:DOCUMENT_POSITION_FOLLOWING);
 
1106
                else {
 
1107
                 // the nodes are of the same type.  Find order.
 
1108
                 if (thisAncestorType == Node.NOTATION_NODE)
 
1109
                 
 
1110
                     if (((NamedNodeMapImpl)container.getNotations()).precedes(otherAncestor,thisAncestor))
 
1111
                       return (DOCUMENT_POSITION_PRECEDING | 
 
1112
                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 
1113
                     else
 
1114
                       return (DOCUMENT_POSITION_FOLLOWING | 
 
1115
                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 
1116
                 else
 
1117
                     if (((NamedNodeMapImpl)container.getEntities()).precedes(otherAncestor,thisAncestor))
 
1118
                       return (DOCUMENT_POSITION_PRECEDING | 
 
1119
                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 
1120
                     else
 
1121
                       return (DOCUMENT_POSITION_FOLLOWING | 
 
1122
                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 
1123
                }
 
1124
              }
 
1125
            }
 
1126
            thisNode = thisAncestor = thisOwnerDoc;
 
1127
            break;
 
1128
          } 
 
1129
          case Node.DOCUMENT_TYPE_NODE: {
 
1130
            if (otherNode == thisOwnerDoc) 
 
1131
              return (DOCUMENT_POSITION_PRECEDING | 
 
1132
                      DOCUMENT_POSITION_CONTAINS);
 
1133
            else if (thisOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
 
1134
              return (DOCUMENT_POSITION_FOLLOWING);
 
1135
            break;
 
1136
          }
 
1137
          case Node.ATTRIBUTE_NODE: {
 
1138
            thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
 
1139
            if (otherAncestorType==Node.ATTRIBUTE_NODE) {
 
1140
              otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
 
1141
              if (otherNode == thisNode) {
 
1142
                if (((NamedNodeMapImpl)thisNode.getAttributes()).precedes(other,this))
 
1143
                  return (DOCUMENT_POSITION_PRECEDING | 
 
1144
                          DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 
1145
                else
 
1146
                  return (DOCUMENT_POSITION_FOLLOWING | 
 
1147
                          DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 
1148
              }
 
1149
            }
 
1150
 
 
1151
            // Now, find the ancestor of the element
 
1152
            thisDepth=0;
 
1153
            for (node=thisNode; node != null; node=node.getParentNode()) {
 
1154
                thisDepth +=1;
 
1155
                if (node == otherNode) 
 
1156
                  {
 
1157
                  // The other node is an ancestor of the owning element
 
1158
                  return (DOCUMENT_POSITION_CONTAINS | 
 
1159
                          DOCUMENT_POSITION_PRECEDING);
 
1160
                  }
 
1161
                thisAncestor = node;
 
1162
            }
 
1163
          }
 
1164
        }
 
1165
        switch (otherAncestorType) {
 
1166
          case Node.NOTATION_NODE:
 
1167
          case Node.ENTITY_NODE: {
 
1168
          DocumentType container = thisOwnerDoc.getDoctype();
 
1169
            if (container == this) return (DOCUMENT_POSITION_IS_CONTAINED | 
 
1170
                                          DOCUMENT_POSITION_FOLLOWING);
 
1171
            otherNode = otherAncestor = thisOwnerDoc;
 
1172
            break;
 
1173
          }
 
1174
          case Node.DOCUMENT_TYPE_NODE: {
 
1175
            if (thisNode == otherOwnerDoc) 
 
1176
              return (DOCUMENT_POSITION_FOLLOWING | 
 
1177
                      DOCUMENT_POSITION_IS_CONTAINED);
 
1178
            else if (otherOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
 
1179
              return (DOCUMENT_POSITION_PRECEDING);
 
1180
            break;
 
1181
          }
 
1182
          case Node.ATTRIBUTE_NODE: {
 
1183
            otherDepth=0;
 
1184
            otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
 
1185
            for (node=otherNode; node != null; node=node.getParentNode()) {
 
1186
                otherDepth +=1;
 
1187
                if (node == thisNode) 
 
1188
                  // The other node is a descendent of the reference 
 
1189
                  // node's element
 
1190
                  return DOCUMENT_POSITION_FOLLOWING | 
 
1191
                         DOCUMENT_POSITION_IS_CONTAINED;
 
1192
                otherAncestor = node;
 
1193
            }
 
1194
 
 
1195
          }
 
1196
        }
 
1197
 
 
1198
        // thisAncestor and otherAncestor must be the same at this point,  
 
1199
        // otherwise, the original nodes are disconnected 
 
1200
        if (thisAncestor != otherAncestor) {
 
1201
          int thisAncestorNum, otherAncestorNum;
 
1202
          thisAncestorNum = ((NodeImpl)thisAncestor).getNodeNumber();
 
1203
          otherAncestorNum = ((NodeImpl)otherAncestor).getNodeNumber();
 
1204
          
 
1205
          if (thisAncestorNum > otherAncestorNum) 
 
1206
            return DOCUMENT_POSITION_DISCONNECTED | 
 
1207
                   DOCUMENT_POSITION_FOLLOWING | 
 
1208
                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
 
1209
          else
 
1210
            return DOCUMENT_POSITION_DISCONNECTED | 
 
1211
                   DOCUMENT_POSITION_PRECEDING | 
 
1212
                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
 
1213
        }
 
1214
 
 
1215
      
 
1216
        // Go up the parent chain of the deeper node, until we find a node 
 
1217
        // with the same depth as the shallower node
 
1218
 
 
1219
        if (thisDepth > otherDepth) {
 
1220
          for (int i=0; i<thisDepth - otherDepth; i++)
 
1221
            thisNode = thisNode.getParentNode();
 
1222
          // Check if the node we have reached is in fact "otherNode". This can
 
1223
          // happen in the case of attributes.  In this case, otherNode 
 
1224
          // "precedes" this.
 
1225
          if (thisNode == otherNode) 
 
1226
{
 
1227
            return DOCUMENT_POSITION_PRECEDING;
 
1228
          }
 
1229
        }
 
1230
 
 
1231
        else {
 
1232
          for (int i=0; i<otherDepth - thisDepth; i++)
 
1233
            otherNode = otherNode.getParentNode();
 
1234
          // Check if the node we have reached is in fact "thisNode".  This can
 
1235
          // happen in the case of attributes.  In this case, otherNode 
 
1236
          // "follows" this.
 
1237
          if (otherNode == thisNode) 
 
1238
            return DOCUMENT_POSITION_FOLLOWING;
 
1239
        }
 
1240
             
 
1241
        // We now have nodes at the same depth in the tree.  Find a common 
 
1242
        // ancestor.                                   
 
1243
        Node thisNodeP, otherNodeP;
 
1244
        for (thisNodeP=thisNode.getParentNode(),
 
1245
                  otherNodeP=otherNode.getParentNode();
 
1246
             thisNodeP!=otherNodeP;) {
 
1247
             thisNode = thisNodeP;
 
1248
             otherNode = otherNodeP;
 
1249
             thisNodeP = thisNodeP.getParentNode();
 
1250
             otherNodeP = otherNodeP.getParentNode();
 
1251
        }
 
1252
 
 
1253
        // At this point, thisNode and otherNode are direct children of 
 
1254
        // the common ancestor.  
 
1255
        // See whether thisNode or otherNode is the leftmost
 
1256
 
 
1257
        for (Node current=thisNodeP.getFirstChild(); 
 
1258
                  current!=null;
 
1259
                  current=current.getNextSibling()) {
 
1260
               if (current==otherNode) {
 
1261
                 return DOCUMENT_POSITION_PRECEDING;
 
1262
               }
 
1263
               else if (current==thisNode) {
 
1264
                 return DOCUMENT_POSITION_FOLLOWING;
 
1265
               }
 
1266
        }
 
1267
        // REVISIT:  shouldn't get here.   Should probably throw an 
 
1268
        // exception
 
1269
        return 0;
 
1270
 
 
1271
    }
 
1272
 
 
1273
    /**
 
1274
     * This attribute returns the text content of this node and its 
 
1275
     * descendants. When it is defined to be null, setting it has no effect. 
 
1276
     * When set, any possible children this node may have are removed and 
 
1277
     * replaced by a single <code>Text</code> node containing the string 
 
1278
     * this attribute is set to. On getting, no serialization is performed, 
 
1279
     * the returned string does not contain any markup. No whitespace 
 
1280
     * normalization is performed, the returned string does not contain the 
 
1281
     * element content whitespaces . Similarly, on setting, no parsing is 
 
1282
     * performed either, the input string is taken as pure textual content.
 
1283
     * <br>The string returned is made of the text content of this node 
 
1284
     * depending on its type, as defined below: 
 
1285
     * <table border='1'>
 
1286
     * <tr>
 
1287
     * <th>Node type</th>
 
1288
     * <th>Content</th>
 
1289
     * </tr>
 
1290
 
 
1291
    /**
 
1292
     * This attribute returns the text content of this node and its 
 
1293
     * descendants. When it is defined to be null, setting it has no effect. 
 
1294
     * When set, any possible children this node may have are removed and 
 
1295
     * replaced by a single <code>Text</code> node containing the string 
 
1296
     * this attribute is set to. On getting, no serialization is performed, 
 
1297
     * the returned string does not contain any markup. No whitespace 
 
1298
     * normalization is performed, the returned string does not contain the 
 
1299
     * element content whitespaces . Similarly, on setting, no parsing is 
 
1300
     * performed either, the input string is taken as pure textual content.
 
1301
     * <br>The string returned is made of the text content of this node 
 
1302
     * depending on its type, as defined below: 
 
1303
     * <table border='1'>
 
1304
     * <tr>
 
1305
     * <th>Node type</th>
 
1306
     * <th>Content</th>
 
1307
     * </tr>
 
1308
     * <tr>
 
1309
     * <td valign='top' rowspan='1' colspan='1'>
 
1310
     * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE, 
 
1311
     * DOCUMENT_FRAGMENT_NODE</td>
 
1312
     * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code> 
 
1313
     * attribute value of every child node, excluding COMMENT_NODE and 
 
1314
     * PROCESSING_INSTRUCTION_NODE nodes</td>
 
1315
     * </tr>
 
1316
     * <tr>
 
1317
     * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE, 
 
1318
     * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
 
1319
     * <td valign='top' rowspan='1' colspan='1'>
 
1320
     * <code>nodeValue</code></td>
 
1321
     * </tr>
 
1322
     * <tr>
 
1323
     * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
 
1324
     * <td valign='top' rowspan='1' colspan='1'>
 
1325
     * null</td>
 
1326
     * </tr>
 
1327
     * </table>
 
1328
     * @exception DOMException
 
1329
     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
 
1330
     * @exception DOMException
 
1331
     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than 
 
1332
     *   fit in a <code>DOMString</code> variable on the implementation 
 
1333
     *   platform.
 
1334
     * @since DOM Level 3
 
1335
     */
 
1336
    public String getTextContent() throws DOMException {
 
1337
        return getNodeValue();  // overriden in some subclasses
 
1338
    }
 
1339
 
 
1340
    // internal method taking a StringBuffer in parameter
 
1341
    void getTextContent(StringBuffer buf) throws DOMException {
 
1342
        String content = getNodeValue();
 
1343
        if (content != null) {
 
1344
            buf.append(content);
 
1345
        }
 
1346
    }
 
1347
 
 
1348
    /**
 
1349
     * This attribute returns the text content of this node and its 
 
1350
     * descendants. When it is defined to be null, setting it has no effect. 
 
1351
     * When set, any possible children this node may have are removed and 
 
1352
     * replaced by a single <code>Text</code> node containing the string 
 
1353
     * this attribute is set to. On getting, no serialization is performed, 
 
1354
     * the returned string does not contain any markup. No whitespace 
 
1355
     * normalization is performed, the returned string does not contain the 
 
1356
     * element content whitespaces . Similarly, on setting, no parsing is 
 
1357
     * performed either, the input string is taken as pure textual content.
 
1358
     * <br>The string returned is made of the text content of this node 
 
1359
     * depending on its type, as defined below: 
 
1360
     * <table border='1'>
 
1361
     * <tr>
 
1362
     * <th>Node type</th>
 
1363
     * <th>Content</th>
 
1364
     * </tr>
 
1365
     * <tr>
 
1366
     * <td valign='top' rowspan='1' colspan='1'>
 
1367
     * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE, 
 
1368
     * DOCUMENT_FRAGMENT_NODE</td>
 
1369
     * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code> 
 
1370
     * attribute value of every child node, excluding COMMENT_NODE and 
 
1371
     * PROCESSING_INSTRUCTION_NODE nodes</td>
 
1372
     * </tr>
 
1373
     * <tr>
 
1374
     * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE, 
 
1375
     * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
 
1376
     * <td valign='top' rowspan='1' colspan='1'>
 
1377
     * <code>nodeValue</code></td>
 
1378
     * </tr>
 
1379
     * <tr>
 
1380
     * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
 
1381
     * <td valign='top' rowspan='1' colspan='1'>
 
1382
     * null</td>
 
1383
     * </tr>
 
1384
     * </table>
 
1385
     * @exception DOMException
 
1386
     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
 
1387
     * @exception DOMException
 
1388
     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than 
 
1389
     *   fit in a <code>DOMString</code> variable on the implementation 
 
1390
     *   platform.
 
1391
     * @since DOM Level 3
 
1392
     */
 
1393
    public void setTextContent(String textContent)
 
1394
        throws DOMException {
 
1395
        setNodeValue(textContent);
 
1396
    }
 
1397
 
 
1398
    /**
 
1399
     * Returns whether this node is the same node as the given one.
 
1400
     * <br>This method provides a way to determine whether two 
 
1401
     * <code>Node</code> references returned by the implementation reference 
 
1402
     * the same object. When two <code>Node</code> references are references 
 
1403
     * to the same object, even if through a proxy, the references may be 
 
1404
     * used completely interchangably, such that all attributes have the 
 
1405
     * same values and calling the same DOM method on either reference 
 
1406
     * always has exactly the same effect.
 
1407
     * @param other The node to test against.
 
1408
     * @return Returns <code>true</code> if the nodes are the same, 
 
1409
     *   <code>false</code> otherwise.
 
1410
     * @since DOM Level 3
 
1411
     */
 
1412
    public boolean isSameNode(Node other) {
 
1413
        // we do not use any wrapper so the answer is obvious
 
1414
        return this == other;
 
1415
    }
 
1416
 
 
1417
 
 
1418
     
 
1419
 
 
1420
    /**
 
1421
     *  DOM Level 3: Experimental
 
1422
     *  This method checks if the specified <code>namespaceURI</code> is the 
 
1423
     *  default namespace or not. 
 
1424
     *  @param namespaceURI The namespace URI to look for.
 
1425
     *  @return  <code>true</code> if the specified <code>namespaceURI</code> 
 
1426
     *   is the default namespace, <code>false</code> otherwise. 
 
1427
     * @since DOM Level 3
 
1428
     */
 
1429
    public boolean isDefaultNamespace(String namespaceURI){
 
1430
        // REVISIT: remove casts when DOM L3 becomes REC.
 
1431
        short type = this.getNodeType();
 
1432
        switch (type) {
 
1433
        case Node.ELEMENT_NODE: {             
 
1434
            String namespace = this.getNamespaceURI();
 
1435
            String prefix = this.getPrefix();
 
1436
            
 
1437
            // REVISIT: is it possible that prefix is empty string?
 
1438
            if (prefix == null || prefix.length() == 0) {
 
1439
                if (namespaceURI == null) {
 
1440
                    return (namespace == namespaceURI);
 
1441
                }
 
1442
                return namespaceURI.equals(namespace);
 
1443
            }
 
1444
            if (this.hasAttributes()) {
 
1445
                ElementImpl elem = (ElementImpl)this;
 
1446
                NodeImpl attr = (NodeImpl)elem.getAttributeNodeNS("http://www.w3.org/2000/xmlns/", "xmlns");
 
1447
                if (attr != null) {
 
1448
                    String value = attr.getNodeValue();
 
1449
                    if (namespaceURI == null) {
 
1450
                        return (namespace == value);
 
1451
                    }
 
1452
                    return namespaceURI.equals(value);
 
1453
                }
 
1454
            }
 
1455
 
 
1456
            NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 
1457
            if (ancestor != null) {
 
1458
                return ancestor.isDefaultNamespace(namespaceURI);
 
1459
            }
 
1460
            return false;
 
1461
        }
 
1462
        case Node.DOCUMENT_NODE:{
 
1463
                return((NodeImpl)((Document)this).getDocumentElement()).isDefaultNamespace(namespaceURI);
 
1464
            }
 
1465
 
 
1466
        case Node.ENTITY_NODE :
 
1467
        case Node.NOTATION_NODE:
 
1468
        case Node.DOCUMENT_FRAGMENT_NODE:
 
1469
        case Node.DOCUMENT_TYPE_NODE:
 
1470
            // type is unknown
 
1471
            return false;
 
1472
        case Node.ATTRIBUTE_NODE:{
 
1473
                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
 
1474
                    return ownerNode.isDefaultNamespace(namespaceURI);
 
1475
 
 
1476
                }
 
1477
                return false;
 
1478
            }
 
1479
        default:{   
 
1480
                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 
1481
                if (ancestor != null) {
 
1482
                    return ancestor.isDefaultNamespace(namespaceURI);
 
1483
                }
 
1484
                return false;
 
1485
            }
 
1486
 
 
1487
        }
 
1488
 
 
1489
 
 
1490
    }
 
1491
 
 
1492
 
 
1493
    /**
 
1494
     * 
 
1495
     * DOM Level 3 - Experimental:
 
1496
     * Look up the prefix associated to the given namespace URI, starting from this node.
 
1497
     * 
 
1498
     * @param namespaceURI
 
1499
     * @return the prefix for the namespace
 
1500
     */
 
1501
    public String lookupPrefix(String namespaceURI){
 
1502
        
 
1503
        // REVISIT: When Namespaces 1.1 comes out this may not be true
 
1504
        // Prefix can't be bound to null namespace
 
1505
        if (namespaceURI == null) {
 
1506
            return null;
 
1507
        }
 
1508
 
 
1509
        short type = this.getNodeType();
 
1510
 
 
1511
        switch (type) {
 
1512
        case Node.ELEMENT_NODE: {
 
1513
 
 
1514
                String namespace = this.getNamespaceURI(); // to flip out children 
 
1515
                return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
 
1516
            }
 
1517
        case Node.DOCUMENT_NODE:{
 
1518
                return((NodeImpl)((Document)this).getDocumentElement()).lookupPrefix(namespaceURI);
 
1519
            }
 
1520
 
 
1521
        case Node.ENTITY_NODE :
 
1522
        case Node.NOTATION_NODE:
 
1523
        case Node.DOCUMENT_FRAGMENT_NODE:
 
1524
        case Node.DOCUMENT_TYPE_NODE:
 
1525
            // type is unknown
 
1526
            return null;
 
1527
        case Node.ATTRIBUTE_NODE:{
 
1528
                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
 
1529
                    return ownerNode.lookupPrefix(namespaceURI);
 
1530
 
 
1531
                }
 
1532
                return null;
 
1533
            }
 
1534
        default:{   
 
1535
                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 
1536
                if (ancestor != null) {
 
1537
                    return ancestor.lookupPrefix(namespaceURI);
 
1538
                }
 
1539
                return null;
 
1540
            }
 
1541
 
 
1542
        }
 
1543
    }
 
1544
    /**
 
1545
     * DOM Level 3 - Experimental:
 
1546
     * Look up the namespace URI associated to the given prefix, starting from this node.
 
1547
     * Use lookupNamespaceURI(null) to lookup the default namespace
 
1548
     * 
 
1549
     * @param namespaceURI
 
1550
     * @return th URI for the namespace
 
1551
     * @since DOM Level 3
 
1552
     */
 
1553
    public String lookupNamespaceURI(String specifiedPrefix) {
 
1554
        short type = this.getNodeType();
 
1555
        switch (type) {
 
1556
        case Node.ELEMENT_NODE : {  
 
1557
                
 
1558
                String namespace = this.getNamespaceURI();
 
1559
                String prefix = this.getPrefix();
 
1560
                if (namespace !=null) {
 
1561
                    // REVISIT: is it possible that prefix is empty string?
 
1562
                    if (specifiedPrefix== null && prefix==specifiedPrefix) {
 
1563
                        // looking for default namespace
 
1564
                        return namespace;
 
1565
                    } else if (prefix != null && prefix.equals(specifiedPrefix)) {
 
1566
                        // non default namespace
 
1567
                        return namespace;
 
1568
                    }
 
1569
                } 
 
1570
                if (this.hasAttributes()) {
 
1571
                    NamedNodeMap map = this.getAttributes();
 
1572
                    int length = map.getLength();
 
1573
                    for (int i=0;i<length;i++) {
 
1574
                        Node attr = map.item(i);
 
1575
                        String attrPrefix = attr.getPrefix();
 
1576
                        String value = attr.getNodeValue();
 
1577
                        namespace = attr.getNamespaceURI();
 
1578
                        if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
 
1579
                            // at this point we are dealing with DOM Level 2 nodes only
 
1580
                            if (specifiedPrefix == null &&
 
1581
                                attr.getNodeName().equals("xmlns")) {
 
1582
                                // default namespace
 
1583
                                return value;
 
1584
                            } else if (attrPrefix !=null && 
 
1585
                                       attrPrefix.equals("xmlns") &&
 
1586
                                       attr.getLocalName().equals(specifiedPrefix)) {
 
1587
                                // non default namespace
 
1588
                                return value;
 
1589
                            }
 
1590
                        }
 
1591
                    }
 
1592
                }
 
1593
                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 
1594
                if (ancestor != null) {
 
1595
                    return ancestor.lookupNamespaceURI(specifiedPrefix);
 
1596
                }
 
1597
 
 
1598
                return null;
 
1599
 
 
1600
 
 
1601
            }
 
1602
        case Node.DOCUMENT_NODE : {   
 
1603
                return((NodeImpl)((Document)this).getDocumentElement()).lookupNamespaceURI(specifiedPrefix);
 
1604
            }
 
1605
        case Node.ENTITY_NODE :
 
1606
        case Node.NOTATION_NODE:
 
1607
        case Node.DOCUMENT_FRAGMENT_NODE:
 
1608
        case Node.DOCUMENT_TYPE_NODE:
 
1609
            // type is unknown
 
1610
            return null;
 
1611
        case Node.ATTRIBUTE_NODE:{
 
1612
                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
 
1613
                    return ownerNode.lookupNamespaceURI(specifiedPrefix);
 
1614
 
 
1615
                }
 
1616
                return null;
 
1617
            }
 
1618
        default:{ 
 
1619
                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 
1620
                if (ancestor != null) {
 
1621
                    return ancestor.lookupNamespaceURI(specifiedPrefix);
 
1622
                }
 
1623
                return null;
 
1624
            }
 
1625
 
 
1626
        }
 
1627
    }
 
1628
 
 
1629
 
 
1630
    Node getElementAncestor (Node currentNode){
 
1631
        Node parent = currentNode.getParentNode();
 
1632
        if (parent != null) {
 
1633
            short type = parent.getNodeType();
 
1634
            if (type == Node.ELEMENT_NODE) {
 
1635
                return parent;
 
1636
            }
 
1637
            return getElementAncestor(parent);
 
1638
        }
 
1639
        return null;
 
1640
    }
 
1641
 
 
1642
    String lookupNamespacePrefix(String namespaceURI, ElementImpl el){
 
1643
        String namespace = this.getNamespaceURI();
 
1644
        // REVISIT: if no prefix is available is it null or empty string, or 
 
1645
        //          could be both?
 
1646
        String prefix = this.getPrefix();
 
1647
 
 
1648
        if (namespace!=null && namespace.equals(namespaceURI)) {
 
1649
            if (prefix != null) {
 
1650
                String foundNamespace =  el.lookupNamespaceURI(prefix);
 
1651
                if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
 
1652
                    return prefix;
 
1653
                }
 
1654
 
 
1655
            }
 
1656
        }
 
1657
        if (this.hasAttributes()) {
 
1658
            NamedNodeMap map = this.getAttributes();
 
1659
            int length = map.getLength();
 
1660
            for (int i=0;i<length;i++) {
 
1661
                Node attr = map.item(i);
 
1662
                String attrPrefix = attr.getPrefix();
 
1663
                String value = attr.getNodeValue();
 
1664
                namespace = attr.getNamespaceURI();
 
1665
                if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
 
1666
                    // DOM Level 2 nodes
 
1667
                    if (((attr.getNodeName().equals("xmlns")) ||
 
1668
                         (attrPrefix !=null && attrPrefix.equals("xmlns")) &&
 
1669
                         value.equals(namespaceURI))) {
 
1670
 
 
1671
                        String localname= attr.getLocalName();
 
1672
                        String foundNamespace = el.lookupNamespaceURI(localname);
 
1673
                        if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
 
1674
                            return localname;
 
1675
                        }
 
1676
                    }
 
1677
 
 
1678
 
 
1679
                }
 
1680
            }
 
1681
        }
 
1682
        NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 
1683
 
 
1684
        if (ancestor != null) {
 
1685
            return ancestor.lookupNamespacePrefix(namespaceURI, el);
 
1686
        }
 
1687
        return null;
 
1688
    }
 
1689
 
 
1690
    /**
 
1691
     * Tests whether two nodes are equal.
 
1692
     * <br>This method tests for equality of nodes, not sameness (i.e., 
 
1693
     * whether the two nodes are references to the same object) which can be 
 
1694
     * tested with <code>Node.isSameNode</code>. All nodes that are the same 
 
1695
     * will also be equal, though the reverse may not be true.
 
1696
     * <br>Two nodes are equal if and only if the following conditions are 
 
1697
     * satisfied: The two nodes are of the same type.The following string 
 
1698
     * attributes are equal: <code>nodeName</code>, <code>localName</code>, 
 
1699
     * <code>namespaceURI</code>, <code>prefix</code>, <code>nodeValue</code>
 
1700
     * , <code>baseURI</code>. This is: they are both <code>null</code>, or 
 
1701
     * they have the same length and are character for character identical.
 
1702
     * The <code>attributes</code> <code>NamedNodeMaps</code> are equal. 
 
1703
     * This is: they are both <code>null</code>, or they have the same 
 
1704
     * length and for each node that exists in one map there is a node that 
 
1705
     * exists in the other map and is equal, although not necessarily at the 
 
1706
     * same index.The <code>childNodes</code> <code>NodeLists</code> are 
 
1707
     * equal. This is: they are both <code>null</code>, or they have the 
 
1708
     * same length and contain equal nodes at the same index. This is true 
 
1709
     * for <code>Attr</code> nodes as for any other type of node. Note that 
 
1710
     * normalization can affect equality; to avoid this, nodes should be 
 
1711
     * normalized before being compared. 
 
1712
     * <br>For two <code>DocumentType</code> nodes to be equal, the following 
 
1713
     * conditions must also be satisfied: The following string attributes 
 
1714
     * are equal: <code>publicId</code>, <code>systemId</code>, 
 
1715
     * <code>internalSubset</code>.The <code>entities</code> 
 
1716
     * <code>NamedNodeMaps</code> are equal.The <code>notations</code> 
 
1717
     * <code>NamedNodeMaps</code> are equal. 
 
1718
     * <br>On the other hand, the following do not affect equality: the 
 
1719
     * <code>ownerDocument</code> attribute, the <code>specified</code> 
 
1720
     * attribute for <code>Attr</code> nodes, the 
 
1721
     * <code>isWhitespaceInElementContent</code> attribute for 
 
1722
     * <code>Text</code> nodes, as well as any user data or event listeners 
 
1723
     * registered on the nodes.
 
1724
     * @param arg The node to compare equality with.
 
1725
     * @param deep If <code>true</code>, recursively compare the subtrees; if 
 
1726
     *   <code>false</code>, compare only the nodes themselves (and its 
 
1727
     *   attributes, if it is an <code>Element</code>).
 
1728
     * @return If the nodes, and possibly subtrees are equal, 
 
1729
     *   <code>true</code> otherwise <code>false</code>.
 
1730
     * @since DOM Level 3
 
1731
     */
 
1732
    public boolean isEqualNode(Node arg) {
 
1733
        if (arg == this) {
 
1734
            return true;
 
1735
        }
 
1736
        if (arg.getNodeType() != getNodeType()) {
 
1737
            return false;
 
1738
        }
 
1739
        // in theory nodeName can't be null but better be careful
 
1740
        // who knows what other implementations may be doing?...
 
1741
        if (getNodeName() == null) {
 
1742
            if (arg.getNodeName() != null) {
 
1743
                return false;
 
1744
            }
 
1745
        }
 
1746
        else if (!getNodeName().equals(arg.getNodeName())) {
 
1747
            return false;
 
1748
        }
 
1749
 
 
1750
        if (getLocalName() == null) {
 
1751
            if (arg.getLocalName() != null) {
 
1752
                return false;
 
1753
            }
 
1754
        }
 
1755
        else if (!getLocalName().equals(arg.getLocalName())) {
 
1756
            return false;
 
1757
        }
 
1758
 
 
1759
        if (getNamespaceURI() == null) {
 
1760
            if (arg.getNamespaceURI() != null) {
 
1761
                return false;
 
1762
            }
 
1763
        }
 
1764
        else if (!getNamespaceURI().equals(arg.getNamespaceURI())) {
 
1765
            return false;
 
1766
        }
 
1767
 
 
1768
        if (getPrefix() == null) {
 
1769
            if (arg.getPrefix() != null) {
 
1770
                return false;
 
1771
            }
 
1772
        }
 
1773
        else if (!getPrefix().equals(arg.getPrefix())) {
 
1774
            return false;
 
1775
        }
 
1776
 
 
1777
        if (getNodeValue() == null) {
 
1778
            if (arg.getNodeValue() != null) {
 
1779
                return false;
 
1780
            }
 
1781
        }
 
1782
        else if (!getNodeValue().equals(arg.getNodeValue())) {
 
1783
            return false;
 
1784
        }
 
1785
 
 
1786
 
 
1787
        return true;
 
1788
    }
 
1789
 
 
1790
    /**
 
1791
     * @since DOM Level 3
 
1792
     */
 
1793
    public Object getFeature(String feature, String version) {
 
1794
        // we don't have any alternate node, either this node does the job
 
1795
        // or we don't have anything that does
 
1796
        return isSupported(feature, version) ? this : null;
 
1797
    }
 
1798
 
 
1799
    /**
 
1800
     * Associate an object to a key on this node. The object can later be 
 
1801
     * retrieved from this node by calling <code>getUserData</code> with the 
 
1802
     * same key.
 
1803
     * @param key The key to associate the object to.
 
1804
     * @param data The object to associate to the given key, or 
 
1805
     *   <code>null</code> to remove any existing association to that key.
 
1806
     * @param handler The handler to associate to that key, or 
 
1807
     *   <code>null</code>.
 
1808
     * @return Returns the <code>DOMObject</code> previously associated to 
 
1809
     *   the given key on this node, or <code>null</code> if there was none.
 
1810
     * @since DOM Level 3
 
1811
     */
 
1812
    public Object setUserData(String key, 
 
1813
                              Object data, 
 
1814
                              UserDataHandler handler) {
 
1815
        return ownerDocument().setUserData(this, key, data, handler);
 
1816
    }
 
1817
 
 
1818
    /**
 
1819
     * Retrieves the object associated to a key on a this node. The object 
 
1820
     * must first have been set to this node by calling 
 
1821
     * <code>setUserData</code> with the same key.
 
1822
     * @param key The key the object is associated to.
 
1823
     * @return Returns the <code>DOMObject</code> associated to the given key 
 
1824
     *   on this node, or <code>null</code> if there was none.
 
1825
     * @since DOM Level 3
 
1826
     */
 
1827
    public Object getUserData(String key) {
 
1828
        return ownerDocument().getUserData(this, key);
 
1829
    }
 
1830
 
 
1831
 
 
1832
    //
 
1833
    // Public methods
 
1834
    //
 
1835
 
 
1836
    /**
 
1837
     * NON-DOM: PR-DOM-Level-1-19980818 mentions readonly nodes in conjunction
 
1838
     * with Entities, but provides no API to support this.
 
1839
     * <P>
 
1840
     * Most DOM users should not touch this method. Its anticpated use
 
1841
     * is during construction of EntityRefernces, where it will be used to
 
1842
     * lock the contents replicated from Entity so they can't be casually
 
1843
     * altered. It _could_ be published as a DOM extension, if desired.
 
1844
     * <P>
 
1845
     * Note: since we never have any children deep is meaningless here,
 
1846
     * ParentNode overrides this behavior.
 
1847
     * @see ParentNode
 
1848
     *
 
1849
     * @param readOnly True or false as desired.
 
1850
     * @param deep If true, children are also toggled. Note that this will
 
1851
     *  not change the state of an EntityReference or its children,
 
1852
     *  which are always read-only.
 
1853
     */
 
1854
    public void setReadOnly(boolean readOnly, boolean deep) {
 
1855
 
 
1856
        if (needsSyncData()) {
 
1857
            synchronizeData();
 
1858
        }
 
1859
        isReadOnly(readOnly);
 
1860
 
 
1861
    } // setReadOnly(boolean,boolean)
 
1862
 
 
1863
    /**
 
1864
     * NON-DOM: Returns true if this node is read-only. This is a
 
1865
     * shallow check.
 
1866
     */
 
1867
    public boolean getReadOnly() {
 
1868
 
 
1869
        if (needsSyncData()) {
 
1870
            synchronizeData();
 
1871
        }
 
1872
        return isReadOnly();
 
1873
 
 
1874
    } // getReadOnly():boolean
 
1875
 
 
1876
    /**
 
1877
     * NON-DOM: As an alternative to subclassing the DOM, this implementation
 
1878
     * has been extended with the ability to attach an object to each node.
 
1879
     * (If you need multiple objects, you can attach a collection such as a
 
1880
     * vector or hashtable, then attach your application information to that.)
 
1881
     * <p><b>Important Note:</b> You are responsible for removing references
 
1882
     * to your data on nodes that are no longer used. Failure to do so will
 
1883
     * prevent the nodes, your data is attached to, to be garbage collected
 
1884
     * until the whole document is.
 
1885
     *
 
1886
     * @param data the object to store or null to remove any existing reference
 
1887
     */
 
1888
    public void setUserData(Object data) {
 
1889
        ownerDocument().setUserData(this, data);
 
1890
    }
 
1891
 
 
1892
    /**
 
1893
     * NON-DOM:
 
1894
     * Returns the user data associated to this node.
 
1895
     */
 
1896
    public Object getUserData() {
 
1897
        return ownerDocument().getUserData(this);
 
1898
    }
 
1899
 
 
1900
    //
 
1901
    // Protected methods
 
1902
    //
 
1903
 
 
1904
    /**
 
1905
     * Denotes that this node has changed.
 
1906
     */
 
1907
    protected void changed() {
 
1908
        // we do not actually store this information on every node, we only
 
1909
        // have a global indicator on the Document. Doing otherwise cost us too
 
1910
        // much for little gain.
 
1911
        ownerDocument().changed();
 
1912
    }
 
1913
 
 
1914
    /**
 
1915
     * Returns the number of changes to this node.
 
1916
     */
 
1917
    protected int changes() {
 
1918
        // we do not actually store this information on every node, we only
 
1919
        // have a global indicator on the Document. Doing otherwise cost us too
 
1920
        // much for little gain.
 
1921
        return ownerDocument().changes();
 
1922
    }
 
1923
 
 
1924
    /**
 
1925
     * Override this method in subclass to hook in efficient
 
1926
     * internal data structure.
 
1927
     */
 
1928
    protected void synchronizeData() {
 
1929
        // By default just change the flag to avoid calling this method again
 
1930
        needsSyncData(false);
 
1931
    }
 
1932
 
 
1933
    /** 
 
1934
     * For non-child nodes, the node which "points" to this node.  
 
1935
     * For example, the owning element for an attribute
 
1936
     */
 
1937
    protected Node getContainer() {
 
1938
       return null;
 
1939
    }
 
1940
 
 
1941
 
 
1942
    /*
 
1943
     * Flags setters and getters
 
1944
     */
 
1945
 
 
1946
    final boolean isReadOnly() {
 
1947
        return (flags & READONLY) != 0;
 
1948
    }
 
1949
 
 
1950
    final void isReadOnly(boolean value) {
 
1951
        flags = (short) (value ? flags | READONLY : flags & ~READONLY);
 
1952
    }
 
1953
 
 
1954
    final boolean needsSyncData() {
 
1955
        return (flags & SYNCDATA) != 0;
 
1956
    }
 
1957
 
 
1958
    final void needsSyncData(boolean value) {
 
1959
        flags = (short) (value ? flags | SYNCDATA : flags & ~SYNCDATA);
 
1960
    }
 
1961
 
 
1962
    final boolean needsSyncChildren() {
 
1963
        return (flags & SYNCCHILDREN) != 0;
 
1964
    }
 
1965
 
 
1966
    public final void needsSyncChildren(boolean value) {
 
1967
        flags = (short) (value ? flags | SYNCCHILDREN : flags & ~SYNCCHILDREN);
 
1968
    }
 
1969
 
 
1970
    final boolean isOwned() {
 
1971
        return (flags & OWNED) != 0;
 
1972
    }
 
1973
 
 
1974
    final void isOwned(boolean value) {
 
1975
        flags = (short) (value ? flags | OWNED : flags & ~OWNED);
 
1976
    }
 
1977
 
 
1978
    final boolean isFirstChild() {
 
1979
        return (flags & FIRSTCHILD) != 0;
 
1980
    }
 
1981
 
 
1982
    final void isFirstChild(boolean value) {
 
1983
        flags = (short) (value ? flags | FIRSTCHILD : flags & ~FIRSTCHILD);
 
1984
    }
 
1985
 
 
1986
    final boolean isSpecified() {
 
1987
        return (flags & SPECIFIED) != 0;
 
1988
    }
 
1989
 
 
1990
    final void isSpecified(boolean value) {
 
1991
        flags = (short) (value ? flags | SPECIFIED : flags & ~SPECIFIED);
 
1992
    }
 
1993
 
 
1994
    // inconsistent name to avoid clash with public method on TextImpl
 
1995
    final boolean internalIsIgnorableWhitespace() {
 
1996
        return (flags & IGNORABLEWS) != 0;
 
1997
    }
 
1998
 
 
1999
    final void isIgnorableWhitespace(boolean value) {
 
2000
        flags = (short) (value ? flags | IGNORABLEWS : flags & ~IGNORABLEWS);
 
2001
    }
 
2002
 
 
2003
    final boolean hasStringValue() {
 
2004
        return (flags & HASSTRING) != 0;
 
2005
    }
 
2006
 
 
2007
    final void hasStringValue(boolean value) {
 
2008
        flags = (short) (value ? flags | HASSTRING : flags & ~HASSTRING);
 
2009
    }
 
2010
 
 
2011
    final boolean isNormalized() {
 
2012
        return (flags & NORMALIZED) != 0;
 
2013
    }
 
2014
 
 
2015
    final void isNormalized(boolean value) {
 
2016
        // See if flag should propagate to parent.
 
2017
        if (!value && isNormalized() && ownerNode != null) {
 
2018
            ownerNode.isNormalized(false);
 
2019
        }
 
2020
        flags = (short) (value ?  flags | NORMALIZED : flags & ~NORMALIZED);
 
2021
    }
 
2022
 
 
2023
    final boolean isIdAttribute() {
 
2024
        return (flags & ID) != 0;
 
2025
    }
 
2026
 
 
2027
    final void isIdAttribute(boolean value) {
 
2028
        flags = (short) (value ? flags | ID : flags & ~ID);
 
2029
    }
 
2030
 
 
2031
    //
 
2032
    // Object methods
 
2033
    //
 
2034
 
 
2035
    /** NON-DOM method for debugging convenience. */
 
2036
    public String toString() {
 
2037
        return "["+getNodeName()+": "+getNodeValue()+"]";
 
2038
    }
 
2039
 
 
2040
    //
 
2041
    // Serialization methods
 
2042
    //
 
2043
 
 
2044
    /** Serialize object. */
 
2045
    private void writeObject(ObjectOutputStream out) throws IOException {
 
2046
 
 
2047
        // synchronize data
 
2048
        if (needsSyncData()) {
 
2049
            synchronizeData();
 
2050
        }
 
2051
        // write object
 
2052
        out.defaultWriteObject();
 
2053
 
 
2054
    } // writeObject(ObjectOutputStream)
 
2055
 
 
2056
} // class NodeImpl