/*
 * @(#)$Id$
 *
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Sun
 * Microsystems., http://www.sun.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * @author Morten Jorgensen
 * @author G. Todd Miller 
 * @author Santiago Pericas-Geertsen
 */

package org.apache.xalan.xsltc.runtime;

import java.util.Vector;

import java.io.IOException;
import java.io.Writer;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;

import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;

public class DefaultSAXOutputHandler implements ContentHandler, LexicalHandler {

    // The output writer
    private Writer _writer;

    // Contains end-tags for closing elements (for speeding up output)
    private Hashtable _endTags = new Hashtable();
    // Contains commonly used attributes (for speeding up output)
    private Hashtable _attributeTemplates = new Hashtable();
    // Contains all HTML elements that should not get an end tag
    private Hashtable _emptyElements = new Hashtable();
    // Contains the name of the last opened element (set in startElement())
    private String _element = null;

    // Settings passed on from TextOutput
    private int	    _outputType = TextOutput.UNKNOWN;
    private String  _encoding   = "UTF-8";
    private String  _version    = "1.0";
    private String  _standalone = null;
    private boolean _indent = false;
    private boolean _omitHeader = false;

    // This variable is set to 'true' when a start tag is left open
    private boolean _startTagOpen = false;

    // Commonly used strings are stored as char arrays for speed
    private static final char[] BEGPI    = "<?".toCharArray();
    private static final char[] ENDPI    = "?>".toCharArray();
    private static final char[] GT_CR    = ">".toCharArray();
    private static final char[] GT_LT_SL = "></".toCharArray();
    private static final char[] SL_GT    = "/>".toCharArray();
    private static final char[] XMLNS    = " xmlns".toCharArray();

    // All of these are used to control/track output indentation
    private static final char[] INDENT = "                    ".toCharArray();
    private static final int MAX_INDENT_LEVEL = (INDENT.length >> 1);
    private static final int MAX_INDENT       = INDENT.length;

    private static final String EMPTYSTRING = "";

    private boolean _lineFeedNextStartTag = false;
    private boolean _linefeedNextEndTag = false;
    private boolean _indentNextEndTag = false;
    private int     _indentLevel = 0;

    // This is used for aggregating namespace declarations
    private Vector _namespaceDecls = null;

    /**
     * Constructor - set Writer to send output to and output encoding
     */
    public DefaultSAXOutputHandler(Writer writer, String encoding)
	throws IOException {
	_writer = writer;
	_encoding = encoding;
	init();
    }

    /**
     * Constructor - simple, initially for use in servlets
     */
    public DefaultSAXOutputHandler(Writer writer) throws IOException {
	this(writer, "UTF-8");
    }

    /**
     * Constructor - set output-stream & output encoding. 
     */
    public DefaultSAXOutputHandler(OutputStream out, String encoding)
	throws IOException {

        OutputStreamWriter writer;
        try {
            writer = new OutputStreamWriter(out, _encoding = encoding);
        }
        catch (java.io.UnsupportedEncodingException e) {
            writer = new OutputStreamWriter(out, _encoding = "UTF-8" );
        }
        _writer = new BufferedWriter(writer);
	init();
    }

    /**
     * Constructor - set output file and output encoding
     */
    public DefaultSAXOutputHandler(String filename, String encoding)
	throws IOException {
	this(new FileOutputStream(filename), encoding);
    }

    /**
     * Utility method: Initialise the output handler 
     */
    private void init() throws IOException {

	// These are HTML tags that can occur as empty elements with
	// no closing tags (such as <br> insteadof XHTML's <br/>).
        final String[] tags = { "area", "base", "basefont", "br",
				"col", "frame", "hr", "img", "input",
				"isindex", "link", "meta", "param" };
        for (int i = 0; i < tags.length; i++)
            _emptyElements.put(tags[i],tags[i]);

	_endTags.clear();
	_outputType = TextOutput.UNKNOWN;
	_indent = false;
	_indentNextEndTag = false;
	_indentLevel = 0;
	_startTagOpen = false;
    }

    /**
     * Close the output stream
     */
    public void close() {
	try {
	    if (_writer != null) _writer.close();
	}
	catch (IOException e) {
	    // what can you do?
	}
    }

    /**
     * Utility method - outputs an XML header
     */
    private void emitHeader() throws SAXException {
	// First check if the 'omit-xml-declaration' was set to yes in the
	// stylesheet's <xsl:output> element (if any)
	if (_omitHeader) return;

	// If not go ahead and output the XML header
	StringBuffer buffer = new StringBuffer();
	buffer.append("<?xml version=\"");
	buffer.append(_version);
	buffer.append("\" encoding=\"");
	buffer.append(_encoding);
	if (_standalone != null) {
	    buffer.append("\" standalone=\"");
	    buffer.append(_standalone);
	}
	buffer.append("\" ?>\n");
	characters(buffer.toString());
    }

    /**
     * Utility method - determine output type; XML or HTML
     */
    private void determineOutputType(String element) throws SAXException {
	// Assume this is an HTML document if first element is <html>
	if ((element != null) && (element.toLowerCase().equals("html"))) {
	    _outputType = TextOutput.HTML;
	}
	// Otherwise we assume this is an XML document
	else {
	    _outputType = TextOutput.XML;
	    emitHeader();
	}
    }

