KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > apache > xerces > parsers > DOMParser


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999,2000 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.enhydra.apache.xerces.parsers;
59
60 import java.util.Enumeration JavaDoc;
61 import java.util.StringTokenizer JavaDoc;
62
63 import org.enhydra.apache.xerces.dom.AttrImpl;
64 import org.enhydra.apache.xerces.dom.DeferredDocumentImpl;
65 import org.enhydra.apache.xerces.dom.DocumentImpl;
66 import org.enhydra.apache.xerces.dom.DocumentTypeImpl;
67 import org.enhydra.apache.xerces.dom.ElementDefinitionImpl;
68 import org.enhydra.apache.xerces.dom.EntityImpl;
69 import org.enhydra.apache.xerces.dom.NotationImpl;
70 import org.enhydra.apache.xerces.dom.TextImpl;
71 import org.enhydra.apache.xerces.framework.XMLAttrList;
72 import org.enhydra.apache.xerces.framework.XMLContentSpec;
73 import org.enhydra.apache.xerces.framework.XMLDocumentHandler;
74 import org.enhydra.apache.xerces.framework.XMLParser;
75 import org.enhydra.apache.xerces.readers.XMLEntityHandler;
76 import org.enhydra.apache.xerces.utils.QName;
77 import org.enhydra.apache.xerces.utils.StringPool;
78 import org.enhydra.apache.xerces.validators.common.XMLAttributeDecl;
79 import org.enhydra.apache.xerces.validators.common.XMLElementDecl;
80 import org.enhydra.apache.xerces.validators.schema.SchemaSymbols;
81 import org.enhydra.apache.xerces.validators.schema.XUtil;
82 import org.w3c.dom.Attr JavaDoc;
83 import org.w3c.dom.Comment JavaDoc;
84 import org.w3c.dom.Document JavaDoc;
85 import org.w3c.dom.DocumentType JavaDoc;
86 import org.w3c.dom.Element JavaDoc;
87 import org.w3c.dom.Entity JavaDoc;
88 import org.w3c.dom.EntityReference JavaDoc;
89 import org.w3c.dom.NamedNodeMap JavaDoc;
90 import org.w3c.dom.Node JavaDoc;
91 import org.w3c.dom.ProcessingInstruction JavaDoc;
92 import org.w3c.dom.Text JavaDoc;
93 import org.xml.sax.SAXException JavaDoc;
94 import org.xml.sax.SAXNotRecognizedException JavaDoc;
95 import org.xml.sax.SAXNotSupportedException JavaDoc;
96
97 /**
98  * DOMParser provides a parser which produces a W3C DOM tree as its output
99  *
100  *
101  * @version $Id: DOMParser.java,v 1.3 2005/01/26 08:28:44 jkjome Exp $
102  */

103 public class DOMParser
104     extends XMLParser
105     implements XMLDocumentHandler
106     {
107
108     //
109
// Constants
110
//
111

112     // public
113

114     /** Default programmatic document class name (org.enhydra.apache.xerces.dom.DocumentImpl). */
115     public static final String JavaDoc DEFAULT_DOCUMENT_CLASS_NAME = "org.enhydra.apache.xerces.dom.DocumentImpl";
116
117     /** Default deferred document class name (org.enhydra.apache.xerces.dom.DeferredDocumentImpl). */
118     public static final String JavaDoc DEFAULT_DEFERRED_DOCUMENT_CLASS_NAME = "org.enhydra.apache.xerces.dom.DeferredDocumentImpl";
119
120     // debugging
121

122     /** Set to true to debug attribute list declaration calls. */
123     private static final boolean DEBUG_ATTLIST_DECL = false;
124
125     // features and properties
126

127     /** Features recognized by this parser. */
128     private static final String JavaDoc RECOGNIZED_FEATURES[] = {
129         // SAX2 core features
130
// Xerces features
131
"http://apache.org/xml/features/dom/defer-node-expansion",
132         "http://apache.org/xml/features/dom/create-entity-ref-nodes",
133         "http://apache.org/xml/features/dom/include-ignorable-whitespace",
134         // Experimental features
135
"http://apache.org/xml/features/domx/grammar-access",
136     };
137
138     /** Properties recognized by this parser. */
139     private static final String JavaDoc RECOGNIZED_PROPERTIES[] = {
140         // SAX2 core properties
141
// Xerces properties
142
"http://apache.org/xml/properties/dom/document-class-name",
143         "http://apache.org/xml/properties/dom/current-element-node",
144     };
145
146     //
147
// Data
148
//
149

150     // common data
151

152     protected Document JavaDoc fDocument;
153
154     // deferred expansion data
155

156     protected DeferredDocumentImpl fDeferredDocumentImpl;
157     protected int fDocumentIndex;
158     protected int fDocumentTypeIndex;
159     protected int fCurrentNodeIndex;
160
161     //DOM Level 3 WD - experimental
162

163     protected int fCurrentEntityName; //name of current entity reference
164
protected int fCurrentEntityNode; //index of entity node corresponding to current entity reference
165

166     // full expansion data
167

168     protected DocumentImpl fDocumentImpl;
169     protected DocumentType JavaDoc fDocumentType;
170     protected Node JavaDoc fCurrentElementNode;
171
172     // state
173

174     protected boolean fInDTD;
175     protected boolean fWithinElement;
176     protected boolean fInCDATA;
177
178     // features
179
private boolean fGrammarAccess;
180
181     // properties
182

183     // REVISIT: Even though these have setters and getters, should they
184
// be protected visibility? -Ac
185
private String JavaDoc fDocumentClassName;
186     private boolean fDeferNodeExpansion;
187     private boolean fCreateEntityReferenceNodes;
188     private boolean fIncludeIgnorableWhitespace;
189
190     // built-in entities
191

192     protected int fAmpIndex;
193     protected int fLtIndex;
194     protected int fGtIndex;
195     protected int fAposIndex;
196     protected int fQuotIndex;
197
198     private boolean fSeenRootElement;
199
200     private boolean fStringPoolInUse;
201
202     private XMLAttrList fAttrList;
203
204     //
205
// Constructors
206
//
207

208     /** Default constructor. */
209     public DOMParser() {
210
211         initHandlers(false, this, this);
212
213         // setup parser state
214
init();
215
216         // set default values
217
try {
218             setDocumentClassName(DEFAULT_DOCUMENT_CLASS_NAME);
219             setCreateEntityReferenceNodes(true);
220             setDeferNodeExpansion(true);
221             setIncludeIgnorableWhitespace(true);
222         } catch (SAXException JavaDoc e) {
223             throw new RuntimeException JavaDoc("PAR001 Fatal error constructing DOMParser.");
224         }
225
226     } // <init>()
227

228     //
229
// Public methods
230
//
231

232     // document
233

234     /** Returns the document. */
235     public Document JavaDoc getDocument() {
236         return fDocument;
237     }
238
239     // features and properties
240

241     /**
242      * Returns a list of features that this parser recognizes.
243      * This method will never return null; if no features are
244      * recognized, this method will return a zero length array.
245      *
246      * @see #isFeatureRecognized
247      * @see #setFeature
248      * @see #getFeature
249      */

250     public String JavaDoc[] getFeaturesRecognized() {
251
252         // get features that super/this recognizes
253
String JavaDoc superRecognized[] = super.getFeaturesRecognized();
254         String JavaDoc thisRecognized[] = RECOGNIZED_FEATURES;
255
256         // is one or the other the empty set?
257
int thisLength = thisRecognized.length;
258         if (thisLength == 0) {
259             return superRecognized;
260         }
261         int superLength = superRecognized.length;
262         if (superLength == 0) {
263             return thisRecognized;
264         }
265
266         // combine the two lists and return
267
String JavaDoc recognized[] = new String JavaDoc[superLength + thisLength];
268         System.arraycopy(superRecognized, 0, recognized, 0, superLength);
269         System.arraycopy(thisRecognized, 0, recognized, superLength, thisLength);
270         return recognized;
271
272     } // getFeaturesRecognized():String[]
273

274     /**
275      * Returns a list of properties that this parser recognizes.
276      * This method will never return null; if no properties are
277      * recognized, this method will return a zero length array.
278      *
279      * @see #isPropertyRecognized
280      * @see #setProperty
281      * @see #getProperty
282      */

283     public String JavaDoc[] getPropertiesRecognized() {
284
285         // get properties that super/this recognizes
286
String JavaDoc superRecognized[] = super.getPropertiesRecognized();
287         String JavaDoc thisRecognized[] = RECOGNIZED_PROPERTIES;
288
289         // is one or the other the empty set?
290
int thisLength = thisRecognized.length;
291         if (thisLength == 0) {
292             return superRecognized;
293         }
294         int superLength = superRecognized.length;
295         if (superLength == 0) {
296             return thisRecognized;
297         }
298
299         // combine the two lists and return
300
String JavaDoc recognized[] = new String JavaDoc[superLength + thisLength];
301         System.arraycopy(superRecognized, 0, recognized, 0, superLength);
302         System.arraycopy(thisRecognized, 0, recognized, superLength, thisLength);
303         return recognized;
304
305     }
306
307     // resetting
308

309     /** Resets the parser. */
310     public void reset() throws Exception JavaDoc {
311         if (fStringPoolInUse) {
312             // we can't reuse the string pool, let's create another one
313
fStringPool = new StringPool();
314             fStringPoolInUse = false;
315         }
316         super.reset();
317         init();
318     }
319
320     /** Resets or copies the parser. */
321     public void resetOrCopy() throws Exception JavaDoc {
322         super.resetOrCopy();
323         init();
324     }
325
326     //
327
// Protected methods
328
//
329

330     // initialization
331

332     /**
333      * Initializes the parser to a pre-parse state. This method is
334      * called between calls to <code>parse()</code>.
335      */

336     protected void init() {
337
338         // init common
339
fDocument = null;
340
341         // init deferred expansion
342
fDeferredDocumentImpl = null;
343         fDocumentIndex = -1;
344         fDocumentTypeIndex = -1;
345         fCurrentNodeIndex = -1;
346
347         //DOM Level 3 WD - experimental
348
fCurrentEntityNode = -1;
349         fCurrentEntityName = -1;
350
351         // init full expansion
352
fDocumentImpl = null;
353         fDocumentType = null;
354         fCurrentElementNode = null;
355
356         // state
357
fInDTD = false;
358         fWithinElement = false;
359         fInCDATA = false;
360
361         // built-in entities
362
fAmpIndex = fStringPool.addSymbol("amp");
363         fLtIndex = fStringPool.addSymbol("lt");
364         fGtIndex = fStringPool.addSymbol("gt");
365         fAposIndex = fStringPool.addSymbol("apos");
366         fQuotIndex = fStringPool.addSymbol("quot");
367
368         fSeenRootElement = false;
369         fStringPoolInUse = false;
370
371         fAttrList = new XMLAttrList(fStringPool);
372
373     } // init()
374

375     // features
376

377     /**
378      * This method sets whether the expansion of the nodes in the default
379      * DOM implementation are deferred.
380      *
381      * @see #getDeferNodeExpansion
382      * @see #setDocumentClassName
383      */

384     protected void setDeferNodeExpansion(boolean deferNodeExpansion)
385         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
386         fDeferNodeExpansion = deferNodeExpansion;
387     }
388
389     /**
390      * Returns true if the expansion of the nodes in the default DOM
391      * implementation are deferred.
392      *
393      * @see #setDeferNodeExpansion
394      */

395     protected boolean getDeferNodeExpansion()
396         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
397         return fDeferNodeExpansion;
398     }
399
400     /**
401      * This feature determines whether entity references within
402      * the document are included in the document tree as
403      * EntityReference nodes.
404      * <p>
405      * Note: The children of the entity reference are always
406      * added to the document. This feature only affects
407      * whether an EntityReference node is also included
408      * as the parent of the entity reference children.
409      *
410      * @param create True to create entity reference nodes; false
411      * to only insert the entity reference children.
412      *
413      * @see #getCreateEntityReferenceNodes
414      */

415     protected void setCreateEntityReferenceNodes(boolean create)
416         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
417         fCreateEntityReferenceNodes = create;
418     }
419
420     /**
421      * Returns true if entity references within the document are
422      * included in the document tree as EntityReference nodes.
423      *
424      * @see #setCreateEntityReferenceNodes
425      */

426     public boolean getCreateEntityReferenceNodes()
427         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
428         return fCreateEntityReferenceNodes;
429     }
430
431     /**
432      * This feature determines whether text nodes that can be
433      * considered "ignorable whitespace" are included in the DOM
434      * tree.
435      * <p>
436      * Note: The only way that the parser can determine if text
437      * is ignorable is by reading the associated grammar
438      * and having a content model for the document. When
439      * ignorable whitespace text nodes *are* included in
440      * the DOM tree, they will be flagged as ignorable.
441      * The ignorable flag can be queried by calling the
442      * TextImpl#isIgnorableWhitespace():boolean method.
443      *
444      * @param include True to include ignorable whitespace text nodes;
445      * false to not include ignorable whitespace text
446      * nodes.
447      *
448      * @see #getIncludeIgnorableWhitespace
449      */

450     public void setIncludeIgnorableWhitespace(boolean include)
451         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
452         fIncludeIgnorableWhitespace = include;
453     }
454
455     /**
456      * Returns true if ignorable whitespace text nodes are included
457      * in the DOM tree.
458      *
459      * @see #setIncludeIgnorableWhitespace
460      */

461     public boolean getIncludeIgnorableWhitespace()
462         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
463         return fIncludeIgnorableWhitespace;
464     }
465
466     // properties
467

468     /**
469      * This method allows the programmer to decide which document
470      * factory to use when constructing the DOM tree. However, doing
471      * so will lose the functionality of the default factory. Also,
472      * a document class other than the default will lose the ability
473      * to defer node expansion on the DOM tree produced.
474      *
475      * @param documentClassName The fully qualified class name of the
476      * document factory to use when constructing
477      * the DOM tree.
478      *
479      * @see #getDocumentClassName
480      * @see #setDeferNodeExpansion
481      * @see #DEFAULT_DOCUMENT_CLASS_NAME
482      */

483     protected void setDocumentClassName(String JavaDoc documentClassName)
484         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
485
486         // normalize class name
487
if (documentClassName == null) {
488             documentClassName = DEFAULT_DOCUMENT_CLASS_NAME;
489         }
490
491         // verify that this class exists and is of the right type
492
try {
493             //jrk_20021208.1_begin
494
//Class _class = Class.forName(documentClassName);
495
Class JavaDoc _class = Class.forName(documentClassName, true, getClass().getClassLoader());
496             //jrk_20021208.1_end
497
//if (!_class.isAssignableFrom(Document.class)) {
498
if (!Document JavaDoc.class.isAssignableFrom(_class)) {
499                 throw new IllegalArgumentException JavaDoc("PAR002 Class, \""+documentClassName+"\", is not of type org.w3c.dom.Document."+"\n"+documentClassName);
500             }
501         }
502         catch (ClassNotFoundException JavaDoc e) {
503             throw new IllegalArgumentException JavaDoc("PAR003 Class, \""+documentClassName+"\", not found."+"\n"+documentClassName);
504         }
505
506         // set document class name
507
fDocumentClassName = documentClassName;
508         if (!documentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME)) {
509             setDeferNodeExpansion(false);
510         }
511
512     } // setDocumentClassName(String)
513

514     /**
515      * Returns the fully qualified class name of the document factory
516      * used when constructing the DOM tree.
517      *
518      * @see #setDocumentClassName
519      */

