KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > dom > CoreDocumentImpl


1 /*
2  * Copyright 1999-2002,2004,2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.dom;
18
19 import java.lang.reflect.Constructor JavaDoc;
20 import java.util.Enumeration JavaDoc;
21 import java.util.Hashtable JavaDoc;
22 import org.apache.xerces.util.URI;
23
24 import org.w3c.dom.DOMConfiguration JavaDoc;
25 import org.w3c.dom.UserDataHandler JavaDoc;
26 import org.apache.xerces.util.XMLChar;
27 import org.apache.xerces.util.XML11Char;
28 import org.apache.xerces.xni.NamespaceContext;
29 import org.w3c.dom.Attr JavaDoc;
30 import org.w3c.dom.CDATASection JavaDoc;
31 import org.w3c.dom.Comment JavaDoc;
32 import org.w3c.dom.DOMException JavaDoc;
33 import org.w3c.dom.DOMImplementation JavaDoc;
34 import org.w3c.dom.Document JavaDoc;
35 import org.w3c.dom.DocumentFragment JavaDoc;
36 import org.w3c.dom.DocumentType JavaDoc;
37 import org.w3c.dom.Element JavaDoc;
38 import org.w3c.dom.Entity JavaDoc;
39 import org.w3c.dom.EntityReference JavaDoc;
40 import org.w3c.dom.NamedNodeMap JavaDoc;
41 import org.w3c.dom.Node JavaDoc;
42 import org.w3c.dom.NodeList JavaDoc;
43 import org.w3c.dom.Notation JavaDoc;
44 import org.w3c.dom.ProcessingInstruction JavaDoc;
45 import org.w3c.dom.Text JavaDoc;
46 import org.w3c.dom.events.Event JavaDoc;
47 import org.w3c.dom.events.EventListener JavaDoc;
48 import org.w3c.dom.ls.DOMImplementationLS JavaDoc;
49 import org.w3c.dom.ls.LSSerializer JavaDoc;
50
51 /**
52  * The Document interface represents the entire HTML or XML document.
53  * Conceptually, it is the root of the document tree, and provides the
54  * primary access to the document's data.
55  * <P>
56  * Since elements, text nodes, comments, processing instructions,
57  * etc. cannot exist outside the context of a Document, the Document
58  * interface also contains the factory methods needed to create these
59  * objects. The Node objects created have a ownerDocument attribute
60  * which associates them with the Document within whose context they
61  * were created.
62  * <p>
63  * The CoreDocumentImpl class only implements the DOM Core. Additional modules
64  * are supported by the more complete DocumentImpl subclass.
65  * <p>
66  * <b>Note:</b> When any node in the document is serialized, the
67  * entire document is serialized along with it.
68  *
69  * @xerces.internal
70  *
71  * @author Arnaud Le Hors, IBM
72  * @author Joe Kesselman, IBM
73  * @author Andy Clark, IBM
74  * @author Ralf Pfeiffer, IBM
75  * @version $Id: CoreDocumentImpl.java,v 1.86 2005/06/13 21:08:07 nddelima Exp $
76  * @since PR-DOM-Level-1-19980818.
77  */

78
79
80 public class CoreDocumentImpl
81 extends ParentNode implements Document JavaDoc {
82
83     /**TODO::
84      * 1. Change XML11Char method names similar to XMLChar. That will prevent lot
85      * of dirty version checking code.
86      *
87      * 2. IMO during cloneNode qname/isXMLName check should not be made.
88      */

89     //
90
// Constants
91
//
92

93     /** Serialization version. */
94     static final long serialVersionUID = 0;
95
96     //
97
// Data
98
//
99

100     // document information
101

102     /** Document type. */
103     protected DocumentTypeImpl docType;
104
105     /** Document element. */
106     protected ElementImpl docElement;
107
108     /** NodeListCache free list */
109     transient NodeListCache fFreeNLCache;
110
111     /**Experimental DOM Level 3 feature: Document encoding */
112     protected String JavaDoc encoding;
113
114     /**Experimental DOM Level 3 feature: Document actualEncoding */
115     protected String JavaDoc actualEncoding;
116
117     /**Experimental DOM Level 3 feature: Document version */
118     protected String JavaDoc version;
119
120     /**Experimental DOM Level 3 feature: Document standalone */
121     protected boolean standalone;
122
123     /**Experimental DOM Level 3 feature: documentURI */
124     protected String JavaDoc fDocumentURI;
125
126     //Revisit :: change to a better data structure.
127
/** Table for user data attached to this document nodes. */
128     protected Hashtable JavaDoc userData;
129
130
131     /** Identifiers. */
132     protected Hashtable JavaDoc identifiers;
133
134     // DOM Level 3: normalizeDocument
135
transient DOMNormalizer domNormalizer = null;
136     transient DOMConfigurationImpl fConfiguration = null;
137     
138     // support of XPath API
139
transient Object JavaDoc fXPathEvaluator = null;
140
141     /** Table for quick check of child insertion. */
142     private final static int[] kidOK;
143
144     /**
145      * Number of alterations made to this document since its creation.
146      * Serves as a "dirty bit" so that live objects such as NodeList can
147      * recognize when an alteration has been made and discard its cached
148      * state information.
149      * <p>
150      * Any method that alters the tree structure MUST cause or be
151      * accompanied by a call to changed(), to inform it that any outstanding
152      * NodeLists may have to be updated.
153      * <p>
154      * (Required because NodeList is simultaneously "live" and integer-
155      * indexed -- a bad decision in the DOM's design.)
156      * <p>
157      * Note that changes which do not affect the tree's structure -- changing
158      * the node's name, for example -- do _not_ have to call changed().
159      * <p>
160      * Alternative implementation would be to use a cryptographic
161      * Digest value rather than a count. This would have the advantage that
162      * "harmless" changes (those producing equal() trees) would not force
163      * NodeList to resynchronize. Disadvantage is that it's slightly more prone
164      * to "false negatives", though that's the difference between "wildly
165      * unlikely" and "absurdly unlikely". IF we start maintaining digests,
166      * we should consider taking advantage of them.
167      *
168      * Note: This used to be done a node basis, so that we knew what
169      * subtree changed. But since only DeepNodeList really use this today,
170      * the gain appears to be really small compared to the cost of having
171      * an int on every (parent) node plus having to walk up the tree all the
172      * way to the root to mark the branch as changed everytime a node is
173      * changed.
174      * So we now have a single counter global to the document. It means that
175      * some objects may flush their cache more often than necessary, but this
176      * makes nodes smaller and only the document needs to be marked as changed.
177      */

178     protected int changes = 0;
179
180     // experimental
181

182     /** Allow grammar access. */
183     protected boolean allowGrammarAccess;
184
185     /** Bypass error checking. */
186     protected boolean errorChecking = true;
187
188     //Did version change at any point when the document was created ?
189
//this field helps us to optimize when normalizingDocument.
190
protected boolean xmlVersionChanged = false ;
191
192     /** The following are required for compareDocumentPosition
193      */

194     // Document number. Documents are ordered across the implementation using
195
// positive integer values. Documents are assigned numbers on demand.
196
private int documentNumber=0;
197     // Node counter and table. Used to assign numbers to nodes for this
198
// document. Node number values are negative integers. Nodes are
199
// assigned numbers on demand.
200
private int nodeCounter = 0;
201     private Hashtable JavaDoc nodeTable;
202     private boolean xml11Version = false; //by default 1.0
203
//
204
// Static initialization
205
//
206

207     static {
208
209         kidOK = new int[13];
210
211         kidOK[DOCUMENT_NODE] =
212         1 << ELEMENT_NODE | 1 << PROCESSING_INSTRUCTION_NODE |
213         1 << COMMENT_NODE | 1 << DOCUMENT_TYPE_NODE;
214
215         kidOK[DOCUMENT_FRAGMENT_NODE] =
216         kidOK[ENTITY_NODE] =
217         kidOK[ENTITY_REFERENCE_NODE] =
218         kidOK[ELEMENT_NODE] =
219         1 << ELEMENT_NODE | 1 << PROCESSING_INSTRUCTION_NODE |
220         1 << COMMENT_NODE | 1 << TEXT_NODE |
221         1 << CDATA_SECTION_NODE | 1 << ENTITY_REFERENCE_NODE ;
222
223
224         kidOK[ATTRIBUTE_NODE] =
225         1 << TEXT_NODE | 1 << ENTITY_REFERENCE_NODE;
226
227         kidOK[DOCUMENT_TYPE_NODE] =
228         kidOK[PROCESSING_INSTRUCTION_NODE] =
229         kidOK[COMMENT_NODE] =
230         kidOK[TEXT_NODE] =
231         kidOK[CDATA_SECTION_NODE] =
232         kidOK[NOTATION_NODE] =
233         0;
234
235     } // static
236

237     //
238
// Constructors
239
//
240

241     /**
242      * NON-DOM: Actually creating a Document is outside the DOM's spec,
243      * since it has to operate in terms of a particular implementation.
244      */

245     public CoreDocumentImpl() {
246         this(false);
247     }
248
249     /** Constructor. */
250     public CoreDocumentImpl(boolean grammarAccess) {
251         super(null);
252         ownerDocument = this;
253         allowGrammarAccess = grammarAccess;
254     }
255
256     /**
257      * For DOM2 support.
258      * The createDocument factory method is in DOMImplementation.
259      */

260     public CoreDocumentImpl(DocumentType JavaDoc doctype) {
261         this(doctype, false);
262     }
263
264     /** For DOM2 support. */
265     public CoreDocumentImpl(DocumentType JavaDoc doctype, boolean grammarAccess) {
266         this(grammarAccess);
267         if (doctype != null) {
268             DocumentTypeImpl doctypeImpl;
269             try {
270                 doctypeImpl = (DocumentTypeImpl) doctype;
271             } catch (ClassCastException JavaDoc e) {
272                 String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
273                 throw new DOMException JavaDoc(DOMException.WRONG_DOCUMENT_ERR, msg);
274             }
275             doctypeImpl.ownerDocument = this;
276             appendChild(doctype);
277         }
278     }
279
280     //
281
// Node methods
282
//
283

284     // even though ownerDocument refers to this in this implementation
285
// the DOM Level 2 spec says it must be null, so make it appear so
286
final public Document JavaDoc getOwnerDocument() {
287         return null;
288     }
289
290     /** Returns the node type. */
291     public short getNodeType() {
292         return Node.DOCUMENT_NODE;
293     }
294
295     /** Returns the node name. */
296     public String JavaDoc getNodeName() {
297         return "#document";
298     }
299
300     /**
301      * Deep-clone a document, including fixing ownerDoc for the cloned
302      * children. Note that this requires bypassing the WRONG_DOCUMENT_ERR
303      * protection. I've chosen to implement it by calling importNode
304      * which is DOM Level 2.
305      *
306      * @return org.w3c.dom.Node
307      * @param deep boolean, iff true replicate children
308      */

309     public Node JavaDoc cloneNode(boolean deep) {
310
311         CoreDocumentImpl newdoc = new CoreDocumentImpl();
312         callUserDataHandlers(this, newdoc, UserDataHandler.NODE_CLONED);
313         cloneNode(newdoc, deep);
314
315         return newdoc;
316
317     } // cloneNode(boolean):Node
318

319
320     /**
321      * internal method to share code with subclass
322      **/

323     protected void cloneNode(CoreDocumentImpl newdoc, boolean deep) {
324
325         // clone the children by importing them
326
if (needsSyncChildren()) {
327             synchronizeChildren();
328         }
329
330         if (deep) {
331             Hashtable JavaDoc reversedIdentifiers = null;
332
333             if (identifiers != null) {
334                 // Build a reverse mapping from element to identifier.
335
reversedIdentifiers = new Hashtable JavaDoc();
336                 Enumeration JavaDoc elementIds = identifiers.keys();
337                 while (elementIds.hasMoreElements()) {
338                     Object JavaDoc elementId = elementIds.nextElement();
339                     reversedIdentifiers.put(identifiers.get(elementId),
340                     elementId);
341                 }
342             }
343
344             // Copy children into new document.
345
for (ChildNode kid = firstChild; kid != null;
346             kid = kid.nextSibling) {
347                 newdoc.appendChild(newdoc.importNode(kid, true, true,
348                 reversedIdentifiers));
349             }
350         }
351
352         // experimental
353
newdoc.allowGrammarAccess = allowGrammarAccess;
354         newdoc.errorChecking = errorChecking;
355
356     } // cloneNode(CoreDocumentImpl,boolean):void
357

358     /**
359      * Since a Document may contain at most one top-level Element child,
360      * and at most one DocumentType declaraction, we need to subclass our
361      * add-children methods to implement this constraint.
362      * Since appendChild() is implemented as insertBefore(,null),
363      * altering the latter fixes both.
364      * <p>
365      * While I'm doing so, I've taken advantage of the opportunity to
366      * cache documentElement and docType so we don't have to
367      * search for them.
368      *
369      * REVISIT: According to the spec it is not allowed to alter neither the
370      * document element nor the document type in any way
371      */

372     public Node JavaDoc insertBefore(Node JavaDoc newChild, Node JavaDoc refChild)
373     throws DOMException JavaDoc {
374
375         // Only one such child permitted
376
int type = newChild.getNodeType();
377         if (errorChecking) {
378             if((type == Node.ELEMENT_NODE && docElement != null) ||
379             (type == Node.DOCUMENT_TYPE_NODE && docType != null)) {
380                 String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null);
381                 throw new DOMException JavaDoc(DOMException.HIERARCHY_REQUEST_ERR, msg);
382             }
383         }
384         // Adopt orphan doctypes
385
if (newChild.getOwnerDocument() == null &&
386         newChild instanceof DocumentTypeImpl) {
387             ((DocumentTypeImpl) newChild).ownerDocument = this;
388         }
389         super.insertBefore(newChild,refChild);
390
391         // If insert succeeded, cache the kid appropriately
392
if (type == Node.ELEMENT_NODE) {
393             docElement = (ElementImpl)newChild;
394         }
395         else if (type == Node.DOCUMENT_TYPE_NODE) {
396             docType = (DocumentTypeImpl)newChild;
397         }
398
399         return newChild;
400
401     } // insertBefore(Node,Node):Node
402

