/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 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;

// Java imports
import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

import java.text.DecimalFormatSymbols;

import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;

// Xalan imports
import org.apache.xml.utils.SystemIDResolver;
import org.apache.xml.utils.QName;
import org.apache.xml.utils.StringVector;
import org.apache.xpath.XPath;

// DOM Imports
//import org.w3c.dom.Node;
//import org.w3c.dom.Document;
import org.apache.xml.dtm.DTM;

// SAX2 Imports
import javax.xml.transform.TransformerException;
import org.xml.sax.Locator;

import javax.xml.transform.SourceLocator;

/**
 * Represents a stylesheet element.
 * <p>All properties in this class have a fixed form of bean-style property
 * accessors for all properties that represent XSL attributes or elements.
 * These properties have setter method names accessed generically by the
 * processor, and so these names must be fixed according to the system
 * defined in the <a href="XSLTAttributeDef#getSetterMethodName">getSetterMethodName</a>
 * function.</p>
 * <p><pre>
 * <!ENTITY % top-level "
 *  (xsl:import*,
 *   (xsl:include
 *   | xsl:strip-space
 *   | xsl:preserve-space
 *   | xsl:output
 *   | xsl:key
 *   | xsl:decimal-format
 *   | xsl:attribute-set
 *   | xsl:variable
 *   | xsl:param
 *   | xsl:template
 *   | xsl:namespace-alias
 *   %non-xsl-top-level;)*)
 * ">
 *
 * <!ENTITY % top-level-atts '
 *   extension-element-prefixes CDATA #IMPLIED
 *   exclude-result-prefixes CDATA #IMPLIED
 *   id ID #IMPLIED
 *   version NMTOKEN #REQUIRED
 *   xmlns:xsl CDATA #FIXED "http://www.w3.org/1999/XSL/Transform"
 *   %space-att;
 * '>
 *
 * <!ELEMENT xsl:stylesheet %top-level;>
 * <!ATTLIST xsl:stylesheet %top-level-atts;>
 *
 * <!ELEMENT xsl:transform %top-level;>
 * <!ATTLIST xsl:transform %top-level-atts;>
 *
 * </p></pre>
 * @see <a href="http://www.w3.org/TR/xslt#section-Stylesheet-Structure">section-Stylesheet-Structure in XSLT Specification</a>
 */
