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  */
21 package org.apache.xalan.templates;
22 
23 import java.util.Vector;
24 
25 import 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  */
46 public 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    */
StylesheetComposed(Stylesheet parent)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    */
isAggregatedType()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    */
recompose(Vector recomposableElements)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    */
recomposeImports()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    */
getImportComposed(int i)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    */
getImportCountComposed()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    */
getEndImportCountComposed()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    */
recomposeIncludes(Stylesheet including)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    */
getIncludeComposed(int i)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    */
getIncludeCountComposed()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    */
recomposeTemplates(boolean flushFirst)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