403     /**
404      * Since insertBefore caches the docElement (and, currently, docType),
405      * removeChild has to know how to undo the cache
406      *
407      * REVISIT: According to the spec it is not allowed to alter neither the
408      * document element nor the document type in any way
409      */

410     public Node JavaDoc removeChild(Node JavaDoc oldChild) throws DOMException JavaDoc {
411
412         super.removeChild(oldChild);
413
414         // If remove succeeded, un-cache the kid appropriately
415
int type = oldChild.getNodeType();
416         if(type == Node.ELEMENT_NODE) {
417             docElement = null;
418         }
419         else if (type == Node.DOCUMENT_TYPE_NODE) {
420             docType = null;
421         }
422
423         return oldChild;
424
425     } // removeChild(Node):Node
426

427     /**
428      * Since we cache the docElement (and, currently, docType),
429      * replaceChild has to update the cache
430      *
431      * REVISIT: According to the spec it is not allowed to alter neither the
432      * document element nor the document type in any way
433      */

434     public Node JavaDoc replaceChild(Node JavaDoc newChild, Node JavaDoc oldChild)
435     throws DOMException JavaDoc {
436
437         // Adopt orphan doctypes
438
if (newChild.getOwnerDocument() == null &&
439         newChild instanceof DocumentTypeImpl) {
440             ((DocumentTypeImpl) newChild).ownerDocument = this;
441         }
442
443         if (errorChecking &&((docType != null &&
444             oldChild.getNodeType() != Node.DOCUMENT_TYPE_NODE &&
445             newChild.getNodeType() == Node.DOCUMENT_TYPE_NODE)
446             || (docElement != null &&
447             oldChild.getNodeType() != Node.ELEMENT_NODE &&
448             newChild.getNodeType() == Node.ELEMENT_NODE))) {
449                 
450             throw new DOMException JavaDoc(
451                 DOMException.HIERARCHY_REQUEST_ERR,
452                 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));
453         }
454         super.replaceChild(newChild, oldChild);
455
456         int type = oldChild.getNodeType();
457         if(type == Node.ELEMENT_NODE) {
458             docElement = (ElementImpl)newChild;
459         }
460         else if (type == Node.DOCUMENT_TYPE_NODE) {
461             docType = (DocumentTypeImpl)newChild;
462         }
463         return oldChild;
464     } // replaceChild(Node,Node):Node
465

466     /*
467      * Get Node text content
468      * @since DOM Level 3
469      */

470     public String JavaDoc getTextContent() throws DOMException JavaDoc {
471         return null;
472     }
473
474     /*
475      * Set Node text content
476      * @since DOM Level 3
477      */

478     public void setTextContent(String JavaDoc textContent)
479     throws DOMException JavaDoc {
480         // no-op
481
}
482
483     /**
484      * @since DOM Level 3
485      */

486     public Object JavaDoc getFeature(String JavaDoc feature, String JavaDoc version) {
487         
488         boolean anyVersion = version == null || version.length() == 0;
489         
490         // if a plus sign "+" is prepended to any feature name, implementations
491
// are considered in which the specified feature may not be directly
492
// castable DOMImplementation.getFeature(feature, version). Without a
493
// plus, only features whose interfaces are directly castable are
494
// considered.
495
if ((feature.equalsIgnoreCase("+XPath"))
496             && (anyVersion || version.equals("3.0"))) {
497             
498             // If an XPathEvaluator was created previously
499
// return it otherwise create a new one.
500
if (fXPathEvaluator != null) {
501                 return fXPathEvaluator;
502             }
503             
504             try {
505                 Class JavaDoc xpathClass = ObjectFactory.findProviderClass(
506                     "org.apache.xpath.domapi.XPathEvaluatorImpl",
507                     ObjectFactory.findClassLoader(), true);
508                 Constructor JavaDoc xpathClassConstr =
509                     xpathClass.getConstructor(new Class JavaDoc[] { Document JavaDoc.class });
510                 
511                 // Check if the DOM XPath implementation implements
512
// the interface org.w3c.dom.XPathEvaluator
513
Class JavaDoc interfaces[] = xpathClass.getInterfaces();
514                 for (int i = 0; i < interfaces.length; i++) {
515                     if (interfaces[i].getName().equals(
516                     "org.w3c.dom.xpath.XPathEvaluator")) {
517                         fXPathEvaluator = xpathClassConstr.newInstance(new Object JavaDoc[] { this });
518                         return fXPathEvaluator;
519                     }
520                 }
521                 return null;
522             } catch (Exception JavaDoc e) {
523                 return null;
524             }
525         }
526         return super.getFeature(feature, version);
527     }
528
529     //
530
// Document methods
531
//
532

533     // factory methods
534

535     /**
536      * Factory method; creates an Attribute having this Document as its
537      * OwnerDoc.
538      *
539      * @param name The name of the attribute. Note that the attribute's value is
540      * _not_ established at the factory; remember to set it!
541      *
542      * @throws DOMException(INVALID_NAME_ERR)
543      * if the attribute name is not acceptable.
544      */

545     public Attr JavaDoc createAttribute(String JavaDoc name)
546         throws DOMException JavaDoc {
547         
548         if (errorChecking && !isXMLName(name,xml11Version)) {
549             String JavaDoc msg =
550                 DOMMessageFormatter.formatMessage(
551                     DOMMessageFormatter.DOM_DOMAIN,
552                     "INVALID_CHARACTER_ERR",
553                     null);
554             throw new DOMException JavaDoc(DOMException.INVALID_CHARACTER_ERR, msg);
555         }
556         return new AttrImpl(this, name);
557         
558     } // createAttribute(String):Attr
559

560     /**
561      * Factory method; creates a CDATASection having this Document as
562      * its OwnerDoc.
563      *
564      * @param data The initial contents of the CDATA
565      *
566      * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents. (HTML
567      * not yet implemented.)
568      */

569     public CDATASection JavaDoc createCDATASection(String JavaDoc data)
570     throws DOMException JavaDoc {
571         return new CDATASectionImpl(this, data);
572     }
573
574     /**
575      * Factory method; creates a Comment having this Document as its
576      * OwnerDoc.
577      *
578      * @param data The initial contents of the Comment. */

579     public Comment JavaDoc createComment(String JavaDoc data) {
580         return new CommentImpl(this, data);
581     }
582
583     /**
584      * Factory method; creates a DocumentFragment having this Document
585      * as its OwnerDoc.
586      */

587     public DocumentFragment JavaDoc createDocumentFragment() {
588         return new DocumentFragmentImpl(this);
589     }
590
591     /**
592      * Factory method; creates an Element having this Document
593      * as its OwnerDoc.
594      *
595      * @param tagName The name of the element type to instantiate. For
596      * XML, this is case-sensitive. For HTML, the tagName parameter may
597      * be provided in any case, but it must be mapped to the canonical
598      * uppercase form by the DOM implementation.
599      *
600      * @throws DOMException(INVALID_NAME_ERR) if the tag name is not
601      * acceptable.
602      */

603     public Element JavaDoc createElement(String JavaDoc tagName)
604     throws DOMException JavaDoc {
605
606         if (errorChecking && !isXMLName(tagName,xml11Version)) {
607             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
608             throw new DOMException JavaDoc(DOMException.INVALID_CHARACTER_ERR, msg);
609         }
610         return new ElementImpl(this, tagName);
611
612     } // createElement(String):Element
613

614     /**
615      * Factory method; creates an EntityReference having this Document
616      * as its OwnerDoc.
617      *
618      * @param name The name of the Entity we wish to refer to
619      *
620      * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
621      * nonstandard entities are not permitted. (HTML not yet
622      * implemented.)
623      */

624     public EntityReference JavaDoc createEntityReference(String JavaDoc name)
625     throws DOMException JavaDoc {
626
627         if (errorChecking && !isXMLName(name,xml11Version)) {
628             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
629             throw new DOMException JavaDoc(DOMException.INVALID_CHARACTER_ERR, msg);
630         }
631         return new EntityReferenceImpl(this, name);
632
633     } // createEntityReference(String):EntityReference
634

635     /**
636      * Factory method; creates a ProcessingInstruction having this Document
637      * as its OwnerDoc.
638      *
639      * @param target The target "processor channel"
640      * @param data Parameter string to be passed to the target.
641      *
642      * @throws DOMException(INVALID_NAME_ERR) if the target name is not
643      * acceptable.
644      *
645      * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents. (HTML
646      * not yet implemented.)
647      */

648     public ProcessingInstruction JavaDoc createProcessingInstruction(String JavaDoc target,
649     String JavaDoc data)
650     throws DOMException JavaDoc {
651
652         if (errorChecking && !isXMLName(target,xml11Version)) {
653             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
654             throw new DOMException JavaDoc(DOMException.INVALID_CHARACTER_ERR, msg);
655         }
656         return new ProcessingInstructionImpl(this, target, data);
657
658     } // createProcessingInstruction(String,String):ProcessingInstruction
659

660     /**
661      * Factory method; creates a Text node having this Document as its
662      * OwnerDoc.
663      *
664      * @param data The initial contents of the Text.
665      */

666     public Text JavaDoc createTextNode(String JavaDoc data) {
667         return new TextImpl(this, data);
668     }
669
670     // other document methods
671

672     /**
673      * For XML, this provides access to the Document Type Definition.
674      * For HTML documents, and XML documents which don't specify a DTD,
675      * it will be null.
676      */

