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 }