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 */ 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