677     public DocumentType JavaDoc getDoctype() {
678         if (needsSyncChildren()) {
679             synchronizeChildren();
680         }
681         return docType;
682     }
683
684
685     /**
686      * Convenience method, allowing direct access to the child node
687      * which is considered the root of the actual document content. For
688      * HTML, where it is legal to have more than one Element at the top
689      * level of the document, we pick the one with the tagName
690      * "HTML". For XML there should be only one top-level
691      *
692      * (HTML not yet supported.)
693      */

694     public Element JavaDoc getDocumentElement() {
695         if (needsSyncChildren()) {
696             synchronizeChildren();
697         }
698         return docElement;
699     }
700
701     /**
702      * Return a <em>live</em> collection of all descendent Elements (not just
703      * immediate children) having the specified tag name.
704      *
705      * @param tagname The type of Element we want to gather. "*" will be
706      * taken as a wildcard, meaning "all elements in the document."
707      *
708      * @see DeepNodeListImpl
709      */

710     public NodeList JavaDoc getElementsByTagName(String JavaDoc tagname) {
711         return new DeepNodeListImpl(this,tagname);
712     }
713
714     /**
715      * Retrieve information describing the abilities of this particular
716      * DOM implementation. Intended to support applications that may be
717      * using DOMs retrieved from several different sources, potentially
718      * with different underlying representations.
719      */

720     public DOMImplementation JavaDoc getImplementation() {
721         // Currently implemented as a singleton, since it's hardcoded
722
// information anyway.
723
return CoreDOMImplementationImpl.getDOMImplementation();
724     }
725
726     //
727
// Public methods
728
//
729

730     // properties
731

732     /**
733      * Sets whether the DOM implementation performs error checking
734      * upon operations. Turning off error checking only affects
735      * the following DOM checks:
736      * <ul>
737      * <li>Checking strings to make sure that all characters are
738      * legal XML characters
739      * <li>Hierarchy checking such as allowed children, checks for
740      * cycles, etc.
741      * </ul>
742      * <p>
743      * Turning off error checking does <em>not</em> turn off the
744      * following checks:
745      * <ul>
746      * <li>Read only checks
747      * <li>Checks related to DOM events
748      * </ul>
749      */

750
751     public void setErrorChecking(boolean check) {
752         errorChecking = check;
753     }
754
755     /*
756      * DOM Level 3 WD - Experimental.
757      */

758     public void setStrictErrorChecking(boolean check) {
759         errorChecking = check;
760     }
761
762     /**
763      * Returns true if the DOM implementation performs error checking.
764      */

765     public boolean getErrorChecking() {
766         return errorChecking;
767     }
768
769     /*
770      * DOM Level 3 WD - Experimental.
771      */

772     public boolean getStrictErrorChecking() {
773         return errorChecking;
774     }
775
776
777     /**
778      * DOM Level 3 CR - Experimental. (Was getActualEncoding)
779      *
780      * An attribute specifying the encoding used for this document
781      * at the time of the parsing. This is <code>null</code> when
782      * it is not known, such as when the <code>Document</code> was
783      * created in memory.
784      * @since DOM Level 3
785      */

786     public String JavaDoc getInputEncoding() {
787         return actualEncoding;
788     }
789
790     /**
791      * DOM Internal
792      * (Was a DOM L3 Core WD public interface method setActualEncoding )
793      *
794      * An attribute specifying the actual encoding of this document. This is
795      * <code>null</code> otherwise.
796      * <br> This attribute represents the property [character encoding scheme]
797      * defined in .
798      */

799     public void setInputEncoding(String JavaDoc value) {
800         actualEncoding = value;
801     }
802
803     /**
804      * DOM Internal
805      * (Was a DOM L3 Core WD public interface method setXMLEncoding )
806      *
807      * An attribute specifying, as part of the XML declaration,
808      * the encoding of this document. This is null when unspecified.
809      */

810     public void setXmlEncoding(String JavaDoc value) {
811         encoding = value;
812     }
813     
814     /**
815      * @deprecated This method is internal and only exists for
816      * compatibility with older applications. New applications
817      * should never call this method.
818      */

819     public void setEncoding(String JavaDoc value) {
820         setXmlEncoding(value);
821     }
822
823     /**
824      * DOM Level 3 WD - Experimental.
825      * The encoding of this document (part of XML Declaration)
826      */

827     public String JavaDoc getXmlEncoding() {
828         return encoding;
829     }
830     
831     /**
832      * @deprecated This method is internal and only exists for
833      * compatibility with older applications. New applications
834      * should never call this method.
835      */

836     public String JavaDoc getEncoding() {
837         return getXmlEncoding();
838     }
839
840     /**
841      * DOM Level 3 CR - Experimental.
842      * version - An attribute specifying, as part of the XML declaration,
843      * the version number of this document.
844      */

845     public void setXmlVersion(String JavaDoc value) {
846         if(value.equals("1.0") || value.equals("1.1")){
847             //we need to change the flag value only --
848
// when the version set is different than already set.
849
if(!getXmlVersion().equals(value)){
850                 xmlVersionChanged = true ;
851                 //change the normalization value back to false
852
isNormalized(false);
853                 version = value;
854             }
855         }
856         else{
857             //NOT_SUPPORTED_ERR: Raised if the vesion is set to a value that is not supported by
858
//this document
859
//we dont support any other XML version
860
String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
861             throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
862
863         }
864         if((getXmlVersion()).equals("1.1")){
865             xml11Version = true;
866         }
867         else{
868             xml11Version = false;
869         }
870     }
871     
872     /**
873      * @deprecated This method is internal and only exists for
874      * compatibility with older applications. New applications
875      * should never call this method.
876      */

877     public void setVersion(String JavaDoc value) {
878         setXmlVersion(value);
879     }
880
881     /**
882      * DOM Level 3 WD - Experimental.
883      * The version of this document (part of XML Declaration)
884      */

885     public String JavaDoc getXmlVersion() {
886         return (version == null)?"1.0":version;
887     }
888     
889     /**
890      * @deprecated This method is internal and only exists for
891      * compatibility with older applications. New applications
892      * should never call this method.
893      */

894     public String JavaDoc getVersion() {
895         return getXmlVersion();
896     }
897
898     /**
899      * DOM Level 3 CR - Experimental.
900      *
901      * Xmlstandalone - An attribute specifying, as part of the XML declaration,
902      * whether this document is standalone
903      * @exception DOMException
904      * NOT_SUPPORTED_ERR: Raised if this document does not support the
905      * "XML" feature.
906      * @since DOM Level 3
907      */

908     public void setXmlStandalone(boolean value)
909                                   throws DOMException JavaDoc {
910             standalone = value;
911     }
912     
913     /**
914      * @deprecated This method is internal and only exists for
915      * compatibility with older applications. New applications
916      * should never call this method.
917      */

918     public void setStandalone(boolean value) {
919         setXmlStandalone(value);
920     }
921
922     /**
923      * DOM Level 3 WD - Experimental.
924      * standalone that specifies whether this document is standalone
925      * (part of XML Declaration)
926      */

927     public boolean getXmlStandalone() {
928         return standalone;
929     }
930     
931     /**
932      * @deprecated This method is internal and only exists for
933      * compatibility with older applications. New applications
934      * should never call this method.
935      */

936     public boolean getStandalone() {
937         return getXmlStandalone();
938     }
939
940     /**
941      * DOM Level 3 WD - Experimental.
942      * The location of the document or <code>null</code> if undefined.
943      * <br>Beware that when the <code>Document</code> supports the feature
944      * "HTML" , the href attribute of the HTML BASE element takes precedence
945      * over this attribute.
946      * @since DOM Level 3
947      */

948     public String JavaDoc getDocumentURI(){
949         return fDocumentURI;
950     }
951
952
953     /**
954      * DOM Level 3 WD - Experimental.
955      * Renaming node
956      */

