/* TeeConsumer.java -- 
   Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package gnu.xml.pipeline;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;

/**
 * Fans its events out to two other consumers, a "tee" filter stage in an
 * event pipeline.  Networks can be assembled with multiple output points.
 *
 * <p> Error handling should be simple if you remember that exceptions
 * you throw will cancel later stages in that callback's pipeline, and
 * generally the producer will stop if it sees such an exception.  You
 * may want to protect your pipeline against such backflows, making a
 * kind of reverse filter (or valve?) so that certain exceptions thrown by
 * your pipeline will caught and handled before the producer sees them.
 * Just use a "try/catch" block, rememebering that really important
 * cleanup tasks should be in "finally" clauses.
 *
 * <p> That issue isn't unique to "tee" consumers, but tee consumers have
 * the additional twist that exceptions thrown by the first consumer
 * will cause the second consumer not to see the callback (except for
 * the endDocument callback, which signals state cleanup).
 *
 * @author David Brownell
 */
final public class TeeConsumer
	implements EventConsumer,
		ContentHandler, DTDHandler,
		LexicalHandler,DeclHandler
{
    private EventConsumer	first, rest;

    // cached to minimize time overhead
    private ContentHandler	docFirst, docRest;
    private DeclHandler		declFirst, declRest;
    private LexicalHandler	lexFirst, lexRest;


    /**
     * Constructs a consumer which sends all its events to the first
     * consumer, and then the second one.  If the first consumer throws
     * an exception, the second one will not see the event which
     * caused that exception to be reported.
     *
     * @param car The first consumer to get the events
     * @param cdr The second consumer to get the events
     */
    public TeeConsumer (EventConsumer car, EventConsumer cdr)
    {
	if (car == null || cdr == null)
	    throw new NullPointerException ();
	first = car;
	rest = cdr;

	//
	// Cache the handlers.
	//
	docFirst = first.getContentHandler ();
	docRest = rest.getContentHandler ();
	// DTD handler isn't cached (rarely needed)

	try {
	    declFirst = null;
	    declFirst = (DeclHandler) first.getProperty (
			EventFilter.DECL_HANDLER);
	} catch (SAXException e) {}
	try {
	    declRest = null;
	    declRest = (DeclHandler) rest.getProperty (
			EventFilter.DECL_HANDLER);
	} catch (SAXException e) {}

	try {
	    lexFirst = null;
	    lexFirst = (LexicalHandler) first.getProperty (
			EventFilter.LEXICAL_HANDLER);
	} catch (SAXException e) {}
	try {
	    lexRest = null;
	    lexRest = (LexicalHandler) rest.getProperty (
			EventFilter.LEXICAL_HANDLER);
	} catch (SAXException e) {}
    }

/* FIXME
    /**
     * Constructs a pipeline, and is otherwise a shorthand for the
     * two-consumer constructor for this class.
     *
     * @param first Description of the first pipeline to get events,
     *	which will be passed to {@link PipelineFactory#createPipeline}
     * @param rest The second pipeline to get the events
     * /
	// constructor used by PipelineFactory
    public TeeConsumer (String first, EventConsumer rest)
    throws IOException
    {
	this (PipelineFactory.createPipeline (first), rest);
    }
*/

    /** Returns the first pipeline to get event calls. */
    public EventConsumer getFirst ()
	{ return first; }

    /** Returns the second pipeline to get event calls. */
    public EventConsumer getRest ()
	{ return rest; }

    /** Returns the content handler being used. */
    final public ContentHandler getContentHandler ()
    {
	if (docRest == null)
	    return docFirst;
	if (docFirst == null)
	    return docRest;
	return this;
    }

    /** Returns the dtd handler being used. */
    final public DTDHandler getDTDHandler ()
    {
	// not cached (hardly used)
	if (rest.getDTDHandler () == null)
	    return first.getDTDHandler ();
	if (first.getDTDHandler () == null)
	    return rest.getDTDHandler ();
	return this;
    }

    /** Returns the declaration or lexical handler being used. */
    final public Object getProperty (String id)
    throws SAXNotRecognizedException
    {
	//
	// in degenerate cases, we have no work to do.
	//
	Object	firstProp = null, restProp = null;

	try { firstProp = first.getProperty (id); }
	catch (SAXNotRecognizedException e) { /* ignore */ }
	try { restProp = rest.getProperty (id); }
	catch (SAXNotRecognizedException e) { /* ignore */ }

	if (restProp == null)
	    return firstProp;
	if (firstProp == null)
	    return restProp;

	//
	// we've got work to do; handle two builtin cases.
	//
	if (EventFilter.DECL_HANDLER.equals (id))
	    return this;
	if (EventFilter.LEXICAL_HANDLER.equals (id))
	    return this;

	//
	// non-degenerate, handled by both consumers, but we don't know
	// how to handle this.
	//
	throw new SAXNotRecognizedException ("can't tee: " + id);
    }

    /**
     * Provides the error handler to both subsequent nodes of
     * this filter stage.
     */
    public void setErrorHandler (ErrorHandler handler)
    {
	first.setErrorHandler (handler);
	rest.setErrorHandler (handler);
    }


    //
    // ContentHandler
    //
    public void setDocumentLocator (Locator locator)
    {
	// this call is not made by all parsers
	docFirst.setDocumentLocator (locator);
	docRest.setDocumentLocator (locator);
    }

    public void startDocument ()
    throws SAXException
    {
	docFirst.startDocument ();
	docRest.startDocument ();
    }

    public void endDocument ()
    throws SAXException
    {
	try {
	    docFirst.endDocument ();
	} finally {
	    docRest.endDocument ();
	}
    }

    public void startPrefixMapping (String prefix, String uri)
    throws SAXException
    {
	docFirst.startPrefixMapping (prefix, uri);
	docRest.startPrefixMapping (prefix, uri);
    }

    public void endPrefixMapping (String prefix)
    throws SAXException
    {
	docFirst.endPrefixMapping (prefix);
	docRest.endPrefixMapping (prefix);
    }

    public void skippedEntity (String name)
    throws SAXException
    {
	docFirst.skippedEntity (name);
	docRest.skippedEntity (name);
    }

    public void startElement (String uri, String localName,
	    String qName, Attributes atts)
    throws SAXException
    {
	docFirst.startElement (uri, localName, qName, atts);
	docRest.startElement (uri, localName, qName, atts);
    }

    public void endElement (String uri, String localName, String qName)
    throws SAXException
    {
	docFirst.endElement (uri, localName, qName);
	docRest.endElement (uri, localName, qName);
    }

    public void processingInstruction (String target, String data)
    throws SAXException
    {
	docFirst.processingInstruction (target, data);
	docRest.processingInstruction (target, data);
    }

    public void characters (char ch [], int start, int length)
    throws SAXException
    {
	docFirst.characters (ch, start, length);
	docRest.characters (ch, start, length);
    }

    public void ignorableWhitespace (char ch [], int start, int length)
    throws SAXException
    {
	docFirst.ignorableWhitespace (ch, start, length);
	docRest.ignorableWhitespace (ch, start, length);
    }


    //
    // DTDHandler
    //
    public void notationDecl (String name, String publicId, String systemId)
    throws SAXException
    {
	DTDHandler	l1 = first.getDTDHandler ();
	DTDHandler	l2 = rest.getDTDHandler ();

	l1.notationDecl (name, publicId, systemId);
	l2.notationDecl (name, publicId, systemId);
    }

    public void unparsedEntityDecl (String name,
	    String publicId, String systemId,
	    String notationName
    ) throws SAXException
    {
	DTDHandler	l1 = first.getDTDHandler ();
	DTDHandler	l2 = rest.getDTDHandler ();

	l1.unparsedEntityDecl (name, publicId, systemId, notationName);
	l2.unparsedEntityDecl (name, publicId, systemId, notationName);
    }


    //
    // DeclHandler
    //
    public void attributeDecl (String eName, String aName,
	String type,
	String mode, String value)
    throws SAXException
    {
	declFirst.attributeDecl (eName, aName, type, mode, value);
	declRest.attributeDecl (eName, aName, type, mode, value);
    }

    public void elementDecl (String name, String model)
    throws SAXException
    {
	declFirst.elementDecl (name, model);
	declRest.elementDecl (name, model);
    }

    public void externalEntityDecl (String name,
	String publicId, String systemId)
    throws SAXException
    {
	declFirst.externalEntityDecl (name, publicId, systemId);
	declRest.externalEntityDecl (name, publicId, systemId);
    }

    public void internalEntityDecl (String name, String value)
    throws SAXException
    {
	declFirst.internalEntityDecl (name, value);
	declRest.internalEntityDecl (name, value);
    }


    //
    // LexicalHandler
    //
    public void comment (char ch [], int start, int length)
    throws SAXException
    {
	lexFirst.comment (ch, start, length);
	lexRest.comment (ch, start, length);
    }
    
    public void startCDATA ()
    throws SAXException
    {
	lexFirst.startCDATA ();
	lexRest.startCDATA ();
    }
    
    public void endCDATA ()
    throws SAXException
    {
	lexFirst.endCDATA ();
	lexRest.endCDATA ();
    }
    
    public void startEntity (String name)
    throws SAXException
    {
	lexFirst.startEntity (name);
	lexRest.startEntity (name);
    }
    
    public void endEntity (String name)
    throws SAXException
    {
	lexFirst.endEntity (name);
	lexRest.endEntity (name);
    }
    
    public void startDTD (String name, String publicId, String systemId)
    throws SAXException
    {
	lexFirst.startDTD (name, publicId, systemId);
	lexRest.startDTD (name, publicId, systemId);
    }
    
    public void endDTD ()
    throws SAXException
    {
	lexFirst.endDTD ();
	lexRest.endDTD ();
    }
}
