/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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$
 */
package org.apache.xalan.templates;

import java.util.Enumeration;
import java.util.Vector;

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.StringVector;
import org.apache.xpath.XPathContext;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.TypeInfo;
import org.w3c.dom.UserDataHandler;
import org.xml.sax.SAXException;

/**
 * Implement a Literal Result Element.
 * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
 * @xsl.usage advanced
 */
public class ElemLiteralResult extends ElemUse
{
    static final long serialVersionUID = -8703409074421657260L;

    /** The return value as Empty String. */
    private static final String EMPTYSTRING = "";

  /**
   * Tells if this element represents a root element
   * that is also the stylesheet element.
   * TODO: This should be a derived class.
   * @serial
   */
  private boolean isLiteralResultAsStylesheet = false;

  /**
   * Set whether this element represents a root element
   * that is also the stylesheet element.
   *
   *
   * @param b boolean flag indicating whether this element
   * represents a root element that is also the stylesheet element.
   */
  public void setIsLiteralResultAsStylesheet(boolean b)
  {
    isLiteralResultAsStylesheet = b;
  }

  /**
   * Return whether this element represents a root element
   * that is also the stylesheet element.
   *
   *
   * @return boolean flag indicating whether this element
   * represents a root element that is also the stylesheet element.
   */
  public boolean getIsLiteralResultAsStylesheet()
  {
    return isLiteralResultAsStylesheet;
  }
  
  /**
   * 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
  {
    super.compose(sroot);
    StylesheetRoot.ComposeState cstate = sroot.getComposeState();
    java.util.Vector vnames = cstate.getVariableNames();
    if (null != m_avts)
    {
      int nAttrs = m_avts.size();

      for (int i = (nAttrs - 1); i >= 0; i--)
      {
        AVT avt = (AVT) m_avts.elementAt(i);
        avt.fixupVariables(vnames, cstate.getGlobalsSize());
      } 
    }   
  }
  
  /**
   * The created element node will have the attribute nodes
   * that were present on the element node in the stylesheet tree,
   * other than attributes with names in the XSLT namespace.
   * @serial
   */
  private Vector m_avts = null;

  /** List of attributes with the XSLT namespace.
   *  @serial */
  private Vector m_xslAttr = null;

  /**
   * Set a literal result attribute (AVTs only).
   *
   * @param avt literal result attribute to add (AVT only)
   */
  public void addLiteralResultAttribute(AVT avt)
  {

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

    m_avts.addElement(avt);
  }

  /**
   * Set a literal result attribute (used for xsl attributes).
   *
   * @param att literal result attribute to add
   */
  public void addLiteralResultAttribute(String att)
  {

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

    m_xslAttr.addElement(att);
  }
  
  /**
   * 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 avt  Enumerated value, either Constants.ATTRVAL_PRESERVE 
   * or Constants.ATTRVAL_STRIP.
   */
  public void setXmlSpace(AVT avt)
  {
    // This function is a bit-o-hack, I guess...
    addLiteralResultAttribute(avt);
    String val = avt.getSimpleString();
    if(val.equals("default"))
    {
      super.setXmlSpace(Constants.ATTRVAL_STRIP);
    }
    else if(val.equals("preserve"))
    {
      super.setXmlSpace(Constants.ATTRVAL_PRESERVE);
    }
    // else maybe it's a real AVT, so we can't resolve it at this time.
  }

  /**
   * Get a literal result attribute by name.
   *
   * @param namespaceURI Namespace URI of attribute node to get
   * @param localName Local part of qualified name of attribute node to get
   *
   * @return literal result attribute (AVT)
   */
  public AVT getLiteralResultAttributeNS(String namespaceURI, String localName)
  {

    if (null != m_avts)
    {
      int nAttrs = m_avts.size();

      for (int i = (nAttrs - 1); i >= 0; i--)
      {
        AVT avt = (AVT) m_avts.elementAt(i);

        if (avt.getName().equals(localName) && 
                avt.getURI().equals(namespaceURI))
        {
          return avt;
        }
      }  // end for
    }

    return null;
  }