520     protected String JavaDoc getDocumentClassName()
521         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
522         return fDocumentClassName;
523     }
524
525     /**
526      * Returns the current element node.
527      * <p>
528      * Note: This method is not supported when the "deferNodeExpansion"
529      * property is set to true and the document factory is set to
530      * the default factory.
531      */

532     protected Element JavaDoc getCurrentElementNode()
533         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
534
535         if (fCurrentElementNode != null &&
536             fCurrentElementNode.getNodeType() == Node.ELEMENT_NODE) {
537             return (Element JavaDoc)fCurrentElementNode;
538         }
539         return null;
540
541     } // getCurrentElementNode():Element
542

543     //
544
// Configurable methods
545
//
546

547     /**
548      * Set the state of any feature in a SAX2 parser. The parser
549      * might not recognize the feature, and if it does recognize
550      * it, it might not be able to fulfill the request.
551      *
552      * @param featureId The unique identifier (URI) of the feature.
553      * @param state The requested state of the feature (true or false).
554      *
555      * @exception SAXNotRecognizedException If the requested feature is
556      * not known.
557      * @exception SAXNotSupportedException If the requested feature is
558      * known, but the requested state
559      * is not supported.
560      */

561     public void setFeature(String JavaDoc featureId, boolean state)
562         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
563
564         //
565
// SAX2 core features
566
//
567

568         if (featureId.startsWith(SAX2_FEATURES_PREFIX)) {
569             //
570
// No additional SAX properties defined for DOMParser.
571
// Pass request off to XMLParser for the common cases.
572
//
573
}
574
575         //
576
// Xerces features
577
//
578

579         else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
580             String JavaDoc feature = featureId.substring(XERCES_FEATURES_PREFIX.length());
581             //
582
// http://apache.org/xml/features/dom/defer-node-expansion
583
// Allows the document tree returned by getDocument()
584
// to be constructed lazily. In other words, the DOM
585
// nodes are constructed as the tree is traversed.
586
// This allows the document to be returned sooner with
587
// the expense of holding all of the blocks of character
588
// data held in memory. Then again, lots of DOM nodes
589
// use a lot of memory as well.
590
//
591
if (feature.equals("dom/defer-node-expansion")) {
592                 if (fParseInProgress) {
593                     throw new SAXNotSupportedException JavaDoc("PAR004 Cannot setFeature("+featureId + "): parse is in progress."+"\n"+featureId);
594                 }
595                 setDeferNodeExpansion(state);
596                 return;
597             }
598             //
599
// http://apache.org/xml/features/dom/create-entity-ref-nodes
600
// This feature determines whether entity references within
601
// the document are included in the document tree as
602
// EntityReference nodes.
603
// Note: The children of the entity reference are always
604
// added to the document. This feature only affects
605
// whether an EntityReference node is also included
606
// as the parent of the entity reference children.
607
//
608
if (feature.equals("dom/create-entity-ref-nodes")) {
609                 setCreateEntityReferenceNodes(state);
610                 return;
611             }
612
613             //
614
// http://apache.org/xml/features/dom/include-ignorable-whitespace
615
// This feature determines whether text nodes that can be
616
// considered "ignorable whitespace" are included in the DOM
617
// tree.
618
// Note: The only way that the parser can determine if text
619
// is ignorable is by reading the associated grammar
620
// and having a content model for the document. When
621
// ignorable whitespace text nodes *are* included in
622
// the DOM tree, they will be flagged as ignorable.
623
// The ignorable flag can be queried by calling the
624
// TextImpl#isIgnorableWhitespace():boolean method.
625
//
626
if (feature.equals("dom/include-ignorable-whitespace")) {
627                 setIncludeIgnorableWhitespace(state);
628                 return;
629             }
630
631             //
632
// Experimental features
633
//
634

635             //
636
// http://apache.org/xml/features/domx/grammar-access
637
// Allows grammar access in the DOM tree. Currently, this
638
// means that there is an XML Schema document tree as a
639
// child of the Doctype node.
640
//
641
if (feature.equals("domx/grammar-access")) {
642                 fGrammarAccess = state;
643                 return;
644             }
645
646             //
647
// Pass request off to XMLParser for the common cases.
648
//
649
}
650
651         //
652
// Pass request off to XMLParser for the common cases.
653
//
654
super.setFeature(featureId, state);
655
656     } // setFeature(String,boolean)
657

658     /**
659      * Query the current state of any feature in a SAX2 parser. The
660      * parser might not recognize the feature.
661      *
662      * @param featureId The unique identifier (URI) of the feature
663      * being set.
664      *
665      * @return The current state of the feature.
666      *
667      * @exception SAXNotRecognizedException If the requested feature is
668      * not known.
669      */

670     public boolean getFeature(String JavaDoc featureId)
671         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
672
673         //
674
// SAX2 core features
675
//
676

677         if (featureId.startsWith(SAX2_FEATURES_PREFIX)) {
678             //
679
// No additional SAX properties defined for DOMParser.
680
// Pass request off to XMLParser for the common cases.
681
//
682
}
683
684         //
685
// Xerces features
686
//
687

688         else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
689             String JavaDoc feature = featureId.substring(XERCES_FEATURES_PREFIX.length());
690             //
691
// http://apache.org/xml/features/dom/defer-node-expansion
692
// Allows the document tree returned by getDocument()
693
// to be constructed lazily. In other words, the DOM
694
// nodes are constructed as the tree is traversed.
695
// This allows the document to be returned sooner with
696
// the expense of holding all of the blocks of character
697
// data held in memory. Then again, lots of DOM nodes
698
// use a lot of memory as well.
699
//
700
if (feature.equals("dom/defer-node-expansion")) {
701                 return getDeferNodeExpansion();
702             }
703             //
704
// http://apache.org/xml/features/dom/create-entity-ref-nodes
705
// This feature determines whether entity references within
706
// the document are included in the document tree as
707
// EntityReference nodes.
708
// Note: The children of the entity reference are always
709
// added to the document. This feature only affects
710
// whether an EntityReference node is also included
711
// as the parent of the entity reference children.
712
//
713
else if (feature.equals("dom/create-entity-ref-nodes")) {
714                 return getCreateEntityReferenceNodes();
715             }
716
717             //
718
// http://apache.org/xml/features/dom/include-ignorable-whitespace
719
// This feature determines whether text nodes that can be
720
// considered "ignorable whitespace" are included in the DOM
721
// tree.
722
// Note: The only way that the parser can determine if text
723
// is ignorable is by reading the associated grammar
724
// and having a content model for the document. When
725
// ignorable whitespace text nodes *are* included in
726
// the DOM tree, they will be flagged as ignorable.
727
// The ignorable flag can be queried by calling the
728
// TextImpl#isIgnorableWhitespace():boolean method.
729
//
730
if (feature.equals("dom/include-ignorable-whitespace")) {
731                 return getIncludeIgnorableWhitespace();
732             }
733
734             //
735
// Experimental features
736
//
737

738             //
739
// http://apache.org/xml/features/domx/grammar-access
740
// Allows grammar access in the DOM tree. Currently, this
741
// means that there is an XML Schema document tree as a
742
// child of the Doctype node.
743
//
744
if (feature.equals("domx/grammar-access")) {
745                 return fGrammarAccess;
746             }
747
748             //
749
// Pass request off to XMLParser for the common cases.
750
//
751
}
752
753         //
754
// Pass request off to XMLParser for the common cases.
755
//
756
return super.getFeature(featureId);
757
758     } // getFeature(String):boolean
759

760     /**
761      * Set the value of any property in a SAX2 parser. The parser
762      * might not recognize the property, and if it does recognize
763      * it, it might not support the requested value.
764      *
765      * @param propertyId The unique identifier (URI) of the property
766      * being set.
767      * @param Object The value to which the property is being set.
768      *
769      * @exception SAXNotRecognizedException If the requested property is
770      * not known.
771      * @exception SAXNotSupportedException If the requested property is
772      * known, but the requested
773      * value is not supported.
774      */

775     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
776         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
777
778         //
779
// Xerces properties
780
//
781

782         if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
783             String JavaDoc property = propertyId.substring(XERCES_PROPERTIES_PREFIX.length());
784             //
785
// http://apache.org/xml/properties/dom/current-element-node
786
// Returns the current element node as the DOM Parser is
787
// parsing. This property is useful for determining the
788
// relative location of the document when an error is
789
// encountered. Note that this feature does *not* work
790
// when the http://apache.org/xml/features/dom/defer-node-expansion
791
// is set to true.
792
//
793
if (property.equals("dom/current-element-node")) {
794                 throw new SAXNotSupportedException JavaDoc("PAR005 Property, \""+propertyId+"\" is read-only.\n"+propertyId);
795             }
796             //
797
// http://apache.org/xml/properties/dom/document-class-name
798
// This property can be used to set/query the name of the
799
// document factory.
800
//
801
else if (property.equals("dom/document-class-name")) {
802                 if (value != null && !(value instanceof String JavaDoc)) {
803                     throw new SAXNotSupportedException JavaDoc("PAR006 Property value must be of type java.lang.String.");
804                 }
805                 setDocumentClassName((String JavaDoc)value);
806                 return;
807             }
808         }
809
810         //
811
// Pass request off to XMLParser for the common cases.
812
//
813
super.setProperty(propertyId, value);
814
815     } // setProperty(String,Object)
816

817     /**
818      * Return the current value of a property in a SAX2 parser.
819      * The parser might not recognize the property.
820      *
821      * @param propertyId The unique identifier (URI) of the property
822      * being set.
823      *
824      * @return The current value of the property.
825      *
826      * @exception SAXNotRecognizedException If the requested property is
827      * not known.
828      *
829      * @see Configurable#getProperty
830      */

831     public Object JavaDoc getProperty(String JavaDoc propertyId)
832         throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
833
834         //
835
// Xerces properties
836
//
837

838         if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
839             String JavaDoc property = propertyId.substring(XERCES_PROPERTIES_PREFIX.length());
840             //
841
// http://apache.org/xml/properties/dom/current-element-node
842
// Returns the current element node as the DOM Parser is
843
// parsing. This property is useful for determining the
844
// relative location of the document when an error is
845
// encountered. Note that this feature does *not* work
846
// when the http://apache.org/xml/features/dom/defer-node-expansion
847
// is set to true.
848
//
849
if (property.equals("dom/current-element-node")) {
850                 boolean throwException = false;
851                 try {
852                     throwException = getFeature(XERCES_FEATURES_PREFIX+"dom/defer-node-expansion");
853                 }
854                 catch (SAXNotSupportedException JavaDoc e) {
855                     // ignore
856
}
857                 catch (SAXNotRecognizedException JavaDoc e) {
858                     // ignore
859
}
860                 if (throwException) {
861                     throw new SAXNotSupportedException JavaDoc("PAR007 Current element node cannot be queried when node expansion is deferred.");
862                 }
863                 return getCurrentElementNode();
864             }
865             //
866
// http://apache.org/xml/properties/dom/document-class-name
867
// This property can be used to set/query the name of the
868
// document factory.
869
//
870
else if (property.equals("dom/document-class-name")) {
871                 return getDocumentClassName();
872             }
873         }
874
875         //
876
// Pass request off to XMLParser for the common cases.
877
//
878
return super.getProperty(propertyId);
879
880     } // getProperty(String):Object
881

882     //
883
// XMLParser methods
884
//
885

886     /** Start document. */
887     public void startDocument() {
888
889         // deferred expansion
890
String JavaDoc documentClassName = null;
891         try {
892             documentClassName = getDocumentClassName();
893         } catch (SAXException JavaDoc e) {
894             throw new RuntimeException JavaDoc("PAR008 Fatal error getting document factory.");
895         }
896         boolean deferNodeExpansion = true;
897         try {
898             deferNodeExpansion = getDeferNodeExpansion();
899         } catch (SAXException JavaDoc e) {
900             throw new RuntimeException JavaDoc("PAR009 Fatal error reading expansion mode.");
901         }
902         try {
903             boolean isDocumentImpl = fDocumentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME);
904             boolean isDeferredImpl = fDocumentClassName.equals(DEFAULT_DEFERRED_DOCUMENT_CLASS_NAME);
905             if (deferNodeExpansion && (isDocumentImpl || isDeferredImpl)) {
906                 boolean nsEnabled = false;
907                 try { nsEnabled = getNamespaces(); }
908                 catch (SAXException JavaDoc s) {}
909                 fDeferredDocumentImpl = new DeferredDocumentImpl(fStringPool, nsEnabled, fGrammarAccess);
910                 fStringPoolInUse = true;
911                 fDocument = fDeferredDocumentImpl;
912                 fDocumentIndex = fDeferredDocumentImpl.createDocument();
913                 fCurrentNodeIndex = fDocumentIndex;
914             }
915
916             // full expansion
917
else {
918                 if (isDocumentImpl) {
919                     fDocumentImpl = new DocumentImpl(fGrammarAccess);
920                     fDocument = fDocumentImpl;
921                     // set DOM error checking off
922
fDocumentImpl.setErrorChecking(false);
923                 }
924                 else {
925                     //jrk_20021208.2_begin
926
//Class documentClass = Class.forName(documentClassName);
927
Class JavaDoc documentClass = Class.forName(documentClassName, true, getClass().getClassLoader());
928                     //jrk_20021208.2_end
929
try {
930                         fDocument = (Document JavaDoc)documentClass.newInstance();
931                     }
932                     catch (Exception JavaDoc e) {
933                         // REVISIT: Localize this message.
934
throw new RuntimeException JavaDoc(
935                                  "Failed to create document object of class: "
936                                  + documentClassName);
937                     }
938                     // if subclass of our own class that's cool too
939
//jrk_20021208.3_begin
940
//Class defaultDocClass =
941
// Class.forName(DEFAULT_DOCUMENT_CLASS_NAME);
942
Class JavaDoc defaultDocClass = Class.forName(DEFAULT_DOCUMENT_CLASS_NAME, true, getClass().getClassLoader());
943                     //jrk_20021208.3_end
944
if (defaultDocClass.isAssignableFrom(documentClass)) {
945                         fDocumentImpl = (DocumentImpl)fDocument;
946                         // set DOM error checking off
947
fDocumentImpl.setErrorChecking(false);
948                     }
949                 }
950                 fCurrentElementNode = fDocument;
951             }
952         }
953         catch (ClassNotFoundException JavaDoc e) {
954             // REVISIT: Localize this message.
955
throw new RuntimeException JavaDoc(documentClassName);
956         }
957
958     } // startDocument()
959

960     /** End document. */
961     public void endDocument() throws Exception JavaDoc {
962         // set DOM error checking back on
963
if (fDocumentImpl != null) {
964             fDocumentImpl.setErrorChecking(true);
965
966             if (fDocumentType!=null) {
967                 // set entities and notations read_only per DOM spec
968
((DocumentTypeImpl)fDocumentType).setReadOnly(true, false);
969             }
970         }
971     }
972
973     /** XML declaration. */
974     public void xmlDecl(int versionIndex, int encodingIndex, int standaloneIndex) throws Exception JavaDoc {
975         boolean standalone = (standaloneIndex!=-1)?(fStringPool.toString(standaloneIndex).equals("yes"))?true:false:false;
976         if (fDocumentImpl != null) { //full node expansion
977
fDocumentImpl.setVersion(fStringPool.toString(versionIndex));
978              fDocumentImpl.setEncoding(fStringPool.toString(encodingIndex));
979              fDocumentImpl.setStandalone(standalone);
980          }
981          else if (fDeferredDocumentImpl != null) {
982              fDeferredDocumentImpl.setVersion(fStringPool.toString(versionIndex));
983              fDeferredDocumentImpl.setEncoding(fStringPool.toString(encodingIndex));
984              fDeferredDocumentImpl.setStandalone(standalone);
985          }
986          else{
987           //non xerces implementation
988
}
989
990
991     }
992
993     /** Text declaration.
994      * added DOM Level 3 WD support - experimental
995     */

