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

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

import javax.xml.transform.TransformerConfigurationException;
import org.apache.xpath.XPath;
import org.apache.xml.utils.QName;
import org.apache.xalan.transformer.TransformerImpl;
import org.apache.xpath.XPathContext;

import org.w3c.dom.Node;
import org.w3c.dom.Element;

import javax.xml.transform.TransformerException;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;

/**
 * Represents a stylesheet that has methods that resolve includes and
 * imports.  It has methods on it that
 * return "composed" properties, which mean that:
 * <ol>
 * <li>Properties that are aggregates, like OutputProperties, will
 * be composed of properties declared in this stylsheet and all
 * included stylesheets.</li>
 * <li>Properties that aren't found, will be searched for first in
 * the includes, and, if none are located, will be searched for in
 * the imports.</li>
 * <li>Properties in that are not atomic on a stylesheet will
 * have the form getXXXComposed. Some properties, like version and id,
 * are not inherited, and so won't have getXXXComposed methods.</li>
 * </ol>
 * <p>In some cases getXXXComposed methods may calculate the composed
 * values dynamically, while in other cases they may store the composed
 * values.</p>
 */
public class StylesheetComposed extends Stylesheet
{

  /**
   * Uses an XSL stylesheet document.
   * @param parent  The including or importing stylesheet.
   */
  public StylesheetComposed(Stylesheet parent)
  {
    super(parent);
  }

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

  /**
   * Adds all recomposable values for this precedence level into the recomposableElements Vector
   * that was passed in as the first parameter.  All elements added to the
   * recomposableElements vector should extend ElemTemplateElement.
   * @param recomposableElements a Vector of ElemTemplateElement objects that we will add all of
   *        our recomposable objects to.
   */
  public void recompose(Vector recomposableElements) throws TransformerException
  {

    //recomposeImports();         // Calculate the number of this import.
    //recomposeIncludes(this);    // Build the global include list for this stylesheet.

    // Now add in all of the recomposable elements at this precedence level

    int n = getIncludeCountComposed();

    for (int i = -1; i < n; i++)
    {
      Stylesheet included = getIncludeComposed(i);

      // Add in the output elements

      int s = included.getOutputCount();
      for (int j = 0; j < s; j++)
      {
        recomposableElements.addElement(included.getOutput(j));
      }

      // Next, add in the attribute-set elements

      s = included.getAttributeSetCount();
      for (int j = 0; j < s; j++)
      {
        recomposableElements.addElement(included.getAttributeSet(j));
      }

      // Now the decimal-formats

      s = included.getDecimalFormatCount();
      for (int j = 0; j < s; j++)
      {
        recomposableElements.addElement(included.getDecimalFormat(j));
      }

      // Now the keys

      s = included.getKeyCount();
      for (int j = 0; j < s; j++)
      {
        recomposableElements.addElement(included.getKey(j));
      }

      // And the namespace aliases

      s = included.getNamespaceAliasCount();
      for (int j = 0; j < s; j++)
      {
        recomposableElements.addElement(included.getNamespaceAlias(j));
      }

      // Next comes the templates

      s = included.getTemplateCount();
      for (int j = 0; j < s; j++)
      {
        recomposableElements.addElement(included.getTemplate(j));
      }

      // Then, the variables

      s = included.getVariableOrParamCount();
      for (int j = 0; j < s; j++)
      {
        recomposableElements.addElement(included.getVariableOrParam(j));
      }

      // And lastly the whitespace preserving and stripping elements

      s = included.getStripSpaceCount();
      for (int j = 0; j < s; j++)
      {
        recomposableElements.addElement(included.getStripSpace(j));
      }

      s = included.getPreserveSpaceCount();
      for (int j = 0; j < s; j++)
      {
        recomposableElements.addElement(included.getPreserveSpace(j));
      }
    }
  }

  /** Order in import chain.
   *  @serial         */
  private int m_importNumber = -1;

  /** The precedence of this stylesheet in the global import list.
   *  The lowest precedence stylesheet is 0.  A higher
   *  number has a higher precedence.
   *  @serial
   */
  private int m_importCountComposed;
  