    /**
     * SAX2: Receive notification of the beginning of a document.
     */
    public void startDocument() throws SAXException { 
    }

    /**
     * SAX2: Receive notification of the end of an element.
     */
    public void endDocument() throws SAXException  { 
        try {
	    _writer.flush();
        } catch (IOException e) {
            throw new SAXException(e);
        }
    }

    /**
     * SAX2: Receive notification of the beginning of an element.
     */
    public void startElement(String uri, String localname,
			     String elementName, Attributes attrs)
	throws SAXException {
	try {
	    // Determine the output document type if not already known
	    if (_outputType == TextOutput.UNKNOWN)
		determineOutputType(elementName);

            if (_startTagOpen) closeStartTag(true); // Close any open element.
            _element = elementName; // Save element name

	    // Handle inden3dcb50483dcb504tation (not a requirement)
            if (_indent) {
		if (!_emptyElements.containsKey(elementName.toLowerCase())) {
		    indent(_lineFeedNextStartTag);
		    _lineFeedNextStartTag = true;
		    _indentNextEndTag = false;
		}
		_indentLevel++;
            }

	    // Now, finally, output the start tag for the element.
	    _writer.write('<');
	    _writer.write(elementName);
	    _startTagOpen = true;
	    _indentNextEndTag = false;

	    // Output namespace declarations first...
	    if (_namespaceDecls != null) {
		int nDecls = _namespaceDecls.size();
		for (int i = 0; i < nDecls; i++) {
		    final String prefix = (String) _namespaceDecls.elementAt(i++);
		    _writer.write(XMLNS);
		    if ((prefix != null) && (prefix != EMPTYSTRING)) {
			_writer.write(':');
			_writer.write(prefix);
		    }
		    _writer.write('=');
		    _writer.write('\"');
		    _writer.write((String) _namespaceDecls.elementAt(i));
		    _writer.write('\"');
		}
		_namespaceDecls.clear();
	    }

	    // ...then output all attributes
	    int attrCount = attrs.getLength();
	    for (int i = 0; i < attrCount; i++) {
		_writer.write(' ');
		_writer.write(attrs.getQName(i));
		_writer.write('=');
		_writer.write('\"');
		_writer.write(attrs.getValue(i));
		_writer.write('\"');
            }
	} catch (IOException e) {
            throw new SAXException(e);
        }
    }

    /**
     * SAX2: Receive notification of the end of an element.
     */
    public void endElement(String uri, String localname,
			   String elementName)  throws SAXException {
	try {

            if (_indent) _indentLevel--;

            if (_startTagOpen) {
                closeStartTag(false);
            }
            else {
                if ((_indent) && (_indentNextEndTag)) {
		    indent(_indentNextEndTag);
		    _indentNextEndTag = true;
		}
                char[] endTag = (char[])_endTags.get(elementName);
                if (endTag == null) {
		    // We dont' want to concatenate String objects!!!!
		    // endTag = ("</"+elementName+">").toCharArray();
		    final int len = elementName.length();
		    final char[] src = elementName.toCharArray();
		    endTag = new char[len+3];
		    System.arraycopy(src, 0, endTag, 2, len);
		    endTag[0] = '<';
		    endTag[1] = '/';
		    endTag[len+2] = '>';
                    _endTags.put(elementName,endTag);
                }
                _writer.write(endTag);
            }
	    /* Will not add this code for performance reasons.
	       The purpose of the code is to avoid line feeds and whitespaces
	       after <img> elements inside <a>...</a> elements in HTML.
	    if (elementName.toLowerCase().equals("img")) {
		_linefeedNextEndTag = false;
		_indentNextEndTag = false;
	    }
	    else {
		_indentNextEndTag = true;
	    }
	    */
	    _indentNextEndTag = true;
        } catch (IOException e) {
            throw new SAXException(e);
        }
    }

    /**
     * Utility method - pass a string to the SAX handler's characters() method
     */
    private void characters(String str) throws SAXException{
	final char[] ch = str.toCharArray();
	characters(ch, 0, ch.length);
    }

    /**
     * Utility method - pass a whole character array to the SAX handler
     */
    private void characters(char[] ch) throws SAXException{
	characters(ch, 0, ch.length);
    }

    /**
     * SAX2: Receive notification of character data.
     */
    public void characters(char[] ch, int off, int len) throws SAXException {
        try {
	    // Determine the output document type if not already known
	    if (_outputType == TextOutput.UNKNOWN)
		determineOutputType(null);
	    
            if (len == 0) return;

            // Close any open start-tags.
            if (_startTagOpen) closeStartTag(true);

            // Output text
	    _writer.write(ch, off, len);
        }
        catch (IOException e) {
            throw new SAXException(e);
        }
    }