996     public void textDecl(int versionIndex, int encodingIndex) throws Exception JavaDoc {
997         if (fDeferredDocumentImpl != null) {
998             String JavaDoc name = fStringPool.toString(fCurrentEntityName);
999             // we only support one context for entity references (name !=null)
1000
if (fDocumentTypeIndex != -1 && name != null) {
1001                // find Entity decl for fCurrentEntityName.
1002
int entityDecl = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false);
1003                while (entityDecl != -1) {
1004                    if (fDeferredDocumentImpl.getNodeType(entityDecl, false) == Node.ENTITY_NODE
1005                    && fDeferredDocumentImpl.getNodeNameString(entityDecl, false).equals(name)) {
1006                        break;
1007                    }
1008                    entityDecl = fDeferredDocumentImpl.getPrevSibling(entityDecl, false);
1009                }
1010                fCurrentEntityNode = entityDecl;
1011                fDeferredDocumentImpl.setEntityInfo(entityDecl, versionIndex, encodingIndex);
1012            }
1013        }
1014       // full node expansion
1015
else if (fDocumentImpl !=null){
1016            NamedNodeMap JavaDoc entities = fDocumentType.getEntities();
1017            if (entities!=null) {
1018                EntityImpl entityNode = (EntityImpl)entities.getNamedItem(fCurrentElementNode.getNodeName());
1019                if (entityNode !=null) {
1020                    entityNode.setVersion(fStringPool.toString(versionIndex));
1021                    entityNode.setEncoding(fStringPool.toString(encodingIndex));
1022                }
1023            }
1024        }
1025        else {
1026           //non xerces implementation
1027
}
1028    }
1029
1030    /** Report the start of the scope of a namespace declaration. */
1031    public void startNamespaceDeclScope(int prefix, int uri) throws Exception JavaDoc {}
1032
1033    /** Report the end of the scope of a namespace declaration. */
1034    public void endNamespaceDeclScope(int prefix) throws Exception JavaDoc {}
1035
1036
1037
1038    /** Start element. */
1039    public void startElement(QName elementQName,
1040                             XMLAttrList xmlAttrList, int attrListIndex)
1041        throws Exception JavaDoc {
1042
1043        // deferred expansion
1044
if (fDeferredDocumentImpl != null) {
1045
1046            // copy schema grammar, if needed
1047
if (!fSeenRootElement) {
1048                fSeenRootElement = true;
1049                // REVISIT: How do we know which grammar is in use?
1050
//Document schemaDocument = fValidator.getSchemaDocument();
1051
if (fGrammarAccess && fGrammarResolver.size() > 0) {
1052                    if (fDocumentTypeIndex == -1) {
1053                        fDocumentTypeIndex = fDeferredDocumentImpl.createDocumentType(elementQName.rawname, -1, -1);
1054                        fDeferredDocumentImpl.appendChild(0, fDocumentTypeIndex);
1055                    }
1056                    Enumeration JavaDoc schemas = fGrammarResolver.nameSpaceKeys();
1057                    Document JavaDoc schemaDocument = fGrammarResolver.getGrammar((String JavaDoc)schemas.nextElement()).getGrammarDocument();
1058                    if (schemaDocument != null) {
1059                        Element JavaDoc schema = schemaDocument.getDocumentElement();
1060                        copyInto(schema, fDocumentTypeIndex);
1061                    }
1062                }
1063            }
1064
1065            int element =
1066                fDeferredDocumentImpl.createElement(elementQName.rawname,
1067                                                    elementQName.uri,
1068                                                    xmlAttrList,
1069                                                    attrListIndex);
1070            fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, element);
1071            fCurrentNodeIndex = element;
1072            fWithinElement = true;
1073
1074            // identifier registration
1075
int index = xmlAttrList.getFirstAttr(attrListIndex);
1076            while (index != -1) {
1077                if (xmlAttrList.getAttType(index) == fStringPool.addSymbol("ID")) {
1078                    int nameIndex = xmlAttrList.getAttValue(index);
1079                    fDeferredDocumentImpl.putIdentifier(nameIndex, element);
1080                }
1081                index = xmlAttrList.getNextAttr(index);
1082            }
1083        }
1084
1085        // full expansion
1086
else {
1087
1088            boolean nsEnabled = false;
1089            try { nsEnabled = getNamespaces(); }
1090            catch (SAXException JavaDoc s) {}
1091
1092            String JavaDoc elementName = fStringPool.toString(elementQName.rawname);
1093
1094            // copy schema grammar, if needed
1095
if (!fSeenRootElement) {
1096                fSeenRootElement = true;
1097                if (fDocumentImpl != null
1098                    && fGrammarAccess && fGrammarResolver.size() > 0) {
1099                    if (fDocumentType == null) {
1100                        String JavaDoc rootName = elementName;
1101                        String JavaDoc systemId = ""; // REVISIT: How do we get this value? -Ac
1102
String JavaDoc publicId = ""; // REVISIT: How do we get this value? -Ac
1103
fDocumentType = fDocumentImpl.createDocumentType(rootName, publicId, systemId);
1104                        fDocument.appendChild(fDocumentType);
1105                        // REVISIT: We could use introspection to get the
1106
// DOMImplementation#createDocumentType method
1107
// for DOM Level 2 implementations. The only
1108
// problem is that the owner document for the
1109
// node created is null. How does it get set
1110
// for document when appended? A cursory look
1111
// at the DOM Level 2 CR didn't yield any
1112
// information. -Ac
1113
}
1114                    Enumeration JavaDoc schemas = fGrammarResolver.nameSpaceKeys();
1115                    Document JavaDoc schemaDocument = fGrammarResolver.getGrammar((String JavaDoc)schemas.nextElement()).getGrammarDocument();
1116                    if (schemaDocument != null) {
1117                        Element JavaDoc schema = schemaDocument.getDocumentElement();
1118                        XUtil.copyInto(schema, fDocumentType);
1119                    }
1120                }
1121            }
1122
1123            Element JavaDoc e;
1124            if (nsEnabled) {
1125                String JavaDoc namespaceURI = fStringPool.toString(elementQName.uri);
1126                // hide the fact that our parser uses an empty string for null
1127
if (namespaceURI.length() == 0) {
1128                    namespaceURI = null;
1129                }
1130                e = fDocument.createElementNS(namespaceURI, elementName);
1131            } else {
1132                e = fDocument.createElement(elementName);
1133            }
1134            int attrHandle = xmlAttrList.getFirstAttr(attrListIndex);
1135            while (attrHandle != -1) {
1136                int attName = xmlAttrList.getAttrName(attrHandle);
1137                String JavaDoc attrName = fStringPool.toString(attName);
1138                String JavaDoc attrValue =
1139                    fStringPool.toString(xmlAttrList.getAttValue(attrHandle));
1140                if (nsEnabled) {
1141            int nsURIIndex = xmlAttrList.getAttrURI(attrHandle);
1142            String JavaDoc namespaceURI = fStringPool.toString(nsURIIndex);
1143            // DOM Level 2 wants all namespace declaration attributes
1144
// to be bound to "http://www.w3.org/2000/xmlns/"
1145
// So as long as the XML parser doesn't do it, it needs to
1146
// done here.
1147
int prefixIndex = xmlAttrList.getAttrPrefix(attrHandle);
1148            String JavaDoc prefix = fStringPool.toString(prefixIndex);
1149                    // hide that our parser uses an empty string for null
1150
if (namespaceURI.length() == 0) {
1151                        namespaceURI = null;
1152                    }
1153            if (namespaceURI == null) {
1154            if (prefix != null) {
1155                if (prefix.equals("xmlns")) {
1156                namespaceURI = "http://www.w3.org/2000/xmlns/";
1157                }
1158            } else if (attrName.equals("xmlns")) {
1159                namespaceURI = "http://www.w3.org/2000/xmlns/";
1160            }
1161            }
1162                    e.setAttributeNS(namespaceURI, attrName, attrValue);
1163                } else {
1164                    e.setAttribute(attrName, attrValue);
1165                }
1166                if (fDocumentImpl != null
1167                    && !xmlAttrList.isSpecified(attrHandle)) {
1168                    ((AttrImpl)e.getAttributeNode(attrName))
1169                        .setSpecified(false);
1170                }
1171                attrHandle = xmlAttrList.getNextAttr(attrHandle);
1172            }
1173            fCurrentElementNode.appendChild(e);
1174            fCurrentElementNode = e;
1175            fWithinElement = true;
1176
1177            // identifier registration
1178
if (fDocumentImpl != null) {
1179                int index = xmlAttrList.getFirstAttr(attrListIndex);
1180                while (index != -1) {
1181                    if (xmlAttrList.getAttType(index) == fStringPool.addSymbol("ID")) {
1182                        String JavaDoc name = fStringPool.toString(xmlAttrList.getAttValue(index));
1183                        fDocumentImpl.putIdentifier(name, e);
1184                    }
1185                    index = xmlAttrList.getNextAttr(index);
1186                }
1187            }
1188
1189            // release attributes
1190
xmlAttrList.releaseAttrList(attrListIndex);
1191        }
1192
1193    } // startElement(QName,XMLAttrList,int)
1194

1195    /** End element. */
1196    public void endElement(QName elementQName)
1197        throws Exception JavaDoc {
1198
1199        // deferred node expansion
1200
if (fDeferredDocumentImpl != null) {
1201            fCurrentNodeIndex = fDeferredDocumentImpl.getParentNode(fCurrentNodeIndex, false);
1202            fWithinElement = false;
1203        }
1204
1205        // full node expansion
1206
else {
1207            fCurrentElementNode = fCurrentElementNode.getParentNode();
1208            fWithinElement = false;
1209        }
1210
1211    } // endElement(QName)
1212

1213    /** Characters. */
1214    public void characters(int dataIndex)
1215        throws Exception JavaDoc {
1216
1217        // deferred node expansion
1218
if (fDeferredDocumentImpl != null) {
1219
1220            int text;
1221
1222            if (fInCDATA) {
1223                text = fDeferredDocumentImpl.createCDATASection(dataIndex, false);
1224            } else {
1225                // The Text normalization is taken care of within the Text Node
1226
// in the DEFERRED case.
1227
text = fDeferredDocumentImpl.createTextNode(dataIndex, false);
1228            }
1229            fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, text);
1230        }
1231
1232        // full node expansion
1233
else {
1234
1235            Text JavaDoc text;
1236
1237            if (fInCDATA) {
1238                text = fDocument.createCDATASection(fStringPool.orphanString(dataIndex));
1239            }
1240            else {
1241
1242                if (fWithinElement && fCurrentElementNode.getNodeType() == Node.ELEMENT_NODE) {
1243                    Node JavaDoc lastChild = fCurrentElementNode.getLastChild();
1244                    if (lastChild != null
1245                        && lastChild.getNodeType() == Node.TEXT_NODE) {
1246                        // Normalization of Text Nodes - append rather than create.
1247
((Text JavaDoc)lastChild).appendData(fStringPool.orphanString(dataIndex));
1248                        return;
1249                    }
1250                }
1251                text = fDocument.createTextNode(fStringPool.orphanString(dataIndex));
1252            }
1253
1254            fCurrentElementNode.appendChild(text);
1255
1256        }
1257
1258    } // characters(int)
1259

1260    /** Ignorable whitespace. */
1261    public void ignorableWhitespace(int dataIndex) throws Exception JavaDoc {
1262
1263        // ignore the whitespace
1264
if (!fIncludeIgnorableWhitespace) {
1265            fStringPool.orphanString(dataIndex);
1266            return;
1267        }
1268
1269        // deferred node expansion
1270
if (fDeferredDocumentImpl != null) {
1271
1272            int text;
1273
1274            if (fInCDATA) {
1275                text = fDeferredDocumentImpl.createCDATASection(dataIndex, true);
1276            } else {
1277                // The Text normalization is taken care of within the Text Node
1278
// in the DEFERRED case.
1279
text = fDeferredDocumentImpl.createTextNode(dataIndex, true);
1280            }
1281            fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, text);
1282        }
1283
1284        // full node expansion
1285
else {
1286
1287            Text JavaDoc text;
1288
1289            if (fInCDATA) {
1290                text = fDocument.createCDATASection(fStringPool.orphanString(dataIndex));
1291            }
1292            else {
1293
1294                if (fWithinElement && fCurrentElementNode.getNodeType() == Node.ELEMENT_NODE) {
1295                    Node JavaDoc lastChild = fCurrentElementNode.getLastChild();
1296                    if (lastChild != null
1297                        && lastChild.getNodeType() == Node.TEXT_NODE) {
1298                        // Normalization of Text Nodes - append rather than create.
1299
((Text JavaDoc)lastChild).appendData(fStringPool.orphanString(dataIndex));
1300                        return;
1301                    }
1302                }
1303                text = fDocument.createTextNode(fStringPool.orphanString(dataIndex));
1304            }
1305
1306            if (fDocumentImpl != null) {
1307                ((TextImpl)text).setIgnorableWhitespace(true);
1308            }
1309
1310            fCurrentElementNode.appendChild(text);
1311
1312        }
1313
1314    } // ignorableWhitespace(int)
1315

1316    /** Processing instruction. */
1317    public void processingInstruction(int targetIndex, int dataIndex)
1318        throws Exception JavaDoc {
1319
1320        // deferred node expansion
1321
if (fDeferredDocumentImpl != null) {
1322            int pi = fDeferredDocumentImpl.createProcessingInstruction(targetIndex, dataIndex);
1323            fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, pi);
1324        }
1325
1326        // full node expansion
1327
else {
1328            String JavaDoc target = fStringPool.orphanString(targetIndex);
1329            String JavaDoc data = fStringPool.orphanString(dataIndex);
1330            ProcessingInstruction JavaDoc pi = fDocument.createProcessingInstruction(target, data);
1331            fCurrentElementNode.appendChild(pi);
1332        }
1333
1334    } // processingInstruction(int,int)
1335

1336    /** Comment. */
1337    public void comment(int dataIndex) throws Exception JavaDoc {
1338
1339        if (fInDTD && !fGrammarAccess) {
1340            fStringPool.orphanString(dataIndex);
1341        }
1342        else {
1343            // deferred node expansion
1344
if (fDeferredDocumentImpl != null) {
1345                int comment = fDeferredDocumentImpl.createComment(dataIndex);
1346                fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, comment);
1347            }
1348
1349            // full node expansion
1350
else {
1351                Comment JavaDoc comment = fDocument.createComment(fStringPool.orphanString(dataIndex));
1352                fCurrentElementNode.appendChild(comment);
1353            }
1354        }
1355
1356    } // comment(int)
1357

1358    // Callers who know they're interacting with this parser should use
1359
// characters(int); callers who don't know which parser they
1360
// are interacting with, or who can't be sure of sharing
1361
// the same stringPool, should use this method.
1362
public void characters(char ch[], int start, int length) throws Exception JavaDoc {
1363        characters(fStringPool.addSymbol(new String JavaDoc(ch, start, length)));
1364    } // characters(char[], int, int)
1365

