/*******************************************************************************
 * Copyright (c) 2008 Standards for Technology in Automotive Retail
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     David Carver - STAR - bug 224197 - initial API and implementation
 *                    based on work from Apache Xalan 2.7.0
 *******************************************************************************/

/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: StylesheetHandler.java,v 1.3 2008/03/28 02:38:16 dacarver Exp $
 */
package org.eclipse.wst.xsl.core.internal.compiler.xslt10.processor;

import java.util.Stack;

import javax.xml.transform.ErrorListener;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.sax.TemplatesHandler;

import org.eclipse.wst.xsl.core.internal.compiler.xslt10.extensions.ExpressionVisitor;
import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.eclipse.wst.xsl.core.internal.compiler.xslt10.templates.Constants;
import org.eclipse.wst.xsl.core.internal.compiler.xslt10.templates.ElemForEach;
import org.eclipse.wst.xsl.core.internal.compiler.xslt10.templates.ElemTemplateElement;
import org.eclipse.wst.xsl.core.internal.compiler.xslt10.templates.Stylesheet;
import org.eclipse.wst.xsl.core.internal.compiler.xslt10.templates.StylesheetRoot;
import org.apache.xml.utils.BoolStack;
import org.apache.xml.utils.NamespaceSupport2;
import org.apache.xml.utils.NodeConsumer;
import org.apache.xml.utils.PrefixResolver;
import org.apache.xml.utils.SAXSourceLocator;
import org.apache.xml.utils.XMLCharacterRecognizer;
import org.eclipse.wst.xsl.core.internal.compiler.xslt10.xpath.XPath;
import org.apache.xpath.compiler.FunctionTable;
import org.w3c.dom.Node;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.NamespaceSupport;

/**
 * Initializes and processes a stylesheet via SAX events. This class acts as
 * essentially a state machine, maintaining a ContentHandler stack, and pushing
 * appropriate content handlers as parse events occur.
 * 
 * @xsl.usage advanced
 */
