blob: 231b691b8af803988a5482d2dfdb41404986e22b [file] [log] [blame]
/*
* 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();
*****************************************/
}
}