1366    /** Not called. */
1367    public void ignorableWhitespace(char ch[], int start, int length) throws Exception JavaDoc {}
1368
1369    //
1370
// XMLDocumentScanner methods
1371
//
1372

1373    /** Start CDATA section. */
1374    public void startCDATA() throws Exception JavaDoc {
1375        fInCDATA = true;
1376    }
1377
1378    /** End CDATA section. */
1379    public void endCDATA() throws Exception JavaDoc {
1380        fInCDATA = false;
1381    }
1382
1383    //
1384
// XMLEntityHandler methods
1385
//
1386

1387    /** Start entity reference. */
1388    public void startEntityReference(int entityName, int entityType,
1389                                     int entityContext) throws Exception JavaDoc {
1390
1391        fCurrentEntityName = entityName;
1392        // are we ignoring entity reference nodes?
1393
if (!fCreateEntityReferenceNodes) {
1394            return;
1395        }
1396
1397
1398        // ignore built-in entities
1399
if (entityName == fAmpIndex ||
1400            entityName == fGtIndex ||
1401            entityName == fLtIndex ||
1402            entityName == fAposIndex ||
1403            entityName == fQuotIndex) {
1404            return;
1405        }
1406
1407        // we only support one context for entity references right now...
1408
if (entityContext != XMLEntityHandler.ENTITYREF_IN_CONTENT) {
1409            return;
1410        }
1411
1412        // deferred node expansion
1413

1414        if (fDeferredDocumentImpl != null) {
1415
1416            int entityRefIndex = fDeferredDocumentImpl.createEntityReference(entityName);
1417            fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, entityRefIndex);
1418
1419            fCurrentNodeIndex = entityRefIndex;
1420
1421        }
1422
1423        // full node expansion
1424
else {
1425
1426            EntityReference JavaDoc er =
1427             fDocument.createEntityReference(fStringPool.toString(entityName));
1428
1429            fCurrentElementNode.appendChild(er);
1430            fCurrentElementNode = er;
1431        }
1432
1433    } // startEntityReference(int,int,int)
1434

1435    /** End entity reference. */
1436    public void endEntityReference(int entityName, int entityType,
1437                                   int entityContext) throws Exception JavaDoc {
1438        // are we ignoring entity reference nodes?
1439
if (!fCreateEntityReferenceNodes) {
1440            return;
1441        }
1442
1443        // ignore built-in entities
1444
if (entityName == fAmpIndex ||
1445            entityName == fGtIndex ||
1446            entityName == fLtIndex ||
1447            entityName == fAposIndex ||
1448            entityName == fQuotIndex) {
1449            return;
1450        }
1451
1452        // we only support one context for entity references right now...
1453
if (entityContext != XMLEntityHandler.ENTITYREF_IN_CONTENT) {
1454            return;
1455        }
1456
1457        // deferred node expansion
1458
if (fDeferredDocumentImpl != null) {
1459
1460            String JavaDoc name = fStringPool.toString(entityName);
1461
1462            int erChild = fCurrentNodeIndex;
1463            fCurrentNodeIndex = fDeferredDocumentImpl.getParentNode(erChild, false);
1464
1465            // should never be true - we should not return here.
1466
if (fDeferredDocumentImpl.getNodeType(erChild, false) != Node.ENTITY_REFERENCE_NODE) return;
1467
1468            erChild = fDeferredDocumentImpl.getLastChild(erChild, false); // first Child of EntityReference
1469
if (fDocumentTypeIndex != -1) {
1470                // if we have seen <?xml..> decl then Entity decl was found and
1471
// set in textDecl() using fCurrentEntityNode
1472
if (fCurrentEntityNode == -1) {
1473                    // find Entity decl for this EntityReference.
1474
int entityDecl = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false);
1475                    while (entityDecl != -1) {
1476                        if (fDeferredDocumentImpl.getNodeType(entityDecl, false) == Node.ENTITY_NODE
1477                            && fDeferredDocumentImpl.getNodeNameString(entityDecl, false).equals(name)) // string compare...
1478
{
1479                            break;
1480                        }
1481                        entityDecl = fDeferredDocumentImpl.getPrevSibling(entityDecl, false);
1482                    }
1483                    fCurrentEntityNode = entityDecl;
1484                }
1485                 if (fCurrentEntityNode != -1
1486                    && fDeferredDocumentImpl.getLastChild(fCurrentEntityNode, false) == -1) {
1487                    // found entityDecl with same name as this reference
1488
// AND it doesn't have any children.
1489

1490                    // we don't need to iterate, because the whole structure
1491
// should already be connected to the 1st child.
1492
fDeferredDocumentImpl.setAsLastChild(fCurrentEntityNode, erChild);
1493                }
1494                 // done with current entity reference.
1495
// reset values
1496
fCurrentEntityNode = -1;
1497                 fCurrentEntityName = -1;
1498            }
1499
1500        }
1501
1502        // full node expansion
1503
else {
1504
1505            Node JavaDoc erNode = fCurrentElementNode;//fCurrentElementNode.getParentNode();
1506
fCurrentElementNode = erNode.getParentNode();
1507
1508            // if necessary populate the related entity now
1509
if (fDocumentImpl != null) {
1510                NamedNodeMap JavaDoc entities = fDocumentType.getEntities();
1511                String JavaDoc name = fStringPool.toString(entityName);
1512                Node JavaDoc entityNode = entities.getNamedItem(name);
1513
1514                // simply return here if there is no entity for
1515
// the reference or if the entity is already populated.
1516
if (entityNode == null || entityNode.hasChildNodes()) {
1517                    return;
1518                }
1519
1520                EntityImpl entity = (EntityImpl) entityNode;
1521                for (Node JavaDoc child = erNode.getFirstChild();
1522                     child != null;
1523                     child = child.getNextSibling()) {
1524                    Node JavaDoc childClone = child.cloneNode(true);
1525                    entity.appendChild(childClone);
1526                }
1527            }
1528        }
1529
1530    } // endEntityReference(int,int,int)
1531

1532    //
1533
// DTDValidator.EventHandler methods
1534
//
1535

1536    /**
1537     * This function will be called when a &lt;!DOCTYPE...&gt; declaration is
1538     * encountered.
1539     */

1540    public void startDTD(QName rootElement, int publicId, int systemId)
1541        throws Exception JavaDoc {
1542
1543        fInDTD = true;
1544
1545        // full expansion
1546
if (fDocumentImpl != null) {
1547            String JavaDoc rootElementName = fStringPool.toString(rootElement.rawname);
1548            String JavaDoc publicString = fStringPool.toString(publicId);
1549            String JavaDoc systemString = fStringPool.toString(systemId);
1550            fDocumentType = fDocumentImpl.
1551                createDocumentType(rootElementName, publicString, systemString);
1552            fDocumentImpl.appendChild(fDocumentType);
1553
1554            if (fGrammarAccess) {
1555                Element JavaDoc schema = fDocument.createElement("schema");
1556                // REVISIT: What should the namespace be? -Ac
1557
schema.setAttribute("xmlns", SchemaSymbols.URI_SCHEMAFORSCHEMA);
1558                ((AttrImpl)schema.getAttributeNode("xmlns")).setSpecified(false);
1559                schema.setAttribute("finalDefault", "");
1560                ((AttrImpl)schema.getAttributeNode("finalDefault")).setSpecified(false);
1561                schema.setAttribute("exactDefault", "");
1562                ((AttrImpl)schema.getAttributeNode("exactDefault")).setSpecified(false);
1563                fDocumentType.appendChild(schema);
1564                fCurrentElementNode = schema;
1565            }
1566        }
1567
1568        // deferred expansion
1569
else if (fDeferredDocumentImpl != null) {
1570            fDocumentTypeIndex =
1571                fDeferredDocumentImpl.
1572                    createDocumentType(rootElement.rawname, publicId, systemId);
1573            fDeferredDocumentImpl.appendChild(fDocumentIndex, fDocumentTypeIndex);
1574
1575            if (fGrammarAccess) {
1576                int handle = fAttrList.startAttrList();
1577                fAttrList.addAttr(
1578                    fStringPool.addSymbol("xmlns"),
1579                    fStringPool.addString(SchemaSymbols.URI_SCHEMAFORSCHEMA),
1580                    fStringPool.addSymbol("CDATA"),
1581                    false,
1582                    false); // search
1583
fAttrList.addAttr(
1584                    fStringPool.addSymbol("finalDefault"),
1585                    fStringPool.addString(""),
1586                    fStringPool.addSymbol("CDATA"),
1587                    false,
1588                    false); // search
1589
fAttrList.addAttr(
1590                    fStringPool.addSymbol("exactDefault"),
1591                    fStringPool.addString(""),
1592                    fStringPool.addSymbol("CDATA"),
1593                    false,
1594                    false); // search
1595
fAttrList.endAttrList();
1596                int schemaIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("schema"), fAttrList, handle);
1597                // REVISIT: What should the namespace be? -Ac
1598
fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, schemaIndex);
1599                fCurrentNodeIndex = schemaIndex;
1600            }
1601        }
1602
1603    } // startDTD(int,int,int)
1604

1605    /**
1606     * Supports DOM Level 2 internalSubset additions.
1607     * Called when the internal subset is completely scanned.
1608     */

1609    public void internalSubset(int internalSubset) {
1610
1611        //System.out.println("internalSubset callback:"+fStringPool.toString(internalSubset));
1612

1613        // full expansion
1614
if (fDocumentImpl != null && fDocumentType != null) {
1615            ((DocumentTypeImpl)fDocumentType).setInternalSubset(fStringPool.toString(internalSubset));
1616        }
1617
1618        // deferred expansion
1619
else if (fDeferredDocumentImpl != null) {
1620            fDeferredDocumentImpl.setInternalSubset(fDocumentTypeIndex, internalSubset);
1621        }
1622
1623    }
1624
1625
1626    /**
1627     * This function will be called at the end of the DTD.
1628     */

1629    public void endDTD() throws Exception JavaDoc {
1630
1631        fInDTD = false;
1632
1633        if (fGrammarAccess) {
1634            if (fDocumentImpl != null) {
1635                fCurrentElementNode = fDocumentImpl;
1636            }
1637            else if (fDeferredDocumentImpl != null) {
1638                fCurrentNodeIndex = 0;
1639            }
1640        }
1641
1642    } // endDTD()
1643

1644    /**
1645     * &lt;!ELEMENT Name contentspec&gt;
1646     */

1647    public void elementDecl(QName elementDecl,
1648                            int contentSpecType,
1649                            int contentSpecIndex,
1650                            XMLContentSpec.Provider contentSpecProvider) throws Exception JavaDoc {
1651
1652        if (DEBUG_ATTLIST_DECL) {
1653            String JavaDoc contentModel = XMLContentSpec.toString(contentSpecProvider, fStringPool, contentSpecIndex);
1654            System.out.println("elementDecl(" + fStringPool.toString(elementDecl.rawname) + ", " +
1655                                                contentModel + ")");
1656        }
1657
1658        //
1659
// Create element declaration
1660
//
1661
if (fGrammarAccess) {
1662
1663            if (fDeferredDocumentImpl != null) {
1664
1665                //
1666
// Build element
1667
//
1668

1669                // get element declaration; create if necessary
1670
int schemaIndex = getLastChildElement(fDocumentTypeIndex, "schema");
1671                String JavaDoc elementName = fStringPool.toString(elementDecl.rawname);
1672                int elementIndex = getLastChildElement(schemaIndex, "element", "name", elementName);
1673                if (elementIndex == -1) {
1674                    int handle = fAttrList.startAttrList();
1675                    fAttrList.addAttr(
1676                        fStringPool.addSymbol("name"),
1677                        fStringPool.addString(elementName),
1678                        fStringPool.addSymbol("NMTOKEN"),
1679                        true,
1680                        false); // search
1681
fAttrList.addAttr(
1682                        fStringPool.addSymbol("minOccurs"), // name
1683
fStringPool.addString("1"), // value
1684
fStringPool.addSymbol("NMTOKEN"), // type
1685
false, // specified
1686
false); // search
1687
fAttrList.addAttr(
1688                        fStringPool.addSymbol("nillable"), // name
1689
fStringPool.addString("false"), // value
1690
fStringPool.addSymbol("ENUMERATION"), // type
1691
false, // specified
1692
false); // search
1693
fAttrList.addAttr(
1694                        fStringPool.addSymbol("abstract"), // name
1695
fStringPool.addString("false"), // value
1696
fStringPool.addSymbol("ENUMERATION"), // type
1697
false, // specified
1698
false); // search
1699
fAttrList.addAttr(
1700                        fStringPool.addSymbol("final"), // name
1701
fStringPool.addString("false"), // value
1702
fStringPool.addSymbol("ENUMERATION"), // type
1703
false, // specified
1704
false); // search
1705
fAttrList.endAttrList();
1706                    elementIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("element"), fAttrList, handle);
1707                    fDeferredDocumentImpl.appendChild(schemaIndex, elementIndex);
1708                }
1709
1710                //
1711
// Build content model
1712
//
1713

1714                // get type element; create if necessary
1715
int typeIndex = getLastChildElement(elementIndex, "complexType");
1716                if (typeIndex == -1 && contentSpecType != XMLElementDecl.TYPE_MIXED_SIMPLE) {
1717                    typeIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("complexType"), null, -1);
1718                    // REVISIT: Check for type redeclaration? -Ac
1719
fDeferredDocumentImpl.insertBefore(elementIndex, typeIndex, getFirstChildElement(elementIndex));
1720                }
1721
1722                // create models
1723
switch (contentSpecType) {
1724                    case XMLElementDecl.TYPE_EMPTY: {
1725                        int attributeIndex = fDeferredDocumentImpl.createAttribute(fStringPool.addSymbol("content"), fStringPool.addString("empty"), true);
1726                        fDeferredDocumentImpl.setAttributeNode(typeIndex, attributeIndex);
1727                        break;
1728                    }
1729                    case XMLElementDecl.TYPE_ANY: {
1730                        int anyIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("any"), null, -1);
1731                        fDeferredDocumentImpl.insertBefore(typeIndex, anyIndex, getFirstChildElement(typeIndex));
1732                        break;
1733                    }
1734                    case XMLElementDecl.TYPE_MIXED_SIMPLE: {
1735                        XMLContentSpec contentSpec = new XMLContentSpec();
1736                        contentSpecProvider.getContentSpec(contentSpecIndex, contentSpec);
1737                        contentSpecIndex = contentSpec.value;
1738                        if (contentSpecIndex == -1) {
1739                            int attributeIndex = fDeferredDocumentImpl.createAttribute(fStringPool.addSymbol("type"), fStringPool.addString("string"), true);
1740                            fDeferredDocumentImpl.setAttributeNode(elementIndex, attributeIndex);
1741                        }
1742                        else {
1743                            if (typeIndex == -1) {
1744                                typeIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("complexType"), null, -1);
1745                                // REVISIT: Check for type redeclaration? -Ac
1746
fDeferredDocumentImpl.insertBefore(elementIndex, typeIndex, getFirstChildElement(elementIndex));
1747                            }
1748                            int attributeIndex = fDeferredDocumentImpl.createAttribute(fStringPool.addSymbol("content"), fStringPool.addString("mixed"), true);
1749                            fDeferredDocumentImpl.setAttributeNode(typeIndex, attributeIndex);
1750                            int handle = fAttrList.startAttrList();
1751                            fAttrList.addAttr(
1752                                fStringPool.addSymbol("minOccurs"),
1753                                fStringPool.addString("0"),
1754                                fStringPool.addSymbol("NMTOKEN"),
1755                                true,
1756                                false); // search
1757
fAttrList.addAttr(
1758                                fStringPool.addSymbol("maxOccurs"),
1759                                fStringPool.addString("unbounded"),
1760                                fStringPool.addSymbol("CDATA"),
1761                                true,
1762                                false); // search
1763
fAttrList.endAttrList();
1764                            int choiceIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("choice"), fAttrList, handle);
1765                            fDeferredDocumentImpl.appendChild(typeIndex, choiceIndex);
1766                            while (contentSpecIndex != -1) {
1767
1768                                // get node
1769
contentSpecProvider.getContentSpec(contentSpecIndex, contentSpec);
1770                                int type = contentSpec.type;
1771                                int left = contentSpec.value;
1772                                int right = contentSpec.otherValue;
1773
1774                                // if leaf, skip "#PCDATA" and stop
1775
if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1776                                    break;
1777                                }
1778
1779                                // add right hand leaf
1780
contentSpecProvider.getContentSpec(right, contentSpec);
1781                                handle = fAttrList.startAttrList();
1782                                fAttrList.addAttr(
1783                                    fStringPool.addSymbol("ref"),
1784                                    fStringPool.addString(fStringPool.toString(contentSpec.value)),
1785                                    fStringPool.addSymbol("NMTOKEN"),
1786                                    true,
1787                                    false); //search
1788
fAttrList.endAttrList();
1789                                int rightIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("element"), fAttrList, handle);
1790                                int refIndex = getFirstChildElement(choiceIndex);
1791                                fDeferredDocumentImpl.insertBefore(choiceIndex, rightIndex, refIndex);
1792
1793                                // go to next node
1794
contentSpecIndex = left;
1795                            }
1796                        }
1797                        break;
1798                    }
1799                    case XMLElementDecl.TYPE_CHILDREN: {
1800                        int attributeIndex = fDeferredDocumentImpl.createAttribute(fStringPool.addSymbol("content"), fStringPool.addString("elementOnly"), true);
1801                        fDeferredDocumentImpl.setAttributeNode(typeIndex, attributeIndex);
1802                        int children = createChildren(contentSpecProvider,
1803                                                      contentSpecIndex,
1804                                                      new XMLContentSpec(),
1805                                                      fDeferredDocumentImpl,
1806                                                      -1);
1807                        fDeferredDocumentImpl.insertBefore(typeIndex, children, getFirstChildElement(typeIndex));
1808                        break;
1809                    }
1810                }
1811
1812            } // if defer-node-expansion
1813

