KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > tax > io > XNIBuilder


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.tax.io;
21
22 import java.io.*;
23 import java.net.URL JavaDoc;
24 import java.util.*;
25 import java.text.MessageFormat JavaDoc;
26 import java.lang.reflect.*;
27
28 import org.xml.sax.*;
29 import org.xml.sax.helpers.LocatorImpl JavaDoc;
30
31 import org.apache.xerces.xni.*;
32 import org.apache.xerces.xni.parser.XMLDTDSource;
33 import org.apache.xerces.xni.parser.XMLDTDContentModelSource;
34 import org.apache.xerces.xni.parser.XMLDocumentSource;
35 import org.apache.xerces.parsers.*;
36
37 import org.netbeans.tax.*;
38 import org.netbeans.tax.io.*;
39 import org.netbeans.tax.decl.*;
40 import java.util.List JavaDoc;
41
42 /**
43  * Xerces Native Interface ("XNI") based implementation. It sets
44  * namespace non-aware and non-validating features.
45  * <p>
46  * Do instantiate it directly, prefer TreeBuilder interface loaded by TreeStreamSource
47  * (i.e. ParserLoader). It will do necessary implementation isolation.
48  * <p>
49  * Every well-formed source must be possible to convert to tree structure.
50  * //!!! A mechanism of supressing particular implemenation constrains will
51  * be needed (JAXP validation on request could be a good approach).
52  *
53  * @author Petr Kuzel
54  * @version rewritten to XNI 2.4.0
55  */