957     public Node JavaDoc renameNode(Node JavaDoc n,String JavaDoc namespaceURI,String JavaDoc name)
958     throws DOMException JavaDoc{
959         
960         if (errorChecking && n.getOwnerDocument() != this && n != this) {
961             String JavaDoc msg = DOMMessageFormatter.formatMessage(
962                     DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
963             throw new DOMException JavaDoc(DOMException.WRONG_DOCUMENT_ERR, msg);
964         }
965         switch (n.getNodeType()) {
966             case ELEMENT_NODE: {
967                 ElementImpl el = (ElementImpl) n;
968                 if (el instanceof ElementNSImpl) {
969                     ((ElementNSImpl) el).rename(namespaceURI, name);
970                     
971                     // fire user data NODE_RENAMED event
972
callUserDataHandlers(el, null, UserDataHandler.NODE_RENAMED);
973                 }
974                 else {
975                     if (namespaceURI == null) {
976                         if (errorChecking) {
977                             int colon1 = name.indexOf(':');
978                             if(colon1 != -1){
979                                 String JavaDoc msg =
980                                     DOMMessageFormatter.formatMessage(
981                                             DOMMessageFormatter.DOM_DOMAIN,
982                                             "NAMESPACE_ERR",
983                                             null);
984                                 throw new DOMException JavaDoc(DOMException.NAMESPACE_ERR, msg);
985                             }
986                             if (!isXMLName(name,xml11Version)) {
987                                 String JavaDoc msg = DOMMessageFormatter.formatMessage(
988                                         DOMMessageFormatter.DOM_DOMAIN,
989                                         "INVALID_CHARACTER_ERR", null);
990                                 throw new DOMException JavaDoc(DOMException.INVALID_CHARACTER_ERR,
991                                         msg);
992                             }
993                         }
994                         el.rename(name);
995                         
996                         // fire user data NODE_RENAMED event
997
callUserDataHandlers(el, null,
998                                 UserDataHandler.NODE_RENAMED);
999                     }
1000                    else {
1001                        // we need to create a new object
1002
ElementNSImpl nel =
1003                            new ElementNSImpl(this, namespaceURI, name);
1004                        
1005                        // register event listeners on new node
1006
copyEventListeners(el, nel);
1007                        
1008                        // remove user data from old node
1009
Hashtable JavaDoc data = removeUserDataTable(el);
1010                        
1011                        // remove old node from parent if any
1012
Node JavaDoc parent = el.getParentNode();
1013                        Node JavaDoc nextSib = el.getNextSibling();
1014                        if (parent != null) {
1015                            parent.removeChild(el);
1016                        }
1017                        // move children to new node
1018
Node JavaDoc child = el.getFirstChild();
1019                        while (child != null) {
1020                            el.removeChild(child);
1021                            nel.appendChild(child);
1022                            child = el.getFirstChild();
1023                        }
1024                        // move specified attributes to new node
1025
nel.moveSpecifiedAttributes(el);
1026                        
1027                        // attach user data to new node
1028
setUserDataTable(nel, data);
1029                        
1030                        // and fire user data NODE_RENAMED event
1031
callUserDataHandlers(el, nel,
1032                                UserDataHandler.NODE_RENAMED);
1033                        
1034                        // insert new node where old one was
1035
if (parent != null) {
1036                            parent.insertBefore(nel, nextSib);
1037                        }
1038                        el = nel;
1039                    }
1040                }
1041                // fire ElementNameChanged event
1042
renamedElement((Element JavaDoc) n, el);
1043                return el;
1044            }
1045            case ATTRIBUTE_NODE: {
1046                AttrImpl at = (AttrImpl) n;
1047                
1048                // dettach attr from element
1049
Element JavaDoc el = at.getOwnerElement();
1050                if (el != null) {
1051                    el.removeAttributeNode(at);
1052                }
1053                if (n instanceof AttrNSImpl) {
1054                    ((AttrNSImpl) at).rename(namespaceURI, name);
1055                    // reattach attr to element
1056
if (el != null) {
1057                        el.setAttributeNodeNS(at);
1058                    }
1059                    
1060                    // fire user data NODE_RENAMED event
1061
callUserDataHandlers(at, null, UserDataHandler.NODE_RENAMED);
1062                }
1063                else {
1064                    if (namespaceURI == null) {
1065                        at.rename(name);
1066                        // reattach attr to element
1067
if (el != null) {
1068                            el.setAttributeNode(at);
1069                        }
1070                        
1071                        // fire user data NODE_RENAMED event
1072
callUserDataHandlers(at, null, UserDataHandler.NODE_RENAMED);
1073                    }
1074                    else {
1075                        // we need to create a new object
1076
AttrNSImpl nat = new AttrNSImpl(this, namespaceURI, name);
1077                        
1078                        // register event listeners on new node
1079
copyEventListeners(at, nat);
1080                        
1081                        // remove user data from old node
1082
Hashtable JavaDoc data = removeUserDataTable(at);
1083                        
1084                        // move children to new node
1085
Node JavaDoc child = at.getFirstChild();
1086                        while (child != null) {
1087                            at.removeChild(child);
1088                            nat.appendChild(child);
1089                            child = at.getFirstChild();
1090                        }
1091                        
1092                        // attach user data to new node
1093
setUserDataTable(nat, data);
1094                        
1095                        // and fire user data NODE_RENAMED event
1096
callUserDataHandlers(at, nat, UserDataHandler.NODE_RENAMED);
1097                        
1098                        // reattach attr to element
1099
if (el != null) {
1100                            el.setAttributeNode(nat);
1101                        }
1102                        at = nat;
1103                    }
1104                }
1105                // fire AttributeNameChanged event
1106
renamedAttrNode((Attr JavaDoc) n, at);
1107                
1108                return at;
1109            }
1110            default: {
1111                String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
1112                throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
1113            }
1114        }
1115        
1116    }
1117
1118
1119    /**
1120     * DOM Level 3 WD - Experimental
1121     * Normalize document.
1122     */

1123    public void normalizeDocument(){
1124        // No need to normalize if already normalized.
1125
if (isNormalized() && !isNormalizeDocRequired()) {
1126            return;
1127        }
1128        if (needsSyncChildren()) {
1129            synchronizeChildren();
1130        }
1131
1132        if (domNormalizer == null) {
1133            domNormalizer = new DOMNormalizer();
1134        }
1135
1136        if (fConfiguration == null) {
1137            fConfiguration = new DOMConfigurationImpl();
1138        }
1139        else {
1140            fConfiguration.reset();
1141        }
1142
1143        domNormalizer.normalizeDocument(this, fConfiguration);
1144        isNormalized(true);
1145        //set the XMLversion changed value to false -- once we have finished
1146
//doing normalization
1147
xmlVersionChanged = false ;
1148    }
1149
1150
1151    /**
1152     * DOM Level 3 CR - Experimental
1153     *
1154     * The configuration used when <code>Document.normalizeDocument</code> is
1155     * invoked.
1156     * @since DOM Level 3
1157     */

1158    public DOMConfiguration JavaDoc getDomConfig(){
1159        if (fConfiguration == null) {
1160            fConfiguration = new DOMConfigurationImpl();
1161        }
1162        return fConfiguration;
1163    }
1164
1165
1166    /**
1167     * Returns the absolute base URI of this node or null if the implementation
1168     * wasn't able to obtain an absolute URI. Note: If the URI is malformed, a
1169     * null is returned.
1170     *
1171     * @return The absolute base URI of this node or null.
1172     * @since DOM Level 3
1173     */

1174    public String JavaDoc getBaseURI() {
1175        if (fDocumentURI != null && fDocumentURI.length() != 0 ) {// attribute value is always empty string
1176
try {
1177                return new URI(fDocumentURI).toString();
1178            }
1179            catch (org.apache.xerces.util.URI.MalformedURIException e){
1180                // REVISIT: what should happen in this case?
1181
return null;
1182            }
1183        }
1184        return fDocumentURI;
1185    }
1186
1187    /**
1188     * DOM Level 3 WD - Experimental.
1189     */

1190    public void setDocumentURI(String JavaDoc documentURI){
1191        fDocumentURI = documentURI;
1192    }
1193
1194
1195    //
1196
// DOM L3 LS
1197
//
1198
/**
1199     * DOM Level 3 WD - Experimental.
1200     * Indicates whether the method load should be synchronous or
1201     * asynchronous. When the async attribute is set to <code>true</code>
1202     * the load method returns control to the caller before the document has
1203     * completed loading. The default value of this property is
1204     * <code>false</code>.
1205     * <br>Setting the value of this attribute might throw NOT_SUPPORTED_ERR
1206     * if the implementation doesn't support the mode the attribute is being
1207     * set to. Should the DOM spec define the default value of this
1208     * property? What if implementing both async and sync IO is impractical
1209     * in some systems? 2001-09-14. default is <code>false</code> but we
1210     * need to check with Mozilla and IE.
1211     */

1212    public boolean getAsync() {
1213        return false;
1214    }
1215
1216    /**
1217     * DOM Level 3 WD - Experimental.
1218     * Indicates whether the method load should be synchronous or
1219     * asynchronous. When the async attribute is set to <code>true</code>
1220     * the load method returns control to the caller before the document has
1221     * completed loading. The default value of this property is
1222     * <code>false</code>.
1223     * <br>Setting the value of this attribute might throw NOT_SUPPORTED_ERR
1224     * if the implementation doesn't support the mode the attribute is being
1225     * set to. Should the DOM spec define the default value of this
1226     * property? What if implementing both async and sync IO is impractical
1227     * in some systems? 2001-09-14. default is <code>false</code> but we
1228     * need to check with Mozilla and IE.
1229     */

1230    public void setAsync(boolean async) {
1231        if (async) {
1232            String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
1233            throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
1234        }
1235    }
1236    /**
1237     * DOM Level 3 WD - Experimental.
1238     * If the document is currently being loaded as a result of the method
1239     * <code>load</code> being invoked the loading and parsing is
1240     * immediately aborted. The possibly partial result of parsing the
1241     * document is discarded and the document is cleared.
1242     */

1243    public void abort() {
1244    }
1245
1246    /**
1247     * DOM Level 3 WD - Experimental.
1248     *
1249     * Replaces the content of the document with the result of parsing the
1250     * given URI. Invoking this method will either block the caller or
1251     * return to the caller immediately depending on the value of the async
1252     * attribute. Once the document is fully loaded a "load" event (as
1253     * defined in [<a HREF='http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331'>DOM Level 3 Events</a>]
1254     * , except that the <code>Event.targetNode</code> will be the document,
1255     * not an element) will be dispatched on the document. If an error
1256     * occurs, an implementation dependent "error" event will be dispatched
1257     * on the document. If this method is called on a document that is
1258     * currently loading, the current load is interrupted and the new URI
1259     * load is initiated.
1260     * <br> When invoking this method the parameters used in the
1261     * <code>DOMParser</code> interface are assumed to have their default
1262     * values with the exception that the parameters <code>"entities"</code>
1263     * , <code>"normalize-characters"</code>,
1264     * <code>"check-character-normalization"</code> are set to
1265     * <code>"false"</code>.
1266     * <br> The result of a call to this method is the same the result of a
1267     * call to <code>DOMParser.parseWithContext</code> with an input stream
1268     * referencing the URI that was passed to this call, the document as the
1269     * context node, and the action <code>ACTION_REPLACE_CHILDREN</code>.
1270     * @param uri The URI reference for the XML file to be loaded. If this is
1271     * a relative URI, the base URI used by the implementation is
1272     * implementation dependent.
1273     * @return If async is set to <code>true</code> <code>load</code> returns
1274     * <code>true</code> if the document load was successfully initiated.
1275     * If an error occurred when initiating the document load,
1276     * <code>load</code> returns <code>false</code>.If async is set to
1277     * <code>false</code> <code>load</code> returns <code>true</code> if
1278     * the document was successfully loaded and parsed. If an error
1279     * occurred when either loading or parsing the URI, <code>load</code>
1280     * returns <code>false</code>.
1281     */

1282    public boolean load(String JavaDoc uri) {
1283        return false;
1284    }
1285
1286    /**
1287     * DOM Level 3 WD - Experimental.
1288     * Replace the content of the document with the result of parsing the
1289     * input string, this method is always synchronous.
1290     * @param source A string containing an XML document.
1291     * @return <code>true</code> if parsing the input string succeeded
1292     * without errors, otherwise <code>false</code>.
1293     */

1294    public boolean loadXML(String JavaDoc source) {
1295        return false;
1296    }
1297
1298    /**
1299     * DOM Level 3 WD - Experimental.
1300     * Save the document or the given node and all its descendants to a string
1301     * (i.e. serialize the document or node).
1302     * <br>The parameters used in the <code>LSSerializer</code> interface are
1303     * assumed to have their default values when invoking this method.
1304     * <br> The result of a call to this method is the same the result of a
1305     * call to <code>LSSerializer.writeToString</code> with the document as
1306     * the node to write.
1307     * @param node Specifies what to serialize, if this parameter is
1308     * <code>null</code> the whole document is serialized, if it's
1309     * non-null the given node is serialized.
1310     * @return The serialized document or <code>null</code> in case an error
1311     * occurred.
1312     * @exception DOMException
1313     * WRONG_DOCUMENT_ERR: Raised if the node passed in as the node
1314     * parameter is from an other document.
1315     */

1316    public String JavaDoc saveXML(Node JavaDoc node)
1317    throws DOMException JavaDoc {
1318        if ( errorChecking && node != null &&
1319            this != node.getOwnerDocument() ) {
1320            String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
1321            throw new DOMException JavaDoc(DOMException.WRONG_DOCUMENT_ERR, msg);
1322        }
1323        DOMImplementationLS JavaDoc domImplLS = (DOMImplementationLS JavaDoc)DOMImplementationImpl.getDOMImplementation();
1324        LSSerializer JavaDoc xmlWriter = domImplLS.createLSSerializer();
1325        if (node == null) {
1326            node = this;
1327        }
1328        return xmlWriter.writeToString(node);
1329    }
1330
1331    /**
1332     * Sets whether the DOM implementation generates mutation events
1333     * upon operations.
1334     */

1335    void setMutationEvents(boolean set) {
1336        // does nothing by default - overidden in subclass
1337
}
1338
1339    /**
1340     * Returns true if the DOM implementation generates mutation events.
1341     */

1342    boolean getMutationEvents() {
1343        // does nothing by default - overriden in subclass
1344
return false;
1345    }
1346
1347
1348
1349    // non-DOM factory methods
1350

1351    /**
1352     * NON-DOM
1353     * Factory method; creates a DocumentType having this Document
1354     * as its OwnerDoc. (REC-DOM-Level-1-19981001 left the process of building
1355     * DTD information unspecified.)
1356     *
1357     * @param name The name of the Entity we wish to provide a value for.
1358     *
1359     * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
1360     * DTDs are not permitted. (HTML not yet implemented.)
1361     */

1362    public DocumentType JavaDoc createDocumentType(String JavaDoc qualifiedName,
1363    String JavaDoc publicID,
1364    String JavaDoc systemID)
1365    throws DOMException JavaDoc {
1366
1367        return new DocumentTypeImpl(this, qualifiedName, publicID, systemID);
1368
1369    } // createDocumentType(String):DocumentType
1370

1371    /**
1372     * NON-DOM
1373     * Factory method; creates an Entity having this Document
1374     * as its OwnerDoc. (REC-DOM-Level-1-19981001 left the process of building
1375     * DTD information unspecified.)
1376     *
1377     * @param name The name of the Entity we wish to provide a value for.
1378     *
1379     * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
1380     * nonstandard entities are not permitted. (HTML not yet
1381     * implemented.)
1382     */

1383    public Entity JavaDoc createEntity(String JavaDoc name)
1384    throws DOMException JavaDoc {
1385
1386
1387        if (errorChecking && !isXMLName(name,xml11Version)) {
1388            String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
1389            throw new DOMException JavaDoc(DOMException.INVALID_CHARACTER_ERR, msg);
1390        }
1391        return new EntityImpl(this, name);
1392
1393    } // createEntity(String):Entity
1394

1395    /**
1396     * NON-DOM
1397     * Factory method; creates a Notation having this Document
1398     * as its OwnerDoc. (REC-DOM-Level-1-19981001 left the process of building
1399     * DTD information unspecified.)
1400     *
1401     * @param name The name of the Notation we wish to describe
1402     *
1403     * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
1404     * notations are not permitted. (HTML not yet
1405     * implemented.)
1406     */

1407    public Notation JavaDoc createNotation(String JavaDoc name)
1408    throws DOMException JavaDoc {
1409
1410        if (errorChecking && !isXMLName(name,xml11Version)) {
1411            String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
1412            throw new DOMException JavaDoc(DOMException.INVALID_CHARACTER_ERR, msg);
1413        }
1414        return new NotationImpl(this, name);
1415
1416    } // createNotation(String):Notation
1417

1418    /**
1419     * NON-DOM Factory method: creates an element definition. Element
1420     * definitions hold default attribute values.
1421     */

1422    public ElementDefinitionImpl createElementDefinition(String JavaDoc name)
1423    throws DOMException JavaDoc {
1424
1425        if (errorChecking && !isXMLName(name,xml11Version)) {
1426            String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
1427            throw new DOMException JavaDoc(DOMException.INVALID_CHARACTER_ERR, msg);
1428        }
1429        return new ElementDefinitionImpl(this, name);
1430
1431    } // createElementDefinition(String):ElementDefinitionImpl
1432

1433    // other non-DOM methods
1434

1435    /** NON-DOM: Get the number associated with this document. Used to
1436     * order documents in the implementation.
1437     */

1438    protected int getNodeNumber() {
1439        if (documentNumber==0) {
1440
1441            CoreDOMImplementationImpl cd = (CoreDOMImplementationImpl)CoreDOMImplementationImpl.getDOMImplementation();
1442            documentNumber = cd.assignDocumentNumber();
1443        }
1444        return documentNumber;
1445    }
1446
1447
1448    /** NON-DOM: Get a number associated with a node created with respect
1449     * to this document. Needed for compareDocumentPosition when nodes
1450     * are disconnected. This is only used on demand.
1451     */

1452    protected int getNodeNumber(Node JavaDoc node) {
1453
1454        // Check if the node is already in the hash
1455
// If so, retrieve the node number
1456
// If not, assign a number to the node
1457
// Node numbers are negative, from -1 to -n
1458
int num;
1459        if (nodeTable == null) {
1460            nodeTable = new Hashtable JavaDoc();
1461            num = --nodeCounter;
1462            nodeTable.put(node, new Integer JavaDoc(num));
1463        }
1464        else {
1465            Integer JavaDoc n = (Integer JavaDoc)nodeTable.get(node);
1466            if (n== null) {
1467                num = --nodeCounter;
1468                nodeTable.put(node, new Integer JavaDoc(num));
1469            }
1470            else
1471                num = n.intValue();
1472        }
1473        return num;
1474    }
1475
1476    /**
1477     * Copies a node from another document to this document. The new nodes are
1478     * created using this document's factory methods and are populated with the
1479     * data from the source's accessor methods defined by the DOM interfaces.
1480     * Its behavior is otherwise similar to that of cloneNode.
1481     * <p>
1482     * According to the DOM specifications, document nodes cannot be imported
1483     * and a NOT_SUPPORTED_ERR exception is thrown if attempted.
1484     */

1485    public Node JavaDoc importNode(Node JavaDoc source, boolean deep)
1486    throws DOMException JavaDoc {
1487        return importNode(source, deep, false, null);
1488    } // importNode(Node,boolean):Node
1489

1490    /**
1491     * Overloaded implementation of DOM's importNode method. This method
1492     * provides the core functionality for the public importNode and cloneNode
1493     * methods.
1494     *
1495     * The reversedIdentifiers parameter is provided for cloneNode to
1496     * preserve the document's identifiers. The Hashtable has Elements as the
1497     * keys and their identifiers as the values. When an element is being
1498     * imported, a check is done for an associated identifier. If one exists,
1499     * the identifier is registered with the new, imported element. If
1500     * reversedIdentifiers is null, the parameter is not applied.
1501     */

1502    private Node JavaDoc importNode(Node JavaDoc source, boolean deep, boolean cloningDoc,
1503    Hashtable JavaDoc reversedIdentifiers)
1504    throws DOMException JavaDoc {
1505        Node JavaDoc newnode=null;
1506        Hashtable JavaDoc userData = null;
1507
1508        // Sigh. This doesn't work; too many nodes have private data that
1509
// would have to be manually tweaked. May be able to add local
1510
// shortcuts to each nodetype. Consider ?????
1511
// if(source instanceof NodeImpl &&
1512
// !(source instanceof DocumentImpl))
1513
// {
1514
// // Can't clone DocumentImpl since it invokes us...
1515
// newnode=(NodeImpl)source.cloneNode(false);
1516
// newnode.ownerDocument=this;
1517
// }
1518
// else
1519
if(source instanceof NodeImpl)
1520            userData = ((NodeImpl)source).getUserDataRecord();
1521        int type = source.getNodeType();
1522        switch (type) {
1523            case ELEMENT_NODE: {
1524                Element JavaDoc newElement;
1525                boolean domLevel20 = source.getOwnerDocument().getImplementation().hasFeature("XML", "2.0");
1526                // Create element according to namespace support/qualification.
1527
if(domLevel20 == false || source.getLocalName() == null)
1528                    newElement = createElement(source.getNodeName());
1529                else
1530                    newElement = createElementNS(source.getNamespaceURI(),
1531                    source.getNodeName());
1532
1533                // Copy element's attributes, if any.
1534
NamedNodeMap JavaDoc sourceAttrs = source.getAttributes();
1535                if (sourceAttrs != null) {
1536                    int length = sourceAttrs.getLength();
1537                    for (int index = 0; index < length; index++) {
1538                        Attr JavaDoc attr = (Attr JavaDoc)sourceAttrs.item(index);
1539
1540                        // NOTE: this methods is used for both importingNode
1541
// and cloning the document node. In case of the
1542
// clonning default attributes should be copied.
1543
// But for importNode defaults should be ignored.
1544
if (attr.getSpecified() || cloningDoc) {
1545                            Attr JavaDoc newAttr = (Attr JavaDoc)importNode(attr, true, cloningDoc,
1546                            reversedIdentifiers);
1547
1548                            // Attach attribute according to namespace
1549
// support/qualification.
1550
if (domLevel20 == false ||
1551                            attr.getLocalName() == null)
1552                                newElement.setAttributeNode(newAttr);
1553                            else
1554                                newElement.setAttributeNodeNS(newAttr);
1555                        }
1556                    }
1557                }
1558
1559                // Register element identifier.
1560
if (reversedIdentifiers != null) {
1561                    // Does element have an associated identifier?
1562
Object JavaDoc elementId = reversedIdentifiers.get(source);
1563                    if (elementId != null) {
1564                        if (identifiers == null)
1565                            identifiers = new Hashtable JavaDoc();
1566
1567                        identifiers.put(elementId, newElement);
1568                    }
1569                }
1570
1571                newnode = newElement;
1572                break;
1573            }
1574
1575            case ATTRIBUTE_NODE: {
1576
1577                if( source.getOwnerDocument().getImplementation().hasFeature("XML", "2.0") ){
1578                    if (source.getLocalName() == null) {
1579                        newnode = createAttribute(source.getNodeName());
1580                    } else {
1581                        newnode = createAttributeNS(source.getNamespaceURI(),
1582                        source.getNodeName());
1583                    }
1584                }
1585                else {
1586                    newnode = createAttribute(source.getNodeName());
1587                }
1588                // if source is an AttrImpl from this very same implementation
1589
// avoid creating the child nodes if possible
1590
if (source instanceof AttrImpl) {
1591                    AttrImpl attr = (AttrImpl) source;
1592                    if (attr.hasStringValue()) {
1593                        AttrImpl newattr = (AttrImpl) newnode;
1594                        newattr.setValue(attr.getValue());
1595                        deep = false;
1596                    }
1597                    else {
1598                        deep = true;
1599                    }
1600                }
1601                else {
1602                    // According to the DOM spec the kids carry the value.
1603
// However, there are non compliant implementations out
1604
// there that fail to do so. To avoid ending up with no
1605
// value at all, in this case we simply copy the text value
1606
// directly.
1607
if (source.getFirstChild() == null) {
1608                        newnode.setNodeValue(source.getNodeValue());
1609                        deep = false;
1610                    } else {
1611                        deep = true;
1612                    }
1613                }
1614                break;
1615            }
1616
1617            case TEXT_NODE: {
1618                newnode = createTextNode(source.getNodeValue());
1619                break;
1620            }
1621
1622            case CDATA_SECTION_NODE: {
1623                newnode = createCDATASection(source.getNodeValue());
1624                break;
1625            }
1626
1627            case ENTITY_REFERENCE_NODE: {
1628                newnode = createEntityReference(source.getNodeName());
1629                // the subtree is created according to this doc by the method
1630
// above, so avoid carrying over original subtree
1631
deep = false;
1632                break;
1633            }
1634
1635            case ENTITY_NODE: {
1636                Entity JavaDoc srcentity = (Entity JavaDoc)source;
1637                EntityImpl newentity =
1638                (EntityImpl)createEntity(source.getNodeName());
1639                newentity.setPublicId(srcentity.getPublicId());
1640                newentity.setSystemId(srcentity.getSystemId());
1641                newentity.setNotationName(srcentity.getNotationName());
1642                // Kids carry additional value,
1643
// allow deep import temporarily
1644
newentity.isReadOnly(false);
1645                newnode = newentity;
1646                break;
1647            }
1648
1649            case PROCESSING_INSTRUCTION_NODE: {
1650                newnode = createProcessingInstruction(source.getNodeName(),
1651                source.getNodeValue());
1652                break;
1653            }
1654
1655            case COMMENT_NODE: {
1656                newnode = createComment(source.getNodeValue());
1657                break;
1658            }
1659
1660            case DOCUMENT_TYPE_NODE: {
1661                // unless this is used as part of cloning a Document
1662
// forbid it for the sake of being compliant to the DOM spec
1663
if (!cloningDoc) {
1664                    String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
1665                    throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
1666                }
1667                DocumentType JavaDoc srcdoctype = (DocumentType JavaDoc)source;
1668                DocumentTypeImpl newdoctype = (DocumentTypeImpl)
1669                createDocumentType(srcdoctype.getNodeName(),
1670                srcdoctype.getPublicId(),
1671                srcdoctype.getSystemId());
1672                // Values are on NamedNodeMaps
1673
NamedNodeMap JavaDoc smap = srcdoctype.getEntities();
1674                NamedNodeMap JavaDoc tmap = newdoctype.getEntities();
1675                if(smap != null) {
1676                    for(int i = 0; i < smap.getLength(); i++) {
1677                        tmap.setNamedItem(importNode(smap.item(i), true, true,
1678                        reversedIdentifiers));
1679                    }
1680                }
1681                smap = srcdoctype.getNotations();
1682                tmap = newdoctype.getNotations();
1683                if (smap != null) {
1684                    for(int i = 0; i < smap.getLength(); i++) {
1685                        tmap.setNamedItem(importNode(smap.item(i), true, true,
1686                        reversedIdentifiers));
1687                    }
1688                }
1689
1690                // NOTE: At this time, the DOM definition of DocumentType
1691
// doesn't cover Elements and their Attributes. domimpl's
1692
// extentions in that area will not be preserved, even if
1693
// copying from domimpl to domimpl. We could special-case
1694
// that here. Arguably we should. Consider. ?????
1695
newnode = newdoctype;
1696                break;
1697            }
1698
1699            case DOCUMENT_FRAGMENT_NODE: {
1700                newnode = createDocumentFragment();
1701                // No name, kids carry value
1702
break;
1703            }
1704
1705            case NOTATION_NODE: {
1706                Notation JavaDoc srcnotation = (Notation JavaDoc)source;
1707                NotationImpl newnotation =
1708                (NotationImpl)createNotation(source.getNodeName());
1709                newnotation.setPublicId(srcnotation.getPublicId());
1710                newnotation.setSystemId(srcnotation.getSystemId());
1711                // Kids carry additional value
1712
newnode = newnotation;
1713                // No name, no value
1714
break;
1715            }
1716            case DOCUMENT_NODE : // Can't import document nodes
1717
default: { // Unknown node type
1718
String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
1719                throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
1720            }
1721        }
1722
1723        if(userData != null)
1724            callUserDataHandlers(source, newnode, UserDataHandler.NODE_IMPORTED,userData);
1725
1726        // If deep, replicate and attach the kids.
1727
if (deep) {
1728            for (Node JavaDoc srckid = source.getFirstChild();
1729            srckid != null;
1730            srckid = srckid.getNextSibling()) {
1731                newnode.appendChild(importNode(srckid, true, cloningDoc,
1732                reversedIdentifiers));
1733            }
1734        }
1735        if (newnode.getNodeType() == Node.ENTITY_NODE) {
1736            ((NodeImpl)newnode).setReadOnly(true, true);
1737        }
1738        return newnode;
1739
1740    } // importNode(Node,boolean,boolean,Hashtable):Node
1741

1742    /**
1743     * DOM Level 3 WD - Experimental
1744     * Change the node's ownerDocument, and its subtree, to this Document
1745     *
1746     * @param source The node to adopt.
1747     * @see #importNode
1748     **/

1749    public Node JavaDoc adoptNode(Node JavaDoc source) {
1750        NodeImpl node;
1751        Hashtable JavaDoc userData = null;
1752        try {
1753            node = (NodeImpl) source;
1754        } catch (ClassCastException JavaDoc e) {
1755            // source node comes from a different DOMImplementation
1756
return null;
1757        }
1758        
1759        // Return null if the source is null
1760

1761        if (source == null ) {
1762            return null;
1763        } else if (source != null && source.getOwnerDocument() != null) {
1764
1765            DOMImplementation JavaDoc thisImpl = this.getImplementation();
1766            DOMImplementation JavaDoc otherImpl = source.getOwnerDocument().getImplementation();
1767            
1768            // when the source node comes from a different implementation.
1769
if (thisImpl != otherImpl) {
1770            
1771                // Adopting from a DefferedDOM to DOM
1772
if (thisImpl instanceof org.apache.xerces.dom.DOMImplementationImpl &&
1773                        otherImpl instanceof org.apache.xerces.dom.DeferredDOMImplementationImpl) {
1774                    // traverse the DOM and expand deffered nodes and then allow adoption
1775
undeferChildren (node);
1776                } else if ( thisImpl instanceof org.apache.xerces.dom.DeferredDOMImplementationImpl
1777                        && otherImpl instanceof org.apache.xerces.dom.DOMImplementationImpl) {
1778                    // Adopting from a DOM into a DefferedDOM, this should be okay
1779
} else {
1780                    // Adopting between two dissimilar DOM's is not allowed
1781
return null;
1782                }
1783            }
1784        }
1785        
1786        switch (node.getNodeType()) {
1787            case ATTRIBUTE_NODE: {
1788                AttrImpl attr = (AttrImpl) node;
1789                // remove node from wherever it is
1790
if( attr.getOwnerElement() != null){
1791                    //1. owner element attribute is set to null
1792
attr.getOwnerElement().removeAttributeNode(attr);
1793                }
1794                //2. specified flag is set to true
1795
attr.isSpecified(true);
1796                userData = node.getUserDataRecord();
1797
1798                //3. change ownership
1799
attr.setOwnerDocument(this);
1800                if(userData != null )
1801                    setUserDataTable(node,userData);
1802                break;
1803            }
1804            //entity, notation nodes are read only nodes.. so they can't be adopted.
1805
//runtime will fall through to NOTATION_NODE
1806
case ENTITY_NODE:
1807            case NOTATION_NODE:{
1808                String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
1809                throw new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
1810
1811            }
1812            //document, documentype nodes can't be adopted.
1813
//runtime will fall through to DocumentTypeNode
1814
case DOCUMENT_NODE:
1815            case DOCUMENT_TYPE_NODE: {
1816                String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
1817                throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
1818            }
1819            case ENTITY_REFERENCE_NODE: {
1820                userData = node.getUserDataRecord();
1821                // remove node from wherever it is
1822
Node JavaDoc parent = node.getParentNode();
1823                if (parent != null) {
1824                    parent.removeChild(source);
1825                }
1826                // discard its replacement value
1827
Node JavaDoc child;
1828                while ((child = node.getFirstChild()) != null) {
1829                    node.removeChild(child);
1830                }
1831                // change ownership
1832
node.setOwnerDocument(this);
1833                if(userData != null)
1834                    setUserDataTable(node,userData);
1835                // set its new replacement value if any
1836
if (docType == null) {
1837                    break;
1838                }
1839                NamedNodeMap JavaDoc entities = docType.getEntities();
1840                Node JavaDoc entityNode = entities.getNamedItem(node.getNodeName());
1841                if (entityNode == null) {
1842                    break;
1843                }
1844                for (child = entityNode.getFirstChild();
1845                child != null; child = child.getNextSibling()) {
1846                    Node JavaDoc childClone = child.cloneNode(true);
1847                    node.appendChild(childClone);
1848                }
1849                break;
1850            }
1851            case ELEMENT_NODE: {
1852                userData = node.getUserDataRecord();
1853                // remove node from wherever it is
1854
Node JavaDoc parent = node.getParentNode();
1855                if (parent != null) {
1856                    parent.removeChild(source);
1857                }
1858                // change ownership
1859
node.setOwnerDocument(this);
1860                if(userData != null)
1861                    setUserDataTable(node,userData);
1862                // reconcile default attributes
1863
((ElementImpl)node).reconcileDefaultAttributes();
1864                break;
1865            }
1866            default: {
1867                userData = node.getUserDataRecord();
1868                // remove node from wherever it is
1869
Node JavaDoc parent = node.getParentNode();
1870                if (parent != null) {
1871                    parent.removeChild(source);
1872                }
1873                // change ownership
1874
node.setOwnerDocument(this);
1875                if(userData != null)
1876                    setUserDataTable(node,userData);
1877            }
1878        }
1879
1880        //DOM L3 Core CR
1881
//http://www.w3.org/TR/2003/CR-DOM-Level-3-Core-20031107/core.html#UserDataHandler-ADOPTED
1882
if(userData != null)
1883            callUserDataHandlers(source, null, UserDataHandler.NODE_ADOPTED,userData);
1884
1885        return node;
1886    }
1887
1888    /**
1889     * Traverses the DOM Tree and expands deferred nodes and their
1890     * children.
1891     *
1892     */

1893    protected void undeferChildren(Node JavaDoc node) {
1894        
1895        Node JavaDoc top = node;
1896        
1897        while (null != node) {
1898            
1899            if (((NodeImpl)node).needsSyncData()) {
1900                ((NodeImpl)node).synchronizeData();
1901            }
1902            
1903            Node JavaDoc nextNode = null;
1904            nextNode = node.getFirstChild();
1905            
1906            while (null == nextNode) {
1907                
1908                if (top.equals(node))
1909                    break;
1910                
1911                nextNode = node.getNextSibling();
1912                
1913                if (null == nextNode) {
1914                    node = node.getParentNode();
1915                    
1916                    if ((null == node) || (top.equals(node))) {
1917                        nextNode = null;
1918                        break;
1919                    }
1920                }
1921            }
1922            
1923            node = nextNode;
1924        }
1925    }
1926    
1927    // identifier maintenence
1928
/**
1929     * Introduced in DOM Level 2
1930     * Returns the Element whose ID is given by elementId. If no such element
1931     * exists, returns null. Behavior is not defined if more than one element
1932     * has this ID.
1933     * <p>
1934     * Note: The DOM implementation must have information that says which
1935     * attributes are of type ID. Attributes with the name "ID" are not of type
1936     * ID unless so defined. Implementations that do not know whether
1937     * attributes are of type ID or not are expected to return null.
1938     * @see #getIdentifier
1939     */

1940    public Element JavaDoc getElementById(String JavaDoc elementId) {
1941        return getIdentifier(elementId);
1942    }
1943
1944    /**
1945     * Remove all identifiers from the ID table
1946     */

1947    protected final void clearIdentifiers(){
1948        if (identifiers != null){
1949            identifiers.clear();
1950        }
1951    }
1952
1953    /**
1954     * Registers an identifier name with a specified element node.
1955     * If the identifier is already registered, the new element
1956     * node replaces the previous node. If the specified element
1957     * node is null, removeIdentifier() is called.
1958     *
1959     * @see #getIdentifier
1960     * @see #removeIdentifier
1961     */

1962    public void putIdentifier(String JavaDoc idName, Element JavaDoc element) {
1963
1964        if (element == null) {
1965            removeIdentifier(idName);
1966            return;
1967        }
1968
1969        if (needsSyncData()) {
1970            synchronizeData();
1971        }
1972
1973        if (identifiers == null) {
1974            identifiers = new Hashtable JavaDoc();
1975        }
1976
1977        identifiers.put(idName, element);
1978
1979    } // putIdentifier(String,Element)
1980

1981    /**
1982     * Returns a previously registered element with the specified
1983     * identifier name, or null if no element is registered.
1984     *
1985     * @see #putIdentifier
1986     * @see #removeIdentifier
1987     */

1988    public Element JavaDoc getIdentifier(String JavaDoc idName) {
1989
1990        if (needsSyncData()) {
1991            synchronizeData();
1992        }
1993
1994        if (identifiers == null) {
1995            return null;
1996        }
1997        Element JavaDoc elem = (Element JavaDoc) identifiers.get(idName);
1998        if (elem != null) {
1999            // check that the element is in the tree
2000
Node JavaDoc parent = elem.getParentNode();
2001            while (parent != null) {
2002                if (parent == this) {
2003                    return elem;
2004                }
2005                parent = parent.getParentNode();
2006            }
2007        }
2008        return null;
2009    } // getIdentifier(String):Element
2010

2011    /**
2012     * Removes a previously registered element with the specified
2013     * identifier name.
2014     *
2015     * @see #putIdentifier
2016     * @see #getIdentifier
2017     */

2018    public void removeIdentifier(String JavaDoc idName) {
2019
2020        if (needsSyncData()) {
2021            synchronizeData();
2022        }
2023
2024        if (identifiers == null) {
2025            return;
2026        }
2027
2028        identifiers.remove(idName);
2029
2030    } // removeIdentifier(String)
2031

2032    /** Returns an enumeration registered of identifier names. */
2033    public Enumeration JavaDoc getIdentifiers() {
2034
2035        if (needsSyncData()) {
2036            synchronizeData();
2037        }
2038
2039        if (identifiers == null) {
2040            identifiers = new Hashtable JavaDoc();
2041        }
2042
2043        return identifiers.keys();
2044
2045    } // getIdentifiers():Enumeration
2046

2047    //
2048
// DOM2: Namespace methods
2049
//
2050

2051    /**
2052     * Introduced in DOM Level 2. <p>
2053     * Creates an element of the given qualified name and namespace URI.
2054     * If the given namespaceURI is null or an empty string and the
2055     * qualifiedName has a prefix that is "xml", the created element
2056     * is bound to the predefined namespace
2057     * "http://www.w3.org/XML/1998/namespace" [Namespaces].
2058     * @param namespaceURI The namespace URI of the element to
2059     * create.
2060     * @param qualifiedName The qualified name of the element type to
2061     * instantiate.
2062     * @return Element A new Element object with the following attributes:
2063     * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified
2064     * name contains an invalid character.
2065     * @throws DOMException NAMESPACE_ERR: Raised if the qualifiedName has a
2066     * prefix that is "xml" and the namespaceURI is
2067     * neither null nor an empty string nor
2068     * "http://www.w3.org/XML/1998/namespace", or
2069     * if the qualifiedName has a prefix different
2070     * from "xml" and the namespaceURI is null or an
2071     * empty string.
2072     * @since WD-DOM-Level-2-19990923
2073     */

2074    public Element JavaDoc createElementNS(String JavaDoc namespaceURI, String JavaDoc qualifiedName)
2075    throws DOMException JavaDoc {
2076        return new ElementNSImpl(this, namespaceURI, qualifiedName);
2077    }
2078
2079    /**
2080     * NON-DOM: a factory method used by the Xerces DOM parser
2081     * to create an element.
2082     *
2083     * @param namespaceURI The namespace URI of the element to
2084     * create.
2085     * @param qualifiedName The qualified name of the element type to
2086     * instantiate.
2087     * @param localpart The local name of the attribute to instantiate.
2088     *
2089     * @return Element A new Element object with the following attributes:
2090     * @exception DOMException INVALID_CHARACTER_ERR: Raised if the specified
2091     * name contains an invalid character.
2092     */

2093    public Element JavaDoc createElementNS(String JavaDoc namespaceURI, String JavaDoc qualifiedName,
2094    String JavaDoc localpart)
2095    throws DOMException JavaDoc {
2096        return new ElementNSImpl(this, namespaceURI, qualifiedName, localpart);
2097    }
2098
2099    /**
2100     * Introduced in DOM Level 2. <p>
2101     * Creates an attribute of the given qualified name and namespace URI.
2102     * If the given namespaceURI is null or an empty string and the
2103     * qualifiedName has a prefix that is "xml", the created element
2104     * is bound to the predefined namespace
2105     * "http://www.w3.org/XML/1998/namespace" [Namespaces].
2106     *
2107     * @param namespaceURI The namespace URI of the attribute to
2108     * create. When it is null or an empty string,
2109     * this method behaves like createAttribute.
2110     * @param qualifiedName The qualified name of the attribute to
2111     * instantiate.
2112     * @return Attr A new Attr object.
2113     * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified
2114     * name contains an invalid character.
2115     * @since WD-DOM-Level-2-19990923
2116     */

2117    public Attr JavaDoc createAttributeNS(String JavaDoc namespaceURI, String JavaDoc qualifiedName)
2118    throws DOMException JavaDoc {
2119        return new AttrNSImpl(this, namespaceURI, qualifiedName);
2120    }
2121
2122    /**
2123     * NON-DOM: a factory method used by the Xerces DOM parser
2124     * to create an element.
2125     *
2126     * @param namespaceURI The namespace URI of the attribute to
2127     * create. When it is null or an empty string,
2128     * this method behaves like createAttribute.
2129     * @param qualifiedName The qualified name of the attribute to
2130     * instantiate.
2131     * @param localpart The local name of the attribute to instantiate.
2132     *
2133     * @return Attr A new Attr object.
2134     * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified
2135     * name contains an invalid character.
2136     */

2137    public Attr JavaDoc createAttributeNS(String JavaDoc namespaceURI, String JavaDoc qualifiedName,
2138    String JavaDoc localpart)
2139    throws DOMException JavaDoc {
2140        return new AttrNSImpl(this, namespaceURI, qualifiedName, localpart);
2141    }
2142
2143    /**
2144     * Introduced in DOM Level 2. <p>
2145     * Returns a NodeList of all the Elements with a given local name and
2146     * namespace URI in the order in which they would be encountered in a
2147     * preorder traversal of the Document tree.
2148     * @param namespaceURI The namespace URI of the elements to match
2149     * on. The special value "*" matches all
2150     * namespaces. When it is null or an empty
2151     * string, this method behaves like
2152     * getElementsByTagName.
2153     * @param localName The local name of the elements to match on.
2154     * The special value "*" matches all local names.
2155     * @return NodeList A new NodeList object containing all the matched
2156     * Elements.
2157     * @since WD-DOM-Level-2-19990923
2158     */

2159    public NodeList JavaDoc getElementsByTagNameNS(String JavaDoc namespaceURI,
2160    String JavaDoc localName) {
2161        return new DeepNodeListImpl(this, namespaceURI, localName);
2162    }
2163
2164    //
2165
// Object methods
2166
//
2167

2168    /** Clone. */
2169    public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
2170        CoreDocumentImpl newdoc = (CoreDocumentImpl) super.clone();
2171        newdoc.docType = null;
2172        newdoc.docElement = null;
2173        return newdoc;
2174    }
2175
2176    //
2177
// Public static methods
2178
//
2179