1814            else if (fDocumentImpl != null) {
1815
1816                //
1817
// Build element
1818
//
1819

1820                // get element declaration; create if necessary
1821
Element JavaDoc schema = XUtil.getLastChildElement(fDocumentType, "schema");
1822                String JavaDoc elementName = fStringPool.toString(elementDecl.rawname);
1823                Element JavaDoc element = XUtil.getLastChildElement(schema, "element", "name", elementName);
1824                if (element == null) {
1825                    element = fDocumentImpl.createElement("element");
1826                    element.setAttribute("name", elementName);
1827                    element.setAttribute("minOccurs", "1");
1828                    ((AttrImpl)element.getAttributeNode("minOccurs")).setSpecified(false);
1829                    element.setAttribute("nillable", "false");
1830                    ((AttrImpl)element.getAttributeNode("nillable")).setSpecified(false);
1831                    element.setAttribute("abstract", "false");
1832                    ((AttrImpl)element.getAttributeNode("abstract")).setSpecified(false);
1833                    element.setAttribute("final", "false");
1834                    ((AttrImpl)element.getAttributeNode("final")).setSpecified(false);
1835                    schema.appendChild(element);
1836                }
1837
1838                //
1839
// Build content model
1840
//
1841

1842                // get type element; create if necessary
1843
Element JavaDoc type = XUtil.getLastChildElement(element, "complexType");
1844                if (type == null && contentSpecType != XMLElementDecl.TYPE_MIXED_SIMPLE) {
1845                    type = fDocumentImpl.createElement("complexType");
1846                    // REVISIT: Check for type redeclaration? -Ac
1847
element.insertBefore(type, XUtil.getFirstChildElement(element));
1848                }
1849
1850                // create models
1851
switch (contentSpecType) {
1852                    case XMLElementDecl.TYPE_EMPTY: {
1853                        type.setAttribute("content", "empty");
1854                        break;
1855                    }
1856                    case XMLElementDecl.TYPE_ANY: {
1857                        Element JavaDoc any = fDocumentImpl.createElement("any");
1858                        type.insertBefore(any, XUtil.getFirstChildElement(type));
1859                        break;
1860                    }
1861                    case XMLElementDecl.TYPE_MIXED_SIMPLE: {
1862                        XMLContentSpec contentSpec = new XMLContentSpec();
1863                        contentSpecProvider.getContentSpec(contentSpecIndex, contentSpec);
1864                        contentSpecIndex = contentSpec.value;
1865                        if (contentSpecIndex == -1) {
1866                            element.setAttribute("type", "string");
1867                        }
1868                        else {
1869                            if (type == null) {
1870                                type = fDocumentImpl.createElement("complexType");
1871                                // REVISIT: Check for type redeclaration? -Ac
1872
element.insertBefore(type, XUtil.getFirstChildElement(element));
1873                            }
1874                            type.setAttribute("content", "mixed");
1875                            Element JavaDoc choice = fDocumentImpl.createElement("choice");
1876                            choice.setAttribute("minOccurs", "0");
1877                            choice.setAttribute("maxOccurs", "unbounded");
1878                            type.appendChild(choice);
1879                            while (contentSpecIndex != -1) {
1880
1881                                // get node
1882
contentSpecProvider.getContentSpec(contentSpecIndex, contentSpec);
1883                                int cstype = contentSpec.type;
1884                                int csleft = contentSpec.value;
1885                                int csright = contentSpec.otherValue;
1886
1887                                // if leaf, skip "#PCDATA" and stop
1888
if (cstype == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1889                                    break;
1890                                }
1891
1892                                // add right hand leaf
1893
contentSpecProvider.getContentSpec(csright, contentSpec);
1894                                Element JavaDoc right = fDocumentImpl.createElement("element");
1895                                right.setAttribute("ref", fStringPool.toString(contentSpec.value));
1896                                Element JavaDoc ref = XUtil.getFirstChildElement(choice);
1897                                choice.insertBefore(right, ref);
1898
1899                                // go to next node
1900
contentSpecIndex = csleft;
1901                            }
1902                        }
1903                        break;
1904                    }
1905                    case XMLElementDecl.TYPE_CHILDREN: {
1906                        type.setAttribute("content", "elementOnly");
1907                        Element JavaDoc children = createChildren(contentSpecProvider,
1908                                                          contentSpecIndex,
1909                                                          new XMLContentSpec(),
1910                                                          fDocumentImpl,
1911                                                          null);
1912                        type.insertBefore(children, XUtil.getFirstChildElement(type));
1913                        break;
1914                    }
1915                }
1916
1917            } // if NOT defer-node-expansion
1918

1919        } // if grammar-access
1920

1921    } // elementDecl(int,String)
1922

1923    /**
1924     * &lt;!ATTLIST Name AttDef&gt;
1925     */

1926    public void attlistDecl(QName elementDecl, QName attributeDecl,
1927                            int attType, boolean attList, String JavaDoc enumString,
1928                            int attDefaultType, int attDefaultValue)
1929        throws Exception JavaDoc {
1930
1931        if (DEBUG_ATTLIST_DECL) {
1932            System.out.println("attlistDecl(" + fStringPool.toString(elementDecl.rawname) + ", " +
1933                                                fStringPool.toString(attributeDecl.rawname) + ", " +
1934                                                fStringPool.toString(attType) + ", " +
1935                                                enumString + ", " +
1936                                                fStringPool.toString(attDefaultType) + ", " +
1937                                                fStringPool.toString(attDefaultValue) + ")");
1938        }
1939
1940        // deferred expansion
1941
if (fDeferredDocumentImpl != null) {
1942
1943            // get the default value
1944
if (attDefaultValue != -1) {
1945                if (DEBUG_ATTLIST_DECL) {
1946                    System.out.println(" adding default attribute value: "+
1947                                       fStringPool.toString(attDefaultValue));
1948                }
1949
1950                // get element definition
1951
int elementDefIndex = fDeferredDocumentImpl.lookupElementDefinition(elementDecl.rawname);
1952
1953                // create element definition if not already there
1954
if (elementDefIndex == -1) {
1955                    elementDefIndex = fDeferredDocumentImpl.createElementDefinition(elementDecl.rawname);
1956                    fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, elementDefIndex);
1957                }
1958
1959                // add default attribute
1960
int attrIndex =
1961                   fDeferredDocumentImpl.createAttribute(attributeDecl.rawname,
1962                                                         attributeDecl.uri,
1963                                                         attDefaultValue,
1964                                                         false);
1965                fDeferredDocumentImpl.appendChild(elementDefIndex, attrIndex);
1966
1967            }
1968
1969            //
1970
// Create attribute declaration
1971
//
1972
if (fGrammarAccess) {
1973
1974                // get element declaration; create it if necessary
1975
int schemaIndex = getLastChildElement(fDocumentTypeIndex, "schema");
1976                String JavaDoc elementName = fStringPool.toString(elementDecl.rawname);
1977                int elementIndex = getLastChildElement(schemaIndex, "element", "name", elementName);
1978                if (elementIndex == -1) {
1979                    int handle = fAttrList.startAttrList();
1980                    fAttrList.addAttr(
1981                        fStringPool.addSymbol("name"),
1982                        fStringPool.addString(elementName),
1983                        fStringPool.addSymbol("NMTOKEN"),
1984                        true,
1985                        false); //search
1986
fAttrList.endAttrList();
1987                    elementIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("element"), fAttrList, handle);
1988                    fDeferredDocumentImpl.appendChild(schemaIndex, elementIndex);
1989                }
1990
1991                // get type element; create it if necessary
1992
int typeIndex = getLastChildElement(elementIndex, "complexType");
1993                if (typeIndex == -1) {
1994                    typeIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("complexType"), null, -1);
1995                    fDeferredDocumentImpl.insertBefore(elementIndex, typeIndex, getLastChildElement(elementIndex));
1996                }
1997
1998                // create attribute and set its attributes
1999
String JavaDoc attributeName = fStringPool.toString(attributeDecl.rawname);
2000                int attributeIndex = getLastChildElement(elementIndex, "attribute", "name", attributeName);
2001                if (attributeIndex == -1) {
2002                    int handle = fAttrList.startAttrList();
2003                    fAttrList.addAttr(
2004                        fStringPool.addSymbol("name"),
2005                        fStringPool.addString(attributeName),
2006                        fStringPool.addSymbol("NMTOKEN"),
2007                        true,
2008                        false); // search
2009
fAttrList.addAttr(
2010                        fStringPool.addSymbol("maxOccurs"),
2011                        fStringPool.addString("1"),
2012                        fStringPool.addSymbol("CDATA"),
2013                        false,
2014                        false); // search
2015
fAttrList.endAttrList();
2016                    attributeIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("attribute"), fAttrList, handle);
2017                    fDeferredDocumentImpl.appendChild(typeIndex, attributeIndex);
2018
2019                    // attribute type: CDATA, ENTITY, ... , NMTOKENS; ENUMERATION
2020
if (attType == XMLAttributeDecl.TYPE_ENUMERATION) {
2021                        handle = fAttrList.startAttrList();
2022                        fAttrList.addAttr(
2023                            fStringPool.addSymbol("base"),
2024                            fStringPool.addString("NMTOKEN"),
2025                            fStringPool.addSymbol("NMTOKEN"),
2026                            true,
2027                            false); // search
2028
fAttrList.endAttrList();
2029                        int simpleTypeIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("simpleType"), fAttrList, handle);
2030                        fDeferredDocumentImpl.appendChild(attributeIndex, simpleTypeIndex);
2031                        String JavaDoc tokenizerString = enumString.substring(1, enumString.length() - 1);
2032                        StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(tokenizerString, "|");
2033                        while (tokenizer.hasMoreTokens()) {
2034                            handle = fAttrList.startAttrList();
2035                            fAttrList.addAttr(
2036                                fStringPool.addSymbol("value"),
2037                                fStringPool.addString(tokenizer.nextToken()),
2038                                fStringPool.addSymbol("CDATA"),
2039                                true,
2040                                false); // search
2041
fAttrList.endAttrList();
2042                            int enumerationIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("enumeration"), fAttrList, handle);
2043                            fDeferredDocumentImpl.appendChild(simpleTypeIndex, enumerationIndex);
2044                        }
2045                    }
2046                    else {
2047                        int typeNameIndex = -1;
2048                        switch (attType) {
2049                            case XMLAttributeDecl.TYPE_ENTITY: {
2050                                typeNameIndex = fStringPool.addString(attList?"ENTITIES":"ENTITY");
2051                                break;
2052                            }
2053                            case XMLAttributeDecl.TYPE_ID: {
2054                                typeNameIndex = fStringPool.addString("ID");
2055                                break;
2056                            }
2057                            case XMLAttributeDecl.TYPE_IDREF: {
2058                                typeNameIndex = fStringPool.addString(attList?"IDREFS":"IDREF");
2059                                break;
2060                            }
2061                            case XMLAttributeDecl.TYPE_NMTOKEN: {
2062                                typeNameIndex = fStringPool.addString(attList?"NMTOKENS":"NMTOKEN");
2063                                break;
2064                            }
2065                            case XMLAttributeDecl.TYPE_NOTATION: {
2066                                typeNameIndex = fStringPool.addString("NOTATION");
2067                                break;
2068                            }
2069                            case XMLAttributeDecl.TYPE_CDATA:
2070                            default: {
2071                                typeNameIndex = fStringPool.addString("string");
2072                                break;
2073                            }
2074                        }
2075                        int attrIndex = fDeferredDocumentImpl.createAttribute(fStringPool.addSymbol("type"), typeNameIndex, true);
2076                        fDeferredDocumentImpl.setAttributeNode(attributeIndex, attrIndex);
2077                    }
2078
2079                    // attribute default type: #IMPLIED, #REQUIRED, #FIXED
2080
boolean fixed = false;
2081                    switch (attDefaultType) {
2082                        case XMLAttributeDecl.DEFAULT_TYPE_REQUIRED: {
2083                            int useAttrIndex = fDeferredDocumentImpl.createAttribute(fStringPool.addSymbol("use"), fStringPool.addString("required"), true);
2084                            fDeferredDocumentImpl.setAttributeNode(attributeIndex, useAttrIndex);
2085                            break;
2086                        }
2087                        case XMLAttributeDecl.DEFAULT_TYPE_FIXED: {
2088                            fixed = true;
2089                            int useAttrIndex = fDeferredDocumentImpl.createAttribute(fStringPool.addSymbol("use"), fStringPool.addString("fixed"), true);
2090                            fDeferredDocumentImpl.setAttributeNode(attributeIndex, useAttrIndex);
2091                            break;
2092                        }
2093                    }
2094
2095                    // attribute default value
2096
if (attDefaultValue != -1) {
2097                        if (!fixed) {
2098                            int useAttrIndex = fDeferredDocumentImpl.createAttribute(fStringPool.addSymbol("use"), fStringPool.addString("default"), true);
2099                            fDeferredDocumentImpl.setAttributeNode(attributeIndex, useAttrIndex);
2100                        }
2101                        int valueAttrIndex = fDeferredDocumentImpl.createAttribute(fStringPool.addSymbol("value"), attDefaultValue, true);
2102                        fDeferredDocumentImpl.setAttributeNode(attributeIndex, valueAttrIndex);
2103                    }
2104                }
2105            }
2106        }
2107
2108        // full expansion
2109
else if (fDocumentImpl != null) {
2110
2111            // get the default value
2112
if (attDefaultValue != -1) {
2113                if (DEBUG_ATTLIST_DECL) {
2114                    System.out.println(" adding default attribute value: "+
2115                                       fStringPool.toString(attDefaultValue));
2116                }
2117
2118                // get element name
2119
String JavaDoc elementName = fStringPool.toString(elementDecl.rawname);
2120
2121                // get element definition node
2122
NamedNodeMap JavaDoc elements = ((DocumentTypeImpl)fDocumentType).getElements();
2123                ElementDefinitionImpl elementDef = (ElementDefinitionImpl)elements.getNamedItem(elementName);
2124                if (elementDef == null) {
2125                    elementDef = fDocumentImpl.createElementDefinition(elementName);
2126                    ((DocumentTypeImpl)fDocumentType).getElements().setNamedItem(elementDef);
2127                }
2128
2129                // REVISIT: Check for uniqueness of element name? -Ac
2130

2131                // get attribute name and value index
2132
String JavaDoc attrName = fStringPool.toString(attributeDecl.rawname);
2133                String JavaDoc attrValue = fStringPool.toString(attDefaultValue);
2134
2135                // create attribute and set properties
2136
boolean nsEnabled = false;
2137                try { nsEnabled = getNamespaces(); }
2138                catch (SAXException JavaDoc s) {}
2139                AttrImpl attr;
2140                if (nsEnabled) {
2141            String JavaDoc namespaceURI = fStringPool.toString(attributeDecl.uri);
2142            // DOM Level 2 wants all namespace declaration attributes
2143
// to be bound to "http://www.w3.org/2000/xmlns/"
2144
// So as long as the XML parser doesn't do it, it needs to
2145
// done here.
2146
String JavaDoc prefix = fStringPool.toString(attributeDecl.prefix);
2147                    // hide that our parser uses an empty string for null
2148
if (namespaceURI.length() == 0) {
2149                        namespaceURI = null;
2150                    }
2151            if (namespaceURI == null) {
2152            if (prefix != null) {
2153                if (prefix.equals("xmlns")) {
2154                namespaceURI = "http://www.w3.org/2000/xmlns/";
2155                }
2156            } else if (attrName.equals("xmlns")) {
2157                namespaceURI = "http://www.w3.org/2000/xmlns/";
2158            }
2159            }
2160                    attr = (AttrImpl)fDocumentImpl.createAttributeNS(namespaceURI,attrName);
2161                }
2162                else{
2163                    attr = (AttrImpl)fDocumentImpl.createAttribute(attrName);
2164                }
2165                attr.setValue(attrValue);
2166                attr.setSpecified(false);
2167
2168                // add default attribute to element definition
2169
if(nsEnabled){
2170                    elementDef.getAttributes().setNamedItemNS(attr);
2171                }
2172                else{
2173                    elementDef.getAttributes().setNamedItem(attr);
2174                }
2175            }
2176
2177            //
2178
// Create attribute declaration
2179
//
2180
try {
2181            if (fGrammarAccess) {
2182
2183                // get element declaration; create it if necessary
2184
Element JavaDoc schema = XUtil.getLastChildElement(fDocumentType, "schema");
2185                String JavaDoc elementName = fStringPool.toString(elementDecl.rawname);
2186                Element JavaDoc element = XUtil.getLastChildElement(schema, "element", "name", elementName);
2187                if (element == null) {
2188                    element = fDocumentImpl.createElement("element");
2189                    element.setAttribute("name", elementName);
2190                    schema.appendChild(element);
2191                }
2192
2193                // get type element; create it if necessary
2194
Element JavaDoc type = XUtil.getLastChildElement(element, "complexType");
2195                if (type == null) {
2196                    type = fDocumentImpl.createElement("complexType");
2197                    element.insertBefore(type, XUtil.getLastChildElement(element));
2198                }
2199
2200                // create attribute and set its attributes
2201
String JavaDoc attributeName = fStringPool.toString(attributeDecl.rawname);
2202                Element JavaDoc attribute = XUtil.getLastChildElement(element, "attribute", "name", attributeName);
2203                if (attribute == null) {
2204                    attribute = fDocumentImpl.createElement("attribute");
2205                    attribute.setAttribute("name", attributeName);
2206                    attribute.setAttribute("maxOccurs", "1");
2207                    ((AttrImpl)attribute.getAttributeNode("maxOccurs")).setSpecified(false);
2208                    type.appendChild(attribute);
2209
2210                    // attribute type: CDATA, ENTITY, ... , NMTOKENS; ENUMERATION
2211
if (attType == XMLAttributeDecl.TYPE_ENUMERATION) {
2212                        Element JavaDoc simpleType = fDocumentImpl.createElement("simpleType");
2213                        simpleType.setAttribute("base", "NMTOKEN");
2214                        attribute.appendChild(simpleType);
2215                        String JavaDoc tokenizerString = enumString.substring(1, enumString.length() - 1);
2216                        StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(tokenizerString, "|");
2217                        while (tokenizer.hasMoreTokens()) {
2218                            Element JavaDoc enumeration = fDocumentImpl.createElement("enumeration");
2219                            enumeration.setAttribute("value", tokenizer.nextToken());
2220                            simpleType.appendChild(enumeration);
2221                        }
2222                    }
2223                    else {
2224                        String JavaDoc typeName = null;
2225                        switch (attType) {
2226                            case XMLAttributeDecl.TYPE_ENTITY: {
2227                                typeName = attList ? "ENTITIES" : "ENTITY";
2228                                break;
2229                            }
2230                            case XMLAttributeDecl.TYPE_ID: {
2231                                typeName = "ID";
2232                                break;
2233                            }
2234                            case XMLAttributeDecl.TYPE_IDREF: {
2235                                typeName = attList ? "IDREFS" : "IDREF";
2236                                break;
2237                            }
2238                            case XMLAttributeDecl.TYPE_NMTOKEN: {
2239                                typeName = attList ? "NMTOKENS" : "NMTOKEN";
2240                                break;
2241                            }
2242                            case XMLAttributeDecl.TYPE_NOTATION: {
2243                                typeName = "NOTATION";
2244                                break;
2245                            }
2246                            case XMLAttributeDecl.TYPE_CDATA:
2247                            default: {
2248                                typeName = "string";
2249                                break;
2250                            }
2251                        }
2252                        attribute.setAttribute("type", typeName);
2253                    }
2254
2255                    // attribute default type: #IMPLIED, #REQUIRED, #FIXED
2256
boolean fixed = false;
2257                    switch (attDefaultType) {
2258                        case XMLAttributeDecl.DEFAULT_TYPE_REQUIRED: {
2259                            attribute.setAttribute("use", "required");
2260                            break;
2261                        }
2262                        case XMLAttributeDecl.DEFAULT_TYPE_FIXED: {
2263                            attribute.setAttribute("use", "fixed");
2264                            fixed = true;
2265                            break;
2266                        }
2267                    }
2268
2269                    // attribute default value
2270
if (attDefaultValue != -1) {
2271                        if (!fixed) {
2272                            attribute.setAttribute("use", "default");
2273                        }
2274                        attribute.setAttribute("value", fStringPool.toString(attDefaultValue));
2275                    }
2276                }
2277            }
2278            }
2279            catch (Exception JavaDoc e) {
2280                e.printStackTrace(System.err);
2281            }
2282
2283        } // if NOT defer-node-expansion
2284

