001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: StylesheetComposed.java 468643 2006-10-28 06:56:03Z minchau $
020 */
021 package org.apache.xalan.templates;
022
023 import java.util.Vector;
024
025 import javax.xml.transform.TransformerException;
026
027 /**
028 * Represents a stylesheet that has methods that resolve includes and
029 * imports. It has methods on it that
030 * return "composed" properties, which mean that:
031 * <ol>
032 * <li>Properties that are aggregates, like OutputProperties, will
033 * be composed of properties declared in this stylsheet and all
034 * included stylesheets.</li>
035 * <li>Properties that aren't found, will be searched for first in
036 * the includes, and, if none are located, will be searched for in
037 * the imports.</li>
038 * <li>Properties in that are not atomic on a stylesheet will
039 * have the form getXXXComposed. Some properties, like version and id,
040 * are not inherited, and so won't have getXXXComposed methods.</li>
041 * </ol>
042 * <p>In some cases getXXXComposed methods may calculate the composed
043 * values dynamically, while in other cases they may store the composed
044 * values.</p>
045 */
046 public class StylesheetComposed extends Stylesheet
047 {
048 static final long serialVersionUID = -3444072247410233923L;
049
050 /**
051 * Uses an XSL stylesheet document.
052 * @param parent The including or importing stylesheet.
053 */
054 public StylesheetComposed(Stylesheet parent)
055 {
056 super(parent);
057 }
058
059 /**
060 * Tell if this can be cast to a StylesheetComposed, meaning, you
061 * can ask questions from getXXXComposed functions.
062 *
063 * @return True since this is a StylesheetComposed
064 */
065 public boolean isAggregatedType()
066 {
067 return true;
068 }
069
070 /**
071 * Adds all recomposable values for this precedence level into the recomposableElements Vector
072 * that was passed in as the first parameter. All elements added to the
073 * recomposableElements vector should extend ElemTemplateElement.
074 * @param recomposableElements a Vector of ElemTemplateElement objects that we will add all of
075 * our recomposable objects to.
076 */
077 public void recompose(Vector recomposableElements) throws TransformerException
078 {
079
080 //recomposeImports(); // Calculate the number of this import.
081 //recomposeIncludes(this); // Build the global include list for this stylesheet.
082
083 // Now add in all of the recomposable elements at this precedence level
084
085 int n = getIncludeCountComposed();
086
087 for (int i = -1; i < n; i++)
088 {
089 Stylesheet included = getIncludeComposed(i);
090
091 // Add in the output elements
092
093 int s = included.getOutputCount();
094 for (int j = 0; j < s; j++)
095 {
096 recomposableElements.addElement(included.getOutput(j));
097 }
098
099 // 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 }