2180    /**
2181     * Check the string against XML's definition of acceptable names for
2182     * elements and attributes and so on using the XMLCharacterProperties
2183     * utility class
2184     */

2185
2186    public static final boolean isXMLName(String JavaDoc s, boolean xml11Version) {
2187
2188        if (s == null) {
2189            return false;
2190        }
2191        if(!xml11Version)
2192            return XMLChar.isValidName(s);
2193        else
2194            return XML11Char.isXML11ValidName(s);
2195
2196    } // isXMLName(String):boolean
2197

2198    /**
2199     * Checks if the given qualified name is legal with respect
2200     * to the version of XML to which this document must conform.
2201     *
2202     * @param prefix prefix of qualified name
2203     * @param local local part of qualified name
2204     */

2205    public static final boolean isValidQName(String JavaDoc prefix, String JavaDoc local, boolean xml11Version) {
2206
2207        // check that both prefix and local part match NCName
2208
if (local == null) return false;
2209        boolean validNCName = false;
2210
2211        if (!xml11Version) {
2212            validNCName = (prefix == null || XMLChar.isValidNCName(prefix))
2213                && XMLChar.isValidNCName(local);
2214        }
2215        else {
2216            validNCName = (prefix == null || XML11Char.isXML11ValidNCName(prefix))
2217                && XML11Char.isXML11ValidNCName(local);
2218        }
2219
2220        return validNCName;
2221    }
2222    //
2223
// Protected methods
2224
//
2225