  /**
   * Return the raw value of the attribute.
   *
   * @param namespaceURI Namespace URI of attribute node to get
   * @param localName Local part of qualified name of attribute node to get
   *
   * @return The Attr value as a string, or the empty string if that attribute 
   * does not have a specified or default value
   */
  public String getAttributeNS(String namespaceURI, String localName)
  {

    AVT avt = getLiteralResultAttributeNS(namespaceURI, localName);

    if ((null != avt))
    {
      return avt.getSimpleString();
    }

    return EMPTYSTRING;
  }

  /**
   * Get a literal result attribute by name. The name is namespaceURI:localname  
   * if namespace is not null.
   *
   * @param name Name of literal result attribute to get
   *
   * @return literal result attribute (AVT)
   */
  public AVT getLiteralResultAttribute(String name)
  {

    if (null != m_avts)
    {
      int nAttrs = m_avts.size();
      String namespace = null;
      for (int i = (nAttrs - 1); i >= 0; i--)
      {
        AVT avt = (AVT) m_avts.elementAt(i);
        namespace = avt.getURI();
        
        if ((namespace != null && (!namespace.equals("")) && (namespace 
                +":"+avt.getName()).equals(name))|| ((namespace == null || 
                namespace.equals(""))&& avt.getRawName().equals(name)))
        {
          return avt;
        }
      }  // end for
    }

    return null;
  }

  /**
   * Return the raw value of the attribute.
   *
   * @param namespaceURI:localName or localName if the namespaceURI is null of 
   * the attribute to get
   *
   * @return The Attr value as a string, or the empty string if that attribute 
   * does not have a specified or default value
   */
  public String getAttribute(String rawName)
  {

    AVT avt = getLiteralResultAttribute(rawName);

    if ((null != avt))
    {
      return avt.getSimpleString();
    }

    return EMPTYSTRING;
  }
  
  /**
   * Get whether or not the passed URL is flagged by
   * the "extension-element-prefixes" or "exclude-result-prefixes"
   * properties.
   * @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.(not currently used)
   * @param uri reference to namespace that prefix maps to
   *
   * @return true if the prefix should normally be excluded.
   */
  public boolean containsExcludeResultPrefix(String prefix, String uri)
  {
    if (uri == null ||
                (null == m_excludeResultPrefixes &&
                 null == m_ExtensionElementURIs)
                )
      return super.containsExcludeResultPrefix(prefix, uri);

    if (prefix.length() == 0)
      prefix = Constants.ATTRVAL_DEFAULT_PREFIX;

    // This loop is ok here because this code only runs during
    // stylesheet compile time.    
        if(m_excludeResultPrefixes!=null)
            for (int i =0; i< m_excludeResultPrefixes.size(); i++)
            {
                if (uri.equals(getNamespaceForPrefix(m_excludeResultPrefixes.elementAt(i))))
                    return true;
            }    
        
        // JJK Bugzilla 1133: Also check locally-scoped extensions
    if(m_ExtensionElementURIs!=null && m_ExtensionElementURIs.contains(uri))
       return true;

        return super.containsExcludeResultPrefix(prefix, uri);
  }

  /**
   * Augment resolvePrefixTables, resolving the namespace aliases once
   * the superclass has resolved the tables.
   *
   * @throws TransformerException
   */
  public void resolvePrefixTables() throws TransformerException
  {

    super.resolvePrefixTables();

    StylesheetRoot stylesheet = getStylesheetRoot();

    if ((null != m_namespace) && (m_namespace.length() > 0))
    {
      NamespaceAlias nsa = stylesheet.getNamespaceAliasComposed(m_namespace);

      if (null != nsa)
      {
        m_namespace = nsa.getResultNamespace();

        // String resultPrefix = nsa.getResultPrefix();
        String resultPrefix = nsa.getStylesheetPrefix();  // As per xsl WG, Mike Kay

        if ((null != resultPrefix) && (resultPrefix.length() > 0))
          m_rawName = resultPrefix + ":" + m_localName;
        else
          m_rawName = m_localName;
      }
    }

    if (null != m_avts)
    {
      int n = m_avts.size();

      for (int i = 0; i < n; i++)
      {
        AVT avt = (AVT) m_avts.elementAt(i);

        // Should this stuff be a method on AVT?
        String ns = avt.getURI();

        if ((null != ns) && (ns.length() > 0))
        {
          NamespaceAlias nsa =
            stylesheet.getNamespaceAliasComposed(m_namespace); // %REVIEW% ns?

          if (null != nsa)
          {
            String namespace = nsa.getResultNamespace();

            // String resultPrefix = nsa.getResultPrefix();
            String resultPrefix = nsa.getStylesheetPrefix();  // As per XSL WG
            String rawName = avt.getName();

            if ((null != resultPrefix) && (resultPrefix.length() > 0))
              rawName = resultPrefix + ":" + rawName;

            avt.setURI(namespace);
            avt.setRawName(rawName);
          }
        }
      }
    }
  }