2285    } // attlistDecl(int,int,int,String,int,int)
2286

2287    /**
2288     * &lt;!ENTITY % Name EntityValue&gt; (internal)
2289     */

2290    public void internalPEDecl(int entityNameIndex, int entityValueIndex) throws Exception JavaDoc {
2291        if (fDeferredDocumentImpl != null) {
2292            if (fGrammarAccess) {
2293                StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2294                str.append("<!ENTITY % ");
2295                str.append(fStringPool.toString(entityNameIndex));
2296                str.append(" \"");
2297                str.append(fStringPool.toString(entityValueIndex));
2298                str.append("\">");
2299                int commentIndex = fStringPool.addString(str.toString());
2300                int internalPEEntityIndex = fDeferredDocumentImpl.createComment(commentIndex);
2301                int schemaIndex = getFirstChildElement(fDocumentTypeIndex, "schema");
2302                fDeferredDocumentImpl.appendChild(schemaIndex, internalPEEntityIndex);
2303            }
2304        }
2305        else if (fDocumentImpl != null) {
2306            if (fGrammarAccess) {
2307                StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2308                str.append("<!ENTITY % ");
2309                str.append(fStringPool.toString(entityNameIndex));
2310                str.append(" \"");
2311                str.append(fStringPool.toString(entityValueIndex));
2312                str.append("\">");
2313                Node JavaDoc internalPEEntity = fDocumentImpl.createComment(str.toString());
2314                Node JavaDoc schema = XUtil.getFirstChildElement(fDocumentType, "schema");
2315                schema.appendChild(internalPEEntity);
2316            }
2317        }
2318        else {
2319            fStringPool.orphanString(entityValueIndex);
2320        }
2321    }
2322
2323    /**
2324     * &lt;!ENTITY % Name ExternalID> (external)
2325     */

2326    public void externalPEDecl(int entityNameIndex, int publicIdIndex, int systemIdIndex) throws Exception JavaDoc {
2327        if (fDeferredDocumentImpl != null) {
2328            if (fGrammarAccess) {
2329                StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2330                str.append("<!ENTITY ");
2331                str.append(fStringPool.toString(entityNameIndex));
2332                str.append(' ');
2333                if (publicIdIndex != -1) {
2334                    str.append("PUBLIC \"");
2335                    str.append(fStringPool.toString(publicIdIndex));
2336                    str.append('"');
2337                    if (systemIdIndex != -1) {
2338                        str.append(" \"");
2339                        str.append(fStringPool.toString(systemIdIndex));
2340                        str.append('"');
2341                    }
2342                }
2343                else if (systemIdIndex != -1) {
2344                    str.append("SYSTEM \"");
2345                    str.append(fStringPool.toString(systemIdIndex));
2346                    str.append('"');
2347                }
2348                str.append('>');
2349                int commentIndex = fStringPool.addString(str.toString());
2350                int externalPEEntityIndex = fDeferredDocumentImpl.createComment(commentIndex);
2351                int schemaIndex = getFirstChildElement(fDocumentTypeIndex, "schema");
2352                fDeferredDocumentImpl.appendChild(schemaIndex, externalPEEntityIndex);
2353            }
2354        }
2355        else if (fDocumentImpl != null) {
2356            if (fGrammarAccess) {
2357                StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2358                str.append("<!ENTITY ");
2359                str.append(fStringPool.toString(entityNameIndex));
2360                str.append(' ');
2361                if (publicIdIndex != -1) {
2362                    str.append("PUBLIC \"");
2363                    str.append(fStringPool.toString(publicIdIndex));
2364                    str.append('"');
2365                    if (systemIdIndex != -1) {
2366                        str.append(" \"");
2367                        str.append(fStringPool.toString(systemIdIndex));
2368                        str.append('"');
2369                    }
2370                }
2371                else if (systemIdIndex != -1) {
2372                    str.append("SYSTEM \"");
2373                    str.append(fStringPool.toString(systemIdIndex));
2374                    str.append('"');
2375                }
2376                str.append('>');
2377                Node JavaDoc externalPEEntity = fDocumentImpl.createComment(str.toString());
2378                Node JavaDoc schema = XUtil.getFirstChildElement(fDocumentType, "schema");
2379                schema.appendChild(externalPEEntity);
2380            }
2381        }
2382    }
2383
2384    /**
2385     * &lt;!ENTITY Name EntityValue&gt; (internal)
2386     */

2387    public void internalEntityDecl(int entityNameIndex, int entityValueIndex)
2388        throws Exception JavaDoc {
2389
2390        // deferred expansion
2391
if (fDeferredDocumentImpl != null) {
2392
2393            if (fDocumentTypeIndex == -1) return; //revisit: should never happen. Exception?
2394

2395            //revisit: how to check if entity was already declared.
2396
// XML spec says that 1st Entity decl is binding.
2397

2398            int newEntityIndex = fDeferredDocumentImpl.createEntity(entityNameIndex, -1, -1, -1);
2399            fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, newEntityIndex);
2400
2401            // REVISIT: Entities were removed from latest working draft. -Ac
2402
// create internal entity declaration
2403
if (fGrammarAccess) {
2404                StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2405                str.append("<!ENTITY ");
2406                str.append(fStringPool.toString(entityNameIndex));
2407                str.append(" \"");
2408                str.append(fStringPool.toString(entityValueIndex));
2409                str.append("\">");
2410                int commentIndex = fStringPool.addString(str.toString());
2411                int textEntityIndex = fDeferredDocumentImpl.createComment(commentIndex);
2412                int schemaIndex = getFirstChildElement(fDocumentTypeIndex, "schema");
2413                fDeferredDocumentImpl.appendChild(schemaIndex, textEntityIndex);
2414            }
2415        }
2416
2417        // full expansion
2418
else if (fDocumentImpl != null) {
2419            if (fDocumentType == null) return; //revisit: should never happen. Exception?
2420

2421            //revisit: how to check if entity was already declared.
2422
// XML spec says that 1st Entity decl is binding.
2423

2424            String JavaDoc entityName = fStringPool.toString(entityNameIndex);
2425
2426            Entity JavaDoc entity = fDocumentImpl.createEntity(entityName);
2427            fDocumentType.getEntities().setNamedItem(entity);
2428
2429            // REVISIT: Entities were removed from latest working draft. -Ac
2430
// create internal entity declaration
2431
if (fGrammarAccess) {
2432                StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2433                str.append("<!ENTITY ");
2434                str.append(fStringPool.toString(entityNameIndex));
2435                str.append(" \"");
2436                str.append(fStringPool.toString(entityValueIndex));
2437                str.append("\">");
2438                Node JavaDoc textEntity = fDocumentImpl.createComment(str.toString());
2439                Node JavaDoc schema = XUtil.getFirstChildElement(fDocumentType, "schema");
2440                schema.appendChild(textEntity);
2441            }
2442        }
2443
2444    } // internalEntityDecl(int,int)
2445

2446    /**
2447     * &lt;!ENTITY Name ExternalID> (external)
2448     */