  /* The count of imports composed for this stylesheet */
  private int m_endImportCountComposed;

  /**
   * Recalculate the precedence of this stylesheet in the global
   * import list.  The lowest precedence stylesheet is 0.  A higher
   * number has a higher precedence.
   */
  void recomposeImports()
  {

    m_importNumber = getStylesheetRoot().getImportNumber(this);

    StylesheetRoot root = getStylesheetRoot();
    int globalImportCount = root.getGlobalImportCount();

    m_importCountComposed = (globalImportCount - m_importNumber) - 1;
    
    // Now get the count of composed imports from this stylesheet's imports
    int count = getImportCount();
    if ( count > 0)
    {
      m_endImportCountComposed += count;
      while (count > 0)
        m_endImportCountComposed += this.getImport(--count).getEndImportCountComposed();
    }
    
    // Now get the count of composed imports from this stylesheet's
    // composed includes.
    count = getIncludeCountComposed();
    while (count>0)
    {
      int imports = getIncludeComposed(--count).getImportCount();
      m_endImportCountComposed += imports;
      while (imports > 0)
        m_endImportCountComposed +=getIncludeComposed(count).getImport(--imports).getEndImportCountComposed();
     
    }                                                            
  }

  /**
   * 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 stylesheet in import list 
   *
   * @return The stylesheet at the given index
   *
   * @throws ArrayIndexOutOfBoundsException
   */
  public StylesheetComposed getImportComposed(int i)
          throws ArrayIndexOutOfBoundsException
  {

    StylesheetRoot root = getStylesheetRoot();

    // Get the stylesheet that is offset past this stylesheet.
    // Thus, if the index of this stylesheet is 3, an argument 
    // to getImportComposed of 0 will return the 4th stylesheet 
    // in the global import list.
    return root.getGlobalImport(1 + m_importNumber + i);
  }

  /**
   * Get the precedence of this stylesheet in the global import list.
   * The lowest precedence is 0.  A higher number has a higher precedence.
   * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
   *
   * @return the precedence of this stylesheet in the global import list.
   */
  public int getImportCountComposed()
  {
    return m_importCountComposed;
  }
  
  /**
   * Get the number of import in this stylesheet's composed list.
   *
   * @return the number of imports in this stylesheet's composed list.
   */
  public int getEndImportCountComposed()
  {
    return m_endImportCountComposed;
  }
  

  /**
   * The combined list of includes.
   * @serial
   */
  private transient Vector m_includesComposed;

  /**
   * Recompose the value of the composed include list.  Builds a composite
   * list of all stylesheets included by this stylesheet to any depth.
   *
   * @param including Stylesheet to recompose
   */
  void recomposeIncludes(Stylesheet including)
  {

    int n = including.getIncludeCount();

    if (n > 0)
    {
      if (null == m_includesComposed)
        m_includesComposed = new Vector();

      for (int i = 0; i < n; i++)
      {
        Stylesheet included = including.getInclude(i);
        m_includesComposed.addElement(included);
        recomposeIncludes(included);
      }
    }
  }

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

    if (-1 == i)
      return this;

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

    return (Stylesheet) m_includesComposed.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 getIncludeCountComposed()
  {
    return (null != m_includesComposed) ? m_includesComposed.size() : 0;
  }

  /**
   * For compilation support, we need the option of overwriting
   * (rather than appending to) previous composition.
   * We could phase out the old API in favor of this one, but I'm
   * holding off until we've made up our minds about compilation.
   * ADDED 9/5/2000 to support compilation experiment.
   * NOTE: GLP 29-Nov-00 I've left this method in so that CompilingStylesheetHandler will compile.  However,
   *                     I'm not sure why it's needed or what it does and I've commented out the body.
   *
   * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
   * @param flushFirst Flag indicating the option of overwriting
   * (rather than appending to) previous composition.
   *
   * @throws TransformerException
   */
  public void recomposeTemplates(boolean flushFirst) throws TransformerException
  {
/***************************************  KEEP METHOD IN FOR COMPILATION
    if (flushFirst)
      m_templateList = new TemplateList(this);

    recomposeTemplates();
*****************************************/
  }
}
