1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xalan" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, Lotus
  53. * Development Corporation., http://www.lotus.com. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package org.apache.xalan.templates;
  58. import java.util.Vector;
  59. import java.util.Hashtable;
  60. import java.util.Enumeration;
  61. import javax.xml.transform.TransformerConfigurationException;
  62. import org.apache.xpath.XPath;
  63. import org.apache.xml.utils.QName;
  64. import org.apache.xalan.transformer.TransformerImpl;
  65. import org.apache.xpath.XPathContext;
  66. import org.w3c.dom.Node;
  67. import org.w3c.dom.Element;
  68. import javax.xml.transform.TransformerException;
  69. import java.text.DecimalFormat;
  70. import java.text.DecimalFormatSymbols;
  71. /**
  72. * Represents a stylesheet that has methods that resolve includes and
  73. * imports. It has methods on it that
  74. * return "composed" properties, which mean that:
  75. * <ol>
  76. * <li>Properties that are aggregates, like OutputProperties, will
  77. * be composed of properties declared in this stylsheet and all
  78. * included stylesheets.</li>
  79. * <li>Properties that aren't found, will be searched for first in
  80. * the includes, and, if none are located, will be searched for in
  81. * the imports.</li>
  82. * <li>Properties in that are not atomic on a stylesheet will
  83. * have the form getXXXComposed. Some properties, like version and id,
  84. * are not inherited, and so won't have getXXXComposed methods.</li>
  85. * </ol>
  86. * <p>In some cases getXXXComposed methods may calculate the composed
  87. * values dynamically, while in other cases they may store the composed
  88. * values.</p>
  89. */
  90. public class StylesheetComposed extends Stylesheet
  91. {
  92. /**
  93. * Uses an XSL stylesheet document.
  94. * @param parent The including or importing stylesheet.
  95. */
  96. public StylesheetComposed(Stylesheet parent)
  97. {
  98. super(parent);
  99. }
  100. /**
  101. * Tell if this can be cast to a StylesheetComposed, meaning, you
  102. * can ask questions from getXXXComposed functions.
  103. *
  104. * @return True since this is a StylesheetComposed
  105. */
  106. public boolean isAggregatedType()
  107. {
  108. return true;
  109. }
  110. /**
  111. * Adds all recomposable values for this precedence level into the recomposableElements Vector
  112. * that was passed in as the first parameter. All elements added to the
  113. * recomposableElements vector should extend ElemTemplateElement.
  114. * @param recomposableElements a Vector of ElemTemplateElement objects that we will add all of
  115. * our recomposable objects to.
  116. */
  117. public void recompose(Vector recomposableElements) throws TransformerException
  118. {
  119. //recomposeImports(); // Calculate the number of this import.
  120. //recomposeIncludes(this); // Build the global include list for this stylesheet.
  121. // Now add in all of the recomposable elements at this precedence level
  122. int n = getIncludeCountComposed();
  123. for (int i = -1; i < n; i++)
  124. {
  125. Stylesheet included = getIncludeComposed(i);
  126. // Add in the output elements
  127. int s = included.getOutputCount();
  128. for (int j = 0; j < s; j++)
  129. {
  130. recomposableElements.addElement(included.getOutput(j));
  131. }
  132. // Next, add in the attribute-set elements
  133. s = included.getAttributeSetCount();
  134. for (int j = 0; j < s; j++)
  135. {
  136. recomposableElements.addElement(included.getAttributeSet(j));
  137. }
  138. // Now the decimal-formats
  139. s = included.getDecimalFormatCount();
  140. for (int j = 0; j < s; j++)
  141. {
  142. recomposableElements.addElement(included.getDecimalFormat(j));
  143. }
  144. // Now the keys
  145. s = included.getKeyCount();
  146. for (int j = 0; j < s; j++)
  147. {
  148. recomposableElements.addElement(included.getKey(j));
  149. }
  150. // And the namespace aliases
  151. s = included.getNamespaceAliasCount();
  152. for (int j = 0; j < s; j++)
  153. {
  154. recomposableElements.addElement(included.getNamespaceAlias(j));
  155. }
  156. // Next comes the templates
  157. s = included.getTemplateCount();
  158. for (int j = 0; j < s; j++)
  159. {
  160. recomposableElements.addElement(included.getTemplate(j));
  161. }
  162. // Then, the variables
  163. s = included.getVariableOrParamCount();
  164. for (int j = 0; j < s; j++)
  165. {
  166. recomposableElements.addElement(included.getVariableOrParam(j));
  167. }
  168. // And lastly the whitespace preserving and stripping elements
  169. s = included.getStripSpaceCount();
  170. for (int j = 0; j < s; j++)
  171. {
  172. recomposableElements.addElement(included.getStripSpace(j));
  173. }
  174. s = included.getPreserveSpaceCount();
  175. for (int j = 0; j < s; j++)
  176. {
  177. recomposableElements.addElement(included.getPreserveSpace(j));
  178. }
  179. }
  180. }
  181. /** Order in import chain.
  182. * @serial */
  183. private int m_importNumber = -1;
  184. /** The precedence of this stylesheet in the global import list.
  185. * The lowest precedence stylesheet is 0. A higher
  186. * number has a higher precedence.
  187. * @serial
  188. */
  189. private int m_importCountComposed;
  190. /* The count of imports composed for this stylesheet */
  191. private int m_endImportCountComposed;
  192. /**
  193. * Recalculate the precedence of this stylesheet in the global
  194. * import list. The lowest precedence stylesheet is 0. A higher
  195. * number has a higher precedence.
  196. */
  197. void recomposeImports()
  198. {
  199. m_importNumber = getStylesheetRoot().getImportNumber(this);
  200. StylesheetRoot root = getStylesheetRoot();
  201. int globalImportCount = root.getGlobalImportCount();
  202. m_importCountComposed = (globalImportCount - m_importNumber) - 1;
  203. // Now get the count of composed imports from this stylesheet's imports
  204. int count = getImportCount();
  205. if ( count > 0)
  206. {
  207. m_endImportCountComposed += count;
  208. while (count > 0)
  209. m_endImportCountComposed += this.getImport(--count).getEndImportCountComposed();
  210. }
  211. // Now get the count of composed imports from this stylesheet's
  212. // composed includes.
  213. count = getIncludeCountComposed();
  214. while (count>0)
  215. {
  216. int imports = getIncludeComposed(--count).getImportCount();
  217. m_endImportCountComposed += imports;
  218. while (imports > 0)
  219. m_endImportCountComposed +=getIncludeComposed(count).getImport(--imports).getEndImportCountComposed();
  220. }
  221. }
  222. /**
  223. * Get a stylesheet from the "import" list.
  224. * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
  225. *
  226. * @param i Index of stylesheet in import list
  227. *
  228. * @return The stylesheet at the given index
  229. *
  230. * @throws ArrayIndexOutOfBoundsException
  231. */
  232. public StylesheetComposed getImportComposed(int i)
  233. throws ArrayIndexOutOfBoundsException
  234. {
  235. StylesheetRoot root = getStylesheetRoot();
  236. // Get the stylesheet that is offset past this stylesheet.
  237. // Thus, if the index of this stylesheet is 3, an argument
  238. // to getImportComposed of 0 will return the 4th stylesheet
  239. // in the global import list.
  240. return root.getGlobalImport(1 + m_importNumber + i);
  241. }
  242. /**
  243. * Get the precedence of this stylesheet in the global import list.
  244. * The lowest precedence is 0. A higher number has a higher precedence.
  245. * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
  246. *
  247. * @return the precedence of this stylesheet in the global import list.
  248. */
  249. public int getImportCountComposed()
  250. {
  251. return m_importCountComposed;
  252. }
  253. /**
  254. * Get the number of import in this stylesheet's composed list.
  255. *
  256. * @return the number of imports in this stylesheet's composed list.
  257. */
  258. public int getEndImportCountComposed()
  259. {
  260. return m_endImportCountComposed;
  261. }
  262. /**
  263. * The combined list of includes.
  264. * @serial
  265. */
  266. private transient Vector m_includesComposed;
  267. /**
  268. * Recompose the value of the composed include list. Builds a composite
  269. * list of all stylesheets included by this stylesheet to any depth.
  270. *
  271. * @param including Stylesheet to recompose
  272. */
  273. void recomposeIncludes(Stylesheet including)
  274. {
  275. int n = including.getIncludeCount();
  276. if (n > 0)
  277. {
  278. if (null == m_includesComposed)
  279. m_includesComposed = new Vector();
  280. for (int i = 0; i < n; i++)
  281. {
  282. Stylesheet included = including.getInclude(i);
  283. m_includesComposed.addElement(included);
  284. recomposeIncludes(included);
  285. }
  286. }
  287. }
  288. /**
  289. * Get an "xsl:include" property.
  290. * @see <a href="http://www.w3.org/TR/xslt#include">include in XSLT Specification</a>
  291. *
  292. * @param i Index of stylesheet in "include" list
  293. *
  294. * @return The stylesheet at the given index in the "include" list
  295. *
  296. * @throws ArrayIndexOutOfBoundsException
  297. */
  298. public Stylesheet getIncludeComposed(int i)
  299. throws ArrayIndexOutOfBoundsException
  300. {
  301. if (-1 == i)
  302. return this;
  303. if (null == m_includesComposed)
  304. throw new ArrayIndexOutOfBoundsException();
  305. return (Stylesheet) m_includesComposed.elementAt(i);
  306. }
  307. /**
  308. * Get the number of included stylesheets.
  309. * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
  310. *
  311. * @return the number of included stylesheets.
  312. */
  313. public int getIncludeCountComposed()
  314. {
  315. return (null != m_includesComposed) ? m_includesComposed.size() : 0;
  316. }
  317. /**
  318. * For compilation support, we need the option of overwriting
  319. * (rather than appending to) previous composition.
  320. * We could phase out the old API in favor of this one, but I'm
  321. * holding off until we've made up our minds about compilation.
  322. * ADDED 9/5/2000 to support compilation experiment.
  323. * NOTE: GLP 29-Nov-00 I've left this method in so that CompilingStylesheetHandler will compile. However,
  324. * I'm not sure why it's needed or what it does and I've commented out the body.
  325. *
  326. * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
  327. * @param flushFirst Flag indicating the option of overwriting
  328. * (rather than appending to) previous composition.
  329. *
  330. * @throws TransformerException
  331. */
  332. public void recomposeTemplates(boolean flushFirst) throws TransformerException
  333. {
  334. /*************************************** KEEP METHOD IN FOR COMPILATION
  335. if (flushFirst)
  336. m_templateList = new TemplateList(this);
  337. recomposeTemplates();
  338. *****************************************/
  339. }
  340. }