    /**
     * SAX2: Receive notification of a processing instruction.
     */
    public void processingInstruction(String target, String data)
	throws SAXException {
	try {
            if (_startTagOpen) closeStartTag(true);
            _writer.write(BEGPI);
            _writer.write(target);
            _writer.write(' ');
            _writer.write(data);
            if (_outputType == TextOutput.HTML)
                _writer.write('>');
            else
                _writer.write(ENDPI);

        } catch (IOException e) {
            throw new SAXException(e);
        }
    }

    /**
     * SAX2: Receive notification of ignorable whitespace in element content.
     */
    public void ignorableWhitespace(char[] ch, int start, int len) { }

    /**
     * SAX2: Receive an object for locating the origin of SAX document events.
     */
    public void setDocumentLocator(Locator locator) { } 

    /**
     * SAX2: Receive notification of a skipped entity.
     */
    public void skippedEntity(String name) { }

    /**
     * SAX2: Begin the scope of a prefix-URI Namespace mapping.
     *       Namespace declarations are output in startElement()
     */
    public void startPrefixMapping(String prefix, String uri) {
	if (_namespaceDecls == null) {
	    _namespaceDecls = new Vector(2);
	}
	_namespaceDecls.addElement(prefix);
	_namespaceDecls.addElement(uri);
    }

    /**
     * SAX2: End the scope of a prefix-URI Namespace mapping.
     */
    public void endPrefixMapping(String prefix) {
	// Do nothing
    }

    // The above are ignored methods of the org.xml.sax.ext.LexicalHandler intf.
    public void startCDATA() { }
    public void endCDATA() { }
    public void comment(char[] ch, int start, int length) { }
    public void startEntity(java.lang.String name) { }
    public void endDTD() { }
    public void endEntity(String name) { }

    /**
     * This method is part of the LexicalHandler interface. It is only used to
     * pass DOCTYPE declarations (based on the doctype-system/public attributes
     * in the <xsl:output> element) to the output handler.
     * @param name     The document type name (name of first element)
     * @param publicId <xsl:output doctype-public="..."/>
     * @param systemId <xsl:output doctype-system="..."/>
     * @throws SAXException Whenever
     */
    public void startDTD(String name, String publicId, String systemId)
	throws SAXException {
	try {
	    StringBuffer buf = new StringBuffer("<!DOCTYPE ");
	    buf.append(name);
	    if (publicId == null) {
		buf.append(" SYSTEM");
	    }
	    else {
		buf.append(" PUBLIC \"");
		buf.append(publicId);
		buf.append("\"");
	    }
	    if (systemId != null) {
		buf.append(" \"");
		buf.append(systemId);
		buf.append("\">\n");
	    }
	    else {
		buf.append(">\n");
	    }
	    _writer.write(buf.toString());
	}
        catch (IOException e) {
            throw new SAXException(e);
        }
    }

    /**
     * Adds a newline in the output stream and indents to correct level
     */
    private void indent(boolean linefeed) throws IOException {
        if (linefeed)
            _writer.write('\n');
        if (_indentLevel < MAX_INDENT_LEVEL)
            _writer.write(INDENT, 0, (_indentLevel+_indentLevel));
        else
            _writer.write(INDENT, 0, MAX_INDENT);
    }

    /**
     * Closes a start tag of an element
     */
    private void closeStartTag(boolean content) throws SAXException {
        try {
            // Take special care when outputting empty tags in HTML documents.
            if (!content) {
                if (_outputType == TextOutput.HTML) {
                    // HTML: output empty element as <tag> or <tag></tag>
                    if (!_emptyElements.containsKey(_element.toLowerCase())){
                        _writer.write(GT_LT_SL);
                        _writer.write(_element);
			_writer.write('>');
                    }
		    else {
			_writer.write(GT_CR);
		    }
                }
                else {
                    // XML: output empty element as <tag/>
                    _writer.write(SL_GT);
                }
            }
            else {
		_writer.write('>');
            }
            _startTagOpen = false;
        }
        catch (IOException e) {
            throw new SAXException(e);
        }
    }

    /**
     * Turns output indentation on/off (used with XML and HTML output only)
     * Breaks the SAX HandlerBase interface, but TextOutput will only call
     * this method of the SAX handler is an instance of this class.
     */
    public void setIndent(boolean indent) {
        _indent = indent;
    }

    /**
     * Sets the version number that will be output in the XML header.
     */
    public void setVersion(String version) {
	_version = version;
    }

    /**
     * Sets the 'standalone' attribute that will be output in the XML header.
     * The attribute will be omitted unless this method is called.
     */
    public void setStandalone(String standalone) {
	_standalone = standalone;
    }

    /**
     * Turns xml declaration generation on/off, dependent on the attribute
     * omit-xml-declaration in any xsl:output element. 
     * Breaks the SAX HandlerBase interface, but TextOutput will only call
     * this method of the SAX handler is an instance of this class.
     */
    public void omitHeader(boolean value) {
        _omitHeader = value;
    }

    /**
     * Set the output type (either TEXT, HTML or XML)
     * Breaks the SAX HandlerBase interface, but TextOutput will only call
     * this method of the SAX handler is an instance of this class.
     */
    public void setOutputType(int type) throws SAXException {
	_outputType = type;
	if (_outputType == TextOutput.XML ) {
	    emitHeader();
	}
    }

}
