blob: 595410ec54adf8466ea1097a6902f5ddf53ba9d4 [file] [log] [blame]
/*
* 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: StylesheetComposed.java 468643 2006-10-28 06:56:03Z minchau $
*/
package org.apache.xalan.templates;
import java.util.Vector;
import javax.xml.transform.TransformerException;
/**
* 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
{
static final long serialVersionUID = -3444072247410233923L;
/**
* 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();
*****************************************/
}
}