2449    public void externalEntityDecl(int entityNameIndex, int publicIdIndex, int systemIdIndex)
2450        throws Exception JavaDoc {
2451
2452        // deferred expansion
2453
if (fDeferredDocumentImpl != null) {
2454
2455            //revisit: how to check if entity was already declared.
2456
// XML spec says that 1st Entity decl is binding.
2457

2458            int newEntityIndex = fDeferredDocumentImpl.createEntity(entityNameIndex, publicIdIndex, systemIdIndex, -1);
2459
2460            fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, newEntityIndex);
2461
2462            // REVISIT: Entities were removed from latest working draft. -Ac
2463
// create external entity declaration
2464
if (fGrammarAccess) {
2465                StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2466                str.append("<!ENTITY ");
2467                str.append(fStringPool.toString(entityNameIndex));
2468                str.append(' ');
2469                if (publicIdIndex != -1) {
2470                    str.append("PUBLIC \"");
2471                    str.append(fStringPool.toString(publicIdIndex));
2472                    str.append('"');
2473                    if (systemIdIndex != -1) {
2474                        str.append(" \"");
2475                        str.append(fStringPool.toString(systemIdIndex));
2476                        str.append('"');
2477                    }
2478                }
2479                else if (systemIdIndex != -1) {
2480                    str.append("SYSTEM \"");
2481                    str.append(fStringPool.toString(systemIdIndex));
2482                    str.append('"');
2483                }
2484                str.append('>');
2485                int commentIndex = fStringPool.addString(str.toString());
2486                int externalEntityIndex = fDeferredDocumentImpl.createComment(commentIndex);
2487                int schemaIndex = getFirstChildElement(fDocumentTypeIndex, "schema");
2488                fDeferredDocumentImpl.appendChild(schemaIndex, externalEntityIndex);
2489            }
2490        }
2491
2492        // full expansion
2493
else if (fDocumentImpl != null) {
2494
2495            //revisit: how to check if entity was already declared.
2496
// XML spec says that 1st Entity decl is binding.
2497

2498            String JavaDoc entityName = fStringPool.toString(entityNameIndex);
2499            String JavaDoc publicId = fStringPool.toString(publicIdIndex);
2500            String JavaDoc systemId = fStringPool.toString(systemIdIndex);
2501
2502            EntityImpl entity = (EntityImpl)fDocumentImpl.createEntity(entityName);
2503            if (publicIdIndex != -1) {
2504                entity.setPublicId(publicId);
2505            }
2506            entity.setSystemId(systemId);
2507            fDocumentType.getEntities().setNamedItem(entity);
2508
2509            // REVISIT: Entities were removed from latest working draft. -Ac
2510
// create external entity declaration
2511
if (fGrammarAccess) {
2512                StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2513                str.append("<!ENTITY ");
2514                str.append(fStringPool.toString(entityNameIndex));
2515                str.append(' ');
2516                if (publicIdIndex != -1) {
2517                    str.append("PUBLIC \"");
2518                    str.append(fStringPool.toString(publicIdIndex));
2519                    str.append('"');
2520                    if (systemIdIndex != -1) {
2521                        str.append(" \"");
2522                        str.append(fStringPool.toString(systemIdIndex));
2523                        str.append('"');
2524                    }
2525                }
2526                else if (systemIdIndex != -1) {
2527                    str.append("SYSTEM \"");
2528                    str.append(fStringPool.toString(systemIdIndex));
2529                    str.append('"');
2530                }
2531                str.append('>');
2532                Node JavaDoc externalEntity = fDocumentImpl.createComment(str.toString());
2533                Node JavaDoc schema = XUtil.getFirstChildElement(fDocumentType, "schema");
2534                schema.appendChild(externalEntity);
2535            }
2536        }
2537
2538    } // externalEntityDecl(int,int,int)
2539

2540    /**
2541     * &lt;!ENTITY Name ExternalID NDataDecl> (unparsed)
2542     */

2543    public void unparsedEntityDecl(int entityNameIndex,
2544                                   int publicIdIndex, int systemIdIndex,
2545                                   int notationNameIndex) throws Exception JavaDoc {
2546
2547        // deferred expansion
2548
if (fDeferredDocumentImpl != null) {
2549
2550            //revisit: how to check if entity was already declared.
2551
// XML spec says that 1st Entity decl is binding.
2552

2553            int newEntityIndex = fDeferredDocumentImpl.createEntity(entityNameIndex, publicIdIndex, systemIdIndex, notationNameIndex);
2554
2555            fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, newEntityIndex);
2556
2557            // REVISIT: Entities were removed from latest working draft. -Ac
2558
// add unparsed entity declaration
2559
if (fGrammarAccess) {
2560                StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2561                str.append("<!ENTITY ");
2562                str.append(fStringPool.toString(entityNameIndex));
2563                str.append(' ');
2564                if (publicIdIndex != -1) {
2565                    str.append("PUBLIC \"");
2566                    str.append(fStringPool.toString(publicIdIndex));
2567                    str.append('"');
2568                    if (systemIdIndex != -1) {
2569                        str.append(" \"");
2570                        str.append(fStringPool.toString(systemIdIndex));
2571                        str.append('"');
2572                    }
2573                }
2574                else if (systemIdIndex != -1) {
2575                    str.append("SYSTEM \"");
2576                    str.append(fStringPool.toString(systemIdIndex));
2577                    str.append('"');
2578                }
2579                str.append(" NDATA ");
2580                str.append(fStringPool.toString(notationNameIndex));
2581                str.append('>');
2582                int commentIndex = fStringPool.addString(str.toString());
2583                int unparsedEntityIndex = fDeferredDocumentImpl.createComment(commentIndex);
2584                int schemaIndex = getFirstChildElement(fDocumentTypeIndex, "schema");
2585                fDeferredDocumentImpl.appendChild(schemaIndex, unparsedEntityIndex);
2586            }
2587        }
2588
2589        // full expansion
2590
else if (fDocumentImpl != null) {
2591
2592            //revisit: how to check if entity was already declared.
2593
// XML spec says that 1st Entity decl is binding.
2594

2595            String JavaDoc entityName = fStringPool.toString(entityNameIndex);
2596            String JavaDoc publicId = fStringPool.toString(publicIdIndex);
2597            String JavaDoc systemId = fStringPool.toString(systemIdIndex);
2598            String JavaDoc notationName = fStringPool.toString(notationNameIndex);
2599
2600            EntityImpl entity = (EntityImpl)fDocumentImpl.createEntity(entityName);
2601            if (publicIdIndex != -1) {
2602                entity.setPublicId(publicId);
2603            }
2604            entity.setSystemId(systemId);
2605            entity.setNotationName(notationName);
2606            fDocumentType.getEntities().setNamedItem(entity);
2607
2608            // REVISIT: Entities were removed from latest working draft. -Ac
2609
// add unparsed entity declaration
2610
if (fGrammarAccess) {
2611                StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2612                str.append("<!ENTITY ");
2613                str.append(fStringPool.toString(entityNameIndex));
2614                str.append(' ');
2615                if (publicIdIndex != -1) {
2616                    str.append("PUBLIC \"");
2617                    str.append(fStringPool.toString(publicIdIndex));
2618                    str.append('"');
2619                    if (systemIdIndex != -1) {
2620                        str.append(" \"");
2621                        str.append(fStringPool.toString(systemIdIndex));
2622                        str.append('"');
2623                    }
2624                }
2625                else if (systemIdIndex != -1) {
2626                    str.append("SYSTEM \"");
2627                    str.append(fStringPool.toString(systemIdIndex));
2628                    str.append('"');
2629                }
2630                str.append(" NDATA ");
2631                str.append(fStringPool.toString(notationNameIndex));
2632                str.append('>');
2633                Node JavaDoc unparsedEntity = fDocumentImpl.createComment(str.toString());
2634                Node JavaDoc schema = XUtil.getFirstChildElement(fDocumentType, "schema");
2635                schema.appendChild(unparsedEntity);
2636            }
2637        }
2638
2639    } // unparsedEntityDecl(int,int,int,int)
2640

2641    /**
2642     * &lt;!NOTATION Name ExternalId>
2643     */

2644    public void notationDecl(int notationNameIndex, int publicIdIndex, int systemIdIndex)
2645        throws Exception JavaDoc {
2646
2647        // deferred expansion
2648
if (fDeferredDocumentImpl != null) {
2649
2650            //revisit: how to check if entity was already declared.
2651
// XML spec says that 1st Entity decl is binding.
2652

2653            int newNotationIndex = fDeferredDocumentImpl.createNotation(notationNameIndex, publicIdIndex, systemIdIndex);
2654
2655            fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, newNotationIndex);
2656
2657            // create notation declaration
2658
if (fGrammarAccess) {
2659                int schemaIndex = getLastChildElement(fDocumentTypeIndex, "schema");
2660                String JavaDoc notationName = fStringPool.toString(notationNameIndex);
2661                int notationIndex = getLastChildElement(schemaIndex, "notation", "name", notationName);
2662                if (notationIndex == -1) {
2663                    int handle = fAttrList.startAttrList();
2664                    fAttrList.addAttr(
2665                        fStringPool.addSymbol("name"),
2666                        fStringPool.addString(notationName),
2667                        fStringPool.addSymbol("NMTOKEN"),
2668                        true,
2669                        false); // search
2670
if (publicIdIndex != -1) {
2671                        fAttrList.addAttr(
2672                            fStringPool.addSymbol("public"),
2673                            publicIdIndex,
2674                            fStringPool.addSymbol("CDATA"),
2675                            true,
2676                            false); // search
2677
}
2678                    if (systemIdIndex != -1) {
2679                        fAttrList.addAttr(
2680                            fStringPool.addSymbol("system"),
2681                            systemIdIndex,
2682                            fStringPool.addSymbol("CDATA"),
2683                            true,
2684                            false); // search
2685
}
2686                    fAttrList.endAttrList();
2687                    notationIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol("notation"), fAttrList, handle);
2688                    fDeferredDocumentImpl.appendChild(schemaIndex, notationIndex);
2689                }
2690            }
2691        }
2692
2693        // full expansion
2694
else if (fDocumentImpl != null) {
2695
2696            // REVISIT: how to check if entity was already declared.
2697
// XML spec says that 1st Entity decl is binding.
2698

2699            String JavaDoc notationName = fStringPool.toString(notationNameIndex);
2700            String JavaDoc publicId = fStringPool.toString(publicIdIndex);
2701            String JavaDoc systemId = fStringPool.toString(systemIdIndex);
2702
2703            NotationImpl notationImpl = (NotationImpl)fDocumentImpl.createNotation(notationName);
2704            notationImpl.setPublicId(publicId);
2705            if (systemIdIndex != -1) {
2706                notationImpl.setSystemId(systemId);
2707            }
2708
2709            fDocumentType.getNotations().setNamedItem(notationImpl);
2710
2711            // create notation declaration
2712
if (fGrammarAccess) {
2713                Element JavaDoc schema = XUtil.getFirstChildElement(fDocumentType, "schema");
2714                Element JavaDoc notation = XUtil.getFirstChildElement(schema, "notation", "name", notationName);
2715                if (notation == null) {
2716                    notation = fDocument.createElement("notation");
2717                    notation.setAttribute("name", notationName);
2718                    //notation.setAttribute("export", "true");
2719
//((AttrImpl)notation.getAttributeNode("export")).setSpecified(false);
2720
if (publicId != null) {
2721                        notation.setAttribute("public", publicId);
2722                    }
2723                    if (systemIdIndex != -1) {
2724                        notation.setAttribute("system", systemId);
2725                    }
2726                    schema.appendChild(notation);
2727                }
2728            }
2729        }
2730
2731    } // notationDecl(int,int,int)
2732

2733    //
2734
// Private methods
2735
//
2736

2737    /** Returns the first child element of the specified node. */
2738    private int getFirstChildElement(int nodeIndex) {
2739        int childIndex = getLastChildElement(nodeIndex);
2740        while (childIndex != -1) {
2741            int prevIndex = getPrevSiblingElement(childIndex);
2742            if (prevIndex == -1) {
2743                break;
2744            }
2745            childIndex = prevIndex;
2746        }
2747        return childIndex;
2748    }
2749
2750    /** Returns the first child element of the specified node. */
2751    private int getFirstChildElement(int nodeIndex, String JavaDoc name) {
2752        int childIndex = getLastChildElement(nodeIndex);
2753        if (childIndex != -1) {
2754            int nameIndex = fStringPool.addSymbol(name);
2755            while (childIndex != -1) {
2756                if (fDeferredDocumentImpl.getNodeName(childIndex, false) == nameIndex) {
2757                    break;
2758                }
2759                int prevIndex = getPrevSiblingElement(childIndex);
2760                childIndex = prevIndex;
2761            }
2762        }
2763        return childIndex;
2764    }
2765
2766    /** Returns the last child element of the specified node. */
2767    private int getLastChildElement(int nodeIndex) {
2768        int childIndex = fDeferredDocumentImpl.getLastChild(nodeIndex, false);
2769        while (childIndex != -1) {
2770            if (fDeferredDocumentImpl.getNodeType(childIndex, false) == Node.ELEMENT_NODE) {
2771                return childIndex;
2772            }
2773            childIndex = fDeferredDocumentImpl.getPrevSibling(childIndex, false);
2774        }
2775        return -1;
2776    }
2777
2778    /** Returns the previous sibling element of the specified node. */
2779    private int getPrevSiblingElement(int nodeIndex) {
2780        int siblingIndex = fDeferredDocumentImpl.getPrevSibling(nodeIndex, false);
2781        while (siblingIndex != -1) {
2782            if (fDeferredDocumentImpl.getNodeType(siblingIndex, false) == Node.ELEMENT_NODE) {
2783                return siblingIndex;
2784            }
2785            siblingIndex = fDeferredDocumentImpl.getPrevSibling(siblingIndex, false);
2786        }
2787        return -1;
2788    }
2789
2790    /** Returns the first child element with the given name. */
2791    private int getLastChildElement(int nodeIndex, String JavaDoc elementName) {
2792        int childIndex = getLastChildElement(nodeIndex);
2793        if (childIndex != -1) {
2794            while (childIndex != -1) {
2795                String JavaDoc nodeName = fDeferredDocumentImpl.getNodeNameString(childIndex, false);
2796                if (nodeName.equals(elementName)) {
2797                    return childIndex;
2798                }
2799                childIndex = getPrevSiblingElement(childIndex);
2800            }
2801        }
2802        return -1;
2803    }
2804
2805    /** Returns the next sibling element with the given name. */
2806    private int getPrevSiblingElement(int nodeIndex, String JavaDoc elementName) {
2807        int siblingIndex = getPrevSiblingElement(nodeIndex);
2808        if (siblingIndex != -1) {
2809            while (siblingIndex != -1) {
2810                String JavaDoc nodeName = fDeferredDocumentImpl.getNodeNameString(siblingIndex, false);
2811                if (nodeName.equals(elementName)) {
2812                    return siblingIndex;
2813                }
2814                siblingIndex = getPrevSiblingElement(siblingIndex);
2815            }
2816        }
2817        return -1;
2818    }
2819
2820    /** Returns the first child element with the given name. */
2821    private int getLastChildElement(int nodeIndex, String JavaDoc elemName, String JavaDoc attrName, String JavaDoc attrValue) {
2822        int childIndex = getLastChildElement(nodeIndex, elemName);
2823        if (childIndex != -1) {
2824            while (childIndex != -1) {
2825                int attrIndex = fDeferredDocumentImpl.getNodeValue(childIndex, false);
2826                while (attrIndex != -1) {
2827                    String JavaDoc nodeName = fDeferredDocumentImpl.getNodeNameString(attrIndex, false);
2828                    if (nodeName.equals(attrName)) {
2829                        // REVISIT: Do we need to normalize the text? -Ac
2830
int textIndex = fDeferredDocumentImpl.getLastChild(attrIndex, false);
2831                        String JavaDoc nodeValue = fDeferredDocumentImpl.getNodeValueString(textIndex, false);
2832                        if (nodeValue.equals(attrValue)) {
2833                            return childIndex;
2834                        }
2835                    }
2836                    attrIndex = fDeferredDocumentImpl.getPrevSibling(attrIndex, false);
2837                }
2838                childIndex = getPrevSiblingElement(childIndex, elemName);
2839            }
2840        }
2841        return -1;
2842    }
2843
2844    /** Returns the next sibling element with the given name and attribute. */
2845    private int getPrevSiblingElement(int nodeIndex, String JavaDoc elemName, String JavaDoc attrName, String JavaDoc attrValue) {
2846        int siblingIndex = getPrevSiblingElement(nodeIndex, elemName);
2847        if (siblingIndex != -1) {
2848            int attributeNameIndex = fStringPool.addSymbol(attrName);
2849            while (siblingIndex != -1) {
2850                int attrIndex = fDeferredDocumentImpl.getNodeValue(siblingIndex, false);
2851                while (attrIndex != -1) {
2852                    int attrValueIndex = fDeferredDocumentImpl.getNodeValue(attrIndex, false);
2853                    if (attrValue.equals(fStringPool.toString(attrValueIndex))) {
2854                        return siblingIndex;
2855                    }
2856                    attrIndex = fDeferredDocumentImpl.getPrevSibling(attrIndex, false);
2857                }
2858                siblingIndex = getPrevSiblingElement(siblingIndex, elemName);
2859            }
2860        }
2861        return -1;
2862    }
2863
2864    /**
2865     * Copies the source tree into the specified place in a destination
2866     * tree. The source node and its children are appended as children
2867     * of the destination node.
2868     * <p>
2869     * <em>Note:</em> This is an iterative implementation.
2870     */

