View Javadoc

1   package net.sf.tomp.xtcl.filter;
2   
3   import net.sf.tomp.general.Parametrized;
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.XMLFilter;
17  import org.xml.sax.XMLReader;
18  import org.xml.sax.ext.LexicalHandler;
19  
20  import java.io.IOException;
21  
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.Properties;
25  
26  /***
27   * DOCUMENT ME!
28   * 
29   * @author tomp
30   */
31  public class DynamicMultiFilterImpl extends XTFilterImpl implements
32          DynamicMultiFilter {
33  
34      /***
35       * DOCUMENT ME!
36       * 
37       * @param parent DOCUMENT ME!
38       * @param f DOCUMENT ME!
39       */
40      protected static void connectHandlers(XMLReader parent, XMLFilter f) {
41          // route messages from parent to f
42          //System.out.println(parent+" *** SETS HANDLERS to "+f);
43          // comm out by TP Oct 5 2004
44  /*        if (f instanceof EntityResolver) {
45              parent.setEntityResolver((EntityResolver) f);
46          }
47  */
48          if (f instanceof DTDHandler) {
49              parent.setDTDHandler((DTDHandler) f);
50          }
51  
52          if (f instanceof ContentHandler) {
53              parent.setContentHandler((ContentHandler) f);
54          }
55  
56          if (f instanceof ErrorHandler) {
57              parent.setErrorHandler((ErrorHandler) f);
58          }
59  
60          try {
61              if (f instanceof LexicalHandler) {
62                  //System.out.println(parent+" *** SETS LexicalHandler to "+f);
63                  parent.setProperty(
64                          "http://xml.org/sax/properties/lexical-handler", f);
65              }
66          } catch (SAXException se) {
67              se.printStackTrace();
68          }
69  
70          // connect f to parent
71          f.setParent(parent);
72      }
73  
74      /***
75       * DOCUMENT ME!
76       * 
77       * @param from DOCUMENT ME!
78       * @param to DOCUMENT ME!
79       */
80      protected static void copyHandlers(XMLReader from, XMLReader to) {
81          // route messages from last filter to further handlers
82          //System.out.println(f+" *** SETS DTD HANDLER to "+getDTDHandler());
83          ContentHandler ch = from.getContentHandler();
84  
85          if (ch != null) {
86              to.setContentHandler(ch);
87          }
88  
89          DTDHandler dh = from.getDTDHandler();
90  
91          if (dh != null) {
92              to.setDTDHandler(dh);
93          }
94  
95  /*        EntityResolver er = from.getEntityResolver();
96  
97          if (er != null) {
98              to.setEntityResolver(er);
99          }
100 */
101         ErrorHandler eh = from.getErrorHandler();
102 
103         if (eh != null) {
104             to.setErrorHandler(eh);
105         }
106 
107         try {
108             Object lh = from
109                     .getProperty("http://xml.org/sax/properties/lexical-handler");
110 
111             if (lh != null) {
112                 to.setProperty("http://xml.org/sax/properties/lexical-handler",
113                         lh);
114             }
115         } catch (SAXException se) {
116             //se.printStackTrace();
117         }
118     }
119     ////////////////////////////////////////////////////////////////////
120     // Internal state.
121     ////////////////////////////////////////////////////////////////////
122 
123     /*** DOCUMENT ME! */
124     protected List filters;
125 
126     /*** DOCUMENT ME! */
127     protected XMLFilter firstFilter = null;
128 
129     /*** DOCUMENT ME! */
130     protected boolean isContentHandler;
131 
132     /*** DOCUMENT ME! */
133     protected boolean isDTDHandler;
134 
135     /*** DOCUMENT ME! */
136     protected boolean isEntityResolver;
137 
138     /*** DOCUMENT ME! */
139     protected boolean isErrorHandler;
140 
141     /*** DOCUMENT ME! */
142     protected boolean isLexicalHandler;
143 
144     /*** DOCUMENT ME! */
145     protected XMLFilter lastFilter = null;
146 
147     /*** DOCUMENT ME! */
148     protected HasOutputProperties outputPropertiesListener = null;
149 
150     ////////////////////////////////////////////////////////////////////
151     // Constructors.
152     ////////////////////////////////////////////////////////////////////
153     public DynamicMultiFilterImpl() {
154         super();
155         filters = new ArrayList();
156 
157         //setFilter(f);
158     }
159 
160     /***
161      * Creates a new DynamicMultiFilterImpl object.
162      * 
163      * @param parent DOCUMENT ME!
164      */
165     public DynamicMultiFilterImpl(XMLReader parent) {
166         this();
167         setParent(parent);
168     }
169 
170     /***
171      * DOCUMENT ME!
172      * 
173      * @param pos DOCUMENT ME!
174      * @param f DOCUMENT ME!
175      * @throws SAXException DOCUMENT ME!
176      */
177     public void addFilter(int pos, XMLFilter f) throws SAXException {
178         // FIXME
179         // use case 1: add(0, f)
180         if (pos == 0) {
181             XMLReader parent = getParent();
182 
183             if (parent != null) {
184                 connectHandlers(parent, f);
185             }
186 
187             if (0 == getFilterCount()) {
188                 // the one and only
189                 copyHandlers(this, f);
190                 lastFilter = f;
191             } else {
192                 // already has some filters...
193                 copyHandlers(firstFilter, f);
194                 connectHandlers(f, firstFilter);
195             }
196 
197             firstFilter = f;
198             determineHandlerInfo();
199 
200             // use case 2: add(last, f)
201         } else if (pos == getFilterCount()) {
202             // already has some filters...
203             copyHandlers(lastFilter, f);
204 
205             connectHandlers(lastFilter, f);
206 
207             lastFilter = f;
208 
209             // use case 3: add(n, f) - general case, # of filters > 1
210         } else {
211             XMLFilter next = getFilter(pos);
212             XMLReader parent = next.getParent();
213 
214             copyHandlers(parent, f);
215             connectHandlers(parent, f);
216         }
217 
218         filters.add(pos, f);
219     }
220 
221     ////////////////////////////////////////////////////////////////////
222     // Implementation of the LexicalHandler.
223     ////////////////////////////////////////////////////////////////////
224 
225     /***
226      * Callback interface for SAX (part of LexicalHandler interface): not for
227      * application use
228      * 
229      * @param ch DOCUMENT ME!
230      * @param start DOCUMENT ME!
231      * @param length DOCUMENT ME!
232      * @throws SAXException DOCUMENT ME!
233      */
234     public void comment(char[] ch, int start, int length) throws SAXException {
235         if (firstFilter != null) {
236             if (isLexicalHandler) {
237                 ((LexicalHandler) firstFilter).comment(ch, start, length);
238             }
239         } else {
240             super.comment(ch, start, length);
241         }
242     }
243 
244     /***
245      * DOCUMENT ME!
246      */
247     protected void determineHandlerInfo() {
248         isContentHandler = firstFilter instanceof ContentHandler;
249         isDTDHandler = firstFilter instanceof DTDHandler;
250         isErrorHandler = firstFilter instanceof ErrorHandler;
251         isLexicalHandler = firstFilter instanceof LexicalHandler;
252         isEntityResolver = firstFilter instanceof EntityResolver;
253     }
254 
255     /***
256      * DOCUMENT ME!
257      * 
258      * @throws SAXException DOCUMENT ME!
259      */
260     public void endCDATA() throws SAXException {
261         if (firstFilter != null) {
262             if (isLexicalHandler) {
263                 ((LexicalHandler) firstFilter).endCDATA();
264             }
265         } else {
266             super.endCDATA();
267         }
268     }
269 
270     /***
271      * Filter an end document event.
272      * 
273      * @exception SAXException The client may throw an exception during
274      *                processing.
275      */
276     public void endDocument() throws SAXException {
277         //System.out.println("---DynamicFilter "+this+".endDocument,
278         // firstFilter="+firstFilter);
279         if (firstFilter != null) {
280             //System.out.println("---firstFilter has
281             // contenthandler="+firstFilter.getContentHandler());
282             if (isContentHandler) {
283                 ((ContentHandler) firstFilter).endDocument();
284             }
285         } else {
286             super.endDocument();
287         }
288     }
289 
290     /***
291      * Register the end of the DTD. Comments in the DTD are skipped because they
292      * are not part of the XPath data model
293      * 
294      * @throws SAXException DOCUMENT ME!
295      */
296     public void endDTD() throws SAXException {
297         if (firstFilter != null) {
298             if (isLexicalHandler) {
299                 ((LexicalHandler) firstFilter).endDTD();
300             }
301         } else {
302             super.endDTD();
303         }
304     }
305 
306     /***
307      * Filter an end element event.
308      * 
309      * @param uri The element's Namespace URI, or the empty string.
310      * @param localName The element's local name, or the empty string.
311      * @param qName The element's qualified (prefixed) name, or the empty
312      *            string.
313      * @exception SAXException The client may throw an exception during
314      *                processing.
315      */
316     public void endElement(String uri, String localName, String qName)
317             throws SAXException {
318         if (firstFilter != null) {
319             if (isContentHandler) {
320                 ((ContentHandler) firstFilter)
321                         .endElement(uri, localName, qName);
322             }
323         } else {
324             super.endElement(uri, localName, qName);
325         }
326     }
327 
328     /***
329      * DOCUMENT ME!
330      * 
331      * @param name DOCUMENT ME!
332      * @throws SAXException DOCUMENT ME!
333      */
334     public void endEntity(String name) throws SAXException {
335         if (firstFilter != null) {
336             if (isLexicalHandler) {
337                 ((LexicalHandler) firstFilter).endEntity(name);
338             }
339         } else {
340             super.endEntity(name);
341         }
342     }
343 
344     /***
345      * Filter an end Namespace prefix mapping event.
346      * 
347      * @param prefix The Namespace prefix.
348      * @exception SAXException The client may throw an exception during
349      *                processing.
350      */
351     public void endPrefixMapping(String prefix) throws SAXException {
352         if (firstFilter != null) {
353             if (isContentHandler) {
354                 ((ContentHandler) firstFilter).endPrefixMapping(prefix);
355             }
356         } else {
357             super.endPrefixMapping(prefix);
358         }
359     }
360 
361     /***
362      * Filter an error event.
363      * 
364      * @param e The error as an exception.
365      * @exception SAXException The client may throw an exception during
366      *                processing.
367      */
368     public void error(SAXParseException e) throws SAXException {
369         if (firstFilter != null) {
370             if (isErrorHandler) {
371                 ((ErrorHandler) firstFilter).error(e);
372             }
373         } else {
374             super.error(e);
375         }
376     }
377 
378     /***
379      * Filter a fatal error event.
380      * 
381      * @param e The error as an exception.
382      * @exception SAXException The client may throw an exception during
383      *                processing.
384      */
385     public void fatalError(SAXParseException e) throws SAXException {
386         if (firstFilter != null) {
387             if (isErrorHandler) {
388                 ((ErrorHandler) firstFilter).fatalError(e);
389             }
390         } else {
391             super.fatalError(e);
392         }
393     }
394 
395     /***
396      * Get the content event handler.
397      * 
398      * @return The current content handler, or null if none was set.
399      */
400     public ContentHandler getContentHandler() {
401         //System.out.println(""+this+".getContentHandler=>"+contentHandler);
402         if (lastFilter != null) {
403             return lastFilter.getContentHandler();
404         } else {
405             return super.getContentHandler();
406         }
407     }
408 
409     /***
410      * Get the current DTD event handler.
411      * 
412      * @return The current DTD handler, or null if none was set.
413      */
414     public DTDHandler getDTDHandler() {
415         if (lastFilter != null) {
416             return lastFilter.getDTDHandler();
417         } else {
418             return super.getDTDHandler();
419         }
420     }
421 
422     /***
423      * Get the current entity resolver.
424      * 
425      * @return The current entity resolver, or null if none was set.
426      */
427     public EntityResolver getEntityResolver() {
428         if (firstFilter != null) {
429             return firstFilter.getEntityResolver();
430         } else {
431             return super.getEntityResolver();
432         }
433     }
434 
435     /***
436      * Get the current error event handler.
437      * 
438      * @return The current error handler, or null if none was set.
439      */
440     public ErrorHandler getErrorHandler() {
441         if (lastFilter != null) {
442             return lastFilter.getErrorHandler();
443         } else {
444             return super.getErrorHandler();
445         }
446     }
447 
448     /***
449      * DOCUMENT ME!
450      * 
451      * @param name DOCUMENT ME!
452      * @return DOCUMENT ME!
453      * @throws SAXNotRecognizedException DOCUMENT ME!
454      * @throws SAXNotSupportedException DOCUMENT ME!
455      */
456     public boolean getFeature(String name) throws SAXNotRecognizedException,
457             SAXNotSupportedException {
458         // FIXME: the same problem
459         if (firstFilter != null) {
460             return firstFilter.getFeature(name);
461         } else {
462             return super.getFeature(name);
463         }
464     }
465 
466     /***
467      * DOCUMENT ME!
468      * 
469      * @param pos DOCUMENT ME!
470      * @return DOCUMENT ME!
471      */
472     public XMLFilter getFilter(int pos) {
473         return (XMLFilter) filters.get(pos);
474     }
475 
476     /***
477      * DOCUMENT ME!
478      * 
479      * @return DOCUMENT ME!
480      */
481     public int getFilterCount() {
482         return filters.size();
483     }
484 
485     /***
486      * DOCUMENT ME!
487      * 
488      * @return DOCUMENT ME!
489      */
490     public Properties getOutputProperties() {
491         //System.out.println(this+" +++++++++++++ getOutputProperties from
492         // lastFilter=" + lastFilter);
493         if (lastFilter instanceof HasOutputProperties) {
494             return ((HasOutputProperties) lastFilter).getOutputProperties();
495         }
496 
497         return null;
498     }
499 
500     /*
501      * public void setProperty (String name, Object value) throws
502      * SAXNotRecognizedException, SAXNotSupportedException { if(firstFilter !=
503      * null) firstFilter.setProperty(name, value); super.setProperty(name,
504      * value); }
505      */
506 
507     /***
508      * Look up the value of a property.
509      * 
510      * @param name The property name.
511      * @return The current value of the property.
512      * @exception SAXNotRecognizedException If the property value can't be
513      *                assigned or retrieved from the parent.
514      * @exception SAXNotSupportedException When the parent recognizes the
515      *                property name but cannot determine its value at this time.
516      */
517     public Object getProperty(String name) throws SAXNotRecognizedException,
518             SAXNotSupportedException {
519         if (firstFilter != null) {
520             return firstFilter.getProperty(name);
521         } else {
522             return super.getProperty(name);
523         }
524     }
525 
526     /***
527      * Filter a character data event.
528      * 
529      * @param ch An array of characters.
530      * @param start The starting position in the array.
531      * @param length The number of characters to use from the array.
532      * @exception SAXException The client may throw an exception during
533      *                processing.
534      */
535     public void characters(char[] ch, int start, int length)
536             throws SAXException {
537         if (firstFilter != null) {
538             if (isContentHandler) {
539                 ((ContentHandler) firstFilter).characters(ch, start, length);
540             }
541         } else {
542             super.characters(ch, start, length);
543         }
544     }
545 
546     /***
547      * Filter an ignorable whitespace event.
548      * 
549      * @param ch An array of characters.
550      * @param start The starting position in the array.
551      * @param length The number of characters to use from the array.
552      * @exception SAXException The client may throw an exception during
553      *                processing.
554      */
555     public void ignorableWhitespace(char[] ch, int start, int length)
556             throws SAXException {
557         if (firstFilter != null) {
558             if (isContentHandler) {
559                 ((ContentHandler) firstFilter).ignorableWhitespace(ch, start,
560                         length);
561             }
562         } else {
563             super.ignorableWhitespace(ch, start, length);
564         }
565     }
566 
567     ////////////////////////////////////////////////////////////////////
568     // Implementation of org.xml.sax.DTDHandler.
569     ////////////////////////////////////////////////////////////////////
570 
571     /***
572      * Filter a notation declaration event.
573      * 
574      * @param name The notation name.
575      * @param publicId The notation's public identifier, or null.
576      * @param systemId The notation's system identifier, or null.
577      * @exception SAXException The client may throw an exception during
578      *                processing.
579      */
580     public void notationDecl(String name, String publicId, String systemId)
581             throws SAXException {
582         if (firstFilter != null) {
583             if (isDTDHandler) {
584                 ((DTDHandler) firstFilter).notationDecl(name, publicId,
585                         systemId);
586             } else {
587                 super.notationDecl(name, publicId, systemId);
588             }
589         }
590     }
591 
592     /***
593      * Parse a document.
594      * 
595      * @param input The input source for the document entity.
596      * @exception SAXException Any SAX exception, possibly wrapping another
597      *                exception.
598      * @exception IOException An IO exception from the parser, possibly from a
599      *                byte stream or character stream supplied by the
600      *                application.
601      */
602     public void parse(InputSource input) throws SAXException, IOException {
603         if (lastFilter != null) {
604             lastFilter.parse(input);
605         } else {
606             super.parse(input);
607         }
608     }
609 
610     /***
611      * Filter a processing instruction event.
612      * 
613      * @param target The processing instruction target.
614      * @param data The text following the target.
615      * @exception SAXException The client may throw an exception during
616      *                processing.
617      */
618     public void processingInstruction(String target, String data)
619             throws SAXException {
620         if (firstFilter != null) {
621             if (isContentHandler) {
622                 ((ContentHandler) firstFilter).processingInstruction(target,
623                         data);
624             }
625         } else {
626             super.processingInstruction(target, data);
627         }
628     }
629 
630 	// No-op methods to satisfy lexical handler interface
631 	
632 	/***
633 	 * Register the start of the DTD. Comments in the DTD are skipped because
634 	 * they are not part of the XPath data model
635 	 * 
636 	 * @param name DOCUMENT ME!
637 	 * @param publicId DOCUMENT ME!
638 	 * @param systemId DOCUMENT ME!
639 	 * @throws SAXException DOCUMENT ME!
640 	 */
641 	public void startDTD(String name, String publicId, String systemId)
642 	        throws SAXException {
643 	    if (firstFilter != null) {
644 	        if (isLexicalHandler) {
645 	            ((LexicalHandler) firstFilter).startDTD(name, publicId,
646 	                    systemId);
647 	        }
648 	    } else {
649 	        super.startDTD(name, publicId, systemId);
650 	    }
651 	}
652 
653     /***
654      * DOCUMENT ME!
655      * 
656      * @param pos DOCUMENT ME!
657      * @throws SAXException DOCUMENT ME!
658      * @throws UnsupportedOperationException DOCUMENT ME!
659      */
660     public void removeFilter(int pos) throws SAXException {
661         // FIXME
662         throw new UnsupportedOperationException();
663     }
664 
665     ////////////////////////////////////////////////////////////////////
666     // Implementation of org.xml.sax.EntityResolver.
667     ////////////////////////////////////////////////////////////////////
668 
669     /***
670      * Filter an external entity resolution.
671      * 
672      * @param publicId The entity's public identifier, or null.
673      * @param systemId The entity's system identifier.
674      * @return A new InputSource or null for the default.
675      * @exception SAXException The client may throw an exception during
676      *                processing.
677      * @exception IOException The client may throw an I/O-related exception
678      *                while obtaining the new InputSource.
679      */
680     public InputSource resolveEntity(String publicId, String systemId)
681             throws SAXException, IOException {
682         // FIXME ??? firstFilter or last or what?
683 //        System.out.println(toString()+"try to resolveEntity="+systemId);
684         if ((firstFilter != null) && isEntityResolver) {
685             return ((EntityResolver) firstFilter).resolveEntity(publicId,
686                     systemId);
687         } else {
688             return super.resolveEntity(publicId, systemId);
689         }
690     }
691 
692     /***
693      * Set the content event handler.
694      * 
695      * @param handler The new content handler.
696      */
697     public void setContentHandler(ContentHandler handler) {
698         //System.out.println(""+this+".setContentHandler="+handler);
699         if (lastFilter != null) {
700             lastFilter.setContentHandler(handler);
701         }
702 
703         super.setContentHandler(handler);
704     }
705 
706     ////////////////////////////////////////////////////////////////////
707     // Implementation of org.xml.sax.ContentHandler.
708     ////////////////////////////////////////////////////////////////////
709 
710     /***
711      * Filter a new document locator event.
712      * 
713      * @param locator The document locator.
714      */
715     public void setDocumentLocator(Locator locator) {
716         if (firstFilter != null) {
717             if (isContentHandler) {
718                 ((ContentHandler) firstFilter).setDocumentLocator(locator);
719             }
720         }
721 
722         super.setDocumentLocator(locator);
723     }
724 
725     /***
726      * Set the DTD event handler.
727      * 
728      * @param handler The new DTD handler.
729      */
730     public void setDTDHandler(DTDHandler handler) {
731         if (lastFilter != null) {
732             lastFilter.setDTDHandler(handler);
733         }
734 
735         super.setDTDHandler(handler);
736     }
737 
738     /***
739      * Set the entity resolver.
740      * 
741      * @param resolver The new entity resolver.
742      */
743     public void setEntityResolver(EntityResolver resolver) {
744         // FIXME: to all???
745         if (firstFilter != null) {
746             firstFilter.setEntityResolver(resolver);
747         }
748 
749         super.setEntityResolver(resolver);
750     }
751 
752     /***
753      * Set the error event handler.
754      * 
755      * @param handler The new error handler.
756      */
757     public void setErrorHandler(ErrorHandler handler) {
758         if (lastFilter != null) {
759             lastFilter.setErrorHandler(handler);
760         }
761 
762         super.setErrorHandler(handler);
763     }
764 
765     ////////////////////////////////////////////////////////////////////
766     // Implementation of org.xml.sax.XMLReader.
767     ////////////////////////////////////////////////////////////////////
768     public void setFeature(String name, boolean value)
769             throws SAXNotRecognizedException, SAXNotSupportedException {
770         // FIXME: setFeature to all filters or the 1st only?
771         if (firstFilter != null) {
772             firstFilter.setFeature(name, value);
773         }
774 
775         super.setFeature(name, value);
776     }
777 
778     /***
779      * DOCUMENT ME!
780      * 
781      * @param pos DOCUMENT ME!
782      * @param f DOCUMENT ME!
783      * @throws SAXException DOCUMENT ME!
784      * @throws UnsupportedOperationException DOCUMENT ME!
785      */
786     public void setFilter(int pos, XMLFilter f) throws SAXException {
787         // FIXME
788         throw new UnsupportedOperationException();
789     }
790 
791     ////////////////////////////////////////////////////////////////////
792     // Internal methods.
793     ////////////////////////////////////////////////////////////////////
794     public void setLexicalHandler(LexicalHandler handler) {
795         //System.out.println(""+this+".setContentHandler="+handler);
796         super.setLexicalHandler(handler);
797 
798         if ((lastFilter != null) && lastFilter instanceof LexicalHandler) {
799             try {
800                 //System.out.println(" *** DMF.setLexicalHandler to "+handler);
801                 lastFilter.setProperty(
802                         "http://xml.org/sax/properties/lexical-handler",
803                         handler);
804             } catch (SAXException se) {
805                 se.printStackTrace();
806             }
807         }
808     }
809 
810     /***
811      * DOCUMENT ME!
812      * 
813      * @param p DOCUMENT ME!
814      * @throws UnsupportedOperationException DOCUMENT ME!
815      */
816     public void setOutputProperties(Properties p) {
817         throw new UnsupportedOperationException(
818                 "Cannot setOutputProperties on " + this);
819     }
820 
821     /***
822      * DOCUMENT ME!
823      * 
824      * @param l DOCUMENT ME!
825      */
826     public void setOutputPropertiesListener(HasOutputProperties l) {
827         outputPropertiesListener = l;
828     }
829 
830     ////////////////////////////////////////////////////////////////////
831     // Implementation of net.sf.tomp.general.Parametrized.
832     ////////////////////////////////////////////////////////////////////
833     public void setParameter(String k, Object v) {
834         //System.out.println("Setting param "+k+"="+v);
835         int fc = getFilterCount();
836         for(int i = 0; i < fc; i++) {
837             setParameterToFilter(k, v, getFilter(i));
838         }
839     }
840 
841     protected void setParameterToFilter(String k, Object v, XMLFilter filter) {
842         if(filter instanceof Parametrized) {
843             Parametrized pf = (Parametrized)filter;
844 //            if(filter instanceof Identifiable) {
845 //                Identifiable fi = (Identifiable)pf;
846 //                if(k.startsWith(fi.getId()+":")) {
847 //                    pf.setParameter(k, v);
848 //                }
849 //            } else {
850 //            System.out.println("DMF Setting param "+k+"="+v+ " to "+filter);
851                 pf.setParameter(k, v);
852 //            }
853         }
854     }
855 
856     ////////////////////////////////////////////////////////////////////
857     // Implementation of org.xml.sax.XMLFilter.
858     ////////////////////////////////////////////////////////////////////
859     public void setParent(XMLReader parent) {
860         super.setParent(parent);
861 
862         //System.out.println(" ***DynamicMultiFilter:"+this+"
863         // setParent="+parent+"... ");
864         if (firstFilter != null) {
865             connectHandlers(parent, firstFilter);
866 
867             //firstFilter.setParent(parent);
868             //System.out.println("... also to firstFilter="+firstFilter);
869         }
870     }
871 
872     /***
873      * Filter a skipped entity event.
874      * 
875      * @param name The name of the skipped entity.
876      * @exception SAXException The client may throw an exception during
877      *                processing.
878      */
879     public void skippedEntity(String name) throws SAXException {
880         if (firstFilter != null) {
881             if (isContentHandler) {
882                 ((ContentHandler) firstFilter).skippedEntity(name);
883             }
884         } else {
885             super.skippedEntity(name);
886         }
887     }
888 
889     /***
890      * DOCUMENT ME!
891      * 
892      * @throws SAXException DOCUMENT ME!
893      */
894     public void startCDATA() throws SAXException {
895         if (firstFilter != null) {
896             if (isLexicalHandler) {
897                 ((LexicalHandler) firstFilter).startCDATA();
898             }
899         } else {
900             super.startCDATA();
901         }
902     }
903 
904     /***
905      * Filter a start document event.
906      * 
907      * @exception SAXException The client may throw an exception during
908      *                processing.
909      */
910     public void startDocument() throws SAXException {
911         //System.out.println(""+this+".startDocument");
912         if (firstFilter != null) {
913             if (isContentHandler) {
914                 ((ContentHandler) firstFilter).startDocument();
915             }
916         } else {
917             super.startDocument();
918         }
919 
920         if (outputPropertiesListener != null) {
921             outputPropertiesListener.setOutputProperties(getOutputProperties());
922         }
923     }
924 
925     // No-op methods to satisfy lexical handler interface
926 
927     /***
928      * Filter a start element event.
929      * 
930      * @param uri The element's Namespace URI, or the empty string.
931      * @param localName The element's local name, or the empty string.
932      * @param qName The element's qualified (prefixed) name, or the empty
933      *            string.
934      * @param atts The element's attributes.
935      * @exception SAXException The client may throw an exception during
936      *                processing.
937      */
938     public void startElement(String uri, String localName, String qName,
939             Attributes atts) throws SAXException {
940         if (firstFilter != null) {
941             if (isContentHandler) {
942                 ((ContentHandler) firstFilter).startElement(uri, localName,
943                         qName, atts);
944             }
945         } else {
946             super.startElement(uri, localName, qName, atts);
947         }
948     }
949 
950     /***
951      * DOCUMENT ME!
952      * 
953      * @param name DOCUMENT ME!
954      * @throws SAXException DOCUMENT ME!
955      */
956     public void startEntity(String name) throws SAXException {
957         if (firstFilter != null) {
958             if (isLexicalHandler) {
959                 ((LexicalHandler) firstFilter).startEntity(name);
960             }
961         } else {
962             super.startEntity(name);
963         }
964     }
965 
966     /***
967      * Filter a start Namespace prefix mapping event.
968      * 
969      * @param prefix The Namespace prefix.
970      * @param uri The Namespace URI.
971      * @exception SAXException The client may throw an exception during
972      *                processing.
973      */
974     public void startPrefixMapping(String prefix, String uri)
975             throws SAXException {
976         if (firstFilter != null) {
977             if (isContentHandler) {
978                 ((ContentHandler) firstFilter).startPrefixMapping(prefix, uri);
979             }
980         } else {
981             super.startPrefixMapping(prefix, uri);
982         }
983     }
984 
985     /***
986      * Filter an unparsed entity declaration event.
987      * 
988      * @param name The entity name.
989      * @param publicId The entity's public identifier, or null.
990      * @param systemId The entity's system identifier, or null.
991      * @param notationName The name of the associated notation.
992      * @exception SAXException The client may throw an exception during
993      *                processing.
994      */
995     public void unparsedEntityDecl(String name, String publicId,
996             String systemId, String notationName) throws SAXException {
997         if (firstFilter != null) {
998             if (isDTDHandler) {
999                 ((DTDHandler) firstFilter).unparsedEntityDecl(name, publicId,
1000                         systemId, notationName);
1001             }
1002         } else {
1003             super.unparsedEntityDecl(name, publicId, systemId, notationName);
1004         }
1005     }
1006 
1007     ////////////////////////////////////////////////////////////////////
1008     // Implementation of org.xml.sax.ErrorHandler.
1009     ////////////////////////////////////////////////////////////////////
1010 
1011     /***
1012      * Filter a warning event.
1013      * 
1014      * @param e The warning as an exception.
1015      * @exception SAXException The client may throw an exception during
1016      *                processing.
1017      */
1018     public void warning(SAXParseException e) throws SAXException {
1019         if (firstFilter != null) {
1020             if (isErrorHandler) {
1021                 ((ErrorHandler) firstFilter).warning(e);
1022             }
1023         } else {
1024             super.warning(e);
1025         }
1026     }
1027 }
1028 
1029 /*
1030  * The contents of this file are subject to the Mozilla Public License Version
1031  * 1.1 (the "License"); you may not use this file except in compliance with the
1032  * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
1033  * Software distributed under the License is distributed on an "AS IS" basis,
1034  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
1035  * the specific language governing rights and limitations under the License. The
1036  * Original Code is: all this file. The Initial Developer of the Original Code
1037  * is: Tomas Pitner, Masaryk University in Brno, Czech Republic. Contributor(s):
1038  */