  /**
   * Return whether we need to check namespace prefixes
   * against the exclude result prefixes or extensions lists.
   * Note that this will create a new prefix table if one
   * has not been created already.
   *
   * NEEDSDOC ($objectName$) @return
   */
  boolean needToCheckExclude()
  {
    if (null == m_excludeResultPrefixes && null == getPrefixTable()
                && m_ExtensionElementURIs==null     // JJK Bugzilla 1133
                )
      return false;
    else
    {

      // Create a new prefix table if one has not already been created.
      if (null == getPrefixTable())
        setPrefixTable(new java.util.ArrayList());

      return true;
    }
  }

  /**
   * The namespace of the element to be created.
   * @serial
   */
  private String m_namespace;

  /**
   * Set the namespace URI of the result element to be created.
   * Note that after resolvePrefixTables has been called, this will
   * return the aliased result namespace, not the original stylesheet
   * namespace.
   *
   * @param ns The Namespace URI, or the empty string if the
   *        element has no Namespace URI.
   */
  public void setNamespace(String ns)
  {
    if(null == ns) // defensive, shouldn't have to do this.
      ns = "";
    m_namespace = ns;
  }

  /**
   * Get the original namespace of the Literal Result Element.
   * 
   * %REVIEW% Why isn't this overriding the getNamespaceURI method
   * rather than introducing a new one?
   *
   * @return The Namespace URI, or the empty string if the
   *        element has no Namespace URI.
   */
  public String getNamespace()
  {
    return m_namespace;
  }

  /**
   * The local name of the element to be created.
   * @serial
   */
  private String m_localName;

  /**
   * Set the local name of the LRE.
   *
   * @param localName The local name (without prefix) of the result element
   *                  to be created.
   */
  public void setLocalName(String localName)
  {
    m_localName = localName;
  }

  /**
   * Get the local name of the Literal Result Element.
   * Note that after resolvePrefixTables has been called, this will
   * return the aliased name prefix, not the original stylesheet
   * namespace prefix.
   *
   * @return The local name (without prefix) of the result element
   *                  to be created.
   */
  public String getLocalName()
  {
    return m_localName;
  }

  /**
   * The raw name of the element to be created.
   * @serial
   */
  private String m_rawName;

  /**
   * Set the raw name of the LRE.
   *
   * @param rawName The qualified name (with prefix), or the
   *        empty string if qualified names are not available.
   */
  public void setRawName(String rawName)
  {
    m_rawName = rawName;
  }

  /**
   * Get the raw name of the Literal Result Element.
   *
   * @return  The qualified name (with prefix), or the
   *        empty string if qualified names are not available.
   */
  public String getRawName()
  {
    return m_rawName;
  }
    
 /**
   * Get the prefix part of the raw name of the Literal Result Element.
   *
   * @return The prefix, or the empty string if noprefix was provided.
   */
  public String getPrefix()
  {
        int len=m_rawName.length()-m_localName.length()-1;
    return (len>0)
            ? m_rawName.substring(0,len)
            : "";
  }


  /**
   * The "extension-element-prefixes" property, actually contains URIs.
   * @serial
   */
  private StringVector m_ExtensionElementURIs;

  /**
   * Set the "extension-element-prefixes" property.
   * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
   *
   * @param v Vector of URIs (not prefixes) to set as the "extension-element-prefixes" property
   */
  public void setExtensionElementPrefixes(StringVector v)
  {
    m_ExtensionElementURIs = v;
  }