2871    private void copyInto(Node JavaDoc src, int destIndex) throws Exception JavaDoc {
2872
2873        // for ignorable whitespace features
2874
boolean domimpl = src != null && src instanceof DocumentImpl;
2875
2876        // placement variables
2877
Node JavaDoc start = src;
2878        Node JavaDoc parent = src;
2879        Node JavaDoc place = src;
2880
2881        // traverse source tree
2882
while (place != null) {
2883
2884            // copy this node
2885
int nodeIndex = -1;
2886            short type = place.getNodeType();
2887            switch (type) {
2888                case Node.CDATA_SECTION_NODE: {
2889                    boolean ignorable = domimpl && ((TextImpl)place).isIgnorableWhitespace();
2890                    nodeIndex = fDeferredDocumentImpl.createCDATASection(fStringPool.addString(place.getNodeValue()), ignorable);
2891                    break;
2892                }
2893                case Node.COMMENT_NODE: {
2894                    nodeIndex = fDeferredDocumentImpl.createComment(fStringPool.addString(place.getNodeValue()));
2895                    break;
2896                }
2897                case Node.ELEMENT_NODE: {
2898                    XMLAttrList attrList = null;
2899                    int handle = -1;
2900                    NamedNodeMap JavaDoc attrs = place.getAttributes();
2901                    if (attrs != null) {
2902                        int length = attrs.getLength();
2903                        if (length > 0) {
2904                            handle = fAttrList.startAttrList();
2905                            for (int i = 0; i < length; i++) {
2906                                Attr JavaDoc attr = (Attr JavaDoc)attrs.item(i);
2907                                String JavaDoc attrName = attr.getNodeName();
2908                                String JavaDoc attrValue = attr.getNodeValue();
2909                                fAttrList.addAttr(
2910                                    fStringPool.addSymbol(attrName),
2911                                    fStringPool.addString(attrValue),
2912                                    fStringPool.addSymbol("CDATA"), // REVISIT
2913
attr.getSpecified(),
2914                                    false); // search
2915
}
2916                            fAttrList.endAttrList();
2917                            attrList = fAttrList;
2918                        }
2919                    }
2920                    nodeIndex = fDeferredDocumentImpl.createElement(fStringPool.addSymbol(place.getNodeName()), attrList, handle);
2921                    break;
2922                }
2923                case Node.ENTITY_REFERENCE_NODE: {
2924                    nodeIndex = fDeferredDocumentImpl.createEntityReference(fStringPool.addSymbol(place.getNodeName()));
2925                    break;
2926                }
2927                case Node.PROCESSING_INSTRUCTION_NODE: {
2928                    nodeIndex = fDeferredDocumentImpl.createProcessingInstruction(fStringPool.addSymbol(place.getNodeName()), fStringPool.addString(place.getNodeValue()));
2929                    break;
2930                }
2931                case Node.TEXT_NODE: {
2932                    boolean ignorable = domimpl && ((TextImpl)place).isIgnorableWhitespace();
2933                    nodeIndex = fDeferredDocumentImpl.createTextNode(fStringPool.addString(place.getNodeValue()), ignorable);
2934                    break;
2935                }
2936                default: {
2937                    throw new IllegalArgumentException JavaDoc("PAR010 Can't copy node type, "+
2938                                                       type+" ("+
2939                                                       place.getNodeName()+')'
2940                                                       +"\n"+type+"\t"+place.getNodeName());
2941                }
2942            }
2943            fDeferredDocumentImpl.appendChild(destIndex, nodeIndex);
2944
2945            // iterate over children
2946
if (place.hasChildNodes()) {
2947                parent = place;
2948                place = place.getFirstChild();
2949                destIndex = nodeIndex;
2950            }
2951
2952            // advance
2953
else {
2954                place = place.getNextSibling();
2955                while (place == null && parent != start) {
2956                    place = parent.getNextSibling();
2957                    parent = parent.getParentNode();
2958                    destIndex = fDeferredDocumentImpl.getParentNode(destIndex, false);
2959                }
2960            }
2961
2962        }
2963
2964    } // copyInto(Node,int)
2965

2966    /**
2967     * Sets the appropriate occurrence count attributes on the specified
2968     * model element.
2969     */

2970    private void setOccurrenceCount(Element JavaDoc model, int minOccur, int maxOccur) {
2971
2972        // min
2973
model.setAttribute("minOccurs", Integer.toString(minOccur));
2974        if (minOccur == 1) {
2975            ((AttrImpl)model.getAttributeNode("minOccurs")).setSpecified(false);
2976        }
2977
2978        // max
2979
if (maxOccur == -1) {
2980            model.setAttribute("maxOccurs", "*");
2981        }
2982        else if (maxOccur != 1) {
2983            model.setAttribute("maxOccurs", Integer.toString(maxOccur));
2984        }
2985
2986    } // setOccurrenceCount(Element,int,int)
2987

2988    /** Creates the children for the element decl. */
2989    private Element JavaDoc createChildren(XMLContentSpec.Provider provider,
2990                                   int index, XMLContentSpec node,
2991                                   DocumentImpl factory,
2992                                   Element JavaDoc parent) throws Exception JavaDoc {
2993
2994        // get occurrence count
2995
provider.getContentSpec(index, node);
2996        int occurs = -1;
2997        switch (node.type) {
2998            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
2999                occurs = '+';
3000                provider.getContentSpec(node.value, node);
3001                break;
3002            }
3003            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
3004                occurs = '*';
3005                provider.getContentSpec(node.value, node);
3006                break;
3007            }
3008            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
3009                occurs = '?';
3010                provider.getContentSpec(node.value, node);
3011                break;
3012            }
3013        }
3014
3015        // flatten model
3016
int nodeType = node.type;
3017        switch (nodeType) {
3018
3019            // CHOICE or SEQUENCE
3020
case XMLContentSpec.CONTENTSPECNODE_CHOICE:
3021            case XMLContentSpec.CONTENTSPECNODE_SEQ: {
3022
3023                // go down left side
3024
int leftIndex = node.value;
3025                int rightIndex = node.otherValue;
3026                Element JavaDoc left = createChildren(provider, leftIndex, node,
3027                                              factory, parent);
3028
3029                // go down right side
3030
Element JavaDoc right = createChildren(provider, rightIndex, node,
3031                                               factory, null);
3032
3033                // append left children
3034
boolean choice = nodeType == XMLContentSpec.CONTENTSPECNODE_CHOICE;
3035                String JavaDoc type = choice ? "choice" : "sequence";
3036                Element JavaDoc model = left;
3037                if (!left.getNodeName().equals(type)) {
3038                    String JavaDoc minOccurs = left.getAttribute("minOccurs");
3039                    String JavaDoc maxOccurs = left.getAttribute("maxOccurs");
3040                    boolean min1 = minOccurs.length() == 0 || minOccurs.equals("1");
3041                    boolean max1 = maxOccurs.length() == 0 || maxOccurs.equals("1");
3042                    if (parent == null || (min1 && max1)) {
3043                        model = factory.createElement(type);
3044                        model.appendChild(left);
3045                    }
3046                    else {
3047                        model = parent;
3048                    }
3049                }
3050
3051                // set occurrence count
3052
switch (occurs) {
3053                    case '+': {
3054                        model.setAttribute("maxOccurs", "unbounded");
3055                        break;
3056                    }
3057                    case '*': {
3058                        model.setAttribute("minOccurs", "0");
3059                        model.setAttribute("maxOccurs", "unbounded");
3060                        break;
3061                    }
3062                    case '?': {
3063                        model.setAttribute("minOccurs", "0");
3064                        break;
3065                    }
3066                }
3067
3068                // append right children
3069
model.appendChild(right);
3070
3071                // return model
3072
return model;
3073            }
3074
3075            // LEAF
3076
case XMLContentSpec.CONTENTSPECNODE_LEAF: {
3077                Element JavaDoc leaf = factory.createElement("element");
3078                leaf.setAttribute("ref", fStringPool.toString(node.value));
3079                switch (occurs) {
3080                    case '+': {
3081                        leaf.setAttribute("maxOccurs", "unbounded");
3082                        break;
3083                    }
3084                    case '*': {
3085                        leaf.setAttribute("minOccurs", "0");
3086                        leaf.setAttribute("maxOccurs", "unbounded");
3087                        break;
3088                    }
3089                    case '?': {
3090                        leaf.setAttribute("minOccurs", "0");
3091                        break;
3092                    }
3093                }
3094                return leaf;
3095            }
3096
3097        } // switch node type
3098

3099        // error
3100
return null;
3101
3102    } // createChildren(XMLContentSpec.Provider,int,XMLContentSpec,DocumentImpl,Element):Element
3103

3104    /** Creates the children for the deferred element decl. */
3105    private int createChildren(XMLContentSpec.Provider provider,
3106                               int index, XMLContentSpec node,
3107                               DeferredDocumentImpl factory,
3108                               int parent) throws Exception JavaDoc {
3109
3110        // get occurrence count
3111
provider.getContentSpec(index, node);
3112        int occurs = -1;
3113        switch (node.type) {
3114            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
3115                occurs = '+';
3116                provider.getContentSpec(node.value, node);
3117                break;
3118            }
3119            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
3120                occurs = '*';
3121                provider.getContentSpec(node.value, node);
3122                break;
3123            }
3124            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
3125                occurs = '?';
3126                provider.getContentSpec(node.value, node);
3127                break;
3128            }
3129        }
3130
3131        // flatten model
3132
int nodeType = node.type;
3133        switch (nodeType) {
3134
3135            // CHOICE or SEQUENCE
3136
case XMLContentSpec.CONTENTSPECNODE_CHOICE:
3137            case XMLContentSpec.CONTENTSPECNODE_SEQ: {
3138
3139                // go down left side
3140
int leftIndex = node.value;
3141                int rightIndex = node.otherValue;
3142                int left = createChildren(provider, leftIndex, node,
3143                                          factory, parent);
3144
3145                // go down right side
3146
int right = createChildren(provider, rightIndex, node,
3147                                           factory, -1);
3148
3149                // append left children
3150
boolean choice = nodeType == XMLContentSpec.CONTENTSPECNODE_CHOICE;
3151                int type = fStringPool.addSymbol(choice ? "choice" : "sequence");
3152                int model = left;
3153                if (factory.getNodeName(left, false) != type) {
3154                    int minOccurs = factory.getAttribute(left, fStringPool.addSymbol("minOccurs"));
3155                    int maxOccurs = factory.getAttribute(left, fStringPool.addSymbol("maxOccurs"));
3156                    boolean min1 = minOccurs == -1 || fStringPool.toString(minOccurs).equals("1");
3157                    boolean max1 = maxOccurs == -1 || fStringPool.toString(maxOccurs).equals("1");
3158                    if (parent == -1 || (min1 && max1)) {
3159                        model = factory.createElement(type, null, -1);
3160                        factory.appendChild(model, left);
3161                    }
3162                    else {
3163                        model = parent;
3164                    }
3165                }
3166
3167                // set occurrence count
3168
switch (occurs) {
3169                    case '+': {
3170                        int maxOccurs = factory.createAttribute(fStringPool.addSymbol("maxOccurs"),
3171                                                                fStringPool.addString("unbounded"),
3172                                                                true);
3173                        factory.setAttributeNode(model, maxOccurs);
3174                        break;
3175                    }
3176                    case '*': {
3177                        int minOccurs = factory.createAttribute(fStringPool.addSymbol("minOccurs"),
3178                                                                fStringPool.addString("0"),
3179                                                                true);
3180                        factory.setAttributeNode(model, minOccurs);
3181                        int maxOccurs = factory.createAttribute(fStringPool.addSymbol("maxOccurs"),
3182                                                                fStringPool.addString("unbounded"),
3183                                                                true);
3184                        factory.setAttributeNode(model, maxOccurs);
3185                        break;
3186                    }
3187                    case '?': {
3188                        int minOccurs = factory.createAttribute(fStringPool.addSymbol("minOccurs"),
3189                                                                fStringPool.addString("0"),
3190                                                                true);
3191                        factory.setAttributeNode(model, minOccurs);
3192                        break;
3193                    }
3194                }
3195
3196                // append right children
3197
factory.appendChild(model, right);
3198
3199                // return model
3200
return model;
3201            }
3202
3203            // LEAF
3204
case XMLContentSpec.CONTENTSPECNODE_LEAF: {
3205                int handle = fAttrList.startAttrList();
3206                fAttrList.addAttr(
3207                    fStringPool.addSymbol("ref"),
3208                    fStringPool.addString(fStringPool.toString(node.value)),
3209                    fStringPool.addSymbol("NMTOKEN"),
3210                    true,
3211                    false); // search
3212
switch (occurs) {
3213                    case '+': {
3214                        fAttrList.addAttr(
3215                            fStringPool.addSymbol("maxOccurs"),
3216                            fStringPool.addString("unbounded"),
3217                            fStringPool.addSymbol("CDATA"),
3218                            true,
3219                            false); // search
3220
break;
3221                    }
3222                    case '*': {
3223                        fAttrList.addAttr(
3224                            fStringPool.addSymbol("minOccurs"),
3225                            fStringPool.addString("0"),
3226                            fStringPool.addSymbol("NMTOKEN"),
3227                            true,
3228                            false); // search
3229
fAttrList.addAttr(
3230                            fStringPool.addSymbol("maxOccurs"),
3231                            fStringPool.addString("unbounded"),
3232                            fStringPool.addSymbol("CDATA"),
3233                            true,
3234                            false); // search
3235
break;
3236                    }
3237                    case '?': {
3238                        fAttrList.addAttr(
3239                            fStringPool.addSymbol("minOccurs"),
3240                            fStringPool.addString("0"),
3241                            fStringPool.addSymbol("NMTOKEN"),
3242                            true,
3243                            false); // search
3244
break;
3245                    }
3246                }
3247                fAttrList.endAttrList();
3248                int leaf = factory.createElement(fStringPool.addSymbol("element"), fAttrList, handle);
3249                return leaf;
3250            }
3251
3252        } // switch node type
3253

3254        // error
3255
return -1;
3256
3257    } // createChildren(XMLContentSpec.Provider,int,XMLContentSpec,DeferredDocumentImpl,int):int
3258

3259} // class DOMParser
3260
Popular Tags