/* NSFilter.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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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 java.util.Enumeration;
import java.util.Stack;

import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.NamespaceSupport;

/**
 * This filter ensures that element and attribute names are properly prefixed,
 * and that such prefixes are declared.  Such data is critical for operations
 * like writing XML text, and validating against DTDs:  names or their prefixes
 * may have been discarded, although they are essential to the exchange of
 * information using XML.  There are various common ways that such data
 * gets discarded: <ul>
 *
 *	<li> By default, SAX2 parsers must discard the "xmlns*"
 *	attributes, and may also choose not to report properly prefixed
 *	names for elements or attributes.  (Some parsers may support
 *	changing the <em>namespace-prefixes</em> value from the default
 *	to <em>true</em>, effectively eliminating the need to use this
 *	filter on their output.)
 *
 *	<li> When event streams are generated from a DOM tree, they may
 *	have never have had prefixes or declarations for namespaces; or
 *	the existing prefixes or declarations may have been invalidated
 *	by structural modifications to that DOM tree.
 *
 *	<li> Other software writing SAX event streams won't necessarily
 *	be worrying about prefix management, and so they will need to
 *	have a transparent solution for managing them.
 *
 *	</ul>
 *
 * <p> This filter uses a heuristic to choose the prefix to assign to any
 * particular name which wasn't already corectly prefixed.  The associated
 * namespace will be correct, and the prefix will be declared.  Original
 * structures facilitating text editing, such as conventions about use of
 * mnemonic prefix names or the scoping of prefixes, can't always be
 * reconstructed after they are discarded, as strongly encouraged by the
 * current SAX2 defaults.
 *
 * <p> Note that this can't possibly know whether values inside attribute
 * value or document content involve prefixed names.  If your application
 * requires using prefixed names in such locations you'll need to add some
 * appropriate logic (perhaps adding additional heuristics in a subclass).
 *
 * @author David Brownell
 */
public class NSFilter extends EventFilter
{
    private NamespaceSupport	nsStack = new NamespaceSupport ();
    private Stack		elementStack = new Stack ();

    private boolean		pushedContext;
    private String		nsTemp [] = new String [3];
    private AttributesImpl	attributes = new AttributesImpl ();
    private boolean		usedDefault;

    // gensymmed prefixes use this root name
    private static final String	prefixRoot = "prefix-";

    
    /**
     * Passes events through to the specified consumer, after first
     * processing them.
     *
     * @param next the next event consumer to receive events.
     */
	// constructor used by PipelineFactory
    public NSFilter (EventConsumer next)
    {
	super (next);

	setContentHandler (this);
    }

    private void fatalError (String message)
    throws SAXException
    {
	SAXParseException	e;
	ErrorHandler		handler = getErrorHandler ();
	Locator			locator = getDocumentLocator ();

	if (locator == null)
	    e = new SAXParseException (message, null, null, -1, -1);
	else
	    e = new SAXParseException (message, locator);
	if (handler != null)
	    handler.fatalError (e);
	throw e;
    }


    public void startDocument () throws SAXException
    {
	elementStack.removeAllElements ();
	nsStack.reset ();
	pushedContext = false;
	super.startDocument ();
    }

    /**
     * This call is not passed to the next consumer in the chain.
     * Prefix declarations and scopes are only exposed in the form
     * of attributes; this callback just records a declaration that
     * will be exposed as an attribute.
     */
    public void startPrefixMapping (String prefix, String uri)
    throws SAXException
    {
	if (pushedContext == false) {
	    nsStack.pushContext ();
	    pushedContext = true;
	}

	// this check is awkward, but the paranoia prevents big trouble
	for (Enumeration e = nsStack.getDeclaredPrefixes ();
		e.hasMoreElements ();
		/* NOP */ ) {
	    String	declared = (String) e.nextElement ();

	    if (!declared.equals (prefix))
		continue;
	    if (uri.equals (nsStack.getURI (prefix)))
		return;
	    fatalError ("inconsistent binding for prefix '" + prefix
		+ "' ... " + uri + " (was " + nsStack.getURI (prefix) + ")");
	}

	if (!nsStack.declarePrefix (prefix, uri))
	    fatalError ("illegal prefix declared: " + prefix);
    }

