/* * 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: *
    *
  1. Properties that are aggregates, like OutputProperties, will * be composed of properties declared in this stylsheet and all * included stylesheets.
  2. *
  3. 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.
  4. *
  5. 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.
  6. *
*

In some cases getXXXComposed methods may calculate the composed * values dynamically, while in other cases they may store the composed * values.

*/ 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 import in XSLT Specification * * @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 import in XSLT Specification * * @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 include in XSLT Specification * * @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 import in XSLT Specification * * @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 section-Defining-Template-Rules in XSLT Specification * @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(); *****************************************/ } }