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    }