Home | History | Annotate | Download | only in templates
      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