56 public final class XNIBuilder implements TreeBuilder {
57         
58     private static final boolean ASSERT = false;
59     
60     // private static final PrintStream dbg = System.err;
61

62     private static final String JavaDoc DTD_WRAPPER = "<!DOCTYPE DTD PUBLIC \"{0}\" \"{1}\">"; // NOI18N
63

64     // TreeStreamSource defines
65
private Class JavaDoc buildClass; //DTD or XML [or Fragment]
66

67     private InputSource inputSource;
68     
69     // interface for reporting errors during the tree construction
70
private TreeStreamBuilderErrorHandler errorHandler;
71     
72     // do not forget to set to the parser
73
private EntityResolver entityResolver;
74     
75     
76     /** Creates new TreeStreamBuilderXercesImpl */
77     public XNIBuilder (Class JavaDoc buildClass, InputSource inputSource, EntityResolver entityResolver, TreeStreamBuilderErrorHandler errorHandler) {
78         init (buildClass, inputSource, entityResolver, errorHandler);
79     }
80     
81     /** Initialize it */
82     private void init (Class JavaDoc buildClass, InputSource inputSource, EntityResolver entityResolver, TreeStreamBuilderErrorHandler errorHandler) {
83         this.inputSource = inputSource;
84         this.buildClass = buildClass;
85         this.errorHandler = errorHandler;
86         this.entityResolver = entityResolver;
87     }
88     
89     /**
90      * Build new TreeDocument by delegating to private class (hiding its
91      * public XNI interfaces implementation).
92      */

93     public TreeDocumentRoot buildDocument () throws TreeException {
94         
95         boolean buildXML = true;
96         InputSource builderSource = inputSource;
97         EntityResolver builderResolver = entityResolver;
98         
99         /*
100          * We are building DTD so wrap into auxiliary InputSource that
101          * can be passed to XML parser.
102          */

103         if (buildClass == TreeDTD.class) {
104             
105             String JavaDoc src = MessageFormat.format (DTD_WRAPPER, new Object JavaDoc[] {
106                 DTDEntityResolver.DTD_ID,
107                 inputSource.getSystemId ()
108             });
109             
110             builderSource = new InputSource (inputSource.getSystemId ());
111             builderSource.setCharacterStream (new StringReader (src));
112             
113             builderResolver = new DTDEntityResolver ();
114             buildXML = false;
115         }
116         
117         XMLBuilder builder = this.new XMLBuilder (buildXML);
118         
119         try {
120             final String JavaDoc SAX_FEATURE = "http://xml.org/sax/features/"; // NOI18N
121
final String JavaDoc XERCES_FEATURE = "http://apache.org/xml/features/"; // NOI18N
122

123             builder.setFeature (SAX_FEATURE + "namespaces", false); //!!! // NOI18N
124
builder.setFeature (SAX_FEATURE + "validation", false); //!!! // NOI18N
125
builder.setFeature (SAX_FEATURE + "external-general-entities", true); // NOI18N
126
builder.setFeature (SAX_FEATURE + "external-parameter-entities", true); // NOI18N
127
builder.setFeature (XERCES_FEATURE + "validation/warn-on-duplicate-attdef", true); // NOI18N
128
// unrecognized in Xerces 2.4.0
129
//builder.setFeature (XERCES_FEATURE + "validation/warn-on-undeclared-elemdef", true); // NOI18N
130
builder.setFeature (XERCES_FEATURE + "allow-java-encodings", true); // NOI18N
131
builder.setFeature (XERCES_FEATURE + "scanner/notify-char-refs", true); // NOI18N
132
builder.setFeature (XERCES_FEATURE + "scanner/notify-builtin-refs", true); // NOI18N
133

134             // final String XERCES_PROPERTY = "http://apache.org/xml/properties/"; // NOI18N
135
// builder.setProperty(XERCES_PROPERTY + "internal/entity-resolver", builderResolver); // NOI18N
136

137             builder.setEntityResolver (builderResolver);
138             
139             // the builder extends XNIDocumentParser that receives
140
// error events directly
141

142             builder.setErrorHandler (new ErrorHandler () {
143                 public void error (org.xml.sax.SAXParseException JavaDoc e) {}
144                 public void warning (org.xml.sax.SAXParseException JavaDoc e) {}
145                 public void fatalError (org.xml.sax.SAXParseException JavaDoc e) {}
146             });
147             builder.parse (builderSource);
148             
149         } catch (DTDStopException stop) {
150             
151             // we just stopped the parser at the end of standalone DTD
152

153         } catch (SAXException sax) {
154             
155             // test whether wrapped exception is XNI one
156
// if so it wrrap actual exception
157

158             Exception JavaDoc exception = sax.getException ();
159             
160             if ((exception instanceof DTDStopException) == false ) {
161                 
162                 if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("sax", sax); // NOI18N
163
if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("exception", exception); // NOI18N
164

165                 if (exception instanceof XNIException) {
166                     exception = ((XNIException)exception).getException ();
167                 }
168                 if (exception != null) {
169                     if (!!! (exception instanceof TreeException)) {
170                         exception = new TreeException (sax);
171                     }
172                 } else {
173                     exception = new TreeException (sax);
174                 }
175                 throw (TreeException) exception;
176             }
177             
178         } catch (IOException exc) {
179             if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("exc", exc); // NOI18N
180

181             throw new TreeException (exc);
182         }
183         
184         return builder.getDocumentRoot ();
185     }
186     
187     
188     /*
189      * Resolve DTD to original InputSource, forward others.
190      * DTD builder uses wrapping InputSource so XML parser can be used as DTD one.
191      */

192     private class DTDEntityResolver implements EntityResolver {
193         
194         static final String JavaDoc DTD_ID = "PRIVATE//AUXILIARY DTD ID//PRIVATE"; // NOI18N
195

196         public InputSource resolveEntity (String JavaDoc publicId, String JavaDoc systemId) throws SAXException, IOException {
197             
198             if (DTD_ID.equals (publicId)) {
199                 return inputSource;
200             } else {
201                 return entityResolver.resolveEntity (publicId, systemId);
202             }
203         }
204         
205     }
206     
207     /*
208      * It is used to signal that we are parsing a DTD and we reached end of it.
209      * So we can stop the parser by throwing it.
210      */

211     private class DTDStopException extends XNIException {
212         
213         /** Serial Version UID */
214         private static final long serialVersionUID =4994054007367982021L;
215         
216         public DTDStopException () {
217             super ("This exception is used to signal end of DTD."); // NOI18N
218
};
219         
220         //
221
// Look like wrapping exception, so it be converted so SAXException
222
// that wraps this one.
223
//
224
public Exception JavaDoc getException () {
225             return this;
226         }
227         
228         public Throwable JavaDoc fillInStackTrace () {
229             return this;
230         }
231     }
232     
233     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
234

235     /*
236      * A pipeline of document components starts with a document source; is
237      * followed by zero or more document filters; and ends with a document
238      * handler.
239      *
240      * The document handler follows.
241      */

242     
243     
244     /**
245      * Listens on XNI creating XML structure. It uses mini XNI pipe
246      * featuring just with scanner. A validator is used but validity
247      * are discarded since tree must be just well-formed ("WF").
248      */

249     private class XMLBuilder extends SAXParser implements XMLDTDContentModelHandler, XMLDocumentHandler, XMLDTDHandler {
250         
251         private TreeDocumentRoot returnDocument; // initial parent
252
private TreeDocumentRoot document; // tmp variable
253

254         private TreeDocumentType doctype; // it will become parent node of DTD content
255
private TreeNode tempNode; // current working node
256

257         private Stack parentObjectListStack; // parents' child lists stack
258
private TreeObjectList parentObjectList; // top of the stack
259
private Stack parentNodeStack; // some times we need nodes directly
260

261         private Stack elementStack; // ??? it could be avoided
262
private int entityCounter; // how deep we entered
263

264         private boolean isXMLDocument; // do we parser XML or standalone DTD
265
private boolean inCDATASection; // we are in the middle of CDATA
266
private boolean inDTD; // we are in DTD
267
private boolean isCorrect; // builder internal error
268
private boolean inCharacterRef; //
269

270         private StringBuffer JavaDoc cdataSectionBuffer; // working CDATA section buffer
271
private QName tmpQName = new QName (); // working Qname
272
private TreeAttlistDecl attlistDecl = null; // latest attlistdecl
273

274         private int errors = 0; // fatal error counter
275

276         private final String JavaDoc XML_ENTITY = "[xml]"; // name of entity that precedes startDocument call // NOI18N
277
private final String JavaDoc DTD_ENTITY = "[dtd]"; // external DTD entity name // NOI18N
278

279         private XMLLocator locator;
280         
281         private boolean hasExternalDTD = false;
282         
283         private RememberingReader rememberingReader;
284
285         private XMLDTDSource xmldtdSource; // XMLDTDHandler 2.4.0
286

287         private XMLDTDContentModelSource xmldtdContentModelSource; // XMLDTDContentModelHandler 2.4.0
288

289         private XMLDocumentSource xmlDocumentSource; // XMLDocumentHanlder 2.4.0
290

291         /**
292          * Create a parser with standard configuration.
293          * @param xmlDocument false if building standalone DTD
294          */

295         public XMLBuilder (boolean xmlDocument) {
296             isXMLDocument = xmlDocument;
297             entityCounter = 0;
298             isCorrect = false;
299             inCDATASection = false;
300             inDTD = false;
301             parentObjectListStack = new Stack ();
302             parentNodeStack = new Stack ();
303             elementStack = new Stack (); //stacks all non-empty elements
304
cdataSectionBuffer = new StringBuffer JavaDoc ();
305             inCharacterRef = false;
306         }
307         
308         
309         /**
310          * Sample user reader replacing it by remebering one suitable for
311          * internal DTD remebering.
312          */

313         public void parse (InputSource in) throws IOException, SAXException {
314             Reader reader = in.getCharacterStream ();
315             if (reader != null) {
316                 rememberingReader = new RememberingReader (reader);
317                 in.setCharacterStream (rememberingReader);
318                 rememberingReader.startRemembering (); //remember internal DTD see startElement for end
319
}
320             
321             super.parse (in);
322         }
323         
324
325         //
326
// XMLDocumentHandler methods
327
//
328

329         public XMLDocumentSource getDocumentSource() {
330             return xmlDocumentSource;
331         }
332
333         public void setDocumentSource(XMLDocumentSource src) {
334             xmlDocumentSource = src;
335         }
336
337         // XMLDocumentHandler 2.4.0
338
public void startDocument (XMLLocator locator, String JavaDoc encoding, NamespaceContext nsCtx, Augmentations a) {
339             startDocument(locator, encoding, a);
340         }
341
342         /**
343          * The start of the document.
344          *
345          * @throws SAXException Thrown by handler to signal an error.
346          */

347         // XMLDocumentHandler 2.0.0b4
348
public void startDocument (XMLLocator locator, String JavaDoc encoding, Augmentations a) {
349             
350             trace ("startDocument()"); // NOI18N
351

352             this.locator = locator;
353             try {
354                 returnDocument = document = new TreeDocument (null,null,null);
355                 pushParentNode ((TreeDocument)document);
356             } catch (TreeException exc) {
357                 throw new XNIException (exc);
358             }
359         } // startDocument()
360

361         /**
362          * Notifies of the presence of an XMLDecl line in the document. If
363          * present, this method will be called immediately following the
364          * startDocument call.
365          *
366          * @param version The XML version.
367          * @param encoding The IANA encoding name of the document, or null if
368          * not specified.
369          * @param standalone The standalone value, or null if not specified.
370          *
371          * @throws SAXException Thrown by handler to signal an error.
372          */

373         public void xmlDecl (String JavaDoc version, String JavaDoc encoding, String JavaDoc standalone, Augmentations a) {
374             
375             trace ("xmlDecl()"); // NOI18N
376

377             try {
378                 ((TreeDocument)document).setHeader (version, encoding, standalone);
379             } catch (TreeException exc) {
380                 throw new XNIException (exc);
381             }
382         } // xmlDecl(String,String,String)
383

384         
385         // XMLDTDHandler 2.4.0 and XMLDocumentHandler > 2.0.0b4
386
public void textDecl (String JavaDoc version, String JavaDoc encoding, Augmentations a) {
387             
388             trace ("textDecl()"); // NOI18N
389

390             // if we are DTD parser scanning base DTD document entity
391
if (isXMLDocument == false && inDTD && inEntity () == false) {
392                 try {
393                     ((TreeDTD)document).setHeader (version, encoding);
394                 } catch (TreeException ex) {
395                     throw new XNIException (ex);
396                 }
397             }
398         }
399
400         // XMLDTDHAndler 2.0.0b4
401
public void textDecl (String JavaDoc version, String JavaDoc encoding) {
402             textDecl(version, encoding, null);
403         }
404         
405         /**
406          * Notifies of the presence of the DOCTYPE line in the document.
407          */

408         public void doctypeDecl (String JavaDoc rootElement, String JavaDoc publicId, String JavaDoc systemId, Augmentations a) {
409             
410             trace ("doctypeDecl(" + rootElement + "," + publicId + ")"); // NOI18N
411

412             try {
413                 TreeDocumentType _doctype =
414                 new TreeDocumentType (rootElement, publicId, systemId);
415                 setBeginPosition (_doctype);
416                 ((TreeDocument)document).setDocumentType (_doctype);
417                 
418                 doctype = _doctype;
419             } catch (TreeException exc) {
420                 throw new XNIException (exc);
421             }
422         } // doctypeDecl(String,String,String)
423

424         
425         /**
426          * The start of an element.
427          */

428         public void startElement (QName element, XMLAttributes attributes, Augmentations a) {
429             
430             trace ("startElement(" + element + ")"); // NOI18N
431

432             try {
433                 tempNode = new TreeElement (element.rawname);
434                 startElementImpl ((TreeElement) tempNode, attributes);
435                 
436                 pushParentNode ((TreeElement)tempNode);
437                 elementStack.push (tempNode);
438                 
439             } catch (TreeException exc) {
440                 throw new XNIException (exc);
441             }
442         } // startElement(QName,XMLAttributes)
443

444         /**
445          * This callback represents &lt;.....<b>/</b>&gt;.
446          */

447         public void emptyElement (QName qName, XMLAttributes attributes, Augmentations a) {
448             
449             trace ("emptyElement(" + qName + ")"); // NOI18N
450

451             try {
452                 tempNode = new TreeElement (qName.rawname, true);
453                 startElementImpl ((TreeElement) tempNode, attributes);
454             } catch (TreeException exc) {
455                 throw new XNIException (exc);
456             }
457         }
458         
459         /**
460          * Insert element and its attributes at hiearchy
461          */

462         private void startElementImpl (TreeElement elem, XMLAttributes attributes) throws TreeException {
463             
464             setBeginPosition (elem);
465             
466             //??? is it really neccessary
467
if (currentParentNode () instanceof TreeDocument) {
468                 ((TreeDocument)currentParentNode ()).setDocumentElement (elem);
469             } else {
470                 appendChild (elem);
471             }
472             
473             // handle attributes
474

475             int attrCount = attributes.getLength ();
476             for (int i = 0; i < attrCount; i++) {
477                 boolean specified = attributes.isSpecified (i);
478                 
479                 if ( specified == true ) { // TEMPORARY -- not specified nodes will not be added into element
480

481                     attributes.getName (i, tmpQName); //fill tmpQName
482
String JavaDoc val = attributes.getNonNormalizedValue (i); //???getNonNormalizedValue
483

484                     TreeAttribute attr; // to be filled
485

486                     if (val.indexOf ('&') < 0) {
487                         
488                         attr = new TreeAttribute (tmpQName.rawname, val, specified);
489                         
490                     } else {
491                         
492                         attr = new TreeAttribute (tmpQName.rawname, "", specified); // NOI18N
493
List JavaDoc list = attr.getValueList ();
494                         list.clear ();
495                         
496                         // build attribute value, split content as refs and text
497

498                         int lastOffset = 0; // offset
499
for (int offset = val.indexOf ('&'); offset >= 0; offset = val.indexOf ('&', offset + 1)) {
500                             
501                             int endOffset = val.indexOf (';', offset);
502                             String JavaDoc name = val.substring (offset + 1, endOffset);
503                             
504                             if (offset > lastOffset) {
505                                 // insert text
506
TreeText text =
507                                 new TreeText (val.substring (lastOffset, offset));
508                                 list.add (text);
509                             }
510                             
511                             
512                             if (name.startsWith ("#")) { // NOI18N
513
TreeCharacterReference chref =
514                                 new TreeCharacterReference (name);
515                                 list.add (chref);
516                             } else {
517                                 TreeGeneralEntityReference gref =
518                                 new TreeGeneralEntityReference (name);
519                                 list.add (gref);
520                             }
521                             
522                             lastOffset = endOffset + 1;
523                         }
524                         
525                         if (val.length () > lastOffset) {
526                             String JavaDoc lastText = val.substring (lastOffset);
527                             list.add (new TreeText (lastText));
528                         }
529                     }
530                     
531                     if ( !!! specified ) {
532                         setReadOnly (attr);
533                     }
534                     elem.addAttribute (attr);
535                     
536                 } // if ( specified == true )
537
}
538             
539             // recall remenbered internal DTD //!!!
540

541             if (rememberingReader == null) {
542                 return;
543             }
544             StringBuffer JavaDoc mem = rememberingReader.stopRemembering ();
545             if (mem == null) return;
546             
547             String JavaDoc idtd = mem.toString ();
548             int start = -1, end = -1; // results
549
int now, last = -1; // tmps
550
char delimiter;
551             
552             if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("TreeStreamBuilderXercesImpl: going to inspect:\n" + idtd);
553
554             // find out DOCTYPE declaration
555
// #23197 eliminate doctypes in comment (simple aproximation)
556

557             final String JavaDoc DOCTYPE = "<!DOCTYPE"; // NOI18N
558
int pos = -1;
559 DOCTYPE_LOOP:
560             while (true) {
561                 pos = idtd.indexOf (DOCTYPE, ++pos);
562                 if (pos == -1) {
563                     Util.THIS.debug ("XNIBuilder: no DOCTYPE detected."); // NOI18N
564
return;
565                 } else {
566                     int comment = -1;
567                     while (true) {
568                         comment = idtd.indexOf("<!--", ++comment); // NOI18N
569
if (comment != -1 && comment < pos) {
570                             if (idtd.indexOf("-->", comment) > pos) { // NOI18N
571
// it is commented out, try another
572
break;
573                             } else {
574                                 // commentd ends before, but it does not proof anything
575
continue;
576                             }
577                         } else {
578                             break DOCTYPE_LOOP;
579                         }
580                     }
581                 }
582             }
583             
584             if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("\nlast index = " + pos);
585
586             // skip root element name
587

588             pos += DOCTYPE.length ();
589             for (; StringUtil.isWS (idtd.charAt (pos)); pos ++);
590             for (; StringUtil.isWS (idtd.charAt (pos)) == false; pos ++);
591             for (; StringUtil.isWS (idtd.charAt (pos)); pos ++);
592             
593
594             if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("\nafter process index = " + pos);
595
596             // SYSTEM or PUBLIC or [
597

598             if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("\nTesting DOCTYPE kind-----\n" + idtd.substring (pos));
599             
600             if (idtd.charAt (pos) == '[') { // just internal dtd
601
start = ++pos;
602             } else if (idtd.charAt (pos) == 'S') { //SYSTEM "" [
603
for (; StringUtil.isWS (idtd.charAt (pos)) == false; pos ++);
604                 for (; StringUtil.isWS (idtd.charAt (pos)); pos ++);
605                 delimiter = idtd.charAt (pos++);
606                 for (; idtd.charAt (pos) != delimiter; pos ++);
607                 pos++;
608                 for (; StringUtil.isWS (idtd.charAt (pos)); pos ++);
609                 if (idtd.charAt (pos) == '[') {
610                     start = ++pos;
611                 }
612             } else if (idtd.charAt (pos) == 'P') { // PUBLIC "" "" [
613
for (; StringUtil.isWS (idtd.charAt (pos)) == false; pos ++);
614                 for (; StringUtil.isWS (idtd.charAt (pos)); pos ++);
615                 delimiter = idtd.charAt (pos++);
616                 for (; idtd.charAt (pos) != delimiter; pos ++);
617                 pos++;
618                 for (; StringUtil.isWS (idtd.charAt (pos)); pos ++);
619                 delimiter = idtd.charAt (pos++);
620                 for (; idtd.charAt (pos) != delimiter; pos ++);
621                 pos++;
622                 for (; StringUtil.isWS (idtd.charAt (pos)); pos ++);
623                 if (idtd.charAt (pos) == '[') {
624                     start = ++pos;
625                 }
626             }
627             
628             if (start == -1) {
629                 if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("TreeStreamBuilderXercesImpl: it does not have internal DTD.");
630
631                 return;
632             } else {
633                 if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("\n---Analyzing internal DTD:\n" + idtd.substring (start));
634             }
635             
636             // search for internal DTD end
637

638             for (last = pos-1; idtd.startsWith ("]>", pos) == false && last < pos;) {
639                 
640                 last = pos;
641                 
642                 // skip comments and WS
643
for (; StringUtil.isWS (idtd.charAt (pos)); pos ++);
644                 
645                 now = StringUtil.skipDelimited (idtd, pos, "<!--", "-->");
646                 if (now != -1) {
647                     pos = now;
648                     continue;
649                 }
650                 
651                 // skip PIs
652
now = StringUtil.skipDelimited (idtd, pos, "<?", "?>");
653                 if (now != -1) {
654                     pos = now;
655                     continue;
656                 }
657                 
658                 // skip decls
659
now = StringUtil.skipDelimited (idtd, pos, '<', '>' , "\"'");
660                 if (now != -1) {
661                     pos = now;
662                     continue;
663                 }
664                 
665                 // skip references
666
now = StringUtil.skipDelimited (idtd, pos, '%', ';' , "");
667                 if (now != -1) {
668                     pos = now;
669                     continue;
670                 }
671                 
672             }
673             
674             if (last == pos) {
675                 if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("TreeStreamBuilderXercesImpl: end not reached");
676
677                 return;
678             }
679             
680             String JavaDoc internalDTDText = idtd.substring (start, pos);
681
682             if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("Internal DTD:" + internalDTDText + "\n--");
683             
684             // use introspectio to set it
685

686             try {
687                 if (doctype == null) return;
688                 Class JavaDoc klass = doctype.getClass ();
689                 Field field = klass.getDeclaredField ("internalDTDText");
690                 field.setAccessible (true);
691                 field.set (doctype, internalDTDText);
692             } catch (RuntimeException JavaDoc ex) {
693                 throw ex;
694             } catch (Exception JavaDoc ex) {
695                 // ignore introspection exceptions
696
if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("TreeStreamBuilderXercesImpl.settingInternaDTDText", ex);
697             }
698             
699         }
700         
701         
702         /**
703          * Character content.
704          */

705         public void characters (XMLString text, Augmentations a) {
706             
707             try {
708                 if (inCharacterRef == true) return; // ignore resolved
709

710                 if (inDTD) {
711                     if (currentParentNode () instanceof TreeConditionalSection) {
712                         if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("\n*** TreeStreamBuilderXercesImpl::characters: XMLString = '" + text + "'"); // NOI18N
713

714                         ((TreeConditionalSection)currentParentNode ()).setIgnoredContent (
715                         text.toString ()
716                         );
717                     }
718                 } else if (inCDATASection) {
719                     cdataSectionBuffer.append (text.toString ());
720                 } else {
721                     tempNode = new TreeText (text.toString ());
722                     setBeginPosition (tempNode);
723                     appendChild ((TreeText)tempNode);
724                 }
725             } catch (TreeException exc) {
726                 throw new XNIException (exc);
727             }
728         } // characters(XMLString)
729

730         
731         // XMLDTDHandler 2.4.0
732
public void ignoredCharacters (XMLString text, Augmentations a) {
733             characters( text, null);
734         }
735
736         // XMLDTDHandler 2.0.0b4
737
public void characters (XMLString text) {
738             characters( text, null);
739         }
740         
741         /**
742          * Ignorable whitespace.
743          */

744         public void ignorableWhitespace (XMLString text, Augmentations a) {
745             try {
746                 tempNode = new TreeText (text.toString ()); //???
747
setBeginPosition (tempNode);
748                 appendChild ((TreeText)tempNode);
749             } catch (TreeException exc) {
750                 throw new XNIException (exc);
751             }
752         } // ignorableWhitespace(XMLString)
753

754         /**
755          * The end of an element.
756          */

757         public void endElement (QName element, Augmentations a) {
758             trace ("endElement(" + element + ")"); // NOI18N
759

760             try {
761                 TreeElement el = (TreeElement) elementStack.pop ();
762                 el.normalize (); //??? parser return multiline text as multiple characters()
763
popParentNode ();
764             } catch (TreeException exc) {
765                 throw new XNIException (exc);
766             }
767         } // endElement(QName)
768

769         /**
770          * The start of a CDATA section. Buffer its content.
771          */

772         public void startCDATA (Augmentations a) {
773             inCDATASection = true;
774             cdataSectionBuffer.delete (0, cdataSectionBuffer.length ());
775             //!!! save position
776
} // startCDATA()
777

778         /**
779          * The end of a CDATA section.
780          */

781         public void endCDATA (Augmentations a) {
782             
783             inCDATASection = false;
784             
785             try {
786                 tempNode = new TreeCDATASection (cdataSectionBuffer.toString ());
787                 setBeginPosition (tempNode); //!!! error
788
appendChild ((TreeCDATASection)tempNode);
789             } catch (TreeException exc) {
790                 throw new XNIException (exc);
791             }
792         } // endCDATA()
793

794         /**
795          * The end of the document.
796          */

797         public void endDocument (Augmentations a) {
798             trace ("endDocument()"); // NOI18N
799

800             if (parentObjectListStack.isEmpty () == false) {
801                 if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("Inconsistency at parentStack: " + parentObjectListStack ); // NOI18N
802
} else if (elementStack.isEmpty () == false) {
803                 if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("Inconsistency at elementStack: " + parentObjectListStack ); // NOI18N
804
} else {
805                 isCorrect = true;
806             }
807         } // endDocument()
808

809         //
810
// XMLDocumentHandler and XMLDTDHandler methods
811
//
812

813         public void endPrefixMapping (String JavaDoc prefix, Augmentations a) {
814             // not interested
815
}
816         
817         public void startPrefixMapping (String JavaDoc prefix, String JavaDoc uri, Augmentations a) {
818             // not interested
819
}
820         
821         // XMLDTDHandler 2.4.0
822
public void startExternalSubset(XMLResourceIdentifier entity, Augmentations a) {
823             startEntity(
824                 "[dtd]", entity.getPublicId(), entity.getLiteralSystemId(),
825                 entity.getBaseSystemId(), null, a
826             );
827         }
828
829         public void startGeneralEntity(String JavaDoc name, XMLResourceIdentifier entity, String JavaDoc encoding, Augmentations a) {
830             startEntity(
831                 name, entity.getPublicId(), entity.getLiteralSystemId(),
832                 entity.getBaseSystemId(), encoding, a
833             );
834         }
835
836         /**
837          * This method notifies of the start of an entity. The document entity
838          * has the pseudo-name of "[xml]"; The DTD has the pseudo-name of "[dtd];
839          * parameter entity names start with '%'; and general entity names are
840          * just the entity name.
841          *
842          * @param encoding special value of "IGNORE" markg parameter
843          * entities in DTD markup (these are ignored)
844          */

845         private void startEntity (String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId,
846         String JavaDoc baseSystemId, String JavaDoc encoding, Augmentations a) {
847             
848             trace ("startEntity(" + name + ")"); // NOI18N
849

850             try {
851                 
852                 // do not theat these as external entities
853
// DTD is wrapped intentionally
854

855                 if (XML_ENTITY.equals (name)) return;
856                 if (isXMLDocument == false && DTD_ENTITY.equals (name)) return;
857                 
858                 
859                 if (DTD_ENTITY.equals (name) && isXMLDocument) {
860                     
861                     hasExternalDTD = true;
862                     
863                     // we are entering external DTD attach all to DOCTYPE ObjectList
864
// There is performance optimalization: External DTD model
865
// can be shared among several instances referring it.
866
// It's currently managed by the TreeDocumentType class
867
TreeObjectList external = doctype.getExternalDTD ();
868                     if (external == null) {
869                         TreeDTDFragment entity = new TreeDTDFragment();
870                         TreeObjectList holder = entity.getChildNodes();
871                         pushParentObjectList (holder);
872                         doctype.setExternalDTD(entity);
873                     } else {
874                         // It was already parsed, ignore its content
875
pushParentObjectList(null);
876                     }
877
878                 } else if (name.startsWith ("#")) { // NOI18N
879

880                     tempNode = new TreeCharacterReference (name);
881                     appendChild (tempNode);
882                     setBeginPosition (tempNode);
883                     inCharacterRef = true;
884                     
885                 } else if ( "lt".equals (name) || "gt".equals (name) || "amp".equals (name) // NOI18N
886
|| "apos".equals (name) || "quot".equals (name)) { // NOI18N
887

888                     tempNode = new TreeGeneralEntityReference (name);
889                     appendChild (tempNode);
890                     setBeginPosition (tempNode);
891                     inCharacterRef = true;
892                     
893                 } else if (name.startsWith ("%")) { // NOI18N
894

895                     if ("IGNORE".equals (encoding)) { // NOI18N
896
// skip entities in markup, place the into unattached list
897
name = name.substring (1);
898                         pushParentNode (new TreeParameterEntityReference (name));
899                         
900                     } else {
901                         name = name.substring (1);
902                         tempNode = new TreeParameterEntityReference (name); //??? external entities
903
appendChild ((TreeParameterEntityReference)tempNode);
904                         setBeginPosition (tempNode);
905                         pushParentNode ((TreeEntityReference)tempNode);
906                     }
907                     
908                 } else {
909                     
910                     tempNode = new TreeGeneralEntityReference (name); //??? external entities
911
appendChild ((TreeGeneralEntityReference)tempNode);
912                     setBeginPosition (tempNode);
913                     pushParentNode ((TreeEntityReference)tempNode);
914                     
915                 }
916                 
917                 enterEntity ();
918                 
919             } catch (TreeException exc) {
920                 throw new XNIException (exc);
921             }
922         } // startEntity(String,String,String,String)
923

924
925         // XMLDTDHandler 2.0.0b4
926
public void startEntity (String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId,
927         String JavaDoc baseSystemId, String JavaDoc encoding) {
928             startEntity(name, publicId, systemId, baseSystemId, encoding, null);
929         }
930         
931         // XMLDTDHanlder 2.4.0
932
public void startParameterEntity(String JavaDoc name, XMLResourceIdentifier entity, String JavaDoc encoding, Augmentations a) {
933             String JavaDoc pname = name;
934             if (false == name.startsWith("%")) {
935                 pname = "%" + name;
936             }
937             startEntity(
938                 pname, entity.getPublicId(), entity.getLiteralSystemId(),
939                 entity.getBaseSystemId(), encoding, a
940             );
941         }
942
943         /**
944          * A comment.
945          */

946         // XMLDTDHandler 2.4.0 and XMLDocumentHandler
947
public void comment (XMLString text, Augmentations a) {
948             
949             trace ("comment()"); // NOI18N
950

951             try {
952                 tempNode = new TreeComment (text.toString ());
953                 setBeginPosition (tempNode);
954                 appendChild ((TreeComment)tempNode);
955             } catch (TreeException exc) {
956                 throw new XNIException (exc);
957             }
958         } // comment(XMLString)
959

960         // XMLDTDHandler 2.0.0b4
961
public void comment (XMLString text) {
962             comment(text, null);
963         }
964         
965         /**
966          * A processing instruction. Processing instructions consist of a
967          * target name and, optionally, text data. The data is only meaningful
968          * to the application.
969          */

970         // XMLDTDHandler 2.4.0 and XMLDocumentHandler > 2.0.0b4
971
public void processingInstruction (String JavaDoc target, XMLString data, Augmentations a) {
972             
973             trace ("processingInstruction(" + target + ")"); // NOI18N
974

975             try {
976                 tempNode = new TreeProcessingInstruction (target, data.toString ());
977                 setBeginPosition (tempNode);
978                 appendChild ((TreeProcessingInstruction)tempNode);
979             } catch (TreeException exc) {
980                 throw new XNIException (exc);
981             }
982         } // processingInstruction(String,XMLString)
983

984         // XMLDTDHandler 2.0.0b4
985
public void processingInstruction (String JavaDoc target, XMLString data) {
986             processingInstruction( target, data, null);
987         }
988         
989         // XMLDTDHandler 2.4.0
990
public void endExternalSubset(Augmentations a) {
991             endEntity("[dtd]", a);
992         }
993
994         // XMLDTDHandler 2.4.0
995
public void endParameterEntity(String JavaDoc name, Augmentations a) {
996             String JavaDoc pname = name;
997             if (false == name.startsWith("%")) {
998                 pname = "%" + name;
999             }
1000            endEntity(pname, a);
1001        }
1002
1003        public void endGeneralEntity(String JavaDoc name, Augmentations a) {
1004            endEntity(name, a);
1005        }
1006
1007        /**
1008         * This method notifies the end of an entity. The document entity has
1009         * the pseudo-name of "[xml]"; the DTD has the pseudo-name of "[dtd];
1010         * parameter entity names start with '%'; and general entity names are
1011         * just the entity name.
1012         */

1013        private void endEntity (String JavaDoc name, Augmentations a) {
1014            trace ("endEntity(" + name + ")"); // NOI18N
1015

1016            // skip for root entities of XML documents and
1017
// standalone DTDs parsed by DTD parser
1018

1019            if (XML_ENTITY.equals (name)) return;
1020            if (isXMLDocument == false && DTD_ENTITY.equals (name)) return;
1021            
1022            exitEntity ();
1023            
1024            if (inCharacterRef == true) {
1025                inCharacterRef = false;
1026                return;
1027            }
1028            
1029            if (isXMLDocument && DTD_ENTITY.equals (name)) {
1030                popParentObjectList (); // DOCTYPE ObjectList
1031
} else {
1032                popParentNode ();
1033            }
1034            
1035        } // endEntity(String)
1036

1037        
1038        //??? DTDHandler
1039
public void endEntity (String JavaDoc name) {
1040            endEntity(name, null);
1041        }
1042        
1043        // XMLDTDHandler methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1044

1045        // XMLDTDHandler 2.4.0
1046
public XMLDTDSource getDTDSource() {
1047            return xmldtdSource;
1048        }
1049
1050        // XMLDTDHandler 2.4.0
1051
public void setDTDSource( XMLDTDSource src) {
1052            xmldtdSource = src;
1053        }
1054
1055        // XMLDTDHandler 2.0.0b4
1056
public void startDTD ( XMLLocator locator, Augmentations a) {
1057            startDTD(locator);
1058        }
1059        
1060        /**
1061         * The start of the DTD (external part of it is reported by startEntity).
1062         */

1063        // XMLDTDHandler 2.0.0b4
1064
public void startDTD ( XMLLocator locator) {
1065            trace ("startDTD()"); // NOI18N
1066

1067            try {
1068                inDTD = true;
1069                
1070                if (isXMLDocument) {
1071                    
1072                    pushParentNode (doctype);
1073                    
1074                } else {
1075                    
1076                    // replace returnDocument
1077
returnDocument = document = new TreeDTD (null,null);
1078                    pushParentNode ((TreeDTD)document);
1079                }
1080            } catch (TreeException exc) {
1081                throw new XNIException (exc);
1082            }
1083        } // startDTD()
1084

1085        // XMLDTDHandler 2.4.0
1086
public void elementDecl (String JavaDoc name, String JavaDoc contentModel, Augmentations a) {
1087            elementDecl(name, contentModel);
1088        }
1089
1090        /**
1091         * An element declaration.
1092         */

1093        // XMLDTDHandler 2.0.0b4
1094
public void elementDecl (String JavaDoc name, String JavaDoc cM) {
1095            trace ("elementDecl(" + name + ")"); // NOI18N
1096
if (ASSERT)
1097                doAssert (inDTD);
1098            
1099            try {
1100                appendChild (new TreeElementDecl (name, this.contentModel));
1101                this.contentModel = null;
1102            } catch (TreeException exc) {
1103                throw new XNIException (exc);
1104            }
1105            
1106        } // elementDecl(String,String)
1107

1108        // XMLDTDHandler 2.4.0
1109
public void startAttlist (String JavaDoc elementName, Augmentations a) {
1110            startAttlist(elementName);
1111        }
1112
1113        /**
1114         * The start of an attribute list.
1115         */

1116        // XMLDTDHandler 2.0.0b4
1117
public void startAttlist (String JavaDoc elementName) {
1118            
1119            trace ("startAttlist(" + elementName + ")"); // NOI18N
1120

1121            try {
1122                tempNode = new TreeAttlistDecl (elementName);
1123                attlistDecl = (TreeAttlistDecl) tempNode;
1124                appendChild (attlistDecl);
1125            } catch (TreeException exc) {
1126                throw new XNIException (exc);
1127            }
1128        } // startAttlist(String)
1129

1130        // XMLDTDHandler 2.4.0
1131
public void attributeDecl(String JavaDoc elementName, String JavaDoc attributeName,
1132                                  String JavaDoc type, String JavaDoc[] enumeration,
1133                                  String JavaDoc defaultType, XMLString defaultValue,
1134                                  XMLString nonNormalizedDefaultValue, Augmentations a) {
1135            attributeDecl(
1136                elementName, attributeName, type,
1137                enumeration, defaultType, defaultValue
1138            );
1139        }
1140
1141        /**
1142         * An attribute declaration.
1143         */

1144        // XMLDTDHandler 2.0.0b4
1145
public void attributeDecl (String JavaDoc elementName, String JavaDoc attributeName,
1146                                   String JavaDoc type, String JavaDoc[] enumeration,
1147                                   String JavaDoc defaultType, XMLString defaultValue) {
1148            
1149            trace ("attributeDecl(" + attributeName + ")"); // NOI18N
1150

1151            try {
1152                TreeAttlistDecl list;
1153                
1154                if (attlistDecl != null) {
1155                    list = attlistDecl;
1156                } else {
1157                    list = new TreeAttlistDecl (elementName);
1158                }
1159                if ( type.equals ("ENUMERATION") ) { // NOI18N
1160
type = null;
1161                }
1162
1163                short shortDefaultType = TreeAttlistDeclAttributeDef.findDefaultType (defaultType);
1164                String JavaDoc newDefaultValue = null;
1165                if ( ( shortDefaultType == TreeAttlistDeclAttributeDef.DEFAULT_TYPE_NULL ) ||
1166                     ( shortDefaultType == TreeAttlistDeclAttributeDef.DEFAULT_TYPE_FIXED ) ) {
1167                    newDefaultValue = defaultValue.toString ();
1168                }
1169                TreeAttlistDeclAttributeDef decl =
1170                new TreeAttlistDeclAttributeDef (attributeName, TreeAttlistDeclAttributeDef.findType (type),
1171                                                 enumeration, shortDefaultType, newDefaultValue);
1172                
1173                list.setAttributeDef (decl);
1174            } catch (TreeException exc) {
1175                //Util.dumpContext("TreeAttlistDecl.setReadOnly(true)"); // NOI18N
1176
throw new XNIException (exc);
1177            }
1178        } // attributeDecl(String,String,String,String[],String,XMLString)
1179

1180        // XMLDTDHandler 2.4.0
1181
public void endAttlist (Augmentations a) {
1182            endAttlist();
1183        }
1184
1185        /**
1186         * The end of an attribute list.
1187         */

1188        // XMLDTDHandler 2.0.0b4
1189
public void endAttlist () {
1190            
1191            trace ("endAttlist()"); // NOI18N
1192

1193            attlistDecl = null;
1194        } // endAttlist()
1195

1196        // XMLDTDHandler 2.4.0
1197
public void internalEntityDecl (String JavaDoc name, XMLString text, XMLString nonNormalizedText, Augmentations a) {
1198            internalEntityDecl(name, text, nonNormalizedText);
1199        }
1200
1201        /**
1202         * An internal entity declaration.
1203         *
1204         * @param name The name of the entity. Parameter entity names start with
1205         * '%', whereas the name of a general entity is just the
1206         * entity name.
1207         */

1208        // XMLDTDHandler 2.0.0b4
1209
public void internalEntityDecl (String JavaDoc name, XMLString text, XMLString nonNormalizedText) {
1210            
1211            trace ("internalEntityDecl(" + name + ")"); // NOI18N
1212

1213            try {
1214                boolean par = name.startsWith ("%"); // NOI18N
1215
if (par) {
1216                    name = name.substring (1);
1217                }
1218                appendChild (new TreeEntityDecl (par, name, text.toString ()));
1219            } catch (TreeException exc) {
1220                throw new XNIException (exc);
1221            }
1222        } // internalEntityDecl(String,XMLString)
1223

1224        // XMLDTDHandler 2.4.0
1225
public void externalEntityDecl (String JavaDoc name, String JavaDoc publicId,
1226        String JavaDoc systemId, String JavaDoc baseSystemId, Augmentations a) {
1227            externalEntityDecl( name, publicId, systemId, baseSystemId);
1228        }
1229
1230        /**
1231         * An external entity declaration.
1232         *
1233         * @param name The name of the entity. Parameter entity names start
1234         * with '%', whereas the name of a general entity is just
1235         * the entity name.
1236         */

1237        // XMLDTDHandler 2.0.0b4
1238
public void externalEntityDecl (String JavaDoc name, String JavaDoc publicId,
1239        String JavaDoc systemId, String JavaDoc baseSystemId) {
1240            
1241            trace ("externalEntityDecl(" + name + ")"); // NOI18N
1242

1243            try {
1244                boolean par = name.startsWith ("%"); // NOI18N
1245
if (par) {
1246                    name = name.substring (1);
1247                }
1248                
1249                appendChild (new TreeEntityDecl (par, name, publicId, systemId));
1250            } catch (TreeException exc) {
1251                throw new XNIException (exc);
1252            }
1253        } // externalEntityDecl(String,String,String)
1254

1255        // XMLDTDHAnlder 2.4.0
1256
public void unparsedEntityDecl (String JavaDoc name,
1257        String JavaDoc publicId, String JavaDoc systemId,
1258        String JavaDoc notation, Augmentations a) {
1259            unparsedEntityDecl(name, publicId, systemId, notation);
1260        }
1261
1262        /**
1263         * An unparsed entity declaration.
1264         */

1265        // XMLDTDHAnlder 2.0.0b4
1266
public void unparsedEntityDecl (String JavaDoc name,
1267        String JavaDoc publicId, String JavaDoc systemId,
1268        String JavaDoc notation) {
1269            
1270            trace ("unparsedEntityDecl(" + name + ")"); // NOI18N
1271

1272            try {
1273                appendChild (new TreeEntityDecl (name, publicId, systemId, notation));
1274            } catch (TreeException exc) {
1275                throw new XNIException (exc);
1276            }
1277        } // unparsedEntityDecl(String,String,String,String)
1278

1279        // XMLDTDHandler 2.4.0
1280
public void notationDecl (String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId, Augmentations a) {
1281            notationDecl(name, publicId, systemId);
1282        }
1283
1284        /**
1285         * A notation declaration
1286         */

1287        // XMLDTDHandler 2.0.0b4
1288
public void notationDecl (String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId) {
1289            
1290            trace ("notationDecl(" + name + ")"); // NOI18N
1291

1292            try {
1293                appendChild (new TreeNotationDecl (name, publicId, systemId));
1294            } catch (TreeException exc) {
1295                throw new XNIException (exc);
1296            }
1297        } // notationDecl(String,String,String)
1298

1299        // XMLDTDHandler 2.4.0
1300
public void startConditional (short type, Augmentations a) {
1301            startConditional(type);
1302        }
1303
1304        /**
1305         * The start of a conditional section.
1306         *
1307         * @param type The type of the conditional section. This value will
1308         * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
1309         */

1310        // XMLDTDHandler 2.0.0b4
1311
public void startConditional (short type) {
1312            trace ("startConditional(" + type + ")"); // NOI18N
1313
if (ASSERT)
1314                doAssert (inDTD);
1315            
1316            if (type == CONDITIONAL_INCLUDE) {
1317                tempNode = new TreeConditionalSection (true);
1318            } else {
1319                tempNode = new TreeConditionalSection (false);
1320            }
1321            
1322            appendChild ((TreeConditionalSection) tempNode);
1323            setBeginPosition (tempNode);
1324            pushParentNode ((TreeConditionalSection) tempNode);
1325            
1326        } // startConditional(short)
1327

1328        // XMLDTDHandler 2.4.0
1329
public void endConditional (Augmentations a) {
1330            endConditional();
1331        }
1332
1333        /**
1334         * The end of a conditional section.
1335         */

1336        // XMLDTDHandler 2.0.0b4
1337
public void endConditional () {
1338            trace ("endConditional()"); // NOI18N
1339

1340            popParentNode ();
1341        } // endConditional()
1342

1343        // XMLDTDHandler 2.4.0
1344
public void endDTD (Augmentations a) {
1345            endDTD();
1346        }
1347
1348        /**
1349         * The end of the DTD.
1350         *
1351         * @throws SAXException Thrown by handler to signal an error.
1352         */

1353        // XMLDTDHandler 2.0.0b4
1354
public void endDTD () {
1355            trace ("endDTD()"); // NOI18N
1356

1357            if (isXMLDocument) {
1358                
1359                popParentNode ();
1360                
1361            } else {
1362                
1363                popParentNode ();
1364                
1365                //??? Xerces miss '<' at the end of entity
1366
// so such documents are reported as correct
1367

1368                isCorrect = errors == 0;
1369                throw new DTDStopException ();
1370                
1371            }
1372            
1373            inDTD = false;
1374        } // endDTD()
1375

1376        
1377        // Content Model parser ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1378

1379        private TreeElementDecl.ContentType lastType; // occurence operators are applied on this
1380
private TreeElementDecl.ContentType contentModel; // OUTPUT result field
1381
private Stack contentModelMembersStack; // stack of parent group members
1382

1383        public XMLDTDContentModelSource getDTDContentModelSource() {
1384            return xmldtdContentModelSource;
1385        }
1386
1387        public void setDTDContentModelSource(XMLDTDContentModelSource src) {
1388            xmldtdContentModelSource = src;
1389        }
1390
1391        public void startContentModel (String JavaDoc elementName, Augmentations a) {
1392            
1393            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("startContentModel(" + elementName + ")"); // NOI18N
1394

1395            lastType = null;
1396            contentModelMembersStack = new Stack ();
1397            
1398        }
1399        
1400        public void any (Augmentations a) {
1401            contentModel = new ANYType ();
1402        }
1403        
1404        public void empty (Augmentations a) {
1405            contentModel = new EMPTYType ();
1406        }
1407        
1408        public void pcdata (Augmentations a) {
1409            setMembersType (new MixedType ());
1410        }
1411        
1412        
1413        // it is not called for mixed type
1414
public void startGroup (Augmentations a) {
1415            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("startGroup()"); // NOI18N
1416

1417            startMembers ();
1418        }
1419        
1420        public void element (String JavaDoc elementName, Augmentations a) {
1421            
1422            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("element(" + elementName + ")"); // NOI18N
1423

1424            lastType = new NameType (elementName);
1425            addMember (lastType);
1426        }
1427        
1428        // determine type of content model group
1429
public void separator (short separator, Augmentations a) {
1430            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("childrenSeparator()"); // NOI18N
1431

1432            switch (separator) {
1433                case SEPARATOR_SEQUENCE:
1434                    setMembersType (new SequenceType ());
1435                    break;
1436                case SEPARATOR_CHOICE:
1437                    setMembersType (new ChoiceType ());
1438                    break;
1439                default:
1440                    doAssert (false);
1441            }
1442        }
1443        
1444        //
1445
// INPUT lastType field
1446
//
1447
public void occurrence (short occurrence, Augmentations a) {
1448            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("childrenOccurrence()"); // NOI18N
1449

1450            switch (occurrence) {
1451                case OCCURS_ZERO_OR_ONE:
1452                    lastType.setMultiplicity ('?');
1453                    break;
1454                case OCCURS_ZERO_OR_MORE:
1455                    lastType.setMultiplicity ('*');
1456                    break;
1457                case OCCURS_ONE_OR_MORE:
1458                    lastType.setMultiplicity ('+');
1459                    break;
1460                default:
1461                    doAssert (false);
1462            }
1463            
1464        }
1465        
1466        public void endGroup (Augmentations a) {
1467            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("childrenEndGroup()"); // NOI18N
1468

1469            ChildrenType group = getMembersType ();
1470            group.addTypes (endMembers ());
1471            lastType = group;
1472            addMember (lastType);
1473        }
1474        
1475        public void endContentModel (Augmentations a) {
1476            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("endContentModel()"); // NOI18N
1477

1478            if (contentModel == null && lastType == null) { // #PCDATA
1479
contentModel = new MixedType ();
1480            } else if (contentModel == null) { // we are of CHILDREN_TYPE or mixed type
1481
contentModel = lastType;
1482                if (contentModel instanceof MixedType) {
1483                    contentModel.setMultiplicity ('*');
1484                }
1485            }
1486        }
1487        
1488        
1489        
1490        private void startMembers () {
1491            contentModelMembersStack.push (new Members (13));
1492        }
1493        
1494        private void addMember (TreeElementDecl.ContentType child) {
1495            
1496            // we are at top level of content model, lastType becomes it
1497
if (contentModelMembersStack.isEmpty ()) return;
1498            
1499            Collection members = (Collection) contentModelMembersStack.peek ();
1500            members.add (child);
1501        }
1502        
1503        private Collection endMembers () {
1504            return (Collection) contentModelMembersStack.pop ();
1505        }
1506        
1507        // we can predict member group now, if know balk it
1508
private void setMembersType (ChildrenType group) {
1509            
1510            // we are at top level of content model, lastType becomes it
1511
if (contentModelMembersStack.isEmpty ()) return;
1512            
1513            Members members = (Members) contentModelMembersStack.peek ();
1514            if (members.group == null) members.group = group;
1515        }
1516        
1517        private ChildrenType getMembersType () {
1518            Members members = (Members) contentModelMembersStack.peek ();
1519            if (members.group == null) {
1520                return new ChoiceType ();
1521            } else {
1522                return members.group;
1523            }
1524        }
1525        
1526        //
1527
// Hold additional information about group that holds these members
1528
//
1529
private class Members extends ArrayList {
1530            
1531            private ChildrenType group;
1532            
1533            private static final long serialVersionUID =4614355994187952965L;
1534            
1535            public Members (int initSize) {
1536                super (initSize);
1537                group = null;
1538            }
1539        }
1540        
1541        // ~~~~~~~~~~~~~~~~~ ERROR HANDLER ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1542

1543        
1544        public void error (org.xml.sax.SAXParseException JavaDoc e) {
1545            trace (e.getMessage ());
1546
1547            errorHandler.message (TreeStreamBuilderErrorHandler.ERROR_ERROR, e);
1548        }
1549        
1550        public void warning (org.xml.sax.SAXParseException JavaDoc e) {
1551            trace (e.getMessage ());
1552
1553            errorHandler.message (TreeStreamBuilderErrorHandler.ERROR_WARNING, e);
1554        }
1555        
1556        public void fatalError (org.xml.sax.SAXParseException JavaDoc e) {
1557            trace (e.getMessage ());
1558
1559            errors++;
1560            errorHandler.message (TreeStreamBuilderErrorHandler.ERROR_FATAL_ERROR, e);
1561        }
1562        
1563        // ~~~~~~~~~~~~~~~~~~ UTILITY ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1564

1565        /**
1566         */

1567        private void setReadOnly (TreeObject treeObject) {
1568            setReadOnly (treeObject, true);
1569        }
1570        
1571        
1572        private void setReadOnly (TreeObject treeObject, boolean value) {
1573            try {
1574                Method setReadOnlyMethod = TreeObject.class.getDeclaredMethod ("setReadOnly", new Class JavaDoc[] { Boolean.TYPE }); // NOI18N
1575
setReadOnlyMethod.setAccessible (true);
1576                setReadOnlyMethod.invoke (treeObject, new Object JavaDoc[] { value == true ? Boolean.TRUE : Boolean.FALSE});
1577            } catch (NoSuchMethodException JavaDoc exc) {
1578            } catch (IllegalAccessException JavaDoc exc) {
1579            } catch (InvocationTargetException exc) {
1580            }
1581        }
1582        
1583        /**
1584         * As positons will be supported
1585         */

1586        private void setBeginPosition (TreeNode n) {
1587            //!!!
1588
}
1589        
1590        
1591        /**
1592         * @return TreeDocument or null if fatal errors occured
1593         */

1594        private TreeDocumentRoot getDocumentRoot () {
1595            TreeDocumentRoot doc = (TreeDocumentRoot) (errors > 0 ? null : returnDocument);
1596            
1597            if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("TreeStreamBuilderXercesImpl returns: " + doc); // NOI18N
1598

1599            return doc;
1600        }
1601        
1602        
1603        /**
1604         * Shortcut - retrieves child list and pushes it at stack
1605         */

1606        private void pushParentNode (TreeParentNode parent) {
1607            parentNodeStack.push (parent);
1608            pushParentObjectList (parent.getChildNodes ());
1609        }
1610        
1611        /**
1612         * Set new parent list pushing original one to node stack
1613         */

1614        private void pushParentObjectList (TreeObjectList parentList) {
1615            parentObjectListStack.push (parentObjectList);
1616
1617            // inherit null parents (for nested parents)
1618
if (parentObjectList != null || parentObjectListStack.size() == 1) {
1619                parentObjectList = parentList;
1620            } else {
1621                parentObjectList = null;
1622            }
1623        }
1624        
1625        /**
1626         * Restore current children list poping it from stack.
1627         */

1628        private void popParentObjectList () {
1629            parentObjectList = (TreeObjectList) parentObjectListStack.pop ();
1630        }
1631        
1632        /**
1633         * Resotore parent node and its list from stack
1634         */

1635        private void popParentNode () {
1636            popParentObjectList ();
1637            TreeParentNode parentNode = (TreeParentNode) parentNodeStack.pop ();
1638            
1639            // referenced things and DTD things are read only
1640

1641            if ( parentNode instanceof TreeGeneralEntityReference ) { // entities in XML doc
1642

1643                setReadOnly (parentNode.getChildNodes ());
1644                
1645            } else if ( parentNode instanceof TreeDTD ) { // whole DTD
1646

1647                setReadOnly (parentNode);
1648                
1649            } else if ( parentNode instanceof TreeDocumentType ) {
1650                
1651                setReadOnly (parentNode.getChildNodes ());
1652
1653                // there can be pure internal DTD
1654
TreeObjectList externalDTD = ((TreeDocumentType)parentNode).getExternalDTD ();
1655                if (externalDTD != null) {
1656                    setReadOnly (externalDTD);
1657                }
1658            }
1659        }
1660        
1661        private TreeParentNode currentParentNode () {
1662            return (TreeParentNode) parentNodeStack.peek ();
1663        }
1664        
1665        /**
1666         * Add child to current parent list.
1667         */

1668        private void appendChild (TreeObject child) {
1669            if (parentObjectList != null) parentObjectList.add (child);
1670        }
1671        
1672        /**
1673         * Enter entity, following events origanes from entity resolution
1674         */

1675        private void enterEntity () {
1676            entityCounter++;
1677        }
1678        
1679        /**
1680         * Exit entity.
1681         */

1682        private void exitEntity () {
1683            entityCounter--;
1684        }
1685        
1686        /**
1687         * Test whether we are in entity, i.e. creating readonly nodes.
1688         */

1689        private boolean inEntity () {
1690            return entityCounter > 0;
1691        }
1692        
1693        private void trace (String JavaDoc msg) {
1694            if ( Util.THIS.isLoggable() ) {
1695                String JavaDoc location = "";
1696                if (locator != null) {
1697                    String JavaDoc entity = locator.getExpandedSystemId ();
1698                    int index = entity.lastIndexOf ('/');
1699                    entity = entity.substring (index > 0 ? index : 0);
1700                    location = entity + "/" + locator.getLineNumber () + ":" + locator.getColumnNumber () ;
1701                }
1702                Util.THIS.debug ("X2T " + location + " " + msg); // NOI18N
1703
}
1704        }
1705        
1706        private void doAssert (boolean asrt) {
1707            if (asrt == false) {
1708                throw new IllegalStateException JavaDoc ("ASSERT"); // NOI18N
1709
}
1710        }
1711        
1712    }
1713    
1714    
1715    
1716}
1717
Popular Tags