1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the  "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18/*
19 * $Id: StylesheetComposed.java 468643 2006-10-28 06:56:03Z minchau $
20 */
21package org.apache.xalan.templates;
22
23import java.util.Vector;
24
25import javax.xml.transform.TransformerException;
26
27/**
28 * Represents a stylesheet that has methods that resolve includes and
29 * imports.  It has methods on it that
30 * return "composed" properties, which mean that:
31 * <ol>
32 * <li>Properties that are aggregates, like OutputProperties, will
33 * be composed of properties declared in this stylsheet and all
34 * included stylesheets.</li>
35 * <li>Properties that aren't found, will be searched for first in
36 * the includes, and, if none are located, will be searched for in
37 * the imports.</li>
38 * <li>Properties in that are not atomic on a stylesheet will
39 * have the form getXXXComposed. Some properties, like version and id,
40 * are not inherited, and so won't have getXXXComposed methods.</li>
41 * </ol>
42 * <p>In some cases getXXXComposed methods may calculate the composed
43 * values dynamically, while in other cases they may store the composed
44 * values.</p>
45 */
46public class StylesheetComposed extends Stylesheet
47{
48    static final long serialVersionUID = -3444072247410233923L;
49
50  /**
51   * Uses an XSL stylesheet document.
52   * @param parent  The including or importing stylesheet.
53   */
54  public StylesheetComposed(Stylesheet parent)
55  {
56    super(parent);
57  }
58
59  /**
60   * Tell if this can be cast to a StylesheetComposed, meaning, you
61   * can ask questions from getXXXComposed functions.
62   *
63   * @return True since this is a StylesheetComposed
64   */
65  public boolean isAggregatedType()
66  {
67    return true;
68  }
69
70  /**
71   * Adds all recomposable values for this precedence level into the recomposableElements Vector
72   * that was passed in as the first parameter.  All elements added to the
73   * recomposableElements vector should extend ElemTemplateElement.
74   * @param recomposableElements a Vector of ElemTemplateElement objects that we will add all of
75   *        our recomposable objects to.
76   */
77  public void recompose(Vector recomposableElements) throws TransformerException
78  {
79
80    //recomposeImports();         // Calculate the number of this import.
81    //recomposeIncludes(this);    // Build the global include list for this stylesheet.
82
83    // Now add in all of the recomposable elements at this precedence level
84
85    int n = getIncludeCountComposed();
86
87    for (int i = -1; i < n; i++)
88    {
89      Stylesheet included = getIncludeComposed(i);
90
91      // Add in the output elements
92
93      int s = included.getOutputCount();
94      for (int j = 0; j < s; j++)
95      {
96        recomposableElements.addElement(included.getOutput(j));
97      }
98
99      // Next, add in the attribute-set elements
100
101      s = included.getAttributeSetCount();
102      for (int j = 0; j < s; j++)
103      {
104        recomposableElements.addElement(included.getAttributeSet(j));
105      }
106
107      // Now the decimal-formats
108
109      s = included.getDecimalFormatCount();
110      for (int j = 0; j < s; j++)
111      {
112        recomposableElements.addElement(included.getDecimalFormat(j));
113      }
114
115      // Now the keys
116
117      s = included.getKeyCount();
118      for (int j = 0; j < s; j++)
119      {
120        recomposableElements.addElement(included.getKey(j));
121      }
122
123      // And the namespace aliases
124
125      s = included.getNamespaceAliasCount();
126      for (int j = 0; j < s; j++)
127      {
128        recomposableElements.addElement(included.getNamespaceAlias(j));
129      }
130
131      // Next comes the templates
132
133      s = included.getTemplateCount();
134      for (int j = 0; j < s; j++)
135      {
136        recomposableElements.addElement(included.getTemplate(j));
137      }
138
139      // Then, the variables
140
141      s = included.getVariableOrParamCount();
142      for (int j = 0; j < s; j++)
143      {
144        recomposableElements.addElement(included.getVariableOrParam(j));
145      }
146
147      // And lastly the whitespace preserving and stripping elements
148
149      s = included.getStripSpaceCount();
150      for (int j = 0; j < s; j++)
151      {
152        recomposableElements.addElement(included.getStripSpace(j));
153      }
154
155      s = included.getPreserveSpaceCount();
156      for (int j = 0; j < s; j++)
157      {
158        recomposableElements.addElement(included.getPreserveSpace(j));
159      }
160    }
161  }
162
163  /** Order in import chain.
164   *  @serial         */
165  private int m_importNumber = -1;
166
167  /** The precedence of this stylesheet in the global import list.
168   *  The lowest precedence stylesheet is 0.  A higher
169   *  number has a higher precedence.
170   *  @serial
171   */
172  private int m_importCountComposed;
173
174  /* The count of imports composed for this stylesheet */
175  private int m_endImportCountComposed;
176
177  /**
178   * Recalculate the precedence of this stylesheet in the global
179   * import list.  The lowest precedence stylesheet is 0.  A higher
180   * number has a higher precedence.
181   */
182  void recomposeImports()
183  {
184
185    m_importNumber = getStylesheetRoot().getImportNumber(this);
186
187    StylesheetRoot root = getStylesheetRoot();
188    int globalImportCount = root.getGlobalImportCount();
189
190    m_importCountComposed = (globalImportCount - m_importNumber) - 1;
191
192    // Now get the count of composed imports from this stylesheet's imports
193    int count = getImportCount();
194    if ( count > 0)
195    {
196      m_endImportCountComposed += count;
197      while (count > 0)
198        m_endImportCountComposed += this.getImport(--count).getEndImportCountComposed();
199    }
200
201    // Now get the count of composed imports from this stylesheet's
202    // composed includes.
203    count = getIncludeCountComposed();
204    while (count>0)
205    {
206      int imports = getIncludeComposed(--count).getImportCount();
207      m_endImportCountComposed += imports;
208      while (imports > 0)
209        m_endImportCountComposed +=getIncludeComposed(count).getImport(--imports).getEndImportCountComposed();
210
211    }
212  }
213
214  /**
215   * Get a stylesheet from the "import" list.
216   * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
217   *
218   * @param i Index of stylesheet in import list
219   *
220   * @return The stylesheet at the given index
221   *
222   * @throws ArrayIndexOutOfBoundsException
223   */
224  public StylesheetComposed getImportComposed(int i)
225          throws ArrayIndexOutOfBoundsException
226  {
227
228    StylesheetRoot root = getStylesheetRoot();
229
230    // Get the stylesheet that is offset past this stylesheet.
231    // Thus, if the index of this stylesheet is 3, an argument
232    // to getImportComposed of 0 will return the 4th stylesheet
233    // in the global import list.
234    return root.getGlobalImport(1 + m_importNumber + i);
235  }
236
237  /**
238   * Get the precedence of this stylesheet in the global import list.
239   * The lowest precedence is 0.  A higher number has a higher precedence.
240   * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
241   *
242   * @return the precedence of this stylesheet in the global import list.
243   */
244  public int getImportCountComposed()
245  {
246    return m_importCountComposed;
247  }
248
249  /**
250   * Get the number of import in this stylesheet's composed list.
251   *
252   * @return the number of imports in this stylesheet's composed list.
253   */
254  public int getEndImportCountComposed()
255  {
256    return m_endImportCountComposed;
257  }
258
259
260  /**
261   * The combined list of includes.
262   * @serial
263   */
264  private transient Vector m_includesComposed;
265
266  /**
267   * Recompose the value of the composed include list.  Builds a composite
268   * list of all stylesheets included by this stylesheet to any depth.
269   *
270   * @param including Stylesheet to recompose
271   */
272  void recomposeIncludes(Stylesheet including)
273  {
274
275    int n = including.getIncludeCount();
276
277    if (n > 0)
278    {
279      if (null == m_includesComposed)
280        m_includesComposed = new Vector();
281
282      for (int i = 0; i < n; i++)
283      {
284        Stylesheet included = including.getInclude(i);
285        m_includesComposed.addElement(included);
286        recomposeIncludes(included);
287      }
288    }
289  }
290
291  /**
292   * Get an "xsl:include" property.
293   * @see <a href="http://www.w3.org/TR/xslt#include">include in XSLT Specification</a>
294   *
295   * @param i Index of stylesheet in "include" list
296   *
297   * @return The stylesheet at the given index in the "include" list
298   *
299   * @throws ArrayIndexOutOfBoundsException
300   */
301  public Stylesheet getIncludeComposed(int i)
302          throws ArrayIndexOutOfBoundsException
303  {
304
305    if (-1 == i)
306      return this;
307
308    if (null == m_includesComposed)
309      throw new ArrayIndexOutOfBoundsException();
310
311    return (Stylesheet) m_includesComposed.elementAt(i);
312  }
313
314  /**
315   * Get the number of included stylesheets.
316   * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
317   *
318   * @return the number of included stylesheets.
319   */
320  public int getIncludeCountComposed()
321  {
322    return (null != m_includesComposed) ? m_includesComposed.size() : 0;
323  }
324
325  /**
326   * For compilation support, we need the option of overwriting
327   * (rather than appending to) previous composition.
328   * We could phase out the old API in favor of this one, but I'm
329   * holding off until we've made up our minds about compilation.
330   * ADDED 9/5/2000 to support compilation experiment.
331   * NOTE: GLP 29-Nov-00 I've left this method in so that CompilingStylesheetHandler will compile.  However,
332   *                     I'm not sure why it's needed or what it does and I've commented out the body.
333   *
334   * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
335   * @param flushFirst Flag indicating the option of overwriting
336   * (rather than appending to) previous composition.
337   *
338   * @throws TransformerException
339   */
340  public void recomposeTemplates(boolean flushFirst) throws TransformerException
341  {
342/***************************************  KEEP METHOD IN FOR COMPILATION
343    if (flushFirst)
344      m_templateList = new TemplateList(this);
345
346    recomposeTemplates();
347*****************************************/
348  }
349}
350