2226    /**
2227     * Uses the kidOK lookup table to check whether the proposed
2228     * tree structure is legal.
2229     */

2230    protected boolean isKidOK(Node JavaDoc parent, Node JavaDoc child) {
2231        if (allowGrammarAccess &&
2232        parent.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
2233            return child.getNodeType() == Node.ELEMENT_NODE;
2234        }
2235        return 0 != (kidOK[parent.getNodeType()] & 1 << child.getNodeType());
2236    }
2237
2238    /**
2239     * Denotes that this node has changed.
2240     */

2241    protected void changed() {
2242        changes++;
2243    }
2244
2245    /**
2246     * Returns the number of changes to this node.
2247     */

2248    protected int changes() {
2249        return changes;
2250    }
2251
2252    // NodeListCache pool
2253

2254    /**
2255     * Returns a NodeListCache for the given node.
2256     */

2257    NodeListCache getNodeListCache(ParentNode owner) {
2258        if (fFreeNLCache == null) {
2259            return new NodeListCache(owner);
2260        }
2261        NodeListCache c = fFreeNLCache;
2262        fFreeNLCache = fFreeNLCache.next;
2263        c.fChild = null;
2264        c.fChildIndex = -1;
2265        c.fLength = -1;
2266        // revoke previous ownership
2267
if (c.fOwner != null) {
2268            c.fOwner.fNodeListCache = null;
2269        }
2270        c.fOwner = owner;
2271        // c.next = null; not necessary, except for confused people...
2272
return c;
2273    }
2274
2275    /**
2276     * Puts the given NodeListCache in the free list.
2277     * Note: The owner node can keep using it until we reuse it
2278     */