    private String fixName (String ns, String l, String name, boolean isAttr)
    throws SAXException
    {
	if ("".equals (name) || name == null) {
	    name = l;
	    if ("".equals (name) || name == null)
		fatalError ("empty/null name");
	}

	// can we correctly process the name as-is?
	// handles "element scope" attribute names here.
	if (nsStack.processName (name, nsTemp, isAttr) != null
		&& nsTemp [0].equals (ns)
		) {
	    return nsTemp [2];
	}

	// nope, gotta modify the name or declare a default mapping
	int	temp;

	// get rid of any current prefix
	if ((temp = name.indexOf (':')) >= 0) {
	    name = name.substring (temp + 1);

	    // ... maybe that's enough (use/prefer default namespace) ...
	    if (!isAttr && nsStack.processName (name, nsTemp, false) != null
		    && nsTemp [0].equals (ns)
		    ) {
		return nsTemp [2];
	    }
	}

	// must we define and use the default/undefined prefix?
	if ("".equals (ns)) {
	    if (isAttr)
		fatalError ("processName bug");
	    if (attributes.getIndex ("xmlns") != -1)
		fatalError ("need to undefine default NS, but it's bound: "
			+ attributes.getValue ("xmlns"));
	    
	    nsStack.declarePrefix ("", "");
	    attributes.addAttribute ("", "", "xmlns", "CDATA", "");
	    return name;
	}

	// is there at least one non-null prefix we can use?
	for (Enumeration e = nsStack.getDeclaredPrefixes ();
		e.hasMoreElements ();
		/* NOP */) {
	    String prefix = (String) e.nextElement ();
	    String uri = nsStack.getURI (prefix);

	    if (uri == null || !uri.equals (ns))
		continue;
	    return prefix + ":" + name;
	}

	// no such luck.  create a prefix name, declare it, use it.
	for (temp = 0; temp >= 0; temp++) {
	    String	prefix = prefixRoot + temp;

	    if (nsStack.getURI (prefix) == null) {
		nsStack.declarePrefix (prefix, ns);
		attributes.addAttribute ("", "", "xmlns:" + prefix,
			"CDATA", ns);
		return prefix + ":" + name;
	    }
	}
	fatalError ("too many prefixes genned");
	// NOTREACHED
	return null;
    }

    public void startElement (
	String uri, String localName,
	String qName, Attributes atts
    ) throws SAXException
    {
	if (!pushedContext)
	    nsStack.pushContext ();
	pushedContext = false;

	// make sure we have all NS declarations handy before we start
	int	length = atts.getLength ();

	for (int i = 0; i < length; i++) {
	    String	aName = atts.getQName (i);

	    if (!aName.startsWith ("xmlns"))
		continue;

	    String	prefix;

	    if ("xmlns".equals (aName))
		prefix = "";
	    else if (aName.indexOf (':') == 5)
		prefix = aName.substring (6);
	    else	// "xmlnsfoo" etc.
		continue;
	    startPrefixMapping (prefix, atts.getValue (i));
	}

	// put namespace decls at the start of our regenned attlist
	attributes.clear ();
	for (Enumeration e = nsStack.getDeclaredPrefixes ();
		e.hasMoreElements ();
		/* NOP */) {
	    String prefix = (String) e.nextElement ();

	    attributes.addAttribute ("", "",
		    ("".equals (prefix)
			? "xmlns"
			: "xmlns:" + prefix),
		    "CDATA",
		    nsStack.getURI (prefix));
	}

	// name fixups:  element, then attributes.
	// fixName may declare a new prefix or, for the element,
	// redeclare the default (if element name needs it).
	qName = fixName (uri, localName, qName, false);

	for (int i = 0; i < length; i++) {
	    String	aName = atts.getQName (i);
	    String	aNS = atts.getURI (i);
	    String	aLocal = atts.getLocalName (i);
	    String	aType = atts.getType (i);
	    String	aValue = atts.getValue (i);

	    if (aName.startsWith ("xmlns"))
		continue;
	    aName = fixName (aNS, aLocal, aName, true);
	    attributes.addAttribute (aNS, aLocal, aName, aType, aValue);
	}

	elementStack.push (qName);

	// pass event along, with cleaned-up names and decls.
	super.startElement (uri, localName, qName, attributes);
    }

    public void endElement (String uri, String localName, String qName)
    throws SAXException
    {
	nsStack.popContext ();
	qName = (String) elementStack.pop ();
	super.endElement (uri, localName, qName);
    }

    /**
     * This call is not passed to the next consumer in the chain.
     * Prefix declarations and scopes are only exposed in their
     * attribute form.
     */
    public void endPrefixMapping (String prefix)
    throws SAXException
	{ }

    public void endDocument () throws SAXException
    {
	elementStack.removeAllElements ();
	nsStack.reset ();
	super.endDocument ();
    }
}