public class StylesheetHandler extends DefaultHandler implements
		TemplatesHandler, PrefixResolver, NodeConsumer {

	/**
	 * The function table of XPath and XSLT;
	 */
	private FunctionTable m_funcTable = new FunctionTable();

	/**
	 * The flag for the setting of the optimize feature;
	 */
	private boolean m_optimize = true;

	/**
	 * The flag for the setting of the incremental feature;
	 */
	private boolean m_incremental = false;

	/**
	 * The flag for the setting of the source_location feature;
	 */
	private boolean m_source_location = false;

	/**
	 * Create a StylesheetHandler object, creating a root stylesheet as the
	 * target.
	 * 
	 * @param processor
	 *            non-null reference to the transformer factory that owns this
	 *            handler.
	 * 
	 * @throws TransformerConfigurationException
	 *             if a StylesheetRoot can not be constructed for some reason.
	 */
	public StylesheetHandler(TransformerFactoryImpl processor)
			throws TransformerConfigurationException {
		Class func = org.apache.xalan.templates.FuncDocument.class;
		m_funcTable.installFunction("document", func);

		// func = new org.apache.xalan.templates.FuncKey();
		// FunctionTable.installFunction("key", func);
		func = org.apache.xalan.templates.FuncFormatNumb.class;

		m_funcTable.installFunction("format-number", func);

		m_optimize = ((Boolean) processor
				.getAttribute(TransformerFactoryImpl.FEATURE_OPTIMIZE))
				.booleanValue();
		m_incremental = ((Boolean) processor
				.getAttribute(TransformerFactoryImpl.FEATURE_INCREMENTAL))
				.booleanValue();
		m_source_location = ((Boolean) processor
				.getAttribute(TransformerFactoryImpl.FEATURE_SOURCE_LOCATION))
				.booleanValue();
		// m_schema = new XSLTSchema();
		init(processor);

	}

	/**
	 * Do common initialization.
	 * 
	 * @param processor
	 *            non-null reference to the transformer factory that owns this
	 *            handler.
	 */
	protected void init(TransformerFactoryImpl processor) {
		m_stylesheetProcessor = processor;

		// Set the initial content handler.
		m_processors.push(m_schema.getElementProcessor());
		this.pushNewNamespaceSupport();

		// m_includeStack.push(SystemIDResolver.getAbsoluteURI(this.getBaseIdentifier(),
		// null));
		// initXPath(processor, null);
	}

	/**
	 * Process an expression string into an XPath. Must be public for access by
	 * the AVT class.
	 * 
	 * @param str
	 *            A non-null reference to a valid or invalid XPath expression
	 *            string.
	 * 
	 * @return A non-null reference to an XPath object that represents the
	 *         string argument.
	 * 
	 * @throws javax.xml.transform.TransformerException
	 *             if the expression can not be processed.
	 * @see <a href="http://www.w3.org/TR/xslt#section-Expressions">Section 4
	 *      Expressions in XSLT Specification</a>
	 */
	public XPath createXPath(String str, ElemTemplateElement owningTemplate)
			throws javax.xml.transform.TransformerException {
		ErrorListener handler = m_stylesheetProcessor.getErrorListener();
		XPath xpath = new XPath(str, owningTemplate, this, XPath.SELECT,
				handler, m_funcTable);
		// Visit the expression, registering namespaces for any extension
		// functions it includes.
		xpath.callVisitors(xpath, new ExpressionVisitor(getStylesheetRoot()));
		return xpath;
	}

	/**
	 * Process an expression string into an XPath.
	 * 
	 * @param str
	 *            A non-null reference to a valid or invalid match pattern
	 *            string.
	 * 
	 * @return A non-null reference to an XPath object that represents the
	 *         string argument.
	 * 
	 * @throws javax.xml.transform.TransformerException
	 *             if the pattern can not be processed.
	 * @see <a href="http://www.w3.org/TR/xslt#patterns">Section 5.2 Patterns in
	 *      XSLT Specification</a>
	 */
	protected XPath createMatchPatternXPath(String str,
			ElemTemplateElement owningTemplate)
			throws javax.xml.transform.TransformerException {
		ErrorListener handler = m_stylesheetProcessor.getErrorListener();
		XPath xpath = new XPath(str, owningTemplate, this, XPath.MATCH,
				handler, m_funcTable);
		// Visit the expression, registering namespaces for any extension
		// functions it includes.
		xpath.callVisitors(xpath, new ExpressionVisitor(getStylesheetRoot()));
		return xpath;
	}

	/**
	 * Given a namespace, get the corrisponding prefix from the current
	 * namespace support context.
	 * 
	 * @param prefix
	 *            The prefix to look up, which may be an empty string ("") for
	 *            the default Namespace.
	 * 
	 * @return The associated Namespace URI, or null if the prefix is undeclared
	 *         in this context.
	 */
	public String getNamespaceForPrefix(String prefix) {
		return this.getNamespaceSupport().getURI(prefix);
	}

	/**
	 * Given a namespace, get the corrisponding prefix. This is here only to
	 * support the {@link org.apache.xml.utils.PrefixResolver} interface, and
	 * will throw an error if invoked on this object.
	 * 
	 * @param prefix
	 *            The prefix to look up, which may be an empty string ("") for
	 *            the default Namespace.
	 * @param context
	 *            The node context from which to look up the URI.
	 * 
	 * @return The associated Namespace URI, or null if the prefix is undeclared
	 *         in this context.
	 */
	public String getNamespaceForPrefix(String prefix, org.w3c.dom.Node context) {

		// Don't need to support this here. Return the current URI for the
		// prefix,
		// ignoring the context.
		assertion(true, "can't process a context node in StylesheetHandler!");

		return null;
	}

	/**
	 * Utility function to see if the stack contains the given URL.
	 * 
	 * @param stack
	 *            non-null reference to a Stack.
	 * @param url
	 *            URL string on which an equality test will be performed.
	 * 
	 * @return true if the stack contains the url argument.
	 */
	private boolean stackContains(Stack stack, String url) {

		int n = stack.size();
		boolean contains = false;

		for (int i = 0; i < n; i++) {
			String url2 = (String) stack.elementAt(i);

			if (url2.equals(url)) {
				contains = true;

				break;
			}
		}

		return contains;
	}

	// //////////////////////////////////////////////////////////////////
	// Implementation of the TRAX TemplatesBuilder interface.
	// //////////////////////////////////////////////////////////////////

	/**
	 * When this object is used as a ContentHandler or ContentHandler, it will
	 * create a Templates object, which the caller can get once the SAX events
	 * have been completed.
	 * 
	 * @return The stylesheet object that was created during the SAX event
	 *         process, or null if no stylesheet has been created.
	 * 
	 * Author <a href="mailto:scott_boag@lotus.com">Scott Boag</a>
	 * 
	 * 
	 */
	public Templates getTemplates() {
		return getStylesheetRoot();
	}

	/**
	 * Set the base ID (URL or system ID) for the stylesheet created by this
	 * builder. This must be set in order to resolve relative URLs in the
	 * stylesheet.
	 * 
	 * @param baseID
	 *            Base URL for this stylesheet.
	 */
	public void setSystemId(String baseID) {
		pushBaseIndentifier(baseID);
	}

	/**
	 * Get the base ID (URI or system ID) from where relative URLs will be
	 * resolved.
	 * 
	 * @return The systemID that was set with {@link #setSystemId}.
	 */
	public String getSystemId() {
		return this.getBaseIdentifier();
	}

	// //////////////////////////////////////////////////////////////////
	// Implementation of the EntityResolver interface.
	// //////////////////////////////////////////////////////////////////

	/**
	 * Resolve an external entity.
	 * 
	 * @param publicId
	 *            The public identifer, or null if none is available.
	 * @param systemId
	 *            The system identifier provided in the XML document.
	 * @return The new input source, or null to require the default behaviour.
	 * 
	 * @throws org.xml.sax.SAXException
	 *             if the entity can not be resolved.
	 */
	@Override
	public InputSource resolveEntity(String publicId, String systemId)
			throws org.xml.sax.SAXException {
		return getCurrentProcessor().resolveEntity(this, publicId, systemId);
	}

	// //////////////////////////////////////////////////////////////////
	// Implementation of DTDHandler interface.
	// //////////////////////////////////////////////////////////////////

	/**
	 * Receive notification of a notation declaration.
	 * 
	 * <p>
	 * By default, do nothing. Application writers may override this method in a
	 * subclass if they wish to keep track of the notations declared in a
	 * document.
	 * </p>
	 * 
	 * @param name
	 *            The notation name.
	 * @param publicId
	 *            The notation public identifier, or null if not available.
	 * @param systemId
	 *            The notation system identifier.
	 * @see org.xml.sax.DTDHandler#notationDecl
	 */
	@Override
	public void notationDecl(String name, String publicId, String systemId) {
		getCurrentProcessor().notationDecl(this, name, publicId, systemId);
	}

	/**
	 * Receive notification of an unparsed entity declaration.
	 * 
	 * @param name
	 *            The entity name.
	 * @param publicId
	 *            The entity public identifier, or null if not available.
	 * @param systemId
	 *            The entity system identifier.
	 * @param notationName
	 *            The name of the associated notation.
	 * @see org.xml.sax.DTDHandler#unparsedEntityDecl
	 */
	@Override
	public void unparsedEntityDecl(String name, String publicId,
			String systemId, String notationName) {
		getCurrentProcessor().unparsedEntityDecl(this, name, publicId,
				systemId, notationName);
	}

	/**
	 * Given a namespace URI, and a local name or a node type, get the processor
	 * for the element, or return null if not allowed.
	 * 
	 * @param uri
	 *            The Namespace URI, or an empty string.
	 * @param localName
	 *            The local name (without prefix), or empty string if not
	 *            namespace processing.
	 * @param rawName
	 *            The qualified name (with prefix).
	 * 
	 * @return A non-null reference to a element processor.
	 * 
	 * @throws org.xml.sax.SAXException
	 *             if the element is not allowed in the found position in the
	 *             stylesheet.
	 */
	public XSLTElementProcessor getProcessorFor(String uri, String localName,
			String rawName) throws org.xml.sax.SAXException {

		XSLTElementProcessor currentProcessor = getCurrentProcessor();
		XSLTElementDef def = currentProcessor.getElemDef();
		XSLTElementProcessor elemProcessor = def
				.getProcessorFor(uri, localName);

		if (null == elemProcessor
				&& !(currentProcessor instanceof ProcessorStylesheetDoc)
				&& ((null == getStylesheet() || Double.valueOf(
						getStylesheet().getVersion()).doubleValue() > org.apache.xml.utils.Constants.XSLTVERSUPPORTED)
						|| (!uri
								.equals(org.apache.xml.utils.Constants.S_XSLNAMESPACEURL) && currentProcessor instanceof ProcessorStylesheetElement) || getElemVersion() > org.apache.xml.utils.Constants.XSLTVERSUPPORTED)) {
			elemProcessor = def.getProcessorForUnknown(uri, localName);
		}

		if (null == elemProcessor)
			error(XSLMessages.createMessage(
					XSLTErrorResources.ER_NOT_ALLOWED_IN_POSITION,
					new Object[] { rawName }), null);// rawName + " is not
														// allowed in this
														// position in the
														// stylesheet!",

		return elemProcessor;
	}

	// //////////////////////////////////////////////////////////////////
	// Implementation of ContentHandler interface.
	// //////////////////////////////////////////////////////////////////

	/**
	 * Receive a Locator object for document events. This is called by the
	 * parser to push a locator for the stylesheet being parsed. The stack needs
	 * to be popped after the stylesheet has been parsed. We pop in
	 * popStylesheet.
	 * 
	 * @param locator
	 *            A locator for all SAX document events.
	 * @see org.xml.sax.ContentHandler#setDocumentLocator
	 * @see org.xml.sax.Locator
	 */
	@Override
	public void setDocumentLocator(Locator locator) {

		// System.out.println("pushing locator for: "+locator.getSystemId());
		m_stylesheetLocatorStack.push(new SAXSourceLocator(locator));
	}

	/**
	 * The level of the stylesheet we are at.
	 */
	private int m_stylesheetLevel = -1;

	/**
	 * Receive notification of the beginning of the document.
	 * 
	 * @see org.xml.sax.ContentHandler#startDocument
	 * 
	 * @throws org.xml.sax.SAXException
	 *             Any SAX exception, possibly wrapping another exception.
	 */
	@Override
	public void startDocument() throws org.xml.sax.SAXException {
		m_stylesheetLevel++;
		pushSpaceHandling(false);
	}

	/**
	 * m_parsingComplete becomes true when the top-level stylesheet and all its
	 * included/imported stylesheets have been been fully parsed, as an
	 * indication that composition/optimization/compilation can begin.
	 * 
	 * @see isStylesheetParsingComplete
	 */
	private boolean m_parsingComplete = false;

	/**
	 * Test whether the _last_ endDocument() has been processed. This is needed
	 * as guidance for stylesheet optimization and compilation engines, which
	 * generally don't want to start until all included and imported stylesheets
	 * have been fully parsed.
	 * 
	 * @return true iff the complete stylesheet tree has been built.
	 */
	public boolean isStylesheetParsingComplete() {
		return m_parsingComplete;
	}

	/**
	 * Receive notification of the end of the document.
	 * 
	 * @see org.xml.sax.ContentHandler#endDocument
	 * 
	 * @throws org.xml.sax.SAXException
	 *             Any SAX exception, possibly wrapping another exception.
	 */
	@Override
	public void endDocument() throws org.xml.sax.SAXException {

		try {
			if (null != getStylesheetRoot()) {
				if (0 == m_stylesheetLevel)
					getStylesheetRoot().recompose();
			} else
				throw new TransformerException(XSLMessages.createMessage(
						XSLTErrorResources.ER_NO_STYLESHEETROOT, null)); // "Did
																			// not
																			// find
																			// the
																			// stylesheet
																			// root!");

			XSLTElementProcessor elemProcessor = getCurrentProcessor();

			if (null != elemProcessor)
				elemProcessor.startNonText(this);

			m_stylesheetLevel--;

			popSpaceHandling();

			// WARNING: This test works only as long as stylesheets are parsed
			// more or less recursively. If we switch to an iterative
			// "work-list"
			// model, this will become true prematurely. In that case,
			// isStylesheetParsingComplete() will have to be adjusted to be
			// aware
			// of the worklist.
			m_parsingComplete = (m_stylesheetLevel < 0);
		} catch (TransformerException te) {
			throw new org.xml.sax.SAXException(te);
		}
	}

	private java.util.Vector m_prefixMappings = new java.util.Vector();

	/**
	 * Receive notification of the start of a Namespace mapping.
	 * 
	 * <p>
	 * By default, do nothing. Application writers may override this method in a
	 * subclass to take specific actions at the start of each element (such as
	 * allocating a new tree node or writing output to a file).
	 * </p>
	 * 
	 * @param prefix
	 *            The Namespace prefix being declared.
	 * @param uri
	 *            The Namespace URI mapped to the prefix.
	 * @see org.xml.sax.ContentHandler#startPrefixMapping
	 * 
	 * @throws org.xml.sax.SAXException
	 *             Any SAX exception, possibly wrapping another exception.
	 */
	@Override
	public void startPrefixMapping(String prefix, String uri)
			throws org.xml.sax.SAXException {

		// m_nsSupport.pushContext();
		// this.getNamespaceSupport().declarePrefix(prefix, uri);
		// m_prefixMappings.add(prefix); // JDK 1.2+ only -sc
		// m_prefixMappings.add(uri); // JDK 1.2+ only -sc
		m_prefixMappings.addElement(prefix); // JDK 1.1.x compat -sc
		m_prefixMappings.addElement(uri); // JDK 1.1.x compat -sc
	}

	/**
	 * Receive notification of the end of a Namespace mapping.
	 * 
	 * <p>
	 * By default, do nothing. Application writers may override this method in a
	 * subclass to take specific actions at the start of each element (such as
	 * allocating a new tree node or writing output to a file).
	 * </p>
	 * 
	 * @param prefix
	 *            The Namespace prefix being declared.
	 * @see org.xml.sax.ContentHandler#endPrefixMapping
	 * 
	 * @throws org.xml.sax.SAXException
	 *             Any SAX exception, possibly wrapping another exception.
	 */
	@Override
	public void endPrefixMapping(String prefix) throws org.xml.sax.SAXException {

		// m_nsSupport.popContext();
	}

	/**
	 * Flush the characters buffer.
	 * 
	 * @throws org.xml.sax.SAXException
	 */
	public void flushCharacters() throws org.xml.sax.SAXException {

		XSLTElementProcessor elemProcessor = getCurrentProcessor();

		if (null != elemProcessor)
			elemProcessor.startNonText(this);
	}

	/**
	 * Receive notification of the start of an element.
	 * 
	 * @param uri
	 *            The Namespace URI, or an empty string.
	 * @param localName
	 *            The local name (without prefix), or empty string if not
	 *            namespace processing.
	 * @param rawName
	 *            The qualified name (with prefix).
	 * @param attributes
	 *            The specified or defaulted attributes.
	 * 
	 * @throws org.xml.sax.SAXException
	 */
	@Override
	public void startElement(String uri, String localName, String rawName,
			Attributes attributes) throws org.xml.sax.SAXException {
		NamespaceSupport nssupport = this.getNamespaceSupport();
		nssupport.pushContext();

		int n = m_prefixMappings.size();

		for (int i = 0; i < n; i++) {
			String prefix = (String) m_prefixMappings.elementAt(i++);
			String nsURI = (String) m_prefixMappings.elementAt(i);
			nssupport.declarePrefix(prefix, nsURI);
		}
		// m_prefixMappings.clear(); // JDK 1.2+ only -sc
		m_prefixMappings.removeAllElements(); // JDK 1.1.x compat -sc

		m_elementID++;

		// This check is currently done for all elements. We should possibly
		// consider
		// limiting this check to xsl:stylesheet elements only since that is all
		// it really
		// applies to. Also, it could be bypassed if m_shouldProcess is already
		// true.
		// In other words, the next two statements could instead look something
		// like this:
		// if (!m_shouldProcess)
		// {
		// if (localName.equals(Constants.ELEMNAME_STYLESHEET_STRING) &&
		// url.equals(Constants.S_XSLNAMESPACEURL))
		// {
		// checkForFragmentID(attributes);
		// if (!m_shouldProcess)
		// return;
		// }
		// else
		// return;
		// }
		// I didn't include this code statement at this time because in practice
		// it is a small performance hit and I was waiting to see if its absence
		// caused a problem. - GLP

		checkForFragmentID(attributes);

		if (!m_shouldProcess)
			return;

		flushCharacters();

		pushSpaceHandling(attributes);

		XSLTElementProcessor elemProcessor = getProcessorFor(uri, localName,
				rawName);

		if (null != elemProcessor) // defensive, for better multiple error
									// reporting. -sb
		{
			this.pushProcessor(elemProcessor);
			elemProcessor.startElement(this, uri, localName, rawName,
					attributes);
		} else {
			m_shouldProcess = false;
			popSpaceHandling();
		}

	}

	/**
	 * Receive notification of the end of an element.
	 * 
	 * @param uri
	 *            The Namespace URI, or an empty string.
	 * @param localName
	 *            The local name (without prefix), or empty string if not
	 *            namespace processing.
	 * @param rawName
	 *            The qualified name (with prefix).
	 * @see org.xml.sax.ContentHandler#endElement
	 * 
	 * @throws org.xml.sax.SAXException
	 *             Any SAX exception, possibly wrapping another exception.
	 */
	@Override
	public void endElement(String uri, String localName, String rawName)
			throws org.xml.sax.SAXException {

		m_elementID--;

		if (!m_shouldProcess)
			return;

		if ((m_elementID + 1) == m_fragmentID)
			m_shouldProcess = false;

		flushCharacters();

		popSpaceHandling();

		XSLTElementProcessor p = getCurrentProcessor();

		p.endElement(this, uri, localName, rawName);
		this.popProcessor();
		this.getNamespaceSupport().popContext();
	}

	/**
	 * Receive notification of character data inside an element.
	 * 
	 * @param ch
	 *            The characters.
	 * @param start
	 *            The start position in the character array.
	 * @param length
	 *            The number of characters to use from the character array.
	 * @see org.xml.sax.ContentHandler#characters
	 * 
	 * @throws org.xml.sax.SAXException
	 *             Any SAX exception, possibly wrapping another exception.
	 */
	@Override
	public void characters(char ch[], int start, int length)
			throws org.xml.sax.SAXException {

		if (!m_shouldProcess)
			return;

		XSLTElementProcessor elemProcessor = getCurrentProcessor();
		XSLTElementDef def = elemProcessor.getElemDef();

		if (def.getType() != XSLTElementDef.T_PCDATA)
			elemProcessor = def.getProcessorFor(null, "text()");

		if (null == elemProcessor) {

			// If it's whitespace, just ignore it, otherwise flag an error.
			if (!XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
				error(
						XSLMessages
								.createMessage(
										XSLTErrorResources.ER_NONWHITESPACE_NOT_ALLOWED_IN_POSITION,
										null), null);// "Non-whitespace text
														// is not allowed in
														// this position in the
														// stylesheet!",

		} else
			elemProcessor.characters(this, ch, start, length);
	}

	/**
	 * Receive notification of ignorable whitespace in element content.
	 * 
	 * @param ch
	 *            The whitespace characters.
	 * @param start
	 *            The start position in the character array.
	 * @param length
	 *            The number of characters to use from the character array.
	 * @see org.xml.sax.ContentHandler#ignorableWhitespace
	 * 
	 * @throws org.xml.sax.SAXException
	 *             Any SAX exception, possibly wrapping another exception.
	 */
	@Override
	public void ignorableWhitespace(char ch[], int start, int length)
			throws org.xml.sax.SAXException {

		if (!m_shouldProcess)
			return;

		getCurrentProcessor().ignorableWhitespace(this, ch, start, length);
	}

	/**
	 * Receive notification of a processing instruction.
	 * 
	 * <p>
	 * The Parser will invoke this method once for each processing instruction
	 * found: note that processing instructions may occur before or after the
	 * main document element.
	 * </p>
	 * 
	 * <p>
	 * A SAX parser should never report an XML declaration (XML 1.0, section
	 * 2.8) or a text declaration (XML 1.0, section 4.3.1) using this method.
	 * </p>
	 * 
	 * <p>
	 * By default, do nothing. Application writers may override this method in a
	 * subclass to take specific actions for each processing instruction, such
	 * as setting status variables or invoking other methods.
	 * </p>
	 * 
	 * @param target
	 *            The processing instruction target.
	 * @param data
	 *            The processing instruction data, or null if none is supplied.
	 * @see org.xml.sax.ContentHandler#processingInstruction
	 * 
	 * @throws org.xml.sax.SAXException
	 *             Any SAX exception, possibly wrapping another exception.
	 */
	@Override
	public void processingInstruction(String target, String data)
			throws org.xml.sax.SAXException {
		if (!m_shouldProcess)
			return;

		// Recreating Scott's kluge:
		// A xsl:for-each or xsl:apply-templates may have a special
		// PI that tells us not to cache the document. This PI
		// should really be namespaced.
		// String localName = getLocalName(target);
		// String ns = m_stylesheet.getNamespaceFromStack(target);
		//
		// %REVIEW%: We need a better PI architecture

		String prefix = "", ns = "", localName = target; //$NON-NLS-1$//$NON-NLS-2$
		int colon = target.indexOf(':');
		if (colon >= 0) {
			ns = getNamespaceForPrefix(prefix = target.substring(0, colon));
			localName = target.substring(colon + 1);
		}

		try {
			// A xsl:for-each or xsl:apply-templates may have a special
			// PI that tells us not to cache the document. This PI
			// should really be namespaced... but since the XML Namespaces
			// spec never defined namespaces as applying to PI's, and since
			// the testcase we're trying to support is inconsistant in whether
			// it binds the prefix, I'm going to make this sloppy for
			// testing purposes.
			if ("xalan-doc-cache-off".equals(target) || //$NON-NLS-1$
					"xalan:doc-cache-off".equals(target) || //$NON-NLS-1$
					("doc-cache-off".equals(localName) && //$NON-NLS-1$
					ns.equals("org.apache.xalan.xslt.extensions.Redirect")) //$NON-NLS-1$
			) {
				if (!(m_elems.peek() instanceof ElemForEach))
					throw new TransformerException(
							"xalan:doc-cache-off not allowed here!", //$NON-NLS-1$
							getLocator());
				ElemForEach elem = (ElemForEach) m_elems.peek();

				elem.m_doc_cache_off = true;

				// System.out.println("JJK***** Recognized <?
				// {"+ns+"}"+prefix+":"+localName+" "+data+"?>");
			}
		} catch (Exception e) {
			// JJK: Officially, unknown PIs can just be ignored.
			// Do we want to issue a warning?
		}

		flushCharacters();
		getCurrentProcessor().processingInstruction(this, target, data);
	}

	/**
	 * Receive notification of a skipped entity.
	 * 
	 * <p>
	 * By default, do nothing. Application writers may override this method in a
	 * subclass to take specific actions for each processing instruction, such
	 * as setting status variables or invoking other methods.
	 * </p>
	 * 
	 * @param name
	 *            The name of the skipped entity.
	 * @see org.xml.sax.ContentHandler#processingInstruction
	 * 
	 * @throws org.xml.sax.SAXException
	 *             Any SAX exception, possibly wrapping another exception.
	 */
	@Override
	public void skippedEntity(String name) throws org.xml.sax.SAXException {

		if (!m_shouldProcess)
			return;

		getCurrentProcessor().skippedEntity(this, name);
	}

	/**
	 * Warn the user of an problem.
	 * 
	 * @param msg
	 *            An key into the
	 *            {@link org.apache.xalan.res.XSLTErrorResources} table, that is
	 *            one of the WG_ prefixed definitions.
	 * @param args
	 *            An array of arguments for the given warning.
	 * 
	 * @throws org.xml.sax.SAXException
	 *             that wraps a {@link javax.xml.transform.TransformerException}
	 *             if the current
	 *             {@link javax.xml.transform.ErrorListener#warning} method
	 *             chooses to flag this condition as an error.
	 * @xsl.usage internal
	 */
	public void warn(String msg, Object args[]) throws org.xml.sax.SAXException {

		String formattedMsg = XSLMessages.createWarning(msg, args);
		SAXSourceLocator locator = getLocator();
		ErrorListener handler = m_stylesheetProcessor.getErrorListener();

		try {
			if (null != handler)
				handler
						.warning(new TransformerException(formattedMsg, locator));
		} catch (TransformerException te) {
			throw new org.xml.sax.SAXException(te);
		}
	}

	/**
	 * Assert that a condition is true. If it is not true, throw an error.
	 * 
	 * @param condition
	 *            false if an error should not be thrown, otherwise true.
	 * @param msg
	 *            Error message to be passed to the RuntimeException as an
	 *            argument.
	 * @throws RuntimeException
	 *             if the condition is not true.
	 * @xsl.usage internal
	 */
	public void assertion(boolean condition, String msg)
			throws RuntimeException {
		if (!condition)
			throw new RuntimeException(msg);
	}

	/**
	 * Tell the user of an error, and probably throw an exception.
	 * 
	 * @param msg
	 *            An error message.
	 * @param e
	 *            An error which the SAXException should wrap.
	 * 
	 * @throws org.xml.sax.SAXException
	 *             that wraps a {@link javax.xml.transform.TransformerException}
	 *             if the current
	 *             {@link javax.xml.transform.ErrorListener#error} method
	 *             chooses to flag this condition as an error.
	 * @xsl.usage internal
	 */
	public void error(String msg, Exception e) throws org.xml.sax.SAXException {

		SAXSourceLocator locator = getLocator();
		ErrorListener handler = m_stylesheetProcessor.getErrorListener();
		TransformerException pe;

		if (!(e instanceof TransformerException)) {
			pe = (null == e) ? new TransformerException(msg, locator)
					: new TransformerException(msg, locator, e);
		} else
			pe = (TransformerException) e;

		if (null != handler) {
			try {
				handler.error(pe);
			} catch (TransformerException te) {
				throw new org.xml.sax.SAXException(te);
			}
		} else
			throw new org.xml.sax.SAXException(pe);
	}

	/**
	 * Tell the user of an error, and probably throw an exception.
	 * 
	 * @param msg
	 *            A key into the {@link org.apache.xalan.res.XSLTErrorResources}
	 *            table, that is one of the WG_ prefixed definitions.
	 * @param args
	 *            An array of arguments for the given warning.
	 * @param e
	 *            An error which the SAXException should wrap.
	 * 
	 * @throws org.xml.sax.SAXException
	 *             that wraps a {@link javax.xml.transform.TransformerException}
	 *             if the current
	 *             {@link javax.xml.transform.ErrorListener#error} method
	 *             chooses to flag this condition as an error.
	 * @xsl.usage internal
	 */
	protected void error(String msg, Object args[], Exception e)
			throws org.xml.sax.SAXException {

		String formattedMsg = XSLMessages.createMessage(msg, args);

		error(formattedMsg, e);
	}

	/**
	 * Receive notification of a XSLT processing warning.
	 * 
	 * @param e
	 *            The warning information encoded as an exception.
	 * 
	 * @throws org.xml.sax.SAXException
	 *             that wraps a {@link javax.xml.transform.TransformerException}
	 *             if the current
	 *             {@link javax.xml.transform.ErrorListener#warning} method
	 *             chooses to flag this condition as an error.
	 */
	@Override
	public void warning(org.xml.sax.SAXParseException e)
			throws org.xml.sax.SAXException {

		String formattedMsg = e.getMessage();
		SAXSourceLocator locator = getLocator();
		ErrorListener handler = m_stylesheetProcessor.getErrorListener();

		try {
			handler.warning(new TransformerException(formattedMsg, locator));
		} catch (TransformerException te) {
			throw new org.xml.sax.SAXException(te);
		}
	}

	/**
	 * Receive notification of a recoverable XSLT processing error.
	 * 
	 * @param e
	 *            The error information encoded as an exception.
	 * 
	 * @throws org.xml.sax.SAXException
	 *             that wraps a {@link javax.xml.transform.TransformerException}
	 *             if the current
	 *             {@link javax.xml.transform.ErrorListener#error} method
	 *             chooses to flag this condition as an error.
	 */
	@Override
	public void error(org.xml.sax.SAXParseException e)
			throws org.xml.sax.SAXException {

		String formattedMsg = e.getMessage();
		SAXSourceLocator locator = getLocator();
		ErrorListener handler = m_stylesheetProcessor.getErrorListener();

		try {
			handler.error(new TransformerException(formattedMsg, locator));
		} catch (TransformerException te) {
			throw new org.xml.sax.SAXException(te);
		}
	}

	/**
	 * Report a fatal XSLT processing error.
	 * 
	 * @param e
	 *            The error information encoded as an exception.
	 * 
	 * @throws org.xml.sax.SAXException
	 *             that wraps a {@link javax.xml.transform.TransformerException}
	 *             if the current
	 *             {@link javax.xml.transform.ErrorListener#fatalError} method
	 *             chooses to flag this condition as an error.
	 */
	@Override
	public void fatalError(org.xml.sax.SAXParseException e)
			throws org.xml.sax.SAXException {

		String formattedMsg = e.getMessage();
		SAXSourceLocator locator = getLocator();
		ErrorListener handler = m_stylesheetProcessor.getErrorListener();

		try {
			handler.fatalError(new TransformerException(formattedMsg, locator));
		} catch (TransformerException te) {
			throw new org.xml.sax.SAXException(te);
		}
	}

	/**
	 * If we have a URL to a XML fragment, this is set to false until the ID is
	 * found. (warning: I worry that this should be in a stack).
	 */
	private boolean m_shouldProcess = true;

	/**
	 * If we have a URL to a XML fragment, the value is stored in this string,
	 * and the m_shouldProcess flag is set to false until we match an ID with
	 * this string. (warning: I worry that this should be in a stack).
	 */
	private String m_fragmentIDString;

	/**
	 * Keep track of the elementID, so we can tell when is has completed. This
	 * isn't a real ID, but rather a nesting level. However, it's good enough
	 * for our purposes. (warning: I worry that this should be in a stack).
	 */
	private int m_elementID = 0;

	/**
	 * The ID of the fragment that has been found (warning: I worry that this
	 * should be in a stack).
	 */
	private int m_fragmentID = 0;

	/**
	 * Check to see if an ID attribute matched the #id, called from
	 * startElement.
	 * 
	 * @param attributes
	 *            The specified or defaulted attributes.
	 */
	private void checkForFragmentID(Attributes attributes) {

		if (!m_shouldProcess) {
			if ((null != attributes) && (null != m_fragmentIDString)) {
				int n = attributes.getLength();

				for (int i = 0; i < n; i++) {
					String name = attributes.getQName(i);

					if (name.equals(Constants.ATTRNAME_ID)) {
						String val = attributes.getValue(i);

						if (val.equalsIgnoreCase(m_fragmentIDString)) {
							m_shouldProcess = true;
							m_fragmentID = m_elementID;
						}
					}
				}
			}
		}
	}

	/**
	 * The XSLT TransformerFactory for needed services.
	 */
	private TransformerFactoryImpl m_stylesheetProcessor;

	/**
	 * Get the XSLT TransformerFactoryImpl for needed services. TODO: This
	 * method should be renamed.
	 * 
	 * @return The TransformerFactoryImpl that owns this handler.
	 */
	public TransformerFactoryImpl getStylesheetProcessor() {
		return m_stylesheetProcessor;
	}

	/**
	 * If getStylesheetType returns this value, the current stylesheet is a root
	 * stylesheet.
	 * 
	 * @xsl.usage internal
	 */
	public static final int STYPE_ROOT = 1;

	/**
	 * If getStylesheetType returns this value, the current stylesheet is an
	 * included stylesheet.
	 * 
	 * @xsl.usage internal
	 */
	public static final int STYPE_INCLUDE = 2;

	/**
	 * If getStylesheetType returns this value, the current stylesheet is an
	 * imported stylesheet.
	 * 
	 * @xsl.usage internal
	 */
	public static final int STYPE_IMPORT = 3;

	/** The current stylesheet type. */
	private int m_stylesheetType = STYPE_ROOT;

	/**
	 * Get the type of stylesheet that should be built or is being processed.
	 * 
	 * @return one of STYPE_ROOT, STYPE_INCLUDE, or STYPE_IMPORT.
	 */
	protected int getStylesheetType() {
		return m_stylesheetType;
	}

	/**
	 * Set the type of stylesheet that should be built or is being processed.
	 * 
	 * @param type
	 *            Must be one of STYPE_ROOT, STYPE_INCLUDE, or STYPE_IMPORT.
	 */
	protected void setStylesheetType(int type) {
		m_stylesheetType = type;
	}

	/**
	 * The stack of stylesheets being processed.
	 */
	private Stack m_stylesheets = new Stack();

	/**
	 * Return the stylesheet that this handler is constructing.
	 * 
	 * @return The current stylesheet that is on top of the stylesheets stack,
	 *         or null if no stylesheet is on the stylesheets stack.
	 */
	protected org.eclipse.wst.xsl.core.internal.compiler.xslt10.templates.Stylesheet getStylesheet() {
		return (m_stylesheets.size() == 0) ? null : (Stylesheet) m_stylesheets
				.peek();
	}

	/**
	 * Return the last stylesheet that was popped off the stylesheets stack.
	 * 
	 * @return The last popped stylesheet, or null.
	 */
	protected Stylesheet getLastPoppedStylesheet() {
		return m_lastPoppedStylesheet;
	}

	/**
	 * Return the stylesheet root that this handler is constructing.
	 * 
	 * @return The root stylesheet of the stylesheets tree.
	 */
	public StylesheetRoot getStylesheetRoot() {
		if (m_stylesheetRoot != null) {
			m_stylesheetRoot.setOptimizer(m_optimize);
			m_stylesheetRoot.setIncremental(m_incremental);
			m_stylesheetRoot.setSource_location(m_source_location);
		}
		return m_stylesheetRoot;
	}

	/** The root stylesheet of the stylesheets tree. */
	StylesheetRoot m_stylesheetRoot;

	/** The last stylesheet that was popped off the stylesheets stack. */
	Stylesheet m_lastPoppedStylesheet;

	/**
	 * Push the current stylesheet being constructed. If no other stylesheets
	 * have been pushed onto the stack, assume the argument is a stylesheet
	 * root, and also set the stylesheet root member.
	 * 
	 * @param s
	 *            non-null reference to a stylesheet.
	 */
	public void pushStylesheet(Stylesheet s) {

		if (m_stylesheets.size() == 0)
			m_stylesheetRoot = (StylesheetRoot) s;

		m_stylesheets.push(s);
	}

	/**
	 * Pop the last stylesheet pushed, and return the stylesheet that this
	 * handler is constructing, and set the last popped stylesheet member. Also
	 * pop the stylesheet locator stack.
	 * 
	 * @return The stylesheet popped off the stack, or the last popped
	 *         stylesheet.
	 */
	protected Stylesheet popStylesheet() {

		// The stylesheetLocatorStack needs to be popped because
		// a locator was pushed in for this stylesheet by the SAXparser by
		// calling
		// setDocumentLocator().
		if (!m_stylesheetLocatorStack.isEmpty())
			m_stylesheetLocatorStack.pop();

		if (!m_stylesheets.isEmpty())
			m_lastPoppedStylesheet = (Stylesheet) m_stylesheets.pop();

		// Shouldn't this be null if stylesheets is empty? -sb
		return m_lastPoppedStylesheet;
	}

	/**
	 * The stack of current processors.
	 */
	private Stack m_processors = new Stack();

	/**
	 * Get the current XSLTElementProcessor at the top of the stack.
	 * 
	 * @return Valid XSLTElementProcessor, which should never be null.
	 */
	protected XSLTElementProcessor getCurrentProcessor() {
		return (XSLTElementProcessor) m_processors.peek();
	}

	/**
	 * Push the current XSLTElementProcessor onto the top of the stack.
	 * 
	 * @param processor
	 *            non-null reference to the current element processor.
	 */
	protected void pushProcessor(XSLTElementProcessor processor) {
		m_processors.push(processor);
	}

	/**
	 * Pop the current XSLTElementProcessor from the top of the stack.
	 * 
	 * @return the XSLTElementProcessor which was popped.
	 */
	protected XSLTElementProcessor popProcessor() {
		return (XSLTElementProcessor) m_processors.pop();
	}

	/**
	 * The root of the XSLT Schema, which tells us how to transition content
	 * handlers, create elements, etc. For the moment at least, this can't be
	 * static, since the processors store state.
	 */
	private XSLTSchema m_schema = new XSLTSchema();

	/**
	 * Get the root of the XSLT Schema, which tells us how to transition content
	 * handlers, create elements, etc.
	 * 
	 * @return The root XSLT Schema, which should never be null.
	 * @xsl.usage internal
	 */
	public XSLTSchema getSchema() {
		return m_schema;
	}

	/**
	 * The stack of elements, pushed and popped as events occur.
	 */
	private Stack m_elems = new Stack();

	/**
	 * Get the current ElemTemplateElement at the top of the stack.
	 * 
	 * @return Valid ElemTemplateElement, which may be null.
	 */
	public ElemTemplateElement getElemTemplateElement() {

		try {
			return (ElemTemplateElement) m_elems.peek();
		} catch (java.util.EmptyStackException ese) {
			return null;
		}
	}

	/**
	 * An increasing number that is used to indicate the order in which this
	 * element was encountered during the parse of the XSLT tree.
	 */
	private int m_docOrderCount = 0;

	/**
	 * Returns the next m_docOrderCount number and increments the number for
	 * future use.
	 */
	public int nextUid() {
		return m_docOrderCount++;
	}

	/**
	 * Push the current XSLTElementProcessor to the top of the stack. As a
	 * side-effect, set the document order index (simply because this is a
	 * convenient place to set it).
	 * 
	 * @param elem
	 *            Should be a non-null reference to the intended current
	 *            template element.
	 */
	public void pushElemTemplateElement(ElemTemplateElement elem) {

		if (elem.getUid() == -1)
			elem.setUid(nextUid());

		m_elems.push(elem);
	}

	/**
	 * Get the current XSLTElementProcessor from the top of the stack.
	 * 
	 * @return the ElemTemplateElement which was popped.
	 */
	public ElemTemplateElement popElemTemplateElement() {
		return (ElemTemplateElement) m_elems.pop();
	}

	/**
	 * This will act as a stack to keep track of the current include base.
	 */
	protected Stack m_baseIdentifiers = new Stack();

	/**
	 * Push a base identifier onto the base URI stack.
	 * 
	 * @param baseID
	 *            The current base identifier for this position in the
	 *            stylesheet, which may be a fragment identifier, or which may
	 *            be null.
	 * @see <a href="http://www.w3.org/TR/xslt#base-uri"> Section 3.2 Base URI
	 *      of XSLT specification.</a>
	 */
	public void pushBaseIndentifier(String baseID) {

		if (null != baseID) {
			int posOfHash = baseID.indexOf('#');

			if (posOfHash > -1) {
				m_fragmentIDString = baseID.substring(posOfHash + 1);
				m_shouldProcess = false;
			} else
				m_shouldProcess = true;
		} else
			m_shouldProcess = true;

		m_baseIdentifiers.push(baseID);
	}

	/**
	 * Pop a base URI from the stack.
	 * 
	 * @return baseIdentifier.
	 */
	public String popBaseIndentifier() {
		return (String) m_baseIdentifiers.pop();
	}

	/**
	 * Return the base identifier.
	 * 
	 * @return The base identifier of the current stylesheet.
	 */
	public String getBaseIdentifier() {

		// Try to get the baseIdentifier from the baseIdentifier's stack,
		// which may not be the same thing as the value found in the
		// SourceLocators stack.
		String base = (String) (m_baseIdentifiers.isEmpty() ? null
				: m_baseIdentifiers.peek());

		// Otherwise try the stylesheet.
		if (null == base) {
			SourceLocator locator = getLocator();

			base = (null == locator) ? "" : locator.getSystemId();
		}

		return base;
	}

	/**
	 * The top of this stack should contain the currently processed stylesheet
	 * SAX locator object.
	 */
	private Stack m_stylesheetLocatorStack = new Stack();

	/**
	 * Get the current stylesheet Locator object.
	 * 
	 * @return non-null reference to the current locator object.
	 */
	public SAXSourceLocator getLocator() {

		if (m_stylesheetLocatorStack.isEmpty()) {
			SAXSourceLocator locator = new SAXSourceLocator();

			locator.setSystemId(this.getStylesheetProcessor().getDOMsystemID());

			return locator;

			// m_stylesheetLocatorStack.push(locator);
		}

		return ((SAXSourceLocator) m_stylesheetLocatorStack.peek());
	}

	/**
	 * A stack of URL hrefs for imported stylesheets. This is used to diagnose
	 * circular imports.
	 */
	private Stack m_importStack = new Stack();

	/**
	 * Push an import href onto the stylesheet stack.
	 * 
	 * @param hrefUrl
	 *            non-null reference to the URL for the current imported
	 *            stylesheet.
	 */
	public void pushImportURL(String hrefUrl) {
		m_importStack.push(hrefUrl);
	}

	/**
	 * See if the imported stylesheet stack already contains the given URL. Used
	 * to test for recursive imports.
	 * 
	 * @param hrefUrl
	 *            non-null reference to a URL string.
	 * 
	 * @return true if the URL is on the import stack.
	 */
	public boolean importStackContains(String hrefUrl) {
		return stackContains(m_importStack, hrefUrl);
	}

	/**
	 * Pop an import href from the stylesheet stack.
	 * 
	 * @return non-null reference to the import URL that was popped.
	 */
	public String popImportURL() {
		return (String) m_importStack.pop();
	}

	/**
	 * If this is set to true, we've already warned about using the older XSLT
	 * namespace URL.
	 */
	private boolean warnedAboutOldXSLTNamespace = false;

	/** Stack of NamespaceSupport objects. */
	private Stack m_nsSupportStack = new Stack();

	/**
	 * Push a new NamespaceSupport instance.
	 */
	public void pushNewNamespaceSupport() {
		m_nsSupportStack.push(new NamespaceSupport2());
	}

	/**
	 * Pop the current NamespaceSupport object.
	 * 
	 */
	public void popNamespaceSupport() {
		m_nsSupportStack.pop();
	}

	/**
	 * Get the current NamespaceSupport object.
	 * 
	 * @return a non-null reference to the current NamespaceSupport object,
	 *         which is the top of the namespace support stack.
	 */
	public NamespaceSupport getNamespaceSupport() {
		return (NamespaceSupport) m_nsSupportStack.peek();
	}

	/**
	 * The originating node if the current stylesheet is being created from a
	 * DOM.
	 * 
	 * @see org.apache.xml.utils.NodeConsumer
	 */
	private Node m_originatingNode;

	/**
	 * Set the node that is originating the SAX event.
	 * 
	 * @param n
	 *            Reference to node that originated the current event.
	 * @see org.apache.xml.utils.NodeConsumer
	 */
	public void setOriginatingNode(Node n) {
		m_originatingNode = n;
	}

	/**
	 * Set the node that is originating the SAX event.
	 * 
	 * @return Reference to node that originated the current event.
	 * @see org.apache.xml.utils.NodeConsumer
	 */
	public Node getOriginatingNode() {
		return m_originatingNode;
	}

	/**
	 * Stack of booleans that are pushed and popped in start/endElement
	 * depending on the value of xml:space=default/preserve.
	 */
	private BoolStack m_spacePreserveStack = new BoolStack();

	/**
	 * Return boolean value from the spacePreserve stack depending on the value
	 * of xml:space=default/preserve.
	 * 
	 * @return true if space should be preserved, false otherwise.
	 */
	public boolean isSpacePreserve() {
		return m_spacePreserveStack.peek();
	}

	/**
	 * Pop boolean value from the spacePreserve stack.
	 */
	public void popSpaceHandling() {
		m_spacePreserveStack.pop();
	}

	/**
	 * Push boolean value on to the spacePreserve stack.
	 * 
	 * @param b
	 *            true if space should be preserved, false otherwise.
	 */
	public void pushSpaceHandling(boolean b)
			throws org.xml.sax.SAXParseException {
		m_spacePreserveStack.push(b);
	}

	/**
	 * Push boolean value on to the spacePreserve stack depending on the value
	 * of xml:space=default/preserve.
	 * 
	 * @param attrs
	 *            list of attributes that were passed to startElement.
	 */
	public void pushSpaceHandling(Attributes attrs)
			throws org.xml.sax.SAXParseException {
		String value = attrs.getValue("xml:space");
		if (null == value) {
			m_spacePreserveStack.push(m_spacePreserveStack.peekOrFalse());
		} else if (value.equals("preserve")) {
			m_spacePreserveStack.push(true);
		} else if (value.equals("default")) {
			m_spacePreserveStack.push(false);
		} else {
			SAXSourceLocator locator = getLocator();
			ErrorListener handler = m_stylesheetProcessor.getErrorListener();

			try {
				handler.error(new TransformerException(XSLMessages
						.createMessage(
								XSLTErrorResources.ER_ILLEGAL_XMLSPACE_VALUE,
								null), locator)); // "Illegal value for
													// xml:space", locator));
			} catch (TransformerException te) {
				throw new org.xml.sax.SAXParseException(te.getMessage(),
						locator, te);
			}
			m_spacePreserveStack.push(m_spacePreserveStack.peek());
		}
	}

	public double getElemVersion() {
		ElemTemplateElement elem = getElemTemplateElement();
		double version = -1;
		while ((version == -1 || version == org.apache.xml.utils.Constants.XSLTVERSUPPORTED)
				&& elem != null) {
			try {
				version = Double.valueOf(elem.getXmlVersion()).doubleValue();
			} catch (Exception ex) {
				version = -1;
			}
			elem = elem.getParentElem();
		}
		return (version == -1) ? org.apache.xml.utils.Constants.XSLTVERSUPPORTED
				: version;
	}

	/**
	 * @see PrefixResolver#handlesNullPrefixes()
	 */
	public boolean handlesNullPrefixes() {
		return false;
	}

	/**
	 * @return Optimization flag
	 */
	public boolean getOptimize() {
		return m_optimize;
	}

	/**
	 * @return Incremental flag
	 */
	public boolean getIncremental() {
		return m_incremental;
	}

	/**
	 * @return Source Location flag
	 */
	public boolean getSource_location() {
		return m_source_location;
	}

}