  /**
   * @see org.w3c.dom.Node
   *
   * @return NamedNodeMap
   */
  public NamedNodeMap getAttributes()
  {
        return new LiteralElementAttributes();
  }

  public class LiteralElementAttributes implements NamedNodeMap{
          private int m_count = -1;
          
          /**
           * Construct a NameNodeMap.
           *
           */
          public LiteralElementAttributes(){         
          }
          
          /**
           * Return the number of Attributes on this Element
           *
           * @return The number of nodes in this map. The range of valid child 
           * node indices is <code>0</code> to <code>length-1</code> inclusive
           */
          public int getLength()
          {
            if (m_count == -1)
            {
               if (null != m_avts) m_count = m_avts.size();
               else m_count = 0;
            }
            return m_count;
          }

          /**
           * Retrieves a node specified by name.
           * @param name The <code>nodeName</code> of a node to retrieve.
           * @return A <code>Node</code> (of any type) with the specified
           *   <code>nodeName</code>, or <code>null</code> if it does not 
           *   identify any node in this map.
           */
          public Node getNamedItem(String name)
          {
                if (getLength() == 0) return null;
                String uri = null;
                String localName = name; 
                int index = name.indexOf(":"); 
                if (-1 != index){
                         uri = name.substring(0, index);
                         localName = name.substring(index+1);
                }
                Node retNode = null;
                Enumeration eum = m_avts.elements();
                while (eum.hasMoreElements()){
                        AVT avt = (AVT) eum.nextElement();
                        if (localName.equals(avt.getName()))
                        {
                          String nsURI = avt.getURI(); 
                          if ((uri == null && nsURI == null)
                            || (uri != null && uri.equals(nsURI)))
                          {
                            retNode = new Attribute(avt, ElemLiteralResult.this);
                            break;
                          }
                        }
                }
                return retNode;
          }

          /**
           * Retrieves a node specified by local name and namespace URI.
           * @param namespaceURI Namespace URI of attribute node to get
           * @param localName Local part of qualified name of attribute node to 
           * get
           * @return A <code>Node</code> (of any type) with the specified
           *   <code>nodeName</code>, or <code>null</code> if it does not 
           *   identify any node in this map.
           */
          public Node getNamedItemNS(String namespaceURI, String localName)
          {
                  if (getLength() == 0) return null;
                  Node retNode = null;
                  Enumeration eum = m_avts.elements();
                  while (eum.hasMoreElements())
                  {
                    AVT avt = (AVT) eum.nextElement();      
                    if (localName.equals(avt.getName()))
                    {
                      String nsURI = avt.getURI(); 
                      if ((namespaceURI == null && nsURI == null)
                        || (namespaceURI != null && namespaceURI.equals(nsURI)))
                      {
                        retNode = new Attribute(avt, ElemLiteralResult.this);
                        break;
                      }
                    }
                  }
                  return retNode;
          }
          
          /**
           * Returns the <code>index</code>th item in the map. If <code>index
           * </code> is greater than or equal to the number of nodes in this 
           * map, this returns <code>null</code>.
           * @param i The index of the requested item.
           * @return The node at the <code>index</code>th position in the map, 
           *   or <code>null</code> if that is not a valid index.
           */
          public Node item(int i)
          {
                if (getLength() == 0 || i >= m_avts.size()) return null;
                else return 
                    new Attribute(((AVT)m_avts.elementAt(i)), 
                        ElemLiteralResult.this);
          }
          
          /**
           * @see org.w3c.dom.NamedNodeMap
           *
           * @param name of the node to remove
           * 
           * @return The node removed from this map if a node with such 
           * a name exists. 
           *
           * @throws DOMException
           */
          public Node removeNamedItem(String name) throws DOMException
          {
                  throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                      XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR); 
                  return null;
          }
          
