View Javadoc

1   package net.sf.tomp.xtcl.filter;
2   
3   import net.sf.tomp.xtcl.Context;
4   
5   import org.xml.sax.Attributes;
6   import org.xml.sax.ContentHandler;
7   import org.xml.sax.DTDHandler;
8   import org.xml.sax.EntityResolver;
9   import org.xml.sax.ErrorHandler;
10  import org.xml.sax.InputSource;
11  import org.xml.sax.Locator;
12  import org.xml.sax.SAXException;
13  import org.xml.sax.SAXNotRecognizedException;
14  import org.xml.sax.SAXNotSupportedException;
15  import org.xml.sax.SAXParseException;
16  import org.xml.sax.XMLReader;
17  import org.xml.sax.ext.LexicalHandler;
18  
19  import java.io.IOException;
20  
21  /***
22   * DOCUMENT ME!
23   * 
24   * @author tomp
25   */
26  public class XTFilterImpl implements XTFilter {
27  	
28  	private Context context;
29      
30      private String id;
31      ////////////////////////////////////////////////////////////////////
32      // Internal state.
33      ////////////////////////////////////////////////////////////////////
34  
35      /*** DOCUMENT ME! */
36      protected XMLReader parent = null;
37  
38      /*** DOCUMENT ME! */
39      protected Locator locator = null;
40  
41      /*** DOCUMENT ME! */
42      protected EntityResolver entityResolver = null;
43  
44      /*** DOCUMENT ME! */
45      protected DTDHandler dtdHandler = null;
46  
47      /*** DOCUMENT ME! */
48      protected ContentHandler contentHandler = null;
49  
50      /*** DOCUMENT ME! */
51      protected ErrorHandler errorHandler = null;
52  
53      /*** DOCUMENT ME! */
54      protected LexicalHandler lexicalHandler = null;
55  
56      ////////////////////////////////////////////////////////////////////
57      // Constructors.
58      ////////////////////////////////////////////////////////////////////
59  
60      /***
61       * Construct an empty XML filter, with no parent.
62       * <p>
63       * This filter will have no parent: you must assign a parent before you
64       * start a parse or do any configuration with setFeature or setProperty,
65       * unless you use this as a pure event consumer rather than as an {@link
66       * XMLReader}.
67       * </p>
68       * 
69       * @see org.xml.sax.XMLReader#setFeature
70       * @see org.xml.sax.XMLReader#setProperty
71       * @see #setParent
72       */
73      public XTFilterImpl() {
74          super();
75      }
76  
77      /***
78       * Construct an XML filter with the specified parent.
79       * 
80       * @param parent DOCUMENT ME!
81       * @see #setParent
82       * @see #getParent
83       */
84      public XTFilterImpl(XMLReader parent) {
85          super();
86          setParent(parent);
87      }
88  
89      public void setId(String i) {
90          id = i;
91      }
92  
93      public String getId() {
94          return id;
95      }
96      
97      //protected Map params = new HashMap();
98      public void setParameter(String k, Object v) {
99          //params.put(k, v);
100         //System.out.println("Setting param "+k+"="+v);
101         throw new UnsupportedOperationException("Cannot set parameters to "
102                 + this);
103     }
104 
105     ////////////////////////////////////////////////////////////////////
106     // Implementation of org.xml.sax.XMLFilter.
107     ////////////////////////////////////////////////////////////////////
108 
109     /***
110      * Set the parent reader.
111      * <p>
112      * This is the {@link org.xml.sax.XMLReader XMLReader}from which this
113      * filter will obtain its events and to which it will pass its configuration
114      * requests. The parent may itself be another filter.
115      * </p>
116      * <p>
117      * If there is no parent reader set, any attempt to parse or to set or get a
118      * feature or property will fail.
119      * </p>
120      * 
121      * @param parent The parent XML reader.
122      * @see #getParent
123      */
124     public void setParent(XMLReader parent) {
125         this.parent = parent;
126     }
127 
128     /***
129      * Get the parent reader.
130      * 
131      * @return The parent XML reader, or null if none is set.
132      * @see #setParent
133      */
134     public XMLReader getParent() {
135         return parent;
136     }
137 
138     ////////////////////////////////////////////////////////////////////
139     // Implementation of org.xml.sax.XMLReader.
140     ////////////////////////////////////////////////////////////////////
141 
142     /***
143      * Set the value of a feature.
144      * <p>
145      * This will always fail if the parent is null.
146      * </p>
147      * 
148      * @param name The feature name.
149      * @param value The requested feature value.
150      * @exception SAXNotRecognizedException If the feature value can't be
151      *                assigned or retrieved from the parent.
152      * @exception SAXNotSupportedException When the parent recognizes the
153      *                feature name but cannot set the requested value.
154      */
155     public void setFeature(String name, boolean value)
156             throws SAXNotRecognizedException, SAXNotSupportedException {
157         if (parent != null) {
158             parent.setFeature(name, value);
159         } else {
160             throw new SAXNotRecognizedException("Feature: " + name);
161         }
162     }
163 
164     /***
165      * Look up the value of a feature.
166      * <p>
167      * This will always fail if the parent is null.
168      * </p>
169      * 
170      * @param name The feature name.
171      * @return The current value of the feature.
172      * @exception SAXNotRecognizedException If the feature value can't be
173      *                assigned or retrieved from the parent.
174      * @exception SAXNotSupportedException When the parent recognizes the
175      *                feature name but cannot determine its value at this time.
176      */
177     public boolean getFeature(String name) throws SAXNotRecognizedException,
178             SAXNotSupportedException {
179         if (parent != null) {
180             return parent.getFeature(name);
181         } else {
182             throw new SAXNotRecognizedException("Feature: " + name);
183         }
184     }
185 
186     /***
187      * Set the value of a property.
188      * <p>
189      * This will always fail if the parent is null.
190      * </p>
191      * 
192      * @param name The property name.
193      * @param value The requested property value.
194      * @exception SAXNotRecognizedException If the property value can't be
195      *                assigned or retrieved from the parent.
196      * @exception SAXNotSupportedException When the parent recognizes the
197      *                property name but cannot set the requested value.
198      */
199     public void setProperty(String name, Object value)
200             throws SAXNotRecognizedException, SAXNotSupportedException {
201         if ("http://xml.org/sax/properties/lexical-handler".equals(name)) {
202             setLexicalHandler((LexicalHandler) value);
203         } else if (parent != null) {
204             parent.setProperty(name, value);
205         } else {
206             throw new SAXNotRecognizedException("Property: " + name);
207         }
208     }
209 
210     /***
211      * Look up the value of a property.
212      * 
213      * @param name The property name.
214      * @return The current value of the property.
215      * @exception SAXNotRecognizedException If the property value can't be
216      *                assigned or retrieved from the parent.
217      * @exception SAXNotSupportedException When the parent recognizes the
218      *                property name but cannot determine its value at this time.
219      */
220     public Object getProperty(String name) throws SAXNotRecognizedException,
221             SAXNotSupportedException {
222         if ("http://xml.org/sax/properties/lexical-handler".equals(name)) {
223             return getLexicalHandler();
224         } else if (parent != null) {
225             return parent.getProperty(name);
226         } else {
227             throw new SAXNotRecognizedException("Property: " + name);
228         }
229     }
230 
231     /***
232      * Set the entity resolver.
233      * 
234      * @param resolver The new entity resolver.
235      */
236     public void setEntityResolver(EntityResolver resolver) {
237         entityResolver = resolver;
238     }
239 
240     /***
241      * Get the current entity resolver.
242      * 
243      * @return The current entity resolver, or null if none was set.
244      */
245     public EntityResolver getEntityResolver() {
246         return entityResolver;
247     }
248 
249     /***
250      * Set the DTD event handler.
251      * 
252      * @param handler The new DTD handler.
253      */
254     public void setDTDHandler(DTDHandler handler) {
255         dtdHandler = handler;
256     }
257 
258     /***
259      * Get the current DTD event handler.
260      * 
261      * @return The current DTD handler, or null if none was set.
262      */
263     public DTDHandler getDTDHandler() {
264         return dtdHandler;
265     }
266 
267     /***
268      * Set the content event handler.
269      * 
270      * @param handler The new content handler.
271      */
272     public void setContentHandler(ContentHandler handler) {
273         //System.out.println(""+this+".setContentHandler="+handler);
274         contentHandler = handler;
275     }
276 
277     /***
278      * Get the content event handler.
279      * 
280      * @return The current content handler, or null if none was set.
281      */
282     public ContentHandler getContentHandler() {
283         //System.out.println(""+this+".getContentHandler=>"+contentHandler);
284         return contentHandler;
285     }
286 
287     /***
288      * Set the lexical event handler.
289      * 
290      * @param handler The new lexical handler.
291      */
292     public void setLexicalHandler(LexicalHandler handler) {
293         //System.out.println(""+this+".setContentHandler="+handler);
294         lexicalHandler = handler;
295     }
296 
297     /***
298      * Get the lexical event handler.
299      * 
300      * @return The current lexical handler, or null if none was set.
301      */
302     public LexicalHandler getLexicalHandler() {
303         //System.out.println(""+this+".getContentHandler=>"+contentHandler);
304         return lexicalHandler;
305     }
306 
307     /***
308      * Set the error event handler.
309      * 
310      * @param handler The new error handler.
311      */
312     public void setErrorHandler(ErrorHandler handler) {
313         errorHandler = handler;
314     }
315 
316     /***
317      * Get the current error event handler.
318      * 
319      * @return The current error handler, or null if none was set.
320      */
321     public ErrorHandler getErrorHandler() {
322         return errorHandler;
323     }
324 
325     /***
326      * Parse a document.
327      * 
328      * @param input The input source for the document entity.
329      * @exception SAXException Any SAX exception, possibly wrapping another
330      *                exception.
331      * @exception IOException An IO exception from the parser, possibly from a
332      *                byte stream or character stream supplied by the
333      *                application.
334      */
335     public void parse(InputSource input) throws SAXException, IOException {
336         setupParse();
337 
338         //System.out.println("XTFilterImpl "+this+" will
339         // parse="+input.getSystemId());
340         parent.parse(input);
341     }
342 
343     /***
344      * Parse a document.
345      * 
346      * @param systemId The system identifier as a fully-qualified URI.
347      * @exception SAXException Any SAX exception, possibly wrapping another
348      *                exception.
349      * @exception IOException An IO exception from the parser, possibly from a
350      *                byte stream or character stream supplied by the
351      *                application.
352      */
353     public void parse(String systemId) throws SAXException, IOException {
354         parse(new InputSource(systemId));
355     }
356 
357     ////////////////////////////////////////////////////////////////////
358     // Implementation of org.xml.sax.EntityResolver.
359     ////////////////////////////////////////////////////////////////////
360 
361     /***
362      * Filter an external entity resolution.
363      * 
364      * @param publicId The entity's public identifier, or null.
365      * @param systemId The entity's system identifier.
366      * @return A new InputSource or null for the default.
367      * @exception SAXException The client may throw an exception during
368      *                processing.
369      * @exception IOException The client may throw an I/O-related exception
370      *                while obtaining the new InputSource.
371      */
372     public InputSource resolveEntity(String publicId, String systemId)
373             throws SAXException, IOException {
374         System.out.println(toString()+"try to resolveEntity="+systemId);
375         if (entityResolver != null) {
376             return entityResolver.resolveEntity(publicId, systemId);
377         } else {
378             System.out.println(toString()+"got null");
379             return null;
380         }
381     }
382 
383     ////////////////////////////////////////////////////////////////////
384     // Implementation of org.xml.sax.DTDHandler.
385     ////////////////////////////////////////////////////////////////////
386 
387     /***
388      * Filter a notation declaration event.
389      * 
390      * @param name The notation name.
391      * @param publicId The notation's public identifier, or null.
392      * @param systemId The notation's system identifier, or null.
393      * @exception SAXException The client may throw an exception during
394      *                processing.
395      */
396     public void notationDecl(String name, String publicId, String systemId)
397             throws SAXException {
398         if (dtdHandler != null) {
399             dtdHandler.notationDecl(name, publicId, systemId);
400         }
401     }
402 
403     /***
404      * Filter an unparsed entity declaration event.
405      * 
406      * @param name The entity name.
407      * @param publicId The entity's public identifier, or null.
408      * @param systemId The entity's system identifier, or null.
409      * @param notationName The name of the associated notation.
410      * @exception SAXException The client may throw an exception during
411      *                processing.
412      */
413     public void unparsedEntityDecl(String name, String publicId,
414             String systemId, String notationName) throws SAXException {
415         if (dtdHandler != null) {
416             dtdHandler.unparsedEntityDecl(name, publicId, systemId,
417                     notationName);
418         }
419     }
420 
421     ////////////////////////////////////////////////////////////////////
422     // Implementation of org.xml.sax.ContentHandler.
423     ////////////////////////////////////////////////////////////////////
424 
425     /***
426      * Filter a new document locator event.
427      * 
428      * @param locator The document locator.
429      */
430     public void setDocumentLocator(Locator locator) {
431         if ((locator == null) || (locator.getSystemId() == null)) {
432             //System.out.println("+++"+this+".(trying
433             // to)setDocumentLocator=null");
434             return;
435         }
436 
437         //System.out.println("+++"+this+".setDocumentLocator.getSystemId="+locator.getSystemId());
438         this.locator = locator;
439 
440         if (contentHandler != null) {
441             //contentHandler.setDocumentLocator(locator);
442         }
443     }
444 
445     public Locator getDocumentLocator() {
446         return locator;
447     }
448 
449     /***
450      * Filter a start document event.
451      * 
452      * @exception SAXException The client may throw an exception during
453      *                processing.
454      */
455     public void startDocument() throws SAXException {
456         //System.out.println(""+this+".startDocument");
457         if (contentHandler != null) {
458             contentHandler.startDocument();
459         }
460     }
461 
462     /***
463      * Filter an end document event.
464      * 
465      * @exception SAXException The client may throw an exception during
466      *                processing.
467      */
468     public void endDocument() throws SAXException {
469         //System.out.println("--- XTFilterImpl "+this+".endDocument,
470         // ch="+contentHandler);
471         if (contentHandler != null) {
472             contentHandler.endDocument();
473         }
474     }
475 
476     /***
477      * Filter a start Namespace prefix mapping event.
478      * 
479      * @param prefix The Namespace prefix.
480      * @param uri The Namespace URI.
481      * @exception SAXException The client may throw an exception during
482      *                processing.
483      */
484     public void startPrefixMapping(String prefix, String uri)
485             throws SAXException {
486         if (contentHandler != null) {
487             contentHandler.startPrefixMapping(prefix, uri);
488         }
489     }
490 
491     /***
492      * Filter an end Namespace prefix mapping event.
493      * 
494      * @param prefix The Namespace prefix.
495      * @exception SAXException The client may throw an exception during
496      *                processing.
497      */
498     public void endPrefixMapping(String prefix) throws SAXException {
499         if (contentHandler != null) {
500             contentHandler.endPrefixMapping(prefix);
501         }
502     }
503 
504     /***
505      * Filter a start element event.
506      * 
507      * @param uri The element's Namespace URI, or the empty string.
508      * @param localName The element's local name, or the empty string.
509      * @param qName The element's qualified (prefixed) name, or the empty
510      *            string.
511      * @param atts The element's attributes.
512      * @exception SAXException The client may throw an exception during
513      *                processing.
514      */
515     public void startElement(String uri, String localName, String qName,
516             Attributes atts) throws SAXException {
517         if (contentHandler != null) {
518             contentHandler.startElement(uri, localName, qName, atts);
519         }
520     }
521 
522     /***
523      * Filter an end element event.
524      * 
525      * @param uri The element's Namespace URI, or the empty string.
526      * @param localName The element's local name, or the empty string.
527      * @param qName The element's qualified (prefixed) name, or the empty
528      *            string.
529      * @exception SAXException The client may throw an exception during
530      *                processing.
531      */
532     public void endElement(String uri, String localName, String qName)
533             throws SAXException {
534         if (contentHandler != null) {
535             contentHandler.endElement(uri, localName, qName);
536         }
537     }
538 
539     /***
540      * Filter a character data event.
541      * 
542      * @param ch An array of characters.
543      * @param start The starting position in the array.
544      * @param length The number of characters to use from the array.
545      * @exception SAXException The client may throw an exception during
546      *                processing.
547      */
548     public void characters(char[] ch, int start, int length)
549             throws SAXException {
550         if (contentHandler != null) {
551             contentHandler.characters(ch, start, length);
552         }
553     }
554 
555     /***
556      * Filter an ignorable whitespace event.
557      * 
558      * @param ch An array of characters.
559      * @param start The starting position in the array.
560      * @param length The number of characters to use from the array.
561      * @exception SAXException The client may throw an exception during
562      *                processing.
563      */
564     public void ignorableWhitespace(char[] ch, int start, int length)
565             throws SAXException {
566         if (contentHandler != null) {
567             contentHandler.ignorableWhitespace(ch, start, length);
568         }
569     }
570 
571     /***
572      * Filter a processing instruction event.
573      * 
574      * @param target The processing instruction target.
575      * @param data The text following the target.
576      * @exception SAXException The client may throw an exception during
577      *                processing.
578      */
579     public void processingInstruction(String target, String data)
580             throws SAXException {
581         if (contentHandler != null) {
582             contentHandler.processingInstruction(target, data);
583         }
584     }
585 
586     /***
587      * Filter a skipped entity event.
588      * 
589      * @param name The name of the skipped entity.
590      * @exception SAXException The client may throw an exception during
591      *                processing.
592      */
593     public void skippedEntity(String name) throws SAXException {
594         if (contentHandler != null) {
595             contentHandler.skippedEntity(name);
596         }
597     }
598 
599     ////////////////////////////////////////////////////////////////////
600     // Implementation of org.xml.sax.ErrorHandler.
601     ////////////////////////////////////////////////////////////////////
602 
603     /***
604      * Filter a warning event.
605      * 
606      * @param e The warning as an exception.
607      * @exception SAXException The client may throw an exception during
608      *                processing.
609      */
610     public void warning(SAXParseException e) throws SAXException {
611         if (errorHandler != null) {
612             errorHandler.warning(e);
613         }
614     }
615 
616     /***
617      * Filter an error event.
618      * 
619      * @param e The error as an exception.
620      * @exception SAXException The client may throw an exception during
621      *                processing.
622      */
623     public void error(SAXParseException e) throws SAXException {
624         if (errorHandler != null) {
625             errorHandler.error(e);
626         }
627     }
628 
629     /***
630      * Filter a fatal error event.
631      * 
632      * @param e The error as an exception.
633      * @exception SAXException The client may throw an exception during
634      *                processing.
635      */
636     public void fatalError(SAXParseException e) throws SAXException {
637         if (errorHandler != null) {
638             errorHandler.fatalError(e);
639         }
640     }
641 
642     ////////////////////////////////////////////////////////////////////
643     // Implementation of the LexicalHandler.
644     ////////////////////////////////////////////////////////////////////
645 
646     /***
647      * Callback interface for SAX (part of LexicalHandler interface): not for
648      * application use
649      * 
650      * @param ch DOCUMENT ME!
651      * @param start DOCUMENT ME!
652      * @param length DOCUMENT ME!
653      * @throws SAXException DOCUMENT ME!
654      */
655     public void comment(char[] ch, int start, int length) throws SAXException {
656         if (lexicalHandler != null) {
657             lexicalHandler.comment(ch, start, length);
658         }
659     }
660 
661     // No-op methods to satisfy lexical handler interface
662 
663     /***
664      * Register the start of the DTD. Comments in the DTD are skipped because
665      * they are not part of the XPath data model
666      * 
667      * @param name DOCUMENT ME!
668      * @param publicId DOCUMENT ME!
669      * @param systemId DOCUMENT ME!
670      * @throws SAXException DOCUMENT ME!
671      */
672     public void startDTD(String name, String publicId, String systemId)
673             throws SAXException {
674         if (lexicalHandler != null) {
675             lexicalHandler.startDTD(name, publicId, systemId);
676         }
677     }
678 
679     /***
680      * Register the end of the DTD. Comments in the DTD are skipped because they
681      * are not part of the XPath data model
682      * 
683      * @throws SAXException DOCUMENT ME!
684      */
685     public void endDTD() throws SAXException {
686         if (lexicalHandler != null) {
687             lexicalHandler.endDTD();
688         }
689     }
690 
691     /***
692      * DOCUMENT ME!
693      * 
694      * @param name DOCUMENT ME!
695      * @throws SAXException DOCUMENT ME!
696      */
697     public void startEntity(String name) throws SAXException {
698         if (lexicalHandler != null) {
699             lexicalHandler.startEntity(name);
700         }
701     }
702 
703     /***
704      * DOCUMENT ME!
705      * 
706      * @param name DOCUMENT ME!
707      * @throws SAXException DOCUMENT ME!
708      */
709     public void endEntity(String name) throws SAXException {
710         if (lexicalHandler != null) {
711             lexicalHandler.endEntity(name);
712         }
713     }
714 
715     /***
716      * DOCUMENT ME!
717      * 
718      * @throws SAXException DOCUMENT ME!
719      */
720     public void startCDATA() throws SAXException {
721         if (lexicalHandler != null) {
722             lexicalHandler.startCDATA();
723         }
724     }
725 
726     /***
727      * DOCUMENT ME!
728      * 
729      * @throws SAXException DOCUMENT ME!
730      */
731     public void endCDATA() throws SAXException {
732         if (lexicalHandler != null) {
733             lexicalHandler.endCDATA();
734         }
735     }
736 
737     ////////////////////////////////////////////////////////////////////
738     // Internal methods.
739     ////////////////////////////////////////////////////////////////////
740 
741     /***
742      * Set up before a parse.
743      * <p>
744      * Before every parse, check whether the parent is non-null, and re-register
745      * the filter for all of the events.
746      * </p>
747      * 
748      * @throws SAXException DOCUMENT ME!
749      * @throws NullPointerException DOCUMENT ME!
750      */
751     protected void setupParse() throws SAXException {
752         if (parent == null) {
753             throw new NullPointerException("No parent for filter " + this);
754         }
755 
756 //        parent.setEntityResolver(this);
757 /*        if(!(parent instanceof net.sf.tomp.xml.type.TypeDetectorFilter)) {
758             parent.setEntityResolver(this);
759 //            System.out.println(parent+".setEntityResolver="+this);
760         } else {
761 //            System.out.println(parent+".would setEntityResolver="+this);
762         }
763 //        System.out.println("orig EntityResolver="+parent.getEntityResolver());
764 */        
765         parent.setDTDHandler(this);
766         parent.setContentHandler(this);
767 
768         //System.out.println(parent+".setContentHandler("+this);
769         parent.setErrorHandler(this);
770 
771         try {
772             parent.setProperty("http://xml.org/sax/properties/lexical-handler",
773                     this);
774         } catch (SAXException se) {
775             //se.printStackTrace();
776         }
777     }
778 
779 	/* (non-Javadoc)
780 	 * @see net.sf.tomp.xtcl.filter.XTFilter#getContext()
781 	 */
782 	public Context getContext() {
783 		return context;
784 	}
785 
786 	/***
787 	 * @param context The context to set.
788 	 */
789 	public void setContext(Context context) {
790 		this.context = context;
791 	}
792 }
793 
794 /*
795  * The contents of this file are subject to the Mozilla Public License Version
796  * 1.1 (the "License"); you may not use this file except in compliance with the
797  * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
798  * Software distributed under the License is distributed on an "AS IS" basis,
799  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
800  * the specific language governing rights and limitations under the License. The
801  * Original Code is: all this file. The Initial Developer of the Original Code
802  * is: Tomas Pitner, Masaryk University in Brno, Czech Republic. Contributor(s):
803  */