2279    void freeNodeListCache(NodeListCache c) {
2280        c.next = fFreeNLCache;
2281        fFreeNLCache = c;
2282    }
2283
2284
2285
2286    /**
2287     * Associate an object to a key on this node. The object can later be
2288     * retrieved from this node by calling <code>getUserData</code> with the
2289     * same key.
2290     * @param n The node to associate the object to.
2291     * @param key The key to associate the object to.
2292     * @param data The object to associate to the given key, or
2293     * <code>null</code> to remove any existing association to that key.
2294     * @param handler The handler to associate to that key, or
2295     * <code>null</code>.
2296     * @return Returns the <code>DOMObject</code> previously associated to
2297     * the given key on this node, or <code>null</code> if there was none.
2298     * @since DOM Level 3
2299     *
2300     * REVISIT: we could use a free list of UserDataRecord here
2301     */

2302    public Object JavaDoc setUserData(Node JavaDoc n, String JavaDoc key,
2303    Object JavaDoc data, UserDataHandler JavaDoc handler) {
2304        if (data == null) {
2305            if (userData != null) {
2306                Hashtable JavaDoc t = (Hashtable JavaDoc) userData.get(n);
2307                if (t != null) {
2308                    Object JavaDoc o = t.remove(key);
2309                    if (o != null) {
2310                        UserDataRecord r = (UserDataRecord) o;
2311                        return r.fData;
2312                    }
2313                }
2314            }
2315            return null;
2316        }
2317        else {
2318            Hashtable JavaDoc t;
2319            if (userData == null) {
2320                userData = new Hashtable JavaDoc();
2321                t = new Hashtable JavaDoc();
2322                userData.put(n, t);
2323            }
2324            else {
2325                t = (Hashtable JavaDoc) userData.get(n);
2326                if (t == null) {
2327                    t = new Hashtable JavaDoc();
2328                    userData.put(n, t);
2329                }
2330            }
2331            Object JavaDoc o = t.put(key, new UserDataRecord(data, handler));
2332            if (o != null) {
2333                UserDataRecord r = (UserDataRecord) o;
2334                return r.fData;
2335            }
2336            return null;
2337        }
2338    }
2339    
2340
2341    /**
2342     * Retrieves the object associated to a key on a this node. The object
2343     * must first have been set to this node by calling
2344     * <code>setUserData</code> with the same key.
2345     * @param n The node the object is associated to.
2346     * @param key The key the object is associated to.
2347     * @return Returns the <code>DOMObject</code> associated to the given key
2348     * on this node, or <code>null</code> if there was none.
2349     * @since DOM Level 3
2350     */

2351    public Object JavaDoc getUserData(Node JavaDoc n, String JavaDoc key) {
2352        if (userData == null) {
2353            return null;
2354        }
2355        Hashtable JavaDoc t = (Hashtable JavaDoc) userData.get(n);
2356        if (t == null) {
2357            return null;
2358        }
2359        Object JavaDoc o = t.get(key);
2360        if (o != null) {
2361            UserDataRecord r = (UserDataRecord) o;
2362            return r.fData;
2363        }
2364        return null;
2365    }
2366
2367    protected Hashtable JavaDoc getUserDataRecord(Node JavaDoc n){
2368        if (userData == null) {
2369            return null;
2370        }
2371        Hashtable JavaDoc t = (Hashtable JavaDoc) userData.get(n);
2372        if (t == null) {
2373            return null;
2374        }
2375        return t;
2376    }
2377    
2378    /**
2379     * Remove user data table for the given node.
2380     * @param n The node this operation applies to.
2381     * @return The removed table.
2382     */

2383    Hashtable JavaDoc removeUserDataTable(Node JavaDoc n) {
2384        if (userData == null) {
2385            return null;
2386        }
2387        return (Hashtable JavaDoc) userData.get(n);
2388    }
2389
2390    /**
2391     * Set user data table for the given node.
2392     * @param n The node this operation applies to.
2393     * @param data The user data table.
2394     */

2395    void setUserDataTable(Node JavaDoc n, Hashtable JavaDoc data) {
2396        if (userData == null)
2397            userData = new Hashtable JavaDoc();
2398        if (data != null) {
2399            userData.put(n, data);
2400        }
2401    }
2402
2403    /**
2404     * Call user data handlers when a node is deleted (finalized)
2405     * @param n The node this operation applies to.
2406     * @param c The copy node or null.
2407     * @param operation The operation - import, clone, or delete.
2408     */