          /**
           * @see org.w3c.dom.NamedNodeMap
           *
           * @param namespaceURI Namespace URI of the node to remove
           * @param localName Local part of qualified name of the node to remove
           * 
           * @return The node removed from this map if a node with such a local
           *  name and namespace URI exists
           *
           * @throws DOMException
           */
          public Node removeNamedItemNS(String namespaceURI, String localName) 
                throws DOMException
          {
                  throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                      XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR); 
                  return null;
          } 
          
          /**
           * Unimplemented. See org.w3c.dom.NamedNodeMap
           *
           * @param A node to store in this map
           * 
           * @return If the new Node replaces an existing node the replaced 
           * Node is returned, otherwise null is returned
           *
           * @throws DOMException
           */
          public Node setNamedItem(Node arg) throws DOMException
          {
                  throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                      XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR); 
                  return null;
          }
          
          /**
           * Unimplemented. See org.w3c.dom.NamedNodeMap
           *
           * @param A node to store in this map
           * 
           * @return If the new Node replaces an existing node the replaced 
           * Node is returned, otherwise null is returned
           *
           * @throws DOMException
           */
          public Node setNamedItemNS(Node arg) throws DOMException
          {
                  throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                      XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR); 
                  return null;
          }                                                                         
  }

  public class Attribute implements Attr{
          private AVT m_attribute;
          private Element m_owner = null;
          /**
           * Construct a Attr.
           *
           */
          public Attribute(AVT avt, Element elem){
                m_attribute = avt;
                m_owner = elem;
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @param newChild New node to append to the list of this node's 
           * children
           *
           *
           * @throws DOMException
           */
          public Node appendChild(Node newChild) throws DOMException
          {
                  throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                      XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR); 
                  return null;
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @param deep Flag indicating whether to clone deep 
           * (clone member variables)
           *
           * @return Returns a duplicate of this node
           */
          public Node cloneNode(boolean deep)
          {
                  return new Attribute(m_attribute, m_owner);
          }
          
          /**
           * @see org.w3c.dom.Node
           *
           * @return null
           */
          public NamedNodeMap getAttributes()
          {
            return null;
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @return a NodeList containing no nodes. 
           */
          public NodeList getChildNodes()
          {
                  return new NodeList(){
                          public int getLength(){
                                  return 0;
                          }
                          public Node item(int index){
                                  return null;
                          }
                  };
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @return null
           */
          public Node getFirstChild()
          {
                  return null;
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @return null
           */
          public Node getLastChild()
          {
                  return null;
          }
          
          /**
           * @see org.w3c.dom.Node
           *
           * @return the local part of the qualified name of this node
           */
          public String getLocalName()
          {
                  return m_attribute.getName();
          }
          
          /**
           * @see org.w3c.dom.Node
           *
           * @return The namespace URI of this node, or null if it is 
           * unspecified
           */
          public String getNamespaceURI()
          {
                  String uri = m_attribute.getURI();
                  return (uri.equals(""))?null:uri;
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @return null
           */
          public Node getNextSibling()
          {
                return null;
          }
          
          /**
           * @see org.w3c.dom.Node
           *
           * @return The name of the attribute
           */
          public String getNodeName()
          {
                  String uri = m_attribute.getURI();
                  String localName = getLocalName();
                  return (uri.equals(""))?localName:uri+":"+localName;
          }
          
          /**
           * @see org.w3c.dom.Node
           *
           * @return The node is an Attr
           */
          public short getNodeType()
          {
                  return ATTRIBUTE_NODE;
          }
          
          /**
           * @see org.w3c.dom.Node
           *
           * @return The value of the attribute
           *
           * @throws DOMException
           */
          public String getNodeValue() throws DOMException
          {
                  return m_attribute.getSimpleString();
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @return null
           */
          public Document getOwnerDocument()
          {
            return m_owner.getOwnerDocument();
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @return the containing element node
           */
          public Node getParentNode()
          {
                  return m_owner;
          }
                    
          /**
           * @see org.w3c.dom.Node
           *
           * @return The namespace prefix of this node, or null if it is 
           * unspecified
           */
          public String getPrefix()
          {
                  String uri = m_attribute.getURI();
                  String rawName = m_attribute.getRawName();
                  return (uri.equals(""))? 
                        null:rawName.substring(0, rawName.indexOf(":"));
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @return null
           */
          public Node getPreviousSibling()
          {
                  return null;
          }
          
          /**
           * @see org.w3c.dom.Node
           *
           * @return false
           */
          public boolean hasAttributes()
          {
                  return false;
          }
          
          /**
           * @see org.w3c.dom.Node
           *
           * @return false
           */
          public boolean hasChildNodes()
          {
                  return false;
          }                    

          /**
           * @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
          {
                  throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                      XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR);
                  return null;
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @return Returns <code>false</code>
           * @since DOM Level 2
           */
          public boolean isSupported(String feature, String version)
          {
            return false;
          }

          /** @see org.w3c.dom.Node */
          public void normalize(){}
          
          /**
           * @see org.w3c.dom.Node
           *
           * @param oldChild Child to be removed
           *
           * @return null
           *
           * @throws DOMException
           */
          public Node removeChild(Node oldChild) throws DOMException
          {
                  throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                      XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR); 
                  return null;
          }         

          /**
           * @see org.w3c.dom.Node
           *
           * @param newChild Replace existing child with this one
           * @param oldChild Existing child to be replaced
           *
           * @return null
           *
           * @throws DOMException
           */
          public Node replaceChild(Node newChild, Node oldChild) throws DOMException
          {
                  throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                      XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR); 
                  return null;
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @param nodeValue Value to set this node to
           *
           * @throws DOMException
           */
          public void setNodeValue(String nodeValue) throws DOMException
          {
                  throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                      XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR); 
          }

          /**
           * @see org.w3c.dom.Node
           *
           * @param prefix Prefix to set for this node
           *
           * @throws DOMException
           */
          public void setPrefix(String prefix) throws DOMException
          {
                  throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                      XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR);
          }
                                                                      
          /**
           *
           * @return The name of this attribute
           */          
          public String getName(){
                  return m_attribute.getName();                            
          }

          /**
           *
           * @return The value of this attribute returned as string
           */          
          public String getValue(){
                  return m_attribute.getSimpleString();                            
          }
          
          /**
           *
           * @return The Element node this attribute is attached to 
           * or null if this attribute is not in use
           */                    
          public Element getOwnerElement(){
                  return m_owner;
          }
          
          /**
           *
           * @return true
           */          
          public boolean getSpecified(){
                  return true;
          }
          
          /**
           * @see org.w3c.dom.Attr
           *
           * @param value Value to set this node to
           *
           * @throws DOMException
           */
          public void setValue(String value) throws DOMException
          {
            throwDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
                XSLTErrorResources.NO_MODIFICATION_ALLOWED_ERR); 
          }

 	  public TypeInfo getSchemaTypeInfo() { return null; }
    
  	  public boolean isId( ) { return false; }

  	  public Object setUserData(String key,
                                    Object data,
                                    UserDataHandler handler) {
        	return getOwnerDocument().setUserData( key, data, handler);
  	  }

  	  public Object getUserData(String key) {
        	return getOwnerDocument().getUserData( key);
  	  } 

  	  public Object getFeature(String feature, String version) {
        	return isSupported(feature, version) ? this : null;
   	  }
          
          public boolean isEqualNode(Node arg) {
          	return arg == this;
          }
          
          public String lookupNamespaceURI(String specifiedPrefix) {
             	return null;
          }
          
          public boolean isDefaultNamespace(String namespaceURI) {
            	return false;
          }

	  public String lookupPrefix(String namespaceURI) {
	    	return null;
	  }
	  
  	  public boolean isSameNode(Node other) {
        	// we do not use any wrapper so the answer is obvious
        	return this == other;
  	  }
          
  	  public void setTextContent(String textContent)
        	throws DOMException {
        	setNodeValue(textContent);
  	  }

  	  public String getTextContent() throws DOMException {
            	return getNodeValue();  // overriden in some subclasses
   	  }

    	  public short compareDocumentPosition(Node other) throws DOMException {
            	return 0;
    	  }

          public String getBaseURI() {
            	return null;
    	  }
  }        
  
  /**
   * Get an "extension-element-prefix" property.
   * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
   *
   * @param i Index of URI ("extension-element-prefix" property) to get
   *
   * @return URI at given index ("extension-element-prefix" property)
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public String getExtensionElementPrefix(int i)
          throws ArrayIndexOutOfBoundsException
  {

    if (null == m_ExtensionElementURIs)
      throw new ArrayIndexOutOfBoundsException();

    return m_ExtensionElementURIs.elementAt(i);
  }

  /**
   * Get the number of "extension-element-prefixes" Strings.
   * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
   *
   * @return the number of "extension-element-prefixes" Strings
   */
  public int getExtensionElementPrefixCount()
  {
    return (null != m_ExtensionElementURIs)
           ? m_ExtensionElementURIs.size() : 0;
  }

  /**
   * Find out if the given "extension-element-prefix" property is defined.
   * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
   *
   * @param uri The URI to find
   *
   * @return True if the given URI is found
   */
  public boolean containsExtensionElementURI(String uri)
  {

    if (null == m_ExtensionElementURIs)
      return false;

    return m_ExtensionElementURIs.contains(uri);
  }

  /**
   * Get an int constant identifying the type of element.
   * @see org.apache.xalan.templates.Constants
   *
   * @return The token ID for this element
   */
  public int getXSLToken()
  {
    return Constants.ELEMNAME_LITERALRESULT;
  }

  /**
   * Return the node name.
   *
   * @return The element's name
   */
  public String getNodeName()
  {

    // TODO: Need prefix.
    return m_rawName;
  }

  /**
   * The XSLT version as specified by this element.
   * @serial
   */
  private String m_version;

  /**
   * Set the "version" property.
   * @see <a href="http://www.w3.org/TR/xslt#forwards">forwards in XSLT Specification</a>
   *
   * @param v Version property value to set
   */
  public void setVersion(String v)
  {
    m_version = v;
  }
  
  /**
   * Get the "version" property.
   * @see <a href="http://www.w3.org/TR/xslt#forwards">forwards in XSLT Specification</a>
   *
   * @return Version property value
   */
  public String getVersion()
  {
    return m_version;
  }

  /**
   * The "exclude-result-prefixes" property.
   * @serial
   */
  private StringVector m_excludeResultPrefixes;

  /**
   * Set the "exclude-result-prefixes" property.
   * The designation of a namespace as an excluded namespace is
   * effective within the subtree of the stylesheet rooted at
   * the element bearing the exclude-result-prefixes or
   * xsl:exclude-result-prefixes attribute; a subtree rooted
   * at an xsl:stylesheet element does not include any stylesheets
   * imported or included by children of that xsl:stylesheet element.
   * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
   *
   * @param v vector of prefixes that are resolvable to strings.
   */
  public void setExcludeResultPrefixes(StringVector v)
  {
    m_excludeResultPrefixes = v;
  }

  /**
   * Tell if the result namespace decl should be excluded.  Should be called before
   * namespace aliasing (I think).
   *
   * @param prefix Prefix of namespace to check
   * @param uri URI of namespace to check
   *
   * @return True if the given namespace should be excluded
   *
   * @throws TransformerException
   */
  private boolean excludeResultNSDecl(String prefix, String uri)
          throws TransformerException
  {

    if (null != m_excludeResultPrefixes)
    {
      return containsExcludeResultPrefix(prefix, uri);
    }

    return false;
  }
  
  /**
   * Copy a Literal Result Element into the Result tree, copy the
   * non-excluded namespace attributes, copy the attributes not
   * of the XSLT namespace, and execute the children of the LRE.
   * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
   *
   * @param transformer non-null reference to the the current transform-time state.
   *
   * @throws TransformerException
   */
    public void execute(TransformerImpl transformer)
        throws TransformerException
    {
        SerializationHandler rhandler = transformer.getSerializationHandler();

        try
        {
            if (transformer.getDebug()) {
                // flush any buffered pending processing before
                // the trace event.
                rhandler.flushPending();
                transformer.getTraceManager().fireTraceEvent(this);
            }

            // JJK Bugzilla 3464, test namespace85 -- make sure LRE's
            // namespace is asserted even if default, since xsl:element
            // may have changed the context.
            rhandler.startPrefixMapping(getPrefix(), getNamespace());

            // Add namespace declarations.
            executeNSDecls(transformer);
            rhandler.startElement(getNamespace(), getLocalName(), getRawName());
        }
        catch (SAXException se)
        {
            throw new TransformerException(se);
        }

        /*
         * If we make it to here we have done a successful startElement()
         * we will do an endElement() call for balance, no matter what happens
         * in the middle.  
         */

        // tException remembers if we had an exception "in the middle"
        TransformerException tException = null;
        try
        {

            // Process any possible attributes from xsl:use-attribute-sets first
            super.execute(transformer);

            //xsl:version, excludeResultPrefixes???
            // Process the list of avts next
            if (null != m_avts)
            {
                int nAttrs = m_avts.size();

                for (int i = (nAttrs - 1); i >= 0; i--)
                {
                    AVT avt = (AVT) m_avts.elementAt(i);
                    XPathContext xctxt = transformer.getXPathContext();
                    int sourceNode = xctxt.getCurrentNode();
                    String stringedValue =
                        avt.evaluate(xctxt, sourceNode, this);

                    if (null != stringedValue)
                    {

                        // Important Note: I'm not going to check for excluded namespace 
                        // prefixes here.  It seems like it's too expensive, and I'm not 
                        // even sure this is right.  But I could be wrong, so this needs 
                        // to be tested against other implementations.

                        rhandler.addAttribute(
                            avt.getURI(),
                            avt.getName(),
                            avt.getRawName(),
                            "CDATA",
                            stringedValue, false);
                    }
                } // end for
            }

            // Now process all the elements in this subtree
            // TODO: Process m_extensionElementPrefixes && m_attributeSetsNames
            transformer.executeChildTemplates(this, true);
        }
        catch (TransformerException te)
        {
            // thrown in finally to prevent original exception consumed by subsequent exceptions
            tException = te;
        }
        catch (SAXException se)
        {
            tException = new TransformerException(se);
        }

        try
        {
            /* we need to do this endElement() to balance the
             * successful startElement() call even if 
             * there was an exception in the middle.
             * Otherwise an exception in the middle could cause a system to hang.
             */
            if (transformer.getDebug()) {
                // flush any buffered pending processing before
                // the trace event.
                //rhandler.flushPending();
                transformer.getTraceManager().fireTraceEndEvent(this);
            }
            rhandler.endElement(getNamespace(), getLocalName(), getRawName());
        }
        catch (SAXException se)
        {
            /* we did call endElement(). If thee was an exception
             * in the middle throw that one, otherwise if there
             * was an exception from endElement() throw that one.
             */
            if (tException != null)
                throw tException;
            else
                throw new TransformerException(se);
        }
        
        /* If an exception was thrown in the middle but not with startElement() or
         * or endElement() then its time to let it percolate.
         */ 
        if (tException != null)
            throw tException; 
        
        unexecuteNSDecls(transformer);

        // JJK Bugzilla 3464, test namespace85 -- balance explicit start.
        try
        {
            rhandler.endPrefixMapping(getPrefix());
        }
        catch (SAXException se)
        {
            throw new TransformerException(se);
        }
    }

  /**
   * Compiling templates requires that we be able to list the AVTs
   * ADDED 9/5/2000 to support compilation experiment
   *
   * @return an Enumeration of the literal result attributes associated
   * with this element.
   */
  public Enumeration enumerateLiteralResultAttributes()
  {
    return (null == m_avts) ? null : m_avts.elements();
  }
  
    /**
     * 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.visitLiteralResultElement(this);
    }

    /**
     * Call the children visitors.
     * @param visitor The visitor whose appropriate method will be called.
     */
    protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
    {
      if (callAttrs && null != m_avts)
      {
        int nAttrs = m_avts.size();

        for (int i = (nAttrs - 1); i >= 0; i--)
        {
          AVT avt = (AVT) m_avts.elementAt(i);
          avt.callVisitors(visitor);
        }
      }
      super.callChildVisitors(visitor, callAttrs);
    }

    /**
     * Throw a DOMException
     *
     * @param msg key of the error that occured.
     */
    public void throwDOMException(short code, String msg)
    {

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

      throw new DOMException(code, themsg);
    }

}
