Merge branch 'Jalview-JS/jim/JAL-3253-JAL-3418' into Jalview-JS/JAL-3253-applet
[jalview.git] / unused / xml / sax / helpers / ParserAdapter.java
1 // ParserAdapter.java - adapt a SAX1 Parser to a SAX2 XMLReader.
2 // http://www.saxproject.org
3 // Written by David Megginson
4 // NO WARRANTY!  This class is in the public domain.
5 // $Id: ParserAdapter.java,v 1.16 2004/04/26 17:34:35 dmegginson Exp $
6
7 package org.xml.sax.helpers;
8
9 import java.io.IOException;
10 import java.util.Enumeration;
11 import java.util.Vector;
12
13 import org.xml.sax.Parser;      // deprecated
14 import org.xml.sax.InputSource;
15 import org.xml.sax.Locator;
16 import org.xml.sax.AttributeList; // deprecated
17 import org.xml.sax.EntityResolver;
18 import org.xml.sax.DTDHandler;
19 import org.xml.sax.DocumentHandler; // deprecated
20 import org.xml.sax.ErrorHandler;
21 import org.xml.sax.SAXException;
22 import org.xml.sax.SAXParseException;
23
24 import org.xml.sax.XMLReader;
25 import org.xml.sax.Attributes;
26 import org.xml.sax.ContentHandler;
27 import org.xml.sax.SAXNotRecognizedException;
28 import org.xml.sax.SAXNotSupportedException;
29
30
31 /**
32  * Adapt a SAX1 Parser as a SAX2 XMLReader.
33  *
34  * <blockquote>
35  * <em>This module, both source code and documentation, is in the
36  * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
37  * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
38  * for further information.
39  * </blockquote>
40  *
41  * <p>This class wraps a SAX1 {@link org.xml.sax.Parser Parser}
42  * and makes it act as a SAX2 {@link org.xml.sax.XMLReader XMLReader},
43  * with feature, property, and Namespace support.  Note
44  * that it is not possible to report {@link org.xml.sax.ContentHandler#skippedEntity
45  * skippedEntity} events, since SAX1 does not make that information available.</p>
46  *
47  * <p>This adapter does not test for duplicate Namespace-qualified
48  * attribute names.</p>
49  *
50  * @since SAX 2.0
51  * @author David Megginson
52  * @version 2.0.1 (sax2r2)
53  * @see org.xml.sax.helpers.XMLReaderAdapter
54  * @see org.xml.sax.XMLReader
55  * @see org.xml.sax.Parser
56  */
57 public class ParserAdapter implements XMLReader, DocumentHandler
58 {
59
60 \f
61     ////////////////////////////////////////////////////////////////////
62     // Constructors.
63     ////////////////////////////////////////////////////////////////////
64
65
66     /**
67      * Construct a new parser adapter.
68      *
69      * <p>Use the "org.xml.sax.parser" property to locate the
70      * embedded SAX1 driver.</p>
71      *
72      * @exception SAXException If the embedded driver
73      *            cannot be instantiated or if the
74      *            org.xml.sax.parser property is not specified.
75      */
76     public ParserAdapter ()
77       throws SAXException
78     {
79         super();
80
81         String driver = System.getProperty("org.xml.sax.parser");
82
83         try {
84             setup(ParserFactory.makeParser());
85         } catch (ClassNotFoundException e1) {
86             throw new
87                 SAXException("Cannot find SAX1 driver class " +
88                              driver, e1);
89         } catch (IllegalAccessException e2) {
90             throw new
91                 SAXException("SAX1 driver class " +
92                              driver +
93                              " found but cannot be loaded", e2);
94         } catch (InstantiationException e3) {
95             throw new
96                 SAXException("SAX1 driver class " +
97                              driver +
98                              " loaded but cannot be instantiated", e3);
99         } catch (ClassCastException e4) {
100             throw new
101                 SAXException("SAX1 driver class " +
102                              driver +
103                              " does not implement org.xml.sax.Parser");
104         } catch (NullPointerException e5) {
105             throw new 
106                 SAXException("System property org.xml.sax.parser not specified");
107         }
108     }
109
110
111     /**
112      * Construct a new parser adapter.
113      *
114      * <p>Note that the embedded parser cannot be changed once the
115      * adapter is created; to embed a different parser, allocate
116      * a new ParserAdapter.</p>
117      *
118      * @param parser The SAX1 parser to embed.
119      * @exception java.lang.NullPointerException If the parser parameter
120      *            is null.
121      */
122     public ParserAdapter (Parser parser)
123     {
124         super();
125         setup(parser);
126     }
127
128
129     /**
130      * Internal setup method.
131      *
132      * @param parser The embedded parser.
133      * @exception java.lang.NullPointerException If the parser parameter
134      *            is null.
135      */
136     private void setup (Parser parser)
137     {
138         if (parser == null) {
139             throw new
140                 NullPointerException("Parser argument must not be null");
141         }
142         this.parser = parser;
143         atts = new AttributesImpl();
144         nsSupport = new NamespaceSupport();
145         attAdapter = new AttributeListAdapter();
146     }
147
148
149 \f
150     ////////////////////////////////////////////////////////////////////
151     // Implementation of org.xml.sax.XMLReader.
152     ////////////////////////////////////////////////////////////////////
153
154
155     //
156     // Internal constants for the sake of convenience.
157     //
158     private final static String FEATURES = "http://xml.org/sax/features/";
159     private final static String NAMESPACES = FEATURES + "namespaces";
160     private final static String NAMESPACE_PREFIXES = FEATURES + "namespace-prefixes";
161     private final static String XMLNS_URIs = FEATURES + "xmlns-uris";
162
163
164     /**
165      * Set a feature flag for the parser.
166      *
167      * <p>The only features recognized are namespaces and 
168      * namespace-prefixes.</p>
169      *
170      * @param name The feature name, as a complete URI.
171      * @param value The requested feature value.
172      * @exception SAXNotRecognizedException If the feature
173      *            can't be assigned or retrieved.
174      * @exception SAXNotSupportedException If the feature
175      *            can't be assigned that value.
176      * @see org.xml.sax.XMLReader#setFeature
177      */
178     @Override
179                 public void setFeature (String name, boolean value)
180         throws SAXNotRecognizedException, SAXNotSupportedException
181     {
182         if (name.equals(NAMESPACES)) {
183             checkNotParsing("feature", name);
184             namespaces = value;
185             if (!namespaces && !prefixes) {
186                 prefixes = true;
187             }
188         } else if (name.equals(NAMESPACE_PREFIXES)) {
189             checkNotParsing("feature", name);
190             prefixes = value;
191             if (!prefixes && !namespaces) {
192                 namespaces = true;
193             }
194         } else if (name.equals(XMLNS_URIs)) {
195             checkNotParsing("feature", name);
196             uris = value;
197         } else {
198             throw new SAXNotRecognizedException("Feature: " + name);
199         }
200     }
201
202
203     /**
204      * Check a parser feature flag.
205      *
206      * <p>The only features recognized are namespaces and 
207      * namespace-prefixes.</p>
208      *
209      * @param name The feature name, as a complete URI.
210      * @return The current feature value.
211      * @exception SAXNotRecognizedException If the feature
212      *            value can't be assigned or retrieved.
213      * @exception SAXNotSupportedException If the
214      *            feature is not currently readable.
215      * @see org.xml.sax.XMLReader#setFeature
216      */
217     @Override
218                 public boolean getFeature (String name)
219         throws SAXNotRecognizedException, SAXNotSupportedException
220     {
221         if (name.equals(NAMESPACES)) {
222             return namespaces;
223         } else if (name.equals(NAMESPACE_PREFIXES)) {
224             return prefixes;
225         } else if (name.equals(XMLNS_URIs)) {
226             return uris;
227         } else {
228             throw new SAXNotRecognizedException("Feature: " + name);
229         }
230     }
231
232
233     /**
234      * Set a parser property.
235      *
236      * <p>No properties are currently recognized.</p>
237      *
238      * @param name The property name.
239      * @param value The property value.
240      * @exception SAXNotRecognizedException If the property
241      *            value can't be assigned or retrieved.
242      * @exception SAXNotSupportedException If the property
243      *            can't be assigned that value.
244      * @see org.xml.sax.XMLReader#setProperty
245      */
246     @Override
247                 public void setProperty (String name, Object value)
248         throws SAXNotRecognizedException, SAXNotSupportedException
249     {
250         throw new SAXNotRecognizedException("Property: " + name);
251     }
252
253
254     /**
255      * Get a parser property.
256      *
257      * <p>No properties are currently recognized.</p>
258      *
259      * @param name The property name.
260      * @return The property value.
261      * @exception SAXNotRecognizedException If the property
262      *            value can't be assigned or retrieved.
263      * @exception SAXNotSupportedException If the property
264      *            value is not currently readable.
265      * @see org.xml.sax.XMLReader#getProperty
266      */
267     @Override
268                 public Object getProperty (String name)
269         throws SAXNotRecognizedException, SAXNotSupportedException
270     {
271         throw new SAXNotRecognizedException("Property: " + name);
272     }
273
274
275     /**
276      * Set the entity resolver.
277      *
278      * @param resolver The new entity resolver.
279      * @see org.xml.sax.XMLReader#setEntityResolver
280      */
281     @Override
282                 public void setEntityResolver (EntityResolver resolver)
283     {
284         entityResolver = resolver;
285     }
286
287
288     /**
289      * Return the current entity resolver.
290      *
291      * @return The current entity resolver, or null if none was supplied.
292      * @see org.xml.sax.XMLReader#getEntityResolver
293      */
294     @Override
295                 public EntityResolver getEntityResolver ()
296     {
297         return entityResolver;
298     }
299
300
301     /**
302      * Set the DTD handler.
303      *
304      * @param handler the new DTD handler
305      * @see org.xml.sax.XMLReader#setEntityResolver
306      */
307     @Override
308                 public void setDTDHandler (DTDHandler handler)
309     {
310         dtdHandler = handler;
311     }
312
313
314     /**
315      * Return the current DTD handler.
316      *
317      * @return the current DTD handler, or null if none was supplied
318      * @see org.xml.sax.XMLReader#getEntityResolver
319      */
320     @Override
321                 public DTDHandler getDTDHandler ()
322     {
323         return dtdHandler;
324     }
325
326
327     /**
328      * Set the content handler.
329      *
330      * @param handler the new content handler
331      * @see org.xml.sax.XMLReader#setEntityResolver
332      */
333     @Override
334                 public void setContentHandler (ContentHandler handler)
335     {
336         contentHandler = handler;
337     }
338
339
340     /**
341      * Return the current content handler.
342      *
343      * @return The current content handler, or null if none was supplied.
344      * @see org.xml.sax.XMLReader#getEntityResolver
345      */
346     @Override
347                 public ContentHandler getContentHandler ()
348     {
349         return contentHandler;
350     }
351
352
353     /**
354      * Set the error handler.
355      *
356      * @param handler The new error handler.
357      * @see org.xml.sax.XMLReader#setEntityResolver
358      */
359     @Override
360                 public void setErrorHandler (ErrorHandler handler)
361     {
362         errorHandler = handler;
363     }
364
365
366     /**
367      * Return the current error handler.
368      *
369      * @return The current error handler, or null if none was supplied.
370      * @see org.xml.sax.XMLReader#getEntityResolver
371      */
372     @Override
373                 public ErrorHandler getErrorHandler ()
374     {
375         return errorHandler;
376     }
377
378
379     /**
380      * Parse an XML document.
381      *
382      * @param systemId The absolute URL of the document.
383      * @exception java.io.IOException If there is a problem reading
384      *            the raw content of the document.
385      * @exception SAXException If there is a problem
386      *            processing the document.
387      * @see #parse(org.xml.sax.InputSource)
388      * @see org.xml.sax.Parser#parse(java.lang.String)
389      */
390     @Override
391                 public void parse (String systemId)
392         throws IOException, SAXException
393     {
394         parse(new InputSource(systemId));
395     }
396
397
398     /**
399      * Parse an XML document.
400      *
401      * @param input An input source for the document.
402      * @exception java.io.IOException If there is a problem reading
403      *            the raw content of the document.
404      * @exception SAXException If there is a problem
405      *            processing the document.
406      * @see #parse(java.lang.String)
407      * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
408      */
409     @Override
410                 public void parse (InputSource input)
411         throws IOException, SAXException
412     {
413         if (parsing) {
414             throw new SAXException("Parser is already in use");
415         }
416         setupParser();
417         parsing = true;
418         try {
419             parser.parse(input);
420         } finally {
421             parsing = false;
422         }
423         parsing = false;
424     }
425
426
427
428     ////////////////////////////////////////////////////////////////////
429     // Implementation of org.xml.sax.DocumentHandler.
430     ////////////////////////////////////////////////////////////////////
431
432
433     /**
434      * Adapter implementation method; do not call.
435      * Adapt a SAX1 document locator event.
436      *
437      * @param locator A document locator.
438      * @see org.xml.sax.ContentHandler#setDocumentLocator
439      */
440     @Override
441                 public void setDocumentLocator (Locator locator)
442     {
443         this.locator = locator;
444         if (contentHandler != null) {
445             contentHandler.setDocumentLocator(locator);
446         }
447     }
448
449
450     /**
451      * Adapter implementation method; do not call.
452      * Adapt a SAX1 start document event.
453      *
454      * @exception SAXException The client may raise a
455      *            processing exception.
456      * @see org.xml.sax.DocumentHandler#startDocument
457      */
458     @Override
459                 public void startDocument ()
460         throws SAXException
461     {
462         if (contentHandler != null) {
463             contentHandler.startDocument();
464         }
465     }
466
467
468     /**
469      * Adapter implementation method; do not call.
470      * Adapt a SAX1 end document event.
471      *
472      * @exception SAXException The client may raise a
473      *            processing exception.
474      * @see org.xml.sax.DocumentHandler#endDocument
475      */
476     @Override
477                 public void endDocument ()
478         throws SAXException
479     {
480         if (contentHandler != null) {
481             contentHandler.endDocument();
482         }
483     }
484
485
486     /**
487      * Adapter implementation method; do not call.
488      * Adapt a SAX1 startElement event.
489      *
490      * <p>If necessary, perform Namespace processing.</p>
491      *
492      * @param qName The qualified (prefixed) name.
493      * @param qAtts The XML attribute list (with qnames).
494      * @exception SAXException The client may raise a
495      *            processing exception.
496      */
497     @Override
498                 public void startElement (String qName, AttributeList qAtts)
499         throws SAXException
500     {
501                                 // These are exceptions from the
502                                 // first pass; they should be
503                                 // ignored if there's a second pass,
504                                 // but reported otherwise.
505         Vector exceptions = null;
506
507                                 // If we're not doing Namespace
508                                 // processing, dispatch this quickly.
509         if (!namespaces) {
510             if (contentHandler != null) {
511                 attAdapter.setAttributeList(qAtts);
512                 contentHandler.startElement("", "", qName.intern(),
513                                             attAdapter);
514             }
515             return;
516         }
517
518
519                                 // OK, we're doing Namespace processing.
520         nsSupport.pushContext();
521         int length = qAtts.getLength();
522         
523                                 // First pass:  handle NS decls
524         for (int i = 0; i < length; i++) {
525             String attQName = qAtts.getName(i);
526
527             if (!attQName.startsWith("xmlns"))
528                 continue;
529                                 // Could be a declaration...
530             String prefix;
531             int n = attQName.indexOf(':');
532
533                                 // xmlns=...
534             if (n == -1 && attQName.length () == 5) {
535                 prefix = "";
536             } else if (n != 5) {
537                 // XML namespaces spec doesn't discuss "xmlnsf:oo"
538                 // (and similarly named) attributes ... at most, warn
539                 continue;
540             } else              // xmlns:foo=...
541                 prefix = attQName.substring(n+1);
542
543             String value = qAtts.getValue(i);
544             if (!nsSupport.declarePrefix(prefix, value)) {
545                 reportError("Illegal Namespace prefix: " + prefix);
546                 continue;
547             }
548             if (contentHandler != null)
549                 contentHandler.startPrefixMapping(prefix, value);
550         }
551         
552                                 // Second pass: copy all relevant
553                                 // attributes into the SAX2 AttributeList
554                                 // using updated prefix bindings
555         atts.clear();
556         for (int i = 0; i < length; i++) {
557             String attQName = qAtts.getName(i);
558             String type = qAtts.getType(i);
559             String value = qAtts.getValue(i);
560
561                                 // Declaration?
562             if (attQName.startsWith("xmlns")) {
563                 String prefix;
564                 int n = attQName.indexOf(':');
565
566                 if (n == -1 && attQName.length () == 5) {
567                     prefix = "";
568                 } else if (n != 5) {
569                     // XML namespaces spec doesn't discuss "xmlnsf:oo"
570                     // (and similarly named) attributes ... ignore
571                     prefix = null;
572                 } else {
573                     prefix = attQName.substring(6);
574                 }
575                                 // Yes, decl:  report or prune
576                 if (prefix != null) {
577                     if (prefixes) {
578                         if (uris)
579                             // note funky case:  localname can be null
580                             // when declaring the default prefix, and
581                             // yet the uri isn't null.
582                             atts.addAttribute (nsSupport.XMLNS, prefix,
583                                     attQName.intern(), type, value);
584                         else
585                             atts.addAttribute ("", "",
586                                     attQName.intern(), type, value);
587                     }
588                     continue;
589                 }
590             } 
591
592                                 // Not a declaration -- report
593             try {
594                 String attName[] = processName(attQName, true, true);
595                 atts.addAttribute(attName[0], attName[1], attName[2],
596                                   type, value);
597             } catch (SAXException e) {
598                 if (exceptions == null)
599                     exceptions = new Vector();
600                 exceptions.addElement(e);
601                 atts.addAttribute("", attQName, attQName, type, value);
602             }
603         }
604         
605         // now handle the deferred exception reports
606         if (exceptions != null && errorHandler != null) {
607             for (int i = 0; i < exceptions.size(); i++)
608                 errorHandler.error((SAXParseException)
609                                 (exceptions.elementAt(i)));
610         }
611
612                                 // OK, finally report the event.
613         if (contentHandler != null) {
614             String name[] = processName(qName, false, false);
615             contentHandler.startElement(name[0], name[1], name[2], atts);
616         }
617     }
618
619
620     /**
621      * Adapter implementation method; do not call.
622      * Adapt a SAX1 end element event.
623      *
624      * @param qName The qualified (prefixed) name.
625      * @exception SAXException The client may raise a
626      *            processing exception.
627      * @see org.xml.sax.DocumentHandler#endElement
628      */
629     @Override
630                 public void endElement (String qName)
631         throws SAXException
632     {
633                                 // If we're not doing Namespace
634                                 // processing, dispatch this quickly.
635         if (!namespaces) {
636             if (contentHandler != null) {
637                 contentHandler.endElement("", "", qName.intern());
638             }
639             return;
640         }
641
642                                 // Split the name.
643         String names[] = processName(qName, false, false);
644         if (contentHandler != null) {
645             contentHandler.endElement(names[0], names[1], names[2]);
646             Enumeration prefixes = nsSupport.getDeclaredPrefixes();
647             while (prefixes.hasMoreElements()) {
648                 String prefix = (String)prefixes.nextElement();
649                 contentHandler.endPrefixMapping(prefix);
650             }
651         }
652         nsSupport.popContext();
653     }
654
655
656     /**
657      * Adapter implementation method; do not call.
658      * Adapt a SAX1 characters event.
659      *
660      * @param ch An array of characters.
661      * @param start The starting position in the array.
662      * @param length The number of characters to use.
663      * @exception SAXException The client may raise a
664      *            processing exception.
665      * @see org.xml.sax.DocumentHandler#characters
666      */
667     @Override
668                 public void characters (char ch[], int start, int length)
669         throws SAXException
670     {
671         if (contentHandler != null) {
672             contentHandler.characters(ch, start, length);
673         }
674     }
675
676
677     /**
678      * Adapter implementation method; do not call.
679      * Adapt a SAX1 ignorable whitespace event.
680      *
681      * @param ch An array of characters.
682      * @param start The starting position in the array.
683      * @param length The number of characters to use.
684      * @exception SAXException The client may raise a
685      *            processing exception.
686      * @see org.xml.sax.DocumentHandler#ignorableWhitespace
687      */
688     @Override
689                 public void ignorableWhitespace (char ch[], int start, int length)
690         throws SAXException
691     {
692         if (contentHandler != null) {
693             contentHandler.ignorableWhitespace(ch, start, length);
694         }
695     }
696
697
698     /**
699      * Adapter implementation method; do not call.
700      * Adapt a SAX1 processing instruction event.
701      *
702      * @param target The processing instruction target.
703      * @param data The remainder of the processing instruction
704      * @exception SAXException The client may raise a
705      *            processing exception.
706      * @see org.xml.sax.DocumentHandler#processingInstruction
707      */
708     @Override
709                 public void processingInstruction (String target, String data)
710         throws SAXException
711     {
712         if (contentHandler != null) {
713             contentHandler.processingInstruction(target, data);
714         }
715     }
716
717
718 \f
719     ////////////////////////////////////////////////////////////////////
720     // Internal utility methods.
721     ////////////////////////////////////////////////////////////////////
722
723
724     /**
725      * Initialize the parser before each run.
726      */
727     private void setupParser ()
728     {
729         // catch an illegal "nonsense" state.
730         if (!prefixes && !namespaces)
731             throw new IllegalStateException ();
732
733         nsSupport.reset();
734         if (uris)
735             nsSupport.setNamespaceDeclUris (true);
736
737         if (entityResolver != null) {
738             parser.setEntityResolver(entityResolver);
739         }
740         if (dtdHandler != null) {
741             parser.setDTDHandler(dtdHandler);
742         }
743         if (errorHandler != null) {
744             parser.setErrorHandler(errorHandler);
745         }
746         parser.setDocumentHandler(this);
747         locator = null;
748     }
749
750
751     /**
752      * Process a qualified (prefixed) name.
753      *
754      * <p>If the name has an undeclared prefix, use only the qname
755      * and make an ErrorHandler.error callback in case the app is
756      * interested.</p>
757      *
758      * @param qName The qualified (prefixed) name.
759      * @param isAttribute true if this is an attribute name.
760      * @return The name split into three parts.
761      * @exception SAXException The client may throw
762      *            an exception if there is an error callback.
763      */
764     private String [] processName (String qName, boolean isAttribute,
765                                    boolean useException)
766         throws SAXException
767     {
768         String parts[] = nsSupport.processName(qName, nameParts,
769                                                isAttribute);
770         if (parts == null) {
771             if (useException)
772                 throw makeException("Undeclared prefix: " + qName);
773             reportError("Undeclared prefix: " + qName);
774             parts = new String[3];
775             parts[0] = parts[1] = "";
776             parts[2] = qName.intern();
777         }
778         return parts;
779     }
780
781
782     /**
783      * Report a non-fatal error.
784      *
785      * @param message The error message.
786      * @exception SAXException The client may throw
787      *            an exception.
788      */
789     void reportError (String message)
790         throws SAXException
791     {
792         if (errorHandler != null)
793             errorHandler.error(makeException(message));
794     }
795
796     
797     /**
798      * Construct an exception for the current context.
799      *
800      * @param message The error message.
801      */
802     private SAXParseException makeException (String message)
803     {
804         if (locator != null) {
805             return new SAXParseException(message, locator);
806         } else {
807             return new SAXParseException(message, null, null, -1, -1);
808         }
809     }
810
811
812     /**
813      * Throw an exception if we are parsing.
814      *
815      * <p>Use this method to detect illegal feature or
816      * property changes.</p>
817      *
818      * @param type The type of thing (feature or property).
819      * @param name The feature or property name.
820      * @exception SAXNotSupportedException If a
821      *            document is currently being parsed.
822      */
823     private void checkNotParsing (String type, String name)
824         throws SAXNotSupportedException
825     {
826         if (parsing) {
827             throw new SAXNotSupportedException("Cannot change " +
828                                                type + ' ' +
829                                                name + " while parsing");
830                                                
831         }
832     }
833
834
835 \f
836     ////////////////////////////////////////////////////////////////////
837     // Internal state.
838     ////////////////////////////////////////////////////////////////////
839
840     private NamespaceSupport nsSupport;
841     private AttributeListAdapter attAdapter;
842
843     private boolean parsing = false;
844     private String nameParts[] = new String[3];
845
846     private Parser parser = null;
847
848     private AttributesImpl atts = null;
849
850                                 // Features
851     private boolean namespaces = true;
852     private boolean prefixes = false;
853     private boolean uris = false;
854
855                                 // Properties
856
857                                 // Handlers
858     Locator locator;
859
860     EntityResolver entityResolver = null;
861     DTDHandler dtdHandler = null;
862     ContentHandler contentHandler = null;
863     ErrorHandler errorHandler = null;
864
865
866 \f
867     ////////////////////////////////////////////////////////////////////
868     // Inner class to wrap an AttributeList when not doing NS proc.
869     ////////////////////////////////////////////////////////////////////
870
871
872     /**
873      * Adapt a SAX1 AttributeList as a SAX2 Attributes object.
874      *
875      * <p>This class is in the Public Domain, and comes with NO
876      * WARRANTY of any kind.</p>
877      *
878      * <p>This wrapper class is used only when Namespace support
879      * is disabled -- it provides pretty much a direct mapping
880      * from SAX1 to SAX2, except that names and types are 
881      * interned whenever requested.</p>
882      */
883     final class AttributeListAdapter implements Attributes
884     {
885
886         /**
887          * Construct a new adapter.
888          */
889         AttributeListAdapter ()
890         {
891         }
892
893
894         /**
895          * Set the embedded AttributeList.
896          *
897          * <p>This method must be invoked before any of the others
898          * can be used.</p>
899          *
900          * @param The SAX1 attribute list (with qnames).
901          */
902         void setAttributeList (AttributeList qAtts)
903         {
904             this.qAtts = qAtts;
905         }
906
907
908         /**
909          * Return the length of the attribute list.
910          *
911          * @return The number of attributes in the list.
912          * @see org.xml.sax.Attributes#getLength
913          */
914         @Override
915         public int getLength ()
916         {
917             return qAtts.getLength();
918         }
919
920
921         /**
922          * Return the Namespace URI of the specified attribute.
923          *
924          * @param The attribute's index.
925          * @return Always the empty string.
926          * @see org.xml.sax.Attributes#getURI
927          */
928         @Override
929         public String getURI (int i)
930         {
931             return "";
932         }
933
934
935         /**
936          * Return the local name of the specified attribute.
937          *
938          * @param The attribute's index.
939          * @return Always the empty string.
940          * @see org.xml.sax.Attributes#getLocalName
941          */
942         @Override
943         public String getLocalName (int i)
944         {
945             return "";
946         }
947
948
949         /**
950          * Return the qualified (prefixed) name of the specified attribute.
951          *
952          * @param The attribute's index.
953          * @return The attribute's qualified name, internalized.
954          */
955         @Override
956         public String getQName (int i)
957         {
958             return qAtts.getName(i).intern();
959         }
960
961
962         /**
963          * Return the type of the specified attribute.
964          *
965          * @param The attribute's index.
966          * @return The attribute's type as an internalized string.
967          */
968         @Override
969         public String getType (int i)
970         {
971             return qAtts.getType(i).intern();
972         }
973
974
975         /**
976          * Return the value of the specified attribute.
977          *
978          * @param The attribute's index.
979          * @return The attribute's value.
980          */
981         @Override
982         public String getValue (int i)
983         {
984             return qAtts.getValue(i);
985         }
986
987
988         /**
989          * Look up an attribute index by Namespace name.
990          *
991          * @param uri The Namespace URI or the empty string.
992          * @param localName The local name.
993          * @return The attributes index, or -1 if none was found.
994          * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
995          */
996         @Override
997         public int getIndex (String uri, String localName)
998         {
999             return -1;
1000         }
1001
1002
1003         /**
1004          * Look up an attribute index by qualified (prefixed) name.
1005          *
1006          * @param qName The qualified name.
1007          * @return The attributes index, or -1 if none was found.
1008          * @see org.xml.sax.Attributes#getIndex(java.lang.String)
1009          */
1010         @Override
1011         public int getIndex (String qName)
1012         {
1013             int max = atts.getLength();
1014             for (int i = 0; i < max; i++) {
1015                 if (qAtts.getName(i).equals(qName)) {
1016                     return i;
1017                 }
1018             }
1019             return -1;
1020         }
1021
1022
1023         /**
1024          * Look up the type of an attribute by Namespace name.
1025          *
1026          * @param uri The Namespace URI
1027          * @param localName The local name.
1028          * @return The attribute's type as an internalized string.
1029          */
1030         @Override
1031         public String getType (String uri, String localName)
1032         {
1033             return null;
1034         }
1035
1036
1037         /**
1038          * Look up the type of an attribute by qualified (prefixed) name.
1039          *
1040          * @param qName The qualified name.
1041          * @return The attribute's type as an internalized string.
1042          */
1043         @Override
1044         public String getType (String qName)
1045         {
1046             return qAtts.getType(qName).intern();
1047         }
1048
1049
1050         /**
1051          * Look up the value of an attribute by Namespace name.
1052          *
1053          * @param uri The Namespace URI
1054          * @param localName The local name.
1055          * @return The attribute's value.
1056          */
1057         @Override
1058         public String getValue (String uri, String localName)
1059         {
1060             return null;
1061         }
1062
1063
1064         /**
1065          * Look up the value of an attribute by qualified (prefixed) name.
1066          *
1067          * @param qName The qualified name.
1068          * @return The attribute's value.
1069          */
1070         @Override
1071         public String getValue (String qName)
1072         {
1073             return qAtts.getValue(qName);
1074         }
1075
1076         private AttributeList qAtts;
1077     }
1078 }
1079
1080 // end of ParserAdapter.java