public class Stylesheet extends ElemTemplateElement
        implements java.io.Serializable /* , Document */
{

  /**
   * Constructor for a Stylesheet.
   * @param parent  The including or importing stylesheet.
   */
  public Stylesheet(Stylesheet parent)
  {

    if (null != parent)
    {
      m_stylesheetParent = parent;
      m_stylesheetRoot = parent.getStylesheetRoot();
    }
  }

  /**
   * 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, itself.
   */
  public Stylesheet getStylesheet()
  {
    return this;
  }

  /**
   * Tell if this can be cast to a StylesheetComposed, meaning, you
   * can ask questions from getXXXComposed functions.
   *
   * @return False if this is not a StylesheetComposed
   */
  public boolean isAggregatedType()
  {
    return false;
  }

  /**
   * Tell if this is the root of the stylesheet tree.
   *
   * @return False is this is not the root of the stylesheet tree.
   */
  public boolean isRoot()
  {
    return false;
  }

  /**
   * Extension to be used when serializing to disk.
   */
  public static final String STYLESHEET_EXT = ".lxc";

  /**
   * Read the stylesheet from a serialization stream.
   *
   * @param stream Input stream to read from
   *
   * @throws IOException
   * @throws TransformerException
   */
  private void readObject(ObjectInputStream stream)
          throws IOException, TransformerException
  {

    // System.out.println("Reading Stylesheet");
    try
    {
      stream.defaultReadObject();
    }
    catch (ClassNotFoundException cnfe)
    {
      throw new TransformerException(cnfe);
    }

    // System.out.println("Done reading Stylesheet");
  }

  /**
   * Write out the given output stream 
   *
   *
   * @param stream The output stream to write out
   *
   * @throws IOException
   */
  private void writeObject(ObjectOutputStream stream) throws IOException
  {

    // System.out.println("Writing Stylesheet");
    stream.defaultWriteObject();

    // System.out.println("Done writing Stylesheet");
  }

  //============== XSLT Properties =================

  /**
   * The "xmlns:xsl" property.
   * @serial
   */
  private String m_XmlnsXsl;

  /**
   * Set the "xmlns:xsl" property.
   * @see <a href="http://www.w3.org/TR/xslt#xslt-namespace">xslt-namespace in XSLT Specification</a>
   *
   * @param v The value to be set for the "xmlns:xsl" property.
   */
  public void setXmlnsXsl(String v)
  {
    m_XmlnsXsl = v;
  }

  /**
   * Get the "xmlns:xsl" property.
   * @see <a href="http://www.w3.org/TR/xslt#xslt-namespace">xslt-namespace in XSLT Specification</a>
   *
   * @return The value of the "xmlns:xsl" property.
   */
  public String getXmlnsXsl()
  {
    return m_XmlnsXsl;
  }

  /**
   * 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 The value to be set for the "extension-element-prefixes" 
   * property: a vector of extension element URIs.
   */
  public void setExtensionElementPrefixes(StringVector v)
  {
    m_ExtensionElementURIs = v;
  }

  /**
   * Get and "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 extension element URI in list 
   *
   * @return The extension element URI at the given index
   *
   * @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 Number of URIs in the list
   */
  public int getExtensionElementPrefixCount()
  {
    return (null != m_ExtensionElementURIs)
           ? m_ExtensionElementURIs.size() : 0;
  }

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

    if (null == m_ExtensionElementURIs)
      return false;

    return m_ExtensionElementURIs.contains(uri);
  }

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

  /**
   * 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 A StringVector of prefixes to exclude 
   */
  public void setExcludeResultPrefixes(StringVector v)
  {
    m_ExcludeResultPrefixs = v;
  }

  /**
   * Get an "exclude-result-prefix" 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 i Index of prefix to get in list 
   *
   * @return Prefix to be excluded at the given index
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public String getExcludeResultPrefix(int i)
          throws ArrayIndexOutOfBoundsException
  {

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

    return m_ExcludeResultPrefixs.elementAt(i);
  }

  /**
   * Get the number of "exclude-result-prefixes" Strings.
   * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
   *
   * @return The number of prefix strings to be excluded. 
   */
  public int getExcludeResultPrefixCount()
  {
    return (null != m_ExcludeResultPrefixs)
           ? m_ExcludeResultPrefixs.size() : 0;
  }

  /**
   * Get whether or not the passed prefix is contained flagged by
   * the "exclude-result-prefixes" property.
   * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-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)
  {

    if (null == m_ExcludeResultPrefixs)
      return false;

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

    return m_ExcludeResultPrefixs.contains(prefix);
  }

  /**
   * The "id" property.
   * @serial
   */
  private String m_Id;

  /**
   * Set the "id" property.
   * @see <a href="http://www.w3.org/TR/xslt#section-Embedding-Stylesheets">section-Embedding-Stylesheets in XSLT Specification</a>
   *
   * @param v Value for the "id" property.
   */
  public void setId(String v)
  {
    m_Id = v;
  }

  /**
   * Get the "id" property.
   * @see <a href="http://www.w3.org/TR/xslt#section-Embedding-Stylesheets">section-Embedding-Stylesheets in XSLT Specification</a>
   *
   * @return The value of the "id" property.
   */
  public String getId()
  {
    return m_Id;
  }

  /**
   * The "version" property.
   * @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 Value for the "version" property.
   */
  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 The value of the "version" property.
   */
  public String getVersion()
  {
    return m_Version;
  }

  /**
   * The "xsl:import" list.
   * @serial
   */
  private Vector m_imports;

  /**
   * Add a stylesheet to the "import" list.
   * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
   *
   * @param v Stylesheet to add to the import list
   */
  public void setImport(StylesheetComposed v)
  {

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

    // I'm going to insert the elements in backwards order,
    // so I can walk them 0 to n.
    m_imports.addElement(v);
  }

  /**
   * Get a stylesheet from the "import" list.
   * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
   *
   * @param i Index of the stylesheet to get
   *
   * @return The stylesheet at the given index
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public StylesheetComposed getImport(int i)
          throws ArrayIndexOutOfBoundsException
  {

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

    return (StylesheetComposed) m_imports.elementAt(i);
  }

  /**
   * Get the number of imported stylesheets.
   * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
   *
   * @return the number of imported stylesheets.
   */
  public int getImportCount()
  {
    return (null != m_imports) ? m_imports.size() : 0;
  }

  /**
   * The "xsl:include" properties.
   * @serial
   */
  private Vector m_includes;

  /**
   * Add a stylesheet to the "include" list.
   * @see <a href="http://www.w3.org/TR/xslt#include">include in XSLT Specification</a>
   *
   * @param v Stylesheet to add to the "include" list  
   */
  public void setInclude(Stylesheet v)
  {

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

    m_includes.addElement(v);
  }

  /**
   * Get the stylesheet at the given in index in "include" list
   * @see <a href="http://www.w3.org/TR/xslt#include">include in XSLT Specification</a>
   *
   * @param i Index of stylesheet to get
   *
   * @return Stylesheet at the given index
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public Stylesheet getInclude(int i) throws ArrayIndexOutOfBoundsException
  {

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

    return (Stylesheet) m_includes.elementAt(i);
  }

  /**
   * Get the number of included stylesheets.
   * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
   *
   * @return the number of included stylesheets.
   */
  public int getIncludeCount()
  {
    return (null != m_includes) ? m_includes.size() : 0;
  }

  /**
   * Table of tables of element decimal-format.
   * @see DecimalFormatProperties
   * @serial
   */
  Stack m_DecimalFormatDeclarations;

  /**
   * Process the xsl:decimal-format element.
   *
   * @param edf Decimal-format element to push into stack  
   */
  public void setDecimalFormat(DecimalFormatProperties edf)
  {

    if (null == m_DecimalFormatDeclarations)
      m_DecimalFormatDeclarations = new Stack();

    // Elements are pushed in by order of importance
    // so that when recomposed, they get overiden properly.
    m_DecimalFormatDeclarations.push(edf);
  }

  /**
   * Get an "xsl:decimal-format" property.
   * 
   * @see DecimalFormatProperties
   * @see <a href="http://www.w3.org/TR/xslt#format-number">format-number in XSLT Specification</a>
   *
   * @param name The qualified name of the decimal format property.
   * @return null if not found, otherwise a DecimalFormatProperties
   * object, from which you can get a DecimalFormatSymbols object.
   */
  public DecimalFormatProperties getDecimalFormat(QName name)
  {

    if (null == m_DecimalFormatDeclarations)
      return null;

    int n = getDecimalFormatCount();

    for (int i = (n - 1); i >= 0; i++)
    {
      DecimalFormatProperties dfp = getDecimalFormat(i);

      if (dfp.getName().equals(name))
        return dfp;
    }

    return null;
  }

  /**
   * Get an "xsl:decimal-format" property.
   * @see <a href="http://www.w3.org/TR/xslt#format-number">format-number in XSLT Specification</a>
   * @see DecimalFormatProperties
   *
   * @param i Index of decimal-format property in stack
   *
   * @return The decimal-format property at the given index 
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public DecimalFormatProperties getDecimalFormat(int i)
          throws ArrayIndexOutOfBoundsException
  {

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

    return (DecimalFormatProperties) m_DecimalFormatDeclarations.elementAt(i);
  }

  /**
   * Get the number of xsl:decimal-format declarations.
   * @see DecimalFormatProperties
   *
   * @return the number of xsl:decimal-format declarations.
   */
  public int getDecimalFormatCount()
  {
    return (null != m_DecimalFormatDeclarations)
           ? m_DecimalFormatDeclarations.size() : 0;
  }

  /**
   * The "xsl:strip-space" properties,
   * A lookup table of all space stripping elements.
   * @serial
   */
  private Vector m_whitespaceStrippingElements;

  /**
   * Set the "xsl:strip-space" properties.
   * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
   *
   * @param wsi WhiteSpaceInfo element to add to list 
   */
  public void setStripSpaces(WhiteSpaceInfo wsi)
  {

    if (null == m_whitespaceStrippingElements)
    {
      m_whitespaceStrippingElements = new Vector();
    }

    m_whitespaceStrippingElements.addElement(wsi);
  }

  /**
   * Get an "xsl:strip-space" property.
   * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
   *
   * @param i Index of WhiteSpaceInfo to get
   *
   * @return WhiteSpaceInfo at given index
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public WhiteSpaceInfo getStripSpace(int i) throws ArrayIndexOutOfBoundsException
  {

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

    return (WhiteSpaceInfo) m_whitespaceStrippingElements.elementAt(i);
  }

  /**
   * Get the number of "xsl:strip-space" properties.
   * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
   *
   * @return the number of "xsl:strip-space" properties.
   */
  public int getStripSpaceCount()
  {
    return (null != m_whitespaceStrippingElements)
           ? m_whitespaceStrippingElements.size() : 0;
  }

  /**
   * The "xsl:preserve-space" property,
   * A lookup table of all space preserving elements.
   * @serial
   */
  private Vector m_whitespacePreservingElements;

  /**
   * Set the "xsl:preserve-space" property.
   * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
   *
   * @param wsi WhiteSpaceInfo element to add to list
   */
  public void setPreserveSpaces(WhiteSpaceInfo wsi)
  {

    if (null == m_whitespacePreservingElements)
    {
      m_whitespacePreservingElements = new Vector();
    }

    m_whitespacePreservingElements.addElement(wsi);
  }

  /**
   * Get a "xsl:preserve-space" property.
   * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
   *
   * @param i Index of WhiteSpaceInfo to get
   *
   * @return WhiteSpaceInfo at the given index
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public WhiteSpaceInfo getPreserveSpace(int i) throws ArrayIndexOutOfBoundsException
  {

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

    return (WhiteSpaceInfo) m_whitespacePreservingElements.elementAt(i);
  }

  /**
   * Get the number of "xsl:preserve-space" properties.
   * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
   *
   * @return the number of "xsl:preserve-space" properties.
   */
  public int getPreserveSpaceCount()
  {
    return (null != m_whitespacePreservingElements)
           ? m_whitespacePreservingElements.size() : 0;
  }

  /**
   * The "xsl:output" properties.  This is a vector of OutputProperties objects.
   * @serial
   */
  private Vector m_output;

  /**
   * Set the "xsl:output" property.
   * @see <a href="http://www.w3.org/TR/xslt#output">output in XSLT Specification</a>
   *
   * @param v non-null reference to the OutputProperties object to be 
   *          added to the collection.
   */
  public void setOutput(OutputProperties v)
  {
    if (null == m_output)
    {
      m_output = new Vector();
    }

    m_output.addElement(v);
  }

  /**
   * Get an "xsl:output" property.
   * @see <a href="http://www.w3.org/TR/xslt#output">output in XSLT Specification</a>
   *
   * @param i Index of OutputFormatExtended to get
   *
   * @return non-null reference to an OutputProperties object.
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public OutputProperties getOutput(int i) throws ArrayIndexOutOfBoundsException
  {

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

    return (OutputProperties) m_output.elementAt(i);
  }

  /**
   * Get the number of "xsl:output" properties.
   * @see <a href="http://www.w3.org/TR/xslt#output">output in XSLT Specification</a>
   *
   * @return The number of OutputProperties objects contained in this stylesheet.
   */
  public int getOutputCount()
  {
    return (null != m_output)
           ? m_output.size() : 0;
  }

  /**
   * The "xsl:key" property.
   * @serial
   */
  private Vector m_keyDeclarations;

  /**
   * Set the "xsl:key" property.
   * @see <a href="http://www.w3.org/TR/xslt#key">key in XSLT Specification</a>
   *
   * @param v KeyDeclaration element to add to the list of key declarations 
   */
  public void setKey(KeyDeclaration v)
  {

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

    m_keyDeclarations.addElement(v);
  }

  /**
   * Get an "xsl:key" property.
   * @see <a href="http://www.w3.org/TR/xslt#key">key in XSLT Specification</a>
   *
   * @param i Index of KeyDeclaration element to get
   *
   * @return KeyDeclaration element at given index in list 
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public KeyDeclaration getKey(int i) throws ArrayIndexOutOfBoundsException
  {

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

    return (KeyDeclaration) m_keyDeclarations.elementAt(i);
  }

  /**
   * Get the number of "xsl:key" properties.
   * @see <a href="http://www.w3.org/TR/xslt#key">key in XSLT Specification</a>
   *
   * @return the number of "xsl:key" properties.
   */
  public int getKeyCount()
  {
    return (null != m_keyDeclarations) ? m_keyDeclarations.size() : 0;
  }

  /**
   * The "xsl:attribute-set" property.
   * @serial
   */
  private Vector m_attributeSets;

  /**
   * Set the "xsl:attribute-set" property.
   * @see <a href="http://www.w3.org/TR/xslt#attribute-sets">attribute-sets in XSLT Specification</a>
   *
   * @param attrSet ElemAttributeSet to add to the list of attribute sets
   */
  public void setAttributeSet(ElemAttributeSet attrSet)
  {

    if (null == m_attributeSets)
    {
      m_attributeSets = new Vector();
    }

    m_attributeSets.addElement(attrSet);
  }

  /**
   * Get an "xsl:attribute-set" property.
   * @see <a href="http://www.w3.org/TR/xslt#attribute-sets">attribute-sets in XSLT Specification</a>
   *
   * @param i Index of ElemAttributeSet to get in list
   *
   * @return ElemAttributeSet at the given index
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public ElemAttributeSet getAttributeSet(int i)
          throws ArrayIndexOutOfBoundsException
  {

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

    return (ElemAttributeSet) m_attributeSets.elementAt(i);
  }

  /**
   * Get the number of "xsl:attribute-set" properties.
   * @see <a href="http://www.w3.org/TR/xslt#attribute-sets">attribute-sets in XSLT Specification</a>
   *
   * @return the number of "xsl:attribute-set" properties.
   */
  public int getAttributeSetCount()
  {
    return (null != m_attributeSets) ? m_attributeSets.size() : 0;
  }

  /**
   * The "xsl:variable" and "xsl:param" properties.
   * @serial
   */
  private Vector m_topLevelVariables;

  /**
   * Set the "xsl:variable" property.
   * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
   *
   * @param v ElemVariable object to add to list of top level variables
   */
  public void setVariable(ElemVariable v)
  {

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

    m_topLevelVariables.addElement(v);
  }
  
  /**
   * Get an "xsl:variable" or "xsl:param" property.
   * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
   *
   * @param qname non-null reference to the qualified name of the variable.
   *
   * @return The ElemVariable with the given name in the list or null
   */
  public ElemVariable getVariableOrParam(QName qname)
  {

    if (null != m_topLevelVariables)
    {
      int n = getVariableOrParamCount();

      for (int i = 0; i < n; i++)
      {
        ElemVariable var = (ElemVariable) getVariableOrParam(i);

        if (var.getName().equals(qname))
          return var;
      }
    }

    return null;
  }


  /**
   * Get an "xsl:variable" property.
   * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
   *
   * @param qname Qualified name of the xsl:variable to get 
   *
   * @return reference to the variable named by qname, or null if not found.
   */
  public ElemVariable getVariable(QName qname)
  {

    if (null != m_topLevelVariables)
    {
      int n = getVariableOrParamCount();

      for (int i = 0; i < n; i++)
      {
        ElemVariable var = getVariableOrParam(i);
        if((var.getXSLToken() == Constants.ELEMNAME_VARIABLE) &&
           (var.getName().equals(qname)))
          return var;
      }
    }

    return null;
  }

  /**
   * Get an "xsl:variable" property.
   * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
   *
   * @param i Index of variable to get in the list
   *
   * @return ElemVariable at the given index in the list 
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public ElemVariable getVariableOrParam(int i) throws ArrayIndexOutOfBoundsException
  {

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

    return (ElemVariable) m_topLevelVariables.elementAt(i);
  }

  /**
   * Get the number of "xsl:variable" properties.
   * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
   *
   * @return the number of "xsl:variable" properties.
   */
  public int getVariableOrParamCount()
  {
    return (null != m_topLevelVariables) ? m_topLevelVariables.size() : 0;
  }

  /**
   * Set an "xsl:param" property.
   * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
   *
   * @param v A non-null ElemParam reference.
   */
  public void setParam(ElemParam v)
  {
    setVariable(v);
  }

  /**
   * Get an "xsl:param" property.
   * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
   *
   * @param qname non-null reference to qualified name of the parameter.
   *
   * @return ElemParam with the given name in the list or null
   */
  public ElemParam getParam(QName qname)
  {

    if (null != m_topLevelVariables)
    {
      int n = getVariableOrParamCount();

      for (int i = 0; i < n; i++)
      {
        ElemVariable var = getVariableOrParam(i);
        if((var.getXSLToken() == Constants.ELEMNAME_PARAMVARIABLE) &&
           (var.getName().equals(qname)))
          return (ElemParam)var;
      }
    }

    return null;
  }

  /**
   * The "xsl:template" properties.
   * @serial
   */
  private Vector m_templates;

  /**
   * Set an "xsl:template" property.
   * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
   *
   * @param v ElemTemplate to add to list of templates
   */
  public void setTemplate(ElemTemplate v)
  {

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

    m_templates.addElement(v);
    v.setStylesheet(this);
  }

  /**
   * Get an "xsl:template" property.
   * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
   *
   * @param i Index of ElemTemplate in the list to get
   *
   * @return ElemTemplate at the given index in the list
   *
   * @throws TransformerException
   */
  public ElemTemplate getTemplate(int i) throws TransformerException
  {

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

    return (ElemTemplate) m_templates.elementAt(i);
  }

  /**
   * Get the number of "xsl:template" properties.
   * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
   *
   * @return the number of "xsl:template" properties.
   */
  public int getTemplateCount()
  {
    return (null != m_templates) ? m_templates.size() : 0;
  }

  /**
   * The "xsl:namespace-alias" properties.
   * @serial
   */
  private Vector m_prefix_aliases;

  /**
   * Set the "xsl:namespace-alias" property.
   * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
   *
   * @param na NamespaceAlias elemeent to add to the list
   */
  public void setNamespaceAlias(NamespaceAlias na)
  {

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

    m_prefix_aliases.addElement(na);
  }

  /**
   * Get an "xsl:namespace-alias" property.
   * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
   *
   * @param i Index of NamespaceAlias element to get from the list 
   *
   * @return NamespaceAlias element at the given index in the list
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public NamespaceAlias getNamespaceAlias(int i)
          throws ArrayIndexOutOfBoundsException
  {

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

    return (NamespaceAlias) m_prefix_aliases.elementAt(i);
  }

  /**
   * Get the number of "xsl:namespace-alias" properties.
   * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
   *
   * @return the number of "xsl:namespace-alias" properties.
   */
  public int getNamespaceAliasCount()
  {
    return (null != m_prefix_aliases) ? m_prefix_aliases.size() : 0;
  }

  /**
   * The "non-xsl-top-level" properties.
   * @serial
   */
  private Hashtable m_NonXslTopLevel;

  /**
   * Set found a non-xslt element.
   * @see <a href="http://www.w3.org/TR/xslt#stylesheet-element">stylesheet-element in XSLT Specification</a>
   *
   * @param name Qualified name of the element
   * @param obj The element object
   */
  public void setNonXslTopLevel(QName name, Object obj)
  {

    if (null == m_NonXslTopLevel)
      m_NonXslTopLevel = new Hashtable();

    m_NonXslTopLevel.put(name, obj);
  }

  /**
   * Get a non-xslt element.
   * @see <a href="http://www.w3.org/TR/xslt#stylesheet-element">stylesheet-element in XSLT Specification</a>
   *
   * @param name Qualified name of the element to get
   *
   * @return The object associate with the given name 
   */
  public Object getNonXslTopLevel(QName name)
  {
    return (null != m_NonXslTopLevel) ? m_NonXslTopLevel.get(name) : null;
  }

  // =========== End top-level XSLT properties ===========

  /**
   * The base URL of the XSL document.
   * @serial
   */
  private String m_href = null;

  /** The doctype-public element.
   *  @serial          */
  private String m_publicId;

  /** The doctype-system element.
   *  @serial          */
  private String m_systemId;

  /**
   * Get the base identifier with which this stylesheet is associated.
   *
   * @return the base identifier with which this stylesheet is associated.
   */
  public String getHref()
  {
    return m_href;
  }

  /**
   * Set the base identifier with which this stylesheet is associated.
   *
   * @param baseIdent the base identifier with which this stylesheet is associated.
   */
  public void setHref(String baseIdent)
  {
    m_href = baseIdent;
  }

  /**
   * Set the location information for this element.
   *
   * @param locator SourceLocator object with location information  
   */
  public void setLocaterInfo(SourceLocator locator)
  {

    if (null != locator)
    {
      m_publicId = locator.getPublicId();
      m_systemId = locator.getSystemId();

      if (null != m_systemId)
      {
        try
        {
          m_href = SystemIDResolver.getAbsoluteURI(m_systemId, null);
        }
        catch (TransformerException se)
        {

          // Ignore this for right now
        }
      }

      super.setLocaterInfo(locator);
    }
  }

  /**
   * The root of the stylesheet, where all the tables common
   * to all stylesheets are kept.
   * @serial
   */
  private StylesheetRoot m_stylesheetRoot;

  /**
   * Get the root of the stylesheet, where all the tables common
   * to all stylesheets are kept.
   *
   * @return the root of the stylesheet
   */
  public StylesheetRoot getStylesheetRoot()
  {
    return m_stylesheetRoot;
  }

  /**
   * Set the root of the stylesheet, where all the tables common
   * to all stylesheets are kept.
   *
   * @param v the root of the stylesheet
   */
  public void setStylesheetRoot(StylesheetRoot v)
  {
    m_stylesheetRoot = v;
  }

  /**
   * The parent of the stylesheet.  This will be null if this
   * is the root stylesheet.
   * @serial
   */
  private Stylesheet m_stylesheetParent;

  /**
   * Get the parent of the stylesheet.  This will be null if this
   * is the root stylesheet.
   *
   * @return the parent of the stylesheet.
   */
  public Stylesheet getStylesheetParent()
  {
    return m_stylesheetParent;
  }

  /**
   * Set the parent of the stylesheet.  This should be null if this
   * is the root stylesheet.
   *
   * @param v the parent of the stylesheet.
   */
  public void setStylesheetParent(Stylesheet v)
  {
    m_stylesheetParent = v;
  }

  /**
   * Get the owning aggregated stylesheet, or this
   * stylesheet if it is aggregated.
   *
   * @return the owning aggregated stylesheet or itself
   */
  public StylesheetComposed getStylesheetComposed()
  {

    Stylesheet sheet = this;

    while (!sheet.isAggregatedType())
    {
      sheet = sheet.getStylesheetParent();
    }

    return (StylesheetComposed) sheet;
  }

  /**
   * Get the type of the node.  We'll pretend we're a Document.
   *
   * @return the type of the node: document node.
   */
  public short getNodeType()
  {
    return DTM.DOCUMENT_NODE;
  }

  /**
   * 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_STYLESHEET;
  }

  /**
   * Return the node name.
   *
   * @return The node name
   */
  public String getNodeName()
  {
    return Constants.ELEMNAME_STYLESHEET_STRING;
  }

  /**
   * Replace an "xsl:template" property.
   * This is a hook for CompilingStylesheetHandler, to allow
   * us to access a template, compile it, instantiate it,
   * and replace the original with the compiled instance.
   * ADDED 9/5/2000 to support compilation experiment
   *
   * @param v Compiled template to replace with
   * @param i Index of template to be replaced
   *
   * @throws TransformerException
   */
  public void replaceTemplate(ElemTemplate v, int i) throws TransformerException
  {

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

    replaceChild(v, (ElemTemplateElement)m_templates.elementAt(i));
    m_templates.setElementAt(v, i);
    v.setStylesheet(this);
  }
  
}