2409    void callUserDataHandlers(Node JavaDoc n, Node JavaDoc c, short operation) {
2410        if (userData == null) {
2411            return;
2412        }
2413        //Hashtable t = (Hashtable) userData.get(n);
2414
if(n instanceof NodeImpl){
2415            Hashtable JavaDoc t = ((NodeImpl)n).getUserDataRecord();
2416            if (t == null || t.isEmpty()) {
2417                return;
2418            }
2419            callUserDataHandlers(n, c, operation,t);
2420        }
2421    }
2422
2423    /**
2424     * Call user data handlers when a node is deleted (finalized)
2425     * @param n The node this operation applies to.
2426     * @param c The copy node or null.
2427     * @param operation The operation - import, clone, or delete.
2428     * @param handlers Data associated with n.
2429    */

2430    void callUserDataHandlers(Node JavaDoc n, Node JavaDoc c, short operation,Hashtable JavaDoc userData) {
2431        if (userData == null || userData.isEmpty()) {
2432            return;
2433        }
2434        Enumeration JavaDoc keys = userData.keys();
2435        while (keys.hasMoreElements()) {
2436            String JavaDoc key = (String JavaDoc) keys.nextElement();
2437            UserDataRecord r = (UserDataRecord) userData.get(key);
2438            if (r.fHandler != null) {
2439                r.fHandler.handle(operation, key, r.fData, n, c);
2440            }
2441        }
2442    }
2443    
2444    /**
2445     * Call user data handlers to let them know the nodes they are related to
2446     * are being deleted. The alternative would be to do that on Node but
2447     * because the nodes are used as the keys we have a reference to them that
2448     * prevents them from being gc'ed until the document is. At the same time,
2449     * doing it here has the advantage of avoiding a finalize() method on Node,
2450     * which would affect all nodes and not just the ones that have a user
2451     * data.
2452     */

2453    // Temporarily comment out this method, because
2454
// 1. It seems that finalizers are not guaranteed to be called, so the
2455
// functionality is not implemented.
2456
// 2. It affects the performance greatly in multi-thread environment.
2457
// -SG
2458
/*public void finalize() {
2459        if (userData == null) {
2460            return;
2461        }
2462        Enumeration nodes = userData.keys();
2463        while (nodes.hasMoreElements()) {
2464            Object node = nodes.nextElement();
2465            Hashtable t = (Hashtable) userData.get(node);
2466            if (t != null && !t.isEmpty()) {
2467                Enumeration keys = t.keys();
2468                while (keys.hasMoreElements()) {
2469                    String key = (String) keys.nextElement();
2470                    UserDataRecord r = (UserDataRecord) t.get(key);
2471                    if (r.fHandler != null) {
2472                        r.fHandler.handle(UserDataHandler.NODE_DELETED,
2473                                          key, r.fData, null, null);
2474                    }
2475                }
2476            }
2477        }
2478    }*/

2479
2480    protected final void checkNamespaceWF( String JavaDoc qname, int colon1,
2481    int colon2) {
2482
2483        if (!errorChecking) {
2484            return;
2485        }
2486        // it is an error for NCName to have more than one ':'
2487
// check if it is valid QName [Namespace in XML production 6]
2488
// :camera , nikon:camera:minolta, camera:
2489
if (colon1 == 0 || colon1 == qname.length() - 1 || colon2 != colon1) {
2490            String JavaDoc msg =
2491            DOMMessageFormatter.formatMessage(
2492            DOMMessageFormatter.DOM_DOMAIN,
2493            "NAMESPACE_ERR",
2494            null);
2495            throw new DOMException JavaDoc(DOMException.NAMESPACE_ERR, msg);
2496        }
2497    }
2498    protected final void checkDOMNSErr(String JavaDoc prefix,
2499    String JavaDoc namespace) {
2500        if (errorChecking) {
2501            if (namespace == null) {
2502                String JavaDoc msg =
2503                DOMMessageFormatter.formatMessage(
2504                DOMMessageFormatter.DOM_DOMAIN,
2505                "NAMESPACE_ERR",
2506                null);
2507                throw new DOMException JavaDoc(DOMException.NAMESPACE_ERR, msg);
2508            }
2509            else if (prefix.equals("xml")
2510            && !namespace.equals(NamespaceContext.XML_URI)) {
2511                String JavaDoc msg =
2512                DOMMessageFormatter.formatMessage(
2513                DOMMessageFormatter.DOM_DOMAIN,
2514                "NAMESPACE_ERR",
2515                null);
2516                throw new DOMException JavaDoc(DOMException.NAMESPACE_ERR, msg);
2517            }
2518            else if (
2519            prefix.equals("xmlns")
2520            && !namespace.equals(NamespaceContext.XMLNS_URI)
2521            || (!prefix.equals("xmlns")
2522            && namespace.equals(NamespaceContext.XMLNS_URI))) {
2523                String JavaDoc msg =
2524                DOMMessageFormatter.formatMessage(
2525                DOMMessageFormatter.DOM_DOMAIN,
2526                "NAMESPACE_ERR",
2527                null);
2528                throw new DOMException JavaDoc(DOMException.NAMESPACE_ERR, msg);
2529            }
2530        }
2531    }
2532
2533    /**
2534     * Checks if the given qualified name is legal with respect
2535     * to the version of XML to which this document must conform.
2536     *
2537     * @param prefix prefix of qualified name
2538     * @param local local part of qualified name
2539     */

2540    protected final void checkQName(String JavaDoc prefix, String JavaDoc local) {
2541        if (!errorChecking) {
2542            return;
2543        }
2544
2545        // check that both prefix and local part match NCName
2546
boolean validNCName = false;
2547        if (!xml11Version) {
2548            validNCName = (prefix == null || XMLChar.isValidNCName(prefix))
2549                && XMLChar.isValidNCName(local);
2550        }
2551        else {
2552            validNCName = (prefix == null || XML11Char.isXML11ValidNCName(prefix))
2553                && XML11Char.isXML11ValidNCName(local);
2554        }
2555
2556        if (!validNCName) {
2557            // REVISIT: add qname parameter to the message
2558
String JavaDoc msg =
2559            DOMMessageFormatter.formatMessage(
2560            DOMMessageFormatter.DOM_DOMAIN,
2561            "INVALID_CHARACTER_ERR",
2562            null);
2563            throw new DOMException JavaDoc(DOMException.INVALID_CHARACTER_ERR, msg);
2564        }
2565    }
2566
2567    /**
2568     * We could have more xml versions in future , but for now we could
2569     * do with this to handle XML 1.0 and 1.1
2570     */

2571    boolean isXML11Version(){
2572        return xml11Version;
2573    }
2574
2575    boolean isNormalizeDocRequired(){
2576        // REVISIT: Implement to optimize when normalization
2577
// is required
2578
return true;
2579    }
2580
2581    //we should be checking the (elements, attribute, entity etc.) names only when
2582
//version of the document is changed.
2583
boolean isXMLVersionChanged(){
2584        return xmlVersionChanged ;
2585    }
2586    /**
2587     * NON-DOM: kept for backward compatibility
2588     * Store user data related to a given node
2589     * This is a place where we could use weak references! Indeed, the node
2590     * here won't be GC'ed as long as some user data is attached to it, since
2591     * the userData table will have a reference to the node.
2592     */

2593    protected void setUserData(NodeImpl n, Object JavaDoc data) {
2594        setUserData(n, "XERCES1DOMUSERDATA", data, null);
2595    }
2596
2597    /**
2598     * NON-DOM: kept for backward compatibility
2599     * Retreive user data related to a given node
2600     */

2601    protected Object JavaDoc getUserData(NodeImpl n) {
2602        return getUserData(n, "XERCES1DOMUSERDATA");
2603    }
2604
2605
2606    // Event related methods overidden in subclass
2607

2608    protected void addEventListener(NodeImpl node, String JavaDoc type,
2609    EventListener JavaDoc listener,
2610    boolean useCapture) {
2611        // does nothing by default - overidden in subclass
2612
}
2613
2614    protected void removeEventListener(NodeImpl node, String JavaDoc type,
2615    EventListener JavaDoc listener,
2616    boolean useCapture) {
2617        // does nothing by default - overidden in subclass
2618
}
2619
2620    protected void copyEventListeners(NodeImpl src, NodeImpl tgt) {
2621        // does nothing by default - overidden in subclass
2622
}
2623
2624    protected boolean dispatchEvent(NodeImpl node, Event JavaDoc event) {
2625        // does nothing by default - overidden in subclass
2626
return false;
2627    }
2628
2629    // Notification methods overidden in subclasses
2630

2631    /**
2632     * A method to be called when some text was changed in a text node,
2633     * so that live objects can be notified.
2634     */

2635    void replacedText(NodeImpl node) {
2636    }
2637
2638    /**
2639     * A method to be called when some text was deleted from a text node,
2640     * so that live objects can be notified.
2641     */

2642    void deletedText(NodeImpl node, int offset, int count) {
2643    }
2644
2645    /**
2646     * A method to be called when some text was inserted into a text node,
2647     * so that live objects can be notified.
2648     */

2649    void insertedText(NodeImpl node, int offset, int count) {
2650    }
2651
2652    /**
2653     * A method to be called when a character data node is about to be modified
2654     */

2655    void modifyingCharacterData(NodeImpl node, boolean replace) {
2656    }
2657
2658    /**
2659     * A method to be called when a character data node has been modified
2660     */

2661    void modifiedCharacterData(NodeImpl node, String JavaDoc oldvalue, String JavaDoc value, boolean replace) {
2662    }
2663
2664    /**
2665     * A method to be called when a node is about to be inserted in the tree.
2666     */

2667    void insertingNode(NodeImpl node, boolean replace) {
2668    }
2669
2670    /**
2671     * A method to be called when a node has been inserted in the tree.
2672     */

2673    void insertedNode(NodeImpl node, NodeImpl newInternal, boolean replace) {
2674    }
2675
2676    /**
2677     * A method to be called when a node is about to be removed from the tree.
2678     */

2679    void removingNode(NodeImpl node, NodeImpl oldChild, boolean replace) {
2680    }
2681
2682    /**
2683     * A method to be called when a node has been removed from the tree.
2684     */

2685    void removedNode(NodeImpl node, boolean replace) {
2686    }
2687
2688    /**
2689     * A method to be called when a node is about to be replaced in the tree.
2690     */

2691    void replacingNode(NodeImpl node) {
2692    }
2693
2694    /**
2695     * A method to be called when a node has been replaced in the tree.
2696     */

2697    void replacedNode(NodeImpl node) {
2698    }
2699
2700    /**
2701     * A method to be called when a character data node is about to be replaced
2702     */

2703    void replacingData(NodeImpl node) {
2704    }
2705
2706    /**
2707     * method to be called when a character data node has been replaced.
2708     */

2709    void replacedCharacterData(NodeImpl node, String JavaDoc oldvalue, String JavaDoc value) {
2710    }
2711
2712    
2713    /**
2714     * A method to be called when an attribute value has been modified
2715     */

2716    void modifiedAttrValue(AttrImpl attr, String JavaDoc oldvalue) {
2717    }
2718
2719    /**
2720     * A method to be called when an attribute node has been set
2721     */

2722    void setAttrNode(AttrImpl attr, AttrImpl previous) {
2723    }
2724
2725    /**
2726     * A method to be called when an attribute node has been removed
2727     */

2728    void removedAttrNode(AttrImpl attr, NodeImpl oldOwner, String JavaDoc name) {
2729    }
2730
2731    /**
2732     * A method to be called when an attribute node has been renamed
2733     */

2734    void renamedAttrNode(Attr JavaDoc oldAt, Attr JavaDoc newAt) {
2735    }
2736
2737    /**
2738     * A method to be called when an element has been renamed
2739     */

2740    void renamedElement(Element JavaDoc oldEl, Element JavaDoc newEl) {
2741    }
2742
2743} // class CoreDocumentImpl
2744
Popular Tags