/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2003 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) 1999, Lotus
 * Development Corporation., http://www.lotus.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
package org.apache.xalan.templates;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;

import javax.xml.transform.SourceLocator;
import javax.xml.transform.TransformerException;

import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.transformer.TransformerImpl;
import org.apache.xml.serializer.SerializationHandler;
import org.apache.xml.utils.PrefixResolver;
import org.apache.xml.utils.UnImplNode;
import org.apache.xpath.ExpressionNode;
import org.apache.xpath.WhitespaceStrippingElementMatcher;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.xml.sax.helpers.NamespaceSupport;

/**
 * An instance of this class represents an element inside
 * an xsl:template class.  It has a single "execute" method
 * which is expected to perform the given action on the
 * result tree.
 * This class acts like a Element node, and implements the
 * Element interface, but is not a full implementation
 * of that interface... it only implements enough for
 * basic traversal of the tree.
 *
 * @see Stylesheet
 * @xsl.usage advanced
 */
public class ElemTemplateElement extends UnImplNode
        implements PrefixResolver, Serializable, ExpressionNode, 
                   WhitespaceStrippingElementMatcher, XSLTVisitable
{

  /**
   * Construct a template element instance.
   *
   * @param transformer The XSLT TransformerFactory.
   * @param stylesheetTree The owning stylesheet.
   * @param name The name of the element.
   * @param atts The element attributes.
   * @param lineNumber The line in the XSLT file that the element occurs on.
   * @param columnNumber The column index in the XSLT file that the element occurs on.
   */
  public ElemTemplateElement(){}

  /**
   * Tell if this template is a compiled template.
   *
   * @return Boolean flag indicating whether this is a compiled template   
   */
  public boolean isCompiledTemplate()
  {
    return false;
  }

  /**
   * Get an integer representation of the element type.
   *
   * @return An integer representation of the element, defined in the
   *     Constants class.
   * @see org.apache.xalan.templates.Constants
   */
  public int getXSLToken()
  {
    return Constants.ELEMNAME_UNDEFINED;
  }

  /**
   * Return the node name.
   *
   * @return An invalid node name
   */
  public String getNodeName()
  {
    return "Unknown XSLT Element";
  }
  
  /**
   * For now, just return the result of getNodeName(), which 
   * the local name.
   *
   * @return The result of getNodeName().
   */
  public String getLocalName()
  {

    return getNodeName();
  }


  /**
   * This function will be called on top-level elements
   * only, just before the transform begins.
   *
   * @param transformer The XSLT TransformerFactory.
   *
   * @throws TransformerException
   */
  public void runtimeInit(TransformerImpl transformer) throws TransformerException{}

  /**
   * Execute the element's primary function.  Subclasses of this
   * function may recursivly execute down the element tree.
   *
   * @param transformer The XSLT TransformerFactory.
   * @param sourceNode The current context node.
   * @param mode The current mode.
   * 
   * @throws TransformerException if any checked exception occurs.
   */
  public void execute(
          TransformerImpl transformer)
            throws TransformerException{}

  /**
   * Get the owning "composed" stylesheet.  This looks up the
   * inheritance chain until it calls getStylesheetComposed
   * on a Stylesheet object, which will Get the owning
   * aggregated stylesheet, or that stylesheet if it is aggregated.
   *
   * @return the owning "composed" stylesheet.
   */
  public StylesheetComposed getStylesheetComposed()
  {
    return m_parentNode.getStylesheetComposed();
  }

  /**
   * Get the owning stylesheet.  This looks up the
   * inheritance chain until it calls getStylesheet
   * on a Stylesheet object, which will return itself.
   *
   * @return the owning stylesheet
   */
  public Stylesheet getStylesheet()
  {
    return (null==m_parentNode) ? null : m_parentNode.getStylesheet();
  }

  /**
   * Get the owning root stylesheet.  This looks up the
   * inheritance chain until it calls StylesheetRoot
   * on a Stylesheet object, which will return a reference
   * to the root stylesheet.
   *
   * @return the owning root stylesheet
   */
  public StylesheetRoot getStylesheetRoot()
  {
    return m_parentNode.getStylesheetRoot();
  }

  /**
   * This function is called during recomposition to
   * control how this element is composed.
   */
  public void recompose(StylesheetRoot root) throws TransformerException
  {
  }

  /**
   * This function is called after everything else has been
   * recomposed, and allows the template to set remaining
   * values that may be based on some other property that
   * depends on recomposition.
   */
  public void compose(StylesheetRoot sroot) throws TransformerException
  {
    resolvePrefixTables();
    ElemTemplateElement t = getFirstChildElem();
    m_hasTextLitOnly = ((t != null) 
              && (t.getXSLToken() == Constants.ELEMNAME_TEXTLITERALRESULT) 
              && (t.getNextSiblingElem() == null));
              
    StylesheetRoot.ComposeState cstate = sroot.getComposeState();
    cstate.pushStackMark();
  }
  
  /**
   * This after the template's children have been composed.
   */
  public void endCompose(StylesheetRoot sroot) throws TransformerException
  {
    StylesheetRoot.ComposeState cstate = sroot.getComposeState();
    cstate.popStackMark();
  }

  /**
   * Validate that the string is an NCName.
   *
   * @param s The name in question.
   * @return True if the string is a valid NCName according to XML rules.
   * @see <a href="http://www.w3.org/TR/REC-xml-names#NT-NCName">XXX in XSLT Specification</a>
   */
  protected boolean isValidNCName(String s)
  {

    int len = s.length();
    char c = s.charAt(0);

    if (!(Character.isLetter(c) || (c == '_')))
      return false;

    if (len > 0)
    {
      for (int i = 1; i < len; i++)
      {
        c = s.charAt(i);

        if (!(Character.isLetterOrDigit(c) || (c == '_') || (c == '-')
              || (c == '.')))
          return false;
      }
    }

    return true;
  }

  /**
   * Throw a template element runtime error.  (Note: should we throw a TransformerException instead?)
   *
   * @param msg key of the error that occured.
   * @param args Arguments to be used in the message
   */
  public void error(String msg, Object[] args)
  {

    String themsg = XSLMessages.createMessage(msg, args);

    throw new RuntimeException(XSLMessages.createMessage(
                                    XSLTErrorResources.ER_ELEMTEMPLATEELEM_ERR,
                                    new Object[]{ themsg }));
  }
  
  /*
   * Throw an error.
   *
   * @param msg Message key for the error
   *
   */
  public void error(String msg)
  {
    error(msg, null);
  }
  

  // Implemented DOM Element methods.
  /**
   * Add a child to the child list.
   * NOTE: This presumes the child did not previously have a parent.
   * Making that assumption makes this a less expensive operation -- but
   * requires that if you *do* want to reparent a node, you use removeChild()
   * first to remove it from its previous context. Failing to do so will
   * damage the tree.
   *
   * @param newChild Child to be added to child list
   *
   * @return Child just added to the child list
   * @throws DOMException
   */
  public Node appendChild(Node newChild) throws DOMException
  {

    if (null == newChild)
    {
      error(XSLTErrorResources.ER_NULL_CHILD, null);  //"Trying to add a null child!");
    }

    ElemTemplateElement elem = (ElemTemplateElement) newChild;

    if (null == m_firstChild)
    {
      m_firstChild = elem;
    }
    else
    {
      ElemTemplateElement last = (ElemTemplateElement) getLastChild();

      last.m_nextSibling = elem;
    }

    elem.m_parentNode = this;

    return newChild;
  }

  /**
   * Add a child to the child list.
   * NOTE: This presumes the child did not previously have a parent.
   * Making that assumption makes this a less expensive operation -- but
   * requires that if you *do* want to reparent a node, you use removeChild()
   * first to remove it from its previous context. Failing to do so will
   * damage the tree.
   *
   * @param newChild Child to be added to child list
   *
   * @return Child just added to the child list
   */
  public ElemTemplateElement appendChild(ElemTemplateElement elem)
  {

    if (null == elem)
    {
      error(XSLTErrorResources.ER_NULL_CHILD, null);  //"Trying to add a null child!");
    }

    if (null == m_firstChild)
    {
      m_firstChild = elem;
    }
    else
    {
      ElemTemplateElement last = getLastChildElem();

      last.m_nextSibling = elem;
    }

    elem.setParentElem(this);

    return elem;
  }


  /**
   * Tell if there are child nodes.
   *
   * @return True if there are child nodes
   */
  public boolean hasChildNodes()
  {
    return (null != m_firstChild);
  }

  /**
   * Get the type of the node.
   *
   * @return Constant for this node type
   */
  public short getNodeType()
  {
    return org.w3c.dom.Node.ELEMENT_NODE;
  }

  /**
   * Return the nodelist (same reference).
   *
   * @return The nodelist containing the child nodes (this)
   */
  public NodeList getChildNodes()
  {
    return this;
  }

  /**
   * Remove a child.
   * ADDED 9/8/200 to support compilation.
   * TODO: ***** Alternative is "removeMe() from my parent if any"
   * ... which is less well checked, but more convenient in some cases.
   * Given that we assume only experts are calling this class, it might
   * be preferable. It's less DOMish, though.
   * 
   * @param childETE The child to remove. This operation is a no-op
   * if oldChild is not a child of this node.
   *
   * @return the removed child, or null if the specified
   * node was not a child of this element.
   */
  public ElemTemplateElement removeChild(ElemTemplateElement childETE)
  {

    if (childETE == null || childETE.m_parentNode != this)
      return null;

    // Pointers to the child
    if (childETE == m_firstChild)
      m_firstChild = childETE.m_nextSibling;
    else
    {
      ElemTemplateElement prev = childETE.getPreviousSiblingElem();

      prev.m_nextSibling = childETE.m_nextSibling;
    }

    // Pointers from the child
    childETE.m_parentNode = null;
    childETE.m_nextSibling = null;

    return childETE;
  }

  /**
   * Replace the old child with a new child.
   *
   * @param newChild New child to replace with
   * @param oldChild Old child to be replaced
   *
   * @return The new child
   *
   * @throws DOMException
   */
  public Node replaceChild(Node newChild, Node oldChild) throws DOMException
  {

    if (oldChild == null || oldChild.getParentNode() != this)
      return null;

    ElemTemplateElement newChildElem = ((ElemTemplateElement) newChild);
    ElemTemplateElement oldChildElem = ((ElemTemplateElement) oldChild);

    // Fix up previous sibling.
    ElemTemplateElement prev =
      (ElemTemplateElement) oldChildElem.getPreviousSibling();

    if (null != prev)
      prev.m_nextSibling = newChildElem;

    // Fix up parent (this)
    if (m_firstChild == oldChildElem)
      m_firstChild = newChildElem;

    newChildElem.m_parentNode = this;
    oldChildElem.m_parentNode = null;
    newChildElem.m_nextSibling = oldChildElem.m_nextSibling;
    oldChildElem.m_nextSibling = null;

    // newChildElem.m_stylesheet = oldChildElem.m_stylesheet;
    // oldChildElem.m_stylesheet = null;
    return newChildElem;
  }
  
  /**
   * Unimplemented. See org.w3c.dom.Node
   *
   * @param newChild New child node to insert
   * @param refChild Insert in front of this child
   *
   * @return null
   *
   * @throws DOMException
   */
  public Node insertBefore(Node newChild, Node refChild) throws DOMException
  {
  	if(null == refChild)
  	{
  		appendChild(newChild);
  		return newChild;
  	}
  	
  	if(newChild == refChild)
  	{
  		// hmm...
  		return newChild;
  	}

    Node node = m_firstChild; 
    Node prev = null;  
    boolean foundit = false;
    
    while (null != node)
    {
    	// If the newChild is already in the tree, it is first removed.
    	if(newChild == node)
    	{
    		if(null != prev)
    			((ElemTemplateElement)prev).m_nextSibling = 
    				(ElemTemplateElement)node.getNextSibling();
    		else
    			m_firstChild = (ElemTemplateElement)node.getNextSibling();
    		node = node.getNextSibling();
    		continue; // prev remains the same.
    	}
    	if(refChild == node)
    	{
    		if(null != prev)
    		{
    			((ElemTemplateElement)prev).m_nextSibling = (ElemTemplateElement)newChild;
    		}
    		else
    		{
    			m_firstChild = (ElemTemplateElement)newChild;
    		}
    		((ElemTemplateElement)newChild).m_nextSibling = (ElemTemplateElement)refChild;
    		((ElemTemplateElement)newChild).setParentElem(this);
    		prev = newChild;
    		node = node.getNextSibling();
    		foundit = true;
    		continue;
    	}
    	prev = node;
    	node = node.getNextSibling();
    }
    
    if(!foundit)
    	throw new DOMException(DOMException.NOT_FOUND_ERR, 
    		"refChild was not found in insertBefore method!");
    else
    	return newChild;
  }


  /**
   * Replace the old child with a new child.
   *
   * @param newChild New child to replace with
   * @param oldChild Old child to be replaced
   *
   * @return The new child
   *
   * @throws DOMException
   */
  public ElemTemplateElement replaceChild(ElemTemplateElement newChildElem, 
                                          ElemTemplateElement oldChildElem)
  {

    if (oldChildElem == null || oldChildElem.getParentElem() != this)
      return null;

    // Fix up previous sibling.
    ElemTemplateElement prev =
      oldChildElem.getPreviousSiblingElem();

    if (null != prev)
      prev.m_nextSibling = newChildElem;

    // Fix up parent (this)
    if (m_firstChild == oldChildElem)
      m_firstChild = newChildElem;

    newChildElem.m_parentNode = this;
    oldChildElem.m_parentNode = null;
    newChildElem.m_nextSibling = oldChildElem.m_nextSibling;
    oldChildElem.m_nextSibling = null;

    // newChildElem.m_stylesheet = oldChildElem.m_stylesheet;
    // oldChildElem.m_stylesheet = null;
    return newChildElem;
  }

  /**
   * NodeList method: Count the immediate children of this node
   *
   * @return The count of children of this node
   */
  public int getLength()
  {

    // It is assumed that the getChildNodes call synchronized
    // the children. Therefore, we can access the first child
    // reference directly.
    int count = 0;

    for (ElemTemplateElement node = m_firstChild; node != null;
            node = node.m_nextSibling)
    {
      count++;
    }

    return count;
  }  // getLength():int

  /**
   * NodeList method: Return the Nth immediate child of this node, or
   * null if the index is out of bounds.
   *
   * @param index Index of child to find
   * @return org.w3c.dom.Node: the child node at given index
   */
  public Node item(int index)
  {

    // It is assumed that the getChildNodes call synchronized
    // the children. Therefore, we can access the first child
    // reference directly.
    ElemTemplateElement node = m_firstChild;

    for (int i = 0; i < index && node != null; i++)
    {
      node = node.m_nextSibling;
    }

    return node;
  }  // item(int):Node

  /**
   * Get the stylesheet owner.
   *
   * @return The stylesheet owner
   */
  public Document getOwnerDocument()
  {
    return getStylesheet();
  }
  
  /**
   * Get the owning xsl:template element.
   *
   * @return The owning xsl:template element, this element if it is a xsl:template, or null if not found.
   */
  public ElemTemplate getOwnerXSLTemplate()
  {
  	ElemTemplateElement el = this;
  	int type = el.getXSLToken();
  	while((null != el) && (type != Constants.ELEMNAME_TEMPLATE))
  	{
    	el = el.getParentElem();
    	if(null != el)
  			type = el.getXSLToken();
  	}
  	return (ElemTemplate)el;
  }


  /**
   * Return the element name.
   *
   * @return The element name
   */
  public String getTagName()
  {
    return getNodeName();
  }
  
  /**
   * Tell if this element only has one text child, for optimization purposes.
   * @return true of this element only has one text literal child.
   */
  public boolean hasTextLitOnly()
  {
    return m_hasTextLitOnly;
  }

  /**
   * Return the base identifier.
   *
   * @return The base identifier 
   */
  public String getBaseIdentifier()
  {

    // Should this always be absolute?
    return this.getSystemId();
  }

  /** line number where the current document event ends.
   *  @serial         */
  private int m_lineNumber;

  /** line number where the current document event ends.
   *  @serial         */
  private int m_endLineNumber;

  /**
   * Return the line number where the current document event ends.
   * Note that this is the line position of the first character
   * after the text associated with the document event.
   * @return The line number, or -1 if none is available.
   * @see #getColumnNumber
   */
  public int getEndLineNumber()
  {
	return m_endLineNumber;
  }

  /**
   * Return the line number where the current document event ends.
   * Note that this is the line position of the first character
   * after the text associated with the document event.
   * @return The line number, or -1 if none is available.
   * @see #getColumnNumber
   */
  public int getLineNumber()
  {
    return m_lineNumber;
  }

  /** the column number where the current document event ends.
   *  @serial        */
  private int m_columnNumber;

  /** the column number where the current document event ends.
   *  @serial        */
  private int m_endColumnNumber;

  /**
   * Return the column number where the current document event ends.
   * Note that this is the column number of the first
   * character after the text associated with the document
   * event.  The first column in a line is position 1.
   * @return The column number, or -1 if none is available.
   * @see #getLineNumber
   */
  public int getEndColumnNumber()
  {
	return m_endColumnNumber;
  }

  /**
   * Return the column number where the current document event ends.
   * Note that this is the column number of the first
   * character after the text associated with the document
   * event.  The first column in a line is position 1.
   * @return The column number, or -1 if none is available.
   * @see #getLineNumber
   */
  public int getColumnNumber()
  {
    return m_columnNumber;
  }

  /**
   * Return the public identifier for the current document event.
   * <p>This will be the public identifier
   * @return A string containing the public identifier, or
   *         null if none is available.
   * @see #getSystemId
   */
  public String getPublicId()
  {
    return (null != m_parentNode) ? m_parentNode.getPublicId() : null;
  }

  /**
   * Return the system identifier for the current document event.
   *
   * <p>If the system identifier is a URL, the parser must resolve it
   * fully before passing it to the application.</p>
   *
   * @return A string containing the system identifier, or null
   *         if none is available.
   * @see #getPublicId
   */
  public String getSystemId()
  {
    Stylesheet sheet=getStylesheet();
    return (sheet==null) ? null : sheet.getHref();
  }

  /**
   * Set the location information for this element.
   *
   * @param locator Source Locator with location information for this element
   */
  public void setLocaterInfo(SourceLocator locator)
  {
    m_lineNumber = locator.getLineNumber();
    m_columnNumber = locator.getColumnNumber();
  }
  
  /**
   * Set the end location information for this element.
   *
   * @param locator Source Locator with location information for this element
   */
  public void setEndLocaterInfo(SourceLocator locator)
  {
	m_endLineNumber = locator.getLineNumber();
	m_endColumnNumber = locator.getColumnNumber();
  } 

  /**
   * Tell if this element has the default space handling
   * turned off or on according to the xml:space attribute.
   * @serial
   */
  private boolean m_defaultSpace = true;

  /**
   * Tell if this element only has one text child, for optimization purposes.
   * @serial
   */
  private boolean m_hasTextLitOnly = false;

  /**
   * Tell if this element only has one text child, for optimization purposes.
   * @serial
   */
  protected boolean m_hasVariableDecl = false;
  
  public boolean hasVariableDecl()
  {
    return m_hasVariableDecl;
  }

  /**
   * Set the "xml:space" attribute.
   * A text node is preserved if an ancestor element of the text node
   * has an xml:space attribute with a value of preserve, and
   * no closer ancestor element has xml:space with a value of default.
   * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
   * @see <a href="http://www.w3.org/TR/xslt#section-Creating-Text">section-Creating-Text in XSLT Specification</a>
   *
   * @param v  Enumerated value, either Constants.ATTRVAL_PRESERVE 
   * or Constants.ATTRVAL_STRIP.
   */
  public void setXmlSpace(int v)
  {
    m_defaultSpace = ((Constants.ATTRVAL_STRIP == v) ? true : false);
  }

  /**
   * Get the "xml:space" attribute.
   * A text node is preserved if an ancestor element of the text node
   * has an xml:space attribute with a value of preserve, and
   * no closer ancestor element has xml:space with a value of default.
   * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
   * @see <a href="http://www.w3.org/TR/xslt#section-Creating-Text">section-Creating-Text in XSLT Specification</a>
   *
   * @return The value of the xml:space attribute
   */
  public boolean getXmlSpace()
  {
    return m_defaultSpace;
  }

  /**
   * The list of namespace declarations for this element only.
   * @serial
   */
  private Vector m_declaredPrefixes;

  /**
   * Return a table that contains all prefixes available
   * within this element context.
   *
   * @return Vector containing the prefixes available within this
   * element context 
   */
  public Vector getDeclaredPrefixes()
  {
    return m_declaredPrefixes;
  }

  /**
   * From the SAX2 helper class, set the namespace table for
   * this element.  Take care to call resolveInheritedNamespaceDecls.
   * after all namespace declarations have been added.
   *
   * @param nsSupport non-null reference to NamespaceSupport from 
   * the ContentHandler.
   *
   * @throws TransformerException
   */
  public void setPrefixes(NamespaceSupport nsSupport) throws TransformerException
  {
    setPrefixes(nsSupport, false);
  }

  /**
   * Copy the namespace declarations from the NamespaceSupport object.  
   * Take care to call resolveInheritedNamespaceDecls.
   * after all namespace declarations have been added.
   *
   * @param nsSupport non-null reference to NamespaceSupport from 
   * the ContentHandler.
   * @param excludeXSLDecl true if XSLT namespaces should be ignored.
   *
   * @throws TransformerException
   */
  public void setPrefixes(NamespaceSupport nsSupport, boolean excludeXSLDecl)
          throws TransformerException
  {

    Enumeration decls = nsSupport.getDeclaredPrefixes();

    while (decls.hasMoreElements())
    {
      String prefix = (String) decls.nextElement();

      if (null == m_declaredPrefixes)
        m_declaredPrefixes = new Vector();

      String uri = nsSupport.getURI(prefix);

      if (excludeXSLDecl && uri.equals(Constants.S_XSLNAMESPACEURL))
        continue;

      // System.out.println("setPrefixes - "+prefix+", "+uri);
      XMLNSDecl decl = new XMLNSDecl(prefix, uri, false);

      m_declaredPrefixes.addElement(decl);
    }
  }

  /**
   * Fullfill the PrefixResolver interface.  Calling this for this class 
   * will throw an error.
   *
   * @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 null if the error listener does not choose to throw an exception.
   */
  public String getNamespaceForPrefix(String prefix, org.w3c.dom.Node context)
  {
    this.error(XSLTErrorResources.ER_CANT_RESOLVE_NSPREFIX, null);

    return null;
  }

  /**
   * Given a namespace, get the corrisponding prefix.
   * 9/15/00: This had been iteratively examining the m_declaredPrefixes
   * field for this node and its parents. That makes life difficult for
   * the compilation experiment, which doesn't have a static vector of
   * local declarations. Replaced a recursive solution, which permits
   * easier subclassing/overriding.
   *
   * @param prefix non-null reference to prefix string, which should map 
   *               to a namespace URL.
   *
   * @return The namespace URL that the prefix maps to, or null if no 
   *         mapping can be found.
   */
  public String getNamespaceForPrefix(String prefix)
  {
//    if (null != prefix && prefix.equals("xmlns"))
//    {
//      return Constants.S_XMLNAMESPACEURI;
//    }

    Vector nsDecls = m_declaredPrefixes;

    if (null != nsDecls)
    {
      int n = nsDecls.size();
      if(prefix.equals(Constants.ATTRVAL_DEFAULT_PREFIX))
      {
        prefix = "";
      }

      for (int i = 0; i < n; i++)
      {
        XMLNSDecl decl = (XMLNSDecl) nsDecls.elementAt(i);

        if (prefix.equals(decl.getPrefix()))
          return decl.getURI();
      }
    }

    // Not found; ask our ancestors
    if (null != m_parentNode)
      return m_parentNode.getNamespaceForPrefix(prefix);

    // JJK: No ancestors; try implicit
    // %REVIEW% Are there literals somewhere that we should use instead?
    // %REVIEW% Is this really the best place to patch?
    if("xml".equals(prefix))
      return "http://www.w3.org/XML/1998/namespace";

    // No parent, so no definition
    return null;
  }

  /**
   * The table of {@link XMLNSDecl}s for this element
   * and all parent elements, screened for excluded prefixes.
   * @serial
   */
  Vector m_prefixTable;

  /**
   * Return a table that contains all prefixes available
   * within this element context.
   *
   * @return reference to vector of {@link XMLNSDecl}s, which may be null.
   */
  public Vector getPrefixes()
  {
    return m_prefixTable;
  }
  
  /**
   * Get whether or not the passed URL is contained flagged by
   * the "extension-element-prefixes" property.  This method is overridden 
   * by {@link ElemLiteralResult#containsExcludeResultPrefix}.
   * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
   *
   * @param prefix non-null reference to prefix that might be excluded.
   *
   * @return true if the prefix should normally be excluded.
   */
  public boolean containsExcludeResultPrefix(String prefix, String uri)
  {
    ElemTemplateElement parent = this.getParentElem();
    if(null != parent)
      return parent.containsExcludeResultPrefix(prefix, uri);
      
    return false;
  }

  /**
   * Tell if the result namespace decl should be excluded.  Should be called before
   * namespace aliasing (I think).
   *
   * @param prefix non-null reference to prefix.
   * @param uri reference to namespace that prefix maps to, which is protected 
   *            for null, but should really never be passed as null.
   *
   * @return true if the given namespace should be excluded.
   *
   * @throws TransformerException
   */
  private boolean excludeResultNSDecl(String prefix, String uri)
          throws TransformerException
  {

    if (uri != null)
    {
      if (uri.equals(Constants.S_XSLNAMESPACEURL)
              || getStylesheet().containsExtensionElementURI(uri)
              || uri.equals(Constants.S_BUILTIN_EXTENSIONS_URL)
              || uri.equals(Constants.S_BUILTIN_OLD_EXTENSIONS_URL))
        return true;

      if (containsExcludeResultPrefix(prefix, uri))
        return true;
    }

    return false;
  }
  
  /**
   * Combine the parent's namespaces with this namespace
   * for fast processing, taking care to reference the
   * parent's namespace if this namespace adds nothing new.
   * (Recursive method, walking the elements depth-first,
   * processing parents before children).
   * Note that this method builds m_prefixTable with aliased 
   * namespaces, *not* the original namespaces.
   *
   * @throws TransformerException
   */
  public void resolvePrefixTables() throws TransformerException
  {
    // Always start with a fresh prefix table!
    m_prefixTable = null;

    // If we have declared declarations, then we look for 
    // a parent that has namespace decls, and add them 
    // to this element's decls.  Otherwise we just point 
    // to the parent that has decls.
    if (null != this.m_declaredPrefixes)
    {
      StylesheetRoot stylesheet = this.getStylesheetRoot();
      
      // Add this element's declared prefixes to the 
      // prefix table.
      int n = m_declaredPrefixes.size();

      for (int i = 0; i < n; i++)
      {
        XMLNSDecl decl = (XMLNSDecl) m_declaredPrefixes.elementAt(i);
        String prefix = decl.getPrefix();
        String uri = decl.getURI();
        if(null == uri)
          uri = "";
        boolean shouldExclude = excludeResultNSDecl(prefix, uri);

        // Create a new prefix table if one has not already been created.
        if (null == m_prefixTable)
          m_prefixTable = new Vector();

        NamespaceAlias nsAlias = stylesheet.getNamespaceAliasComposed(uri);
        if(null != nsAlias)
        {
          // Should I leave the non-aliased element in the table as 
          // an excluded element?
          
          // The exclusion should apply to the non-aliased prefix, so 
          // we don't calculate it here.  -sb
          // Use stylesheet prefix, as per xsl WG
          decl = new XMLNSDecl(nsAlias.getStylesheetPrefix(), 
                              nsAlias.getResultNamespace(), shouldExclude);
        }
        else
          decl = new XMLNSDecl(prefix, uri, shouldExclude);

        m_prefixTable.addElement(decl);
        
      }
    }

    ElemTemplateElement parent = this.getParentNodeElem();

    if (null != parent)
    {

      // The prefix table of the parent should never be null!
      Vector prefixes = parent.m_prefixTable;

      if (null == m_prefixTable && !needToCheckExclude())
      {

        // Nothing to combine, so just use parent's table!
        this.m_prefixTable = parent.m_prefixTable;
      }
      else
      {

        // Add the prefixes from the parent's prefix table.
        int n = prefixes.size();
        
        for (int i = 0; i < n; i++)
        {
          XMLNSDecl decl = (XMLNSDecl) prefixes.elementAt(i);
          boolean shouldExclude = excludeResultNSDecl(decl.getPrefix(),
                                                      decl.getURI());

          if (shouldExclude != decl.getIsExcluded())
          {
            decl = new XMLNSDecl(decl.getPrefix(), decl.getURI(),
                                 shouldExclude);
          }
          
          //m_prefixTable.addElement(decl);
          addOrReplaceDecls(decl);
        }
      }
    }
    else if (null == m_prefixTable)
    {

      // Must be stylesheet element without any result prefixes!
      m_prefixTable = new Vector();
    }
  }
  
  /**
   * Add or replace this namespace declaration in list
   * of namespaces in scope for this element.
   *
   * @param newDecl namespace declaration to add to list
   */
  void addOrReplaceDecls(XMLNSDecl newDecl)
  {
      int n = m_prefixTable.size();

        for (int i = n - 1; i >= 0; i--)
        {
          XMLNSDecl decl = (XMLNSDecl) m_prefixTable.elementAt(i);

          if (decl.getPrefix().equals(newDecl.getPrefix()))
          {
            return;
          }
        }
      m_prefixTable.addElement(newDecl);    
    
  }
  
  /**
   * Return whether we need to check namespace prefixes 
   * against and exclude result prefixes list.
   */
  boolean needToCheckExclude()
  {
    return false;    
  } 

  /**
   * Send startPrefixMapping events to the result tree handler
   * for all declared prefix mappings in the stylesheet.
   *
   * @param transformer non-null reference to the the current transform-time state.
   *
   * @throws TransformerException
   */
  void executeNSDecls(TransformerImpl transformer) throws TransformerException
  {
       executeNSDecls(transformer, null);
  }

  /**
   * Send startPrefixMapping events to the result tree handler
   * for all declared prefix mappings in the stylesheet.
   *
   * @param transformer non-null reference to the the current transform-time state.
   * @param ignorePrefix string prefix to not startPrefixMapping
   *
   * @throws TransformerException
   */
  void executeNSDecls(TransformerImpl transformer, String ignorePrefix) throws TransformerException
  {  
    try
    {
      if (null != m_prefixTable)
      {
        SerializationHandler rhandler = transformer.getResultTreeHandler();
        int n = m_prefixTable.size();

        for (int i = n - 1; i >= 0; i--)
        {
          XMLNSDecl decl = (XMLNSDecl) m_prefixTable.elementAt(i);

          if (!decl.getIsExcluded() && !(null != ignorePrefix && decl.getPrefix().equals(ignorePrefix)))
          {
            rhandler.startPrefixMapping(decl.getPrefix(), decl.getURI(), true);
          }
        }
      }
    }
    catch(org.xml.sax.SAXException se)
    {
      throw new TransformerException(se);
    }
  }

  /**
   * Send endPrefixMapping events to the result tree handler
   * for all declared prefix mappings in the stylesheet.
   *
   * @param transformer non-null reference to the the current transform-time state.
   *
   * @throws TransformerException
   */
  void unexecuteNSDecls(TransformerImpl transformer) throws TransformerException
  {
       unexecuteNSDecls(transformer, null);
  }

  /**
   * Send endPrefixMapping events to the result tree handler
   * for all declared prefix mappings in the stylesheet.
   *
   * @param transformer non-null reference to the the current transform-time state.
   * @param ignorePrefix string prefix to not endPrefixMapping
   * 
   * @throws TransformerException
   */
  void unexecuteNSDecls(TransformerImpl transformer, String ignorePrefix) throws TransformerException
  {
 
    try
    {
      if (null != m_prefixTable)
      {
        SerializationHandler rhandler = transformer.getResultTreeHandler();
        int n = m_prefixTable.size();

        for (int i = 0; i < n; i++)
        {
          XMLNSDecl decl = (XMLNSDecl) m_prefixTable.elementAt(i);

          if (!decl.getIsExcluded() && !(null != ignorePrefix && decl.getPrefix().equals(ignorePrefix)))
          {
            rhandler.endPrefixMapping(decl.getPrefix());
          }
        }
      }
    }
    catch(org.xml.sax.SAXException se)
    {
      throw new TransformerException(se);
    }
  }
  
  /** The *relative* document order number of this element.
   *  @serial */
  protected int m_docOrderNumber = -1;
  
  /**
   * Set the UID (document order index).
   *
   * @param kIndex Index of this child.
   */
  public void setUid(int i)
  {
    m_docOrderNumber = i;
  }

  /**
   * Get the UID (document order index).
   *
   * @return Index of this child
   */
  public int getUid()
  {
    return m_docOrderNumber;
  }


  /**
   * Parent node.
   * @serial
   */
  protected ElemTemplateElement m_parentNode;

  /**
   * Get the parent as a Node.
   *
   * @return This node's parent node
   */
  public Node getParentNode()
  {
    return m_parentNode;
  }

  /**
   * Get the parent as an ElemTemplateElement.
   *
   * @return This node's parent as an ElemTemplateElement
   */
  public ElemTemplateElement getParentElem()
  {
    return m_parentNode;
  }

  /**
   * Set the parent as an ElemTemplateElement.
   *
   * @param parent This node's parent as an ElemTemplateElement
   */
  public void setParentElem(ElemTemplateElement p)
  {
    m_parentNode = p;
  }

  /**
   * Next sibling.
   * @serial
   */
  ElemTemplateElement m_nextSibling;

  /**
   * Get the next sibling (as a Node) or return null.
   *
   * @return this node's next sibling or null
   */
  public Node getNextSibling()
  {
    return m_nextSibling;
  }

  /**
   * Get the previous sibling (as a Node) or return null.
   * Note that this may be expensive if the parent has many kids;
   * we accept that price in exchange for avoiding the prev pointer
   * TODO: If we were sure parents and sibs are always ElemTemplateElements,
   * we could hit the fields directly rather than thru accessors.
   *
   * @return This node's previous sibling or null
   */
  public Node getPreviousSibling()
  {

    Node walker = getParentNode(), prev = null;

    if (walker != null)
      for (walker = walker.getFirstChild(); walker != null;
              prev = walker, walker = walker.getNextSibling())
      {
        if (walker == this)
          return prev;
      }

    return null;
  }

  /**
   * Get the previous sibling (as a Node) or return null.
   * Note that this may be expensive if the parent has many kids;
   * we accept that price in exchange for avoiding the prev pointer
   * TODO: If we were sure parents and sibs are always ElemTemplateElements,
   * we could hit the fields directly rather than thru accessors.
   *
   * @return This node's previous sibling or null
   */
  public ElemTemplateElement getPreviousSiblingElem()
  {

    ElemTemplateElement walker = getParentNodeElem();
    ElemTemplateElement prev = null;

    if (walker != null)
      for (walker = walker.getFirstChildElem(); walker != null;
              prev = walker, walker = walker.getNextSiblingElem())
      {
        if (walker == this)
          return prev;
      }

    return null;
  }


  /**
   * Get the next sibling (as a ElemTemplateElement) or return null.
   *
   * @return This node's next sibling (as a ElemTemplateElement) or null 
   */
  public ElemTemplateElement getNextSiblingElem()
  {
    return m_nextSibling;
  }
  
  /**
   * Get the parent element.
   *
   * @return This node's next parent (as a ElemTemplateElement) or null 
   */
  public ElemTemplateElement getParentNodeElem()
  {
    return m_parentNode;
  }


  /**
   * First child.
   * @serial
   */
  ElemTemplateElement m_firstChild;

  /**
   * Get the first child as a Node.
   *
   * @return This node's first child or null
   */
  public Node getFirstChild()
  {
    return m_firstChild;
  }

  /**
   * Get the first child as a ElemTemplateElement.
   *
   * @return This node's first child (as a ElemTemplateElement) or null
   */
  public ElemTemplateElement getFirstChildElem()
  {
    return m_firstChild;
  }

  /**
   * Get the last child.
   *
   * @return This node's last child
   */
  public Node getLastChild()
  {

    ElemTemplateElement lastChild = null;

    for (ElemTemplateElement node = m_firstChild; node != null;
            node = node.m_nextSibling)
    {
      lastChild = node;
    }

    return lastChild;
  }

  /**
   * Get the last child.
   *
   * @return This node's last child
   */
  public ElemTemplateElement getLastChildElem()
  {

    ElemTemplateElement lastChild = null;

    for (ElemTemplateElement node = m_firstChild; node != null;
            node = node.m_nextSibling)
    {
      lastChild = node;
    }

    return lastChild;
  }


  /** DOM backpointer that this element originated from.          */
  transient private org.w3c.dom.Node m_DOMBackPointer;

  /**
   * If this stylesheet was created from a DOM, get the
   * DOM backpointer that this element originated from.
   * For tooling use.
   *
   * @return DOM backpointer that this element originated from or null.
   */
  public org.w3c.dom.Node getDOMBackPointer()
  {
    return m_DOMBackPointer;
  }

  /**
   * If this stylesheet was created from a DOM, set the
   * DOM backpointer that this element originated from.
   * For tooling use.
   *
   * @param n DOM backpointer that this element originated from.
   */
  public void setDOMBackPointer(org.w3c.dom.Node n)
  {
    m_DOMBackPointer = n;
  }

  /**
   * Compares this object with the specified object for precedence order.
   * The order is determined by the getImportCountComposed() of the containing
   * composed stylesheet and the getUid() of this element.
   * Returns a negative integer, zero, or a positive integer as this
   * object is less than, equal to, or greater than the specified object.
   * 
   * @param o The object to be compared to this object
   * @return  a negative integer, zero, or a positive integer as this object is
   *          less than, equal to, or greater than the specified object.
   * @throws ClassCastException if the specified object's
   *         type prevents it from being compared to this Object.
   */
  public int compareTo(Object o) throws ClassCastException {
    
    ElemTemplateElement ro = (ElemTemplateElement) o;
    int roPrecedence = ro.getStylesheetComposed().getImportCountComposed();
    int myPrecedence = this.getStylesheetComposed().getImportCountComposed();

    if (myPrecedence < roPrecedence)
      return -1;
    else if (myPrecedence > roPrecedence)
      return 1;
    else
      return this.getUid() - ro.getUid();
  }
  
  /**
   * Get information about whether or not an element should strip whitespace.
   * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
   *
   * @param support The XPath runtime state.
   * @param targetElement Element to check
   *
   * @return true if the whitespace should be stripped.
   *
   * @throws TransformerException
   */
  public boolean shouldStripWhiteSpace(
          org.apache.xpath.XPathContext support, 
          org.w3c.dom.Element targetElement) throws TransformerException
  {
    StylesheetRoot sroot = this.getStylesheetRoot();
    return (null != sroot) ? sroot.shouldStripWhiteSpace(support, targetElement) :false;
  }
  
  /**
   * Get information about whether or not whitespace can be stripped.
   * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
   *
   * @return true if the whitespace can be stripped.
   */
  public boolean canStripWhiteSpace()
  {
    StylesheetRoot sroot = this.getStylesheetRoot();
    return (null != sroot) ? sroot.canStripWhiteSpace() : false;
  }
  
  /**
   * Tell if this element can accept variable declarations.
   * @return true if the element can accept and process variable declarations.
   */
  public boolean canAcceptVariables()
  {
  	return true;
  }
  
  //=============== ExpressionNode methods ================
  
  /** 
   * Set the parent of this node.
   * @param n Must be a ElemTemplateElement.
   */
  public void exprSetParent(ExpressionNode n)
  {
  	// This obviously requires that only a ElemTemplateElement can 
  	// parent a node of this type.
  	setParentElem((ElemTemplateElement)n);
  }
  
  /**
   * Get the ExpressionNode parent of this node.
   */
  public ExpressionNode exprGetParent()
  {
  	return getParentElem();
  }

  /** 
   * This method tells the node to add its argument to the node's
   * list of children. 
   * @param n Must be a ElemTemplateElement. 
   */
  public void exprAddChild(ExpressionNode n, int i)
  {
  	appendChild((ElemTemplateElement)n);
  }

  /** This method returns a child node.  The children are numbered
     from zero, left to right. */
  public ExpressionNode exprGetChild(int i)
  {
  	return (ExpressionNode)item(i);
  }

  /** Return the number of children the node has. */
  public int exprGetNumChildren()
  {
  	return getLength();
  }
  
  /**
   * Accept a visitor and call the appropriate method 
   * for this class.
   * 
   * @param visitor The visitor whose appropriate method will be called.
   * @return true if the children of the object should be visited.
   */
  protected boolean accept(XSLTVisitor visitor)
  {
  	return visitor.visitInstruction(this);
  }

  /**
   * @see XSLTVisitable#callVisitors(XSLTVisitor)
   */
  public void callVisitors(XSLTVisitor visitor)
  {
  	if(accept(visitor))
  	{
		callChildVisitors(visitor);
  	}
  }

  /**
   * Call the children visitors.
   * @param visitor The visitor whose appropriate method will be called.
   */
  protected void callChildVisitors(XSLTVisitor visitor, boolean callAttributes)
  {
    for (ElemTemplateElement node = m_firstChild;
      node != null;
      node = node.m_nextSibling)
      {
      node.callVisitors(visitor);
    }
  }
  
  /**
   * Call the children visitors.
   * @param visitor The visitor whose appropriate method will be called.
   */
  protected void callChildVisitors(XSLTVisitor visitor)
  {
  	callChildVisitors(visitor, true);
  }


	/**
	 * @see PrefixResolver#handlesNullPrefixes()
	 */
	public boolean handlesNullPrefixes() {
		return false;
	}

}
