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: Stylesheet.java 468643 2006-10-28 06:56:03Z minchau $
020     */
021    package org.apache.xalan.templates;
022    
023    import java.io.IOException;
024    import java.io.ObjectInputStream;
025    import java.io.ObjectOutputStream;
026    import java.util.Hashtable;
027    import java.util.Stack;
028    import java.util.Vector;
029    
030    import javax.xml.transform.SourceLocator;
031    import javax.xml.transform.TransformerException;
032    
033    import org.apache.xml.dtm.DTM;
034    import org.apache.xml.utils.QName;
035    import org.apache.xml.utils.StringVector;
036    import org.apache.xml.utils.SystemIDResolver;
037    
038    /**
039     * Represents a stylesheet element.
040     * <p>All properties in this class have a fixed form of bean-style property
041     * accessors for all properties that represent XSL attributes or elements.
042     * These properties have setter method names accessed generically by the
043     * processor, and so these names must be fixed according to the system
044     * defined in the <a href="XSLTAttributeDef#getSetterMethodName">getSetterMethodName</a>
045     * function.</p>
046     * <p><pre>
047     * <!ENTITY % top-level "
048     *  (xsl:import*,
049     *   (xsl:include
050     *   | xsl:strip-space
051     *   | xsl:preserve-space
052     *   | xsl:output
053     *   | xsl:key
054     *   | xsl:decimal-format
055     *   | xsl:attribute-set
056     *   | xsl:variable
057     *   | xsl:param
058     *   | xsl:template
059     *   | xsl:namespace-alias
060     *   %non-xsl-top-level;)*)
061     * ">
062     *
063     * <!ENTITY % top-level-atts '
064     *   extension-element-prefixes CDATA #IMPLIED
065     *   exclude-result-prefixes CDATA #IMPLIED
066     *   id ID #IMPLIED
067     *   version NMTOKEN #REQUIRED
068     *   xmlns:xsl CDATA #FIXED "http://www.w3.org/1999/XSL/Transform"
069     *   %space-att;
070     * '>
071     *
072     * <!ELEMENT xsl:stylesheet %top-level;>
073     * <!ATTLIST xsl:stylesheet %top-level-atts;>
074     *
075     * <!ELEMENT xsl:transform %top-level;>
076     * <!ATTLIST xsl:transform %top-level-atts;>
077     *
078     * </p></pre>
079     * @see <a href="http://www.w3.org/TR/xslt#section-Stylesheet-Structure">section-Stylesheet-Structure in XSLT Specification</a>
080     */
081    public class Stylesheet extends ElemTemplateElement
082            implements java.io.Serializable /* , Document */
083    {
084        static final long serialVersionUID = 2085337282743043776L;
085    
086      /**
087       * Constructor for a Stylesheet.
088       * @param parent  The including or importing stylesheet.
089       */
090      public Stylesheet(Stylesheet parent)
091      {
092    
093        if (null != parent)
094        {
095          m_stylesheetParent = parent;
096          m_stylesheetRoot = parent.getStylesheetRoot();
097        }
098      }
099    
100      /**
101       * Get the owning stylesheet.  This looks up the
102       * inheritance chain until it calls getStylesheet
103       * on a Stylesheet object, which will return itself.
104       *
105       * @return The owning stylesheet, itself.
106       */
107      public Stylesheet getStylesheet()
108      {
109        return this;
110      }
111    
112      /**
113       * Tell if this can be cast to a StylesheetComposed, meaning, you
114       * can ask questions from getXXXComposed functions.
115       *
116       * @return False if this is not a StylesheetComposed
117       */
118      public boolean isAggregatedType()
119      {
120        return false;
121      }
122    
123      /**
124       * Tell if this is the root of the stylesheet tree.
125       *
126       * @return False is this is not the root of the stylesheet tree.
127       */
128      public boolean isRoot()
129      {
130        return false;
131      }
132    
133      /**
134       * Extension to be used when serializing to disk.
135       */
136      public static final String STYLESHEET_EXT = ".lxc";
137    
138      /**
139       * Read the stylesheet from a serialization stream.
140       *
141       * @param stream Input stream to read from
142       *
143       * @throws IOException
144       * @throws TransformerException
145       */
146      private void readObject(ObjectInputStream stream)
147              throws IOException, TransformerException
148      {
149    
150        // System.out.println("Reading Stylesheet");
151        try
152        {
153          stream.defaultReadObject();
154        }
155        catch (ClassNotFoundException cnfe)
156        {
157          throw new TransformerException(cnfe);
158        }
159    
160        // System.out.println("Done reading Stylesheet");
161      }
162    
163      /**
164       * Write out the given output stream 
165       *
166       *
167       * @param stream The output stream to write out
168       *
169       * @throws IOException
170       */
171      private void writeObject(ObjectOutputStream stream) throws IOException
172      {
173    
174        // System.out.println("Writing Stylesheet");
175        stream.defaultWriteObject();
176    
177        // System.out.println("Done writing Stylesheet");
178      }
179    
180      //============== XSLT Properties =================
181    
182      /**
183       * The "xmlns:xsl" property.
184       * @serial
185       */
186      private String m_XmlnsXsl;
187    
188      /**
189       * Set the "xmlns:xsl" property.
190       * @see <a href="http://www.w3.org/TR/xslt#xslt-namespace">xslt-namespace in XSLT Specification</a>
191       *
192       * @param v The value to be set for the "xmlns:xsl" property.
193       */
194      public void setXmlnsXsl(String v)
195      {
196        m_XmlnsXsl = v;
197      }
198    
199      /**
200       * Get the "xmlns:xsl" property.
201       * @see <a href="http://www.w3.org/TR/xslt#xslt-namespace">xslt-namespace in XSLT Specification</a>
202       *
203       * @return The value of the "xmlns:xsl" property.
204       */
205      public String getXmlnsXsl()
206      {
207        return m_XmlnsXsl;
208      }
209    
210      /**
211       * The "extension-element-prefixes" property, actually contains URIs.
212       * @serial
213       */
214      private StringVector m_ExtensionElementURIs;
215    
216      /**
217       * Set the "extension-element-prefixes" property.
218       * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
219       *
220       * @param v The value to be set for the "extension-element-prefixes" 
221       * property: a vector of extension element URIs.
222       */
223      public void setExtensionElementPrefixes(StringVector v)
224      {
225        m_ExtensionElementURIs = v;
226      }
227    
228      /**
229       * Get and "extension-element-prefix" property.
230       * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
231       *
232       * @param i Index of extension element URI in list 
233       *
234       * @return The extension element URI at the given index
235       *
236       * @throws ArrayIndexOutOfBoundsException
237       */
238      public String getExtensionElementPrefix(int i)
239              throws ArrayIndexOutOfBoundsException
240      {
241    
242        if (null == m_ExtensionElementURIs)
243          throw new ArrayIndexOutOfBoundsException();
244    
245        return m_ExtensionElementURIs.elementAt(i);
246      }
247    
248      /**
249       * Get the number of "extension-element-prefixes" Strings.
250       * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
251       *
252       * @return Number of URIs in the list
253       */
254      public int getExtensionElementPrefixCount()
255      {
256        return (null != m_ExtensionElementURIs)
257               ? m_ExtensionElementURIs.size() : 0;
258      }
259    
260      /**
261       * Find out if this contains a given "extension-element-prefix" property.
262       * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
263       *
264       * @param uri URI of extension element to look for
265       *
266       * @return True if the given URI was found in the list 
267       */
268      public boolean containsExtensionElementURI(String uri)
269      {
270    
271        if (null == m_ExtensionElementURIs)
272          return false;
273    
274        return m_ExtensionElementURIs.contains(uri);
275      }
276    
277      /**
278       * The "exclude-result-prefixes" property.
279       * @serial
280       */
281      private StringVector m_ExcludeResultPrefixs;
282    
283      /**
284       * Set the "exclude-result-prefixes" property.
285       * The designation of a namespace as an excluded namespace is
286       * effective within the subtree of the stylesheet rooted at
287       * the element bearing the exclude-result-prefixes or
288       * xsl:exclude-result-prefixes attribute; a subtree rooted
289       * at an xsl:stylesheet element does not include any stylesheets
290       * imported or included by children of that xsl:stylesheet element.
291       * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
292       *
293       * @param v A StringVector of prefixes to exclude 
294       */
295      public void setExcludeResultPrefixes(StringVector v)
296      {
297        m_ExcludeResultPrefixs = v;
298      }
299    
300      /**
301       * Get an "exclude-result-prefix" property.
302       * The designation of a namespace as an excluded namespace is
303       * effective within the subtree of the stylesheet rooted at
304       * the element bearing the exclude-result-prefixes or
305       * xsl:exclude-result-prefixes attribute; a subtree rooted
306       * at an xsl:stylesheet element does not include any stylesheets
307       * imported or included by children of that xsl:stylesheet element.
308       * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
309       *
310       * @param i Index of prefix to get in list 
311       *
312       * @return Prefix to be excluded at the given index
313       *
314       * @throws ArrayIndexOutOfBoundsException
315       */
316      public String getExcludeResultPrefix(int i)
317              throws ArrayIndexOutOfBoundsException
318      {
319    
320        if (null == m_ExcludeResultPrefixs)
321          throw new ArrayIndexOutOfBoundsException();
322    
323        return m_ExcludeResultPrefixs.elementAt(i);
324      }
325    
326      /**
327       * Get the number of "exclude-result-prefixes" Strings.
328       * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
329       *
330       * @return The number of prefix strings to be excluded. 
331       */
332      public int getExcludeResultPrefixCount()
333      {
334        return (null != m_ExcludeResultPrefixs)
335               ? m_ExcludeResultPrefixs.size() : 0;
336      }
337    
338      /**
339       * Get whether or not the passed prefix is contained flagged by
340       * the "exclude-result-prefixes" property.
341       * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
342       *
343       * @param prefix non-null reference to prefix that might be excluded.
344       * @param uri reference to namespace that prefix maps to
345       *
346       * @return true if the prefix should normally be excluded.>
347       */
348      public boolean containsExcludeResultPrefix(String prefix, String uri) 
349      {
350    
351        if (null == m_ExcludeResultPrefixs || uri == null )
352          return false;
353        
354        // This loop is ok here because this code only runs during
355        // stylesheet compile time.
356        for (int i =0; i< m_ExcludeResultPrefixs.size(); i++)
357        {
358          if (uri.equals(getNamespaceForPrefix(m_ExcludeResultPrefixs.elementAt(i))))
359            return true;
360        }
361        
362        return false;
363    
364      /*  if (prefix.length() == 0)
365          prefix = Constants.ATTRVAL_DEFAULT_PREFIX;
366    
367        return m_ExcludeResultPrefixs.contains(prefix); */
368      }
369    
370      /**
371       * The "id" property.
372       * @serial
373       */
374      private String m_Id;
375    
376      /**
377       * Set the "id" property.
378       * @see <a href="http://www.w3.org/TR/xslt#section-Embedding-Stylesheets">section-Embedding-Stylesheets in XSLT Specification</a>
379       *
380       * @param v Value for the "id" property.
381       */
382      public void setId(String v)
383      {
384        m_Id = v;
385      }
386    
387      /**
388       * Get the "id" property.
389       * @see <a href="http://www.w3.org/TR/xslt#section-Embedding-Stylesheets">section-Embedding-Stylesheets in XSLT Specification</a>
390       *
391       * @return The value of the "id" property.
392       */
393      public String getId()
394      {
395        return m_Id;
396      }
397    
398      /**
399       * The "version" property.
400       * @serial
401       */
402      private String m_Version;
403      
404      /**
405       * Whether or not the stylesheet is in "Forward Compatibility Mode" 
406       * @serial
407       */
408      private boolean m_isCompatibleMode = false;
409    
410      /**
411       * Set the "version" property.
412       * @see <a href="http://www.w3.org/TR/xslt#forwards">forwards in XSLT Specification</a>
413       *
414       * @param v Value for the "version" property.
415       */
416      public void setVersion(String v)
417      {
418        m_Version = v;
419        m_isCompatibleMode = (Double.valueOf(v).doubleValue() > Constants.XSLTVERSUPPORTED);
420      }
421    
422      /**
423       * Get whether or not the stylesheet is in "Forward Compatibility Mode"
424       * 
425       * @return true if in forward compatible mode, false otherwise
426       */
427      public boolean getCompatibleMode()
428      {
429            return m_isCompatibleMode;
430      }
431    
432      /**
433       * Get the "version" property.
434       * @see <a href="http://www.w3.org/TR/xslt#forwards">forwards in XSLT Specification</a>
435       *
436       * @return The value of the "version" property.
437       */
438      public String getVersion()
439      {
440        return m_Version;
441      }
442    
443      /**
444       * The "xsl:import" list.
445       * @serial
446       */
447      private Vector m_imports;
448    
449      /**
450       * Add a stylesheet to the "import" list.
451       * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
452       *
453       * @param v Stylesheet to add to the import list
454       */
455      public void setImport(StylesheetComposed v)
456      {
457    
458        if (null == m_imports)
459          m_imports = new Vector();
460    
461        // I'm going to insert the elements in backwards order,
462        // so I can walk them 0 to n.
463        m_imports.addElement(v);
464      }
465    
466      /**
467       * Get a stylesheet from the "import" list.
468       * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
469       *
470       * @param i Index of the stylesheet to get
471       *
472       * @return The stylesheet at the given index
473       *
474       * @throws ArrayIndexOutOfBoundsException
475       */
476      public StylesheetComposed getImport(int i)
477              throws ArrayIndexOutOfBoundsException
478      {
479    
480        if (null == m_imports)
481          throw new ArrayIndexOutOfBoundsException();
482    
483        return (StylesheetComposed) m_imports.elementAt(i);
484      }
485    
486      /**
487       * Get the number of imported stylesheets.
488       * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
489       *
490       * @return the number of imported stylesheets.
491       */
492      public int getImportCount()
493      {
494        return (null != m_imports) ? m_imports.size() : 0;
495      }
496    
497      /**
498       * The "xsl:include" properties.
499       * @serial
500       */
501      private Vector m_includes;
502    
503      /**
504       * Add a stylesheet to the "include" list.
505       * @see <a href="http://www.w3.org/TR/xslt#include">include in XSLT Specification</a>
506       *
507       * @param v Stylesheet to add to the "include" list  
508       */
509      public void setInclude(Stylesheet v)
510      {
511    
512        if (null == m_includes)
513          m_includes = new Vector();
514    
515        m_includes.addElement(v);
516      }
517    
518      /**
519       * Get the stylesheet at the given in index in "include" list
520       * @see <a href="http://www.w3.org/TR/xslt#include">include in XSLT Specification</a>
521       *
522       * @param i Index of stylesheet to get
523       *
524       * @return Stylesheet at the given index
525       *
526       * @throws ArrayIndexOutOfBoundsException
527       */
528      public Stylesheet getInclude(int i) throws ArrayIndexOutOfBoundsException
529      {
530    
531        if (null == m_includes)
532          throw new ArrayIndexOutOfBoundsException();
533    
534        return (Stylesheet) m_includes.elementAt(i);
535      }
536    
537      /**
538       * Get the number of included stylesheets.
539       * @see <a href="http://www.w3.org/TR/xslt#import">import in XSLT Specification</a>
540       *
541       * @return the number of included stylesheets.
542       */
543      public int getIncludeCount()
544      {
545        return (null != m_includes) ? m_includes.size() : 0;
546      }
547    
548      /**
549       * Table of tables of element decimal-format.
550       * @see DecimalFormatProperties
551       * @serial
552       */
553      Stack m_DecimalFormatDeclarations;
554    
555      /**
556       * Process the xsl:decimal-format element.
557       *
558       * @param edf Decimal-format element to push into stack  
559       */
560      public void setDecimalFormat(DecimalFormatProperties edf)
561      {
562    
563        if (null == m_DecimalFormatDeclarations)
564          m_DecimalFormatDeclarations = new Stack();
565    
566        // Elements are pushed in by order of importance
567        // so that when recomposed, they get overiden properly.
568        m_DecimalFormatDeclarations.push(edf);
569      }
570    
571      /**
572       * Get an "xsl:decimal-format" property.
573       * 
574       * @see DecimalFormatProperties
575       * @see <a href="http://www.w3.org/TR/xslt#format-number">format-number in XSLT Specification</a>
576       *
577       * @param name The qualified name of the decimal format property.
578       * @return null if not found, otherwise a DecimalFormatProperties
579       * object, from which you can get a DecimalFormatSymbols object.
580       */
581      public DecimalFormatProperties getDecimalFormat(QName name)
582      {
583    
584        if (null == m_DecimalFormatDeclarations)
585          return null;
586    
587        int n = getDecimalFormatCount();
588    
589        for (int i = (n - 1); i >= 0; i++)
590        {
591          DecimalFormatProperties dfp = getDecimalFormat(i);
592    
593          if (dfp.getName().equals(name))
594            return dfp;
595        }
596    
597        return null;
598      }
599    
600      /**
601       * Get an "xsl:decimal-format" property.
602       * @see <a href="http://www.w3.org/TR/xslt#format-number">format-number in XSLT Specification</a>
603       * @see DecimalFormatProperties
604       *
605       * @param i Index of decimal-format property in stack
606       *
607       * @return The decimal-format property at the given index 
608       *
609       * @throws ArrayIndexOutOfBoundsException
610       */
611      public DecimalFormatProperties getDecimalFormat(int i)
612              throws ArrayIndexOutOfBoundsException
613      {
614    
615        if (null == m_DecimalFormatDeclarations)
616          throw new ArrayIndexOutOfBoundsException();
617    
618        return (DecimalFormatProperties) m_DecimalFormatDeclarations.elementAt(i);
619      }
620    
621      /**
622       * Get the number of xsl:decimal-format declarations.
623       * @see DecimalFormatProperties
624       *
625       * @return the number of xsl:decimal-format declarations.
626       */
627      public int getDecimalFormatCount()
628      {
629        return (null != m_DecimalFormatDeclarations)
630               ? m_DecimalFormatDeclarations.size() : 0;
631      }
632    
633      /**
634       * The "xsl:strip-space" properties,
635       * A lookup table of all space stripping elements.
636       * @serial
637       */
638      private Vector m_whitespaceStrippingElements;
639    
640      /**
641       * Set the "xsl:strip-space" properties.
642       * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
643       *
644       * @param wsi WhiteSpaceInfo element to add to list 
645       */
646      public void setStripSpaces(WhiteSpaceInfo wsi)
647      {
648    
649        if (null == m_whitespaceStrippingElements)
650        {
651          m_whitespaceStrippingElements = new Vector();
652        }
653    
654        m_whitespaceStrippingElements.addElement(wsi);
655      }
656    
657      /**
658       * Get an "xsl:strip-space" property.
659       * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
660       *
661       * @param i Index of WhiteSpaceInfo to get
662       *
663       * @return WhiteSpaceInfo at given index
664       *
665       * @throws ArrayIndexOutOfBoundsException
666       */
667      public WhiteSpaceInfo getStripSpace(int i) throws ArrayIndexOutOfBoundsException
668      {
669    
670        if (null == m_whitespaceStrippingElements)
671          throw new ArrayIndexOutOfBoundsException();
672    
673        return (WhiteSpaceInfo) m_whitespaceStrippingElements.elementAt(i);
674      }
675    
676      /**
677       * Get the number of "xsl:strip-space" properties.
678       * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
679       *
680       * @return the number of "xsl:strip-space" properties.
681       */
682      public int getStripSpaceCount()
683      {
684        return (null != m_whitespaceStrippingElements)
685               ? m_whitespaceStrippingElements.size() : 0;
686      }
687    
688      /**
689       * The "xsl:preserve-space" property,
690       * A lookup table of all space preserving elements.
691       * @serial
692       */
693      private Vector m_whitespacePreservingElements;
694    
695      /**
696       * Set the "xsl:preserve-space" property.
697       * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
698       *
699       * @param wsi WhiteSpaceInfo element to add to list
700       */
701      public void setPreserveSpaces(WhiteSpaceInfo wsi)
702      {
703    
704        if (null == m_whitespacePreservingElements)
705        {
706          m_whitespacePreservingElements = new Vector();
707        }
708    
709        m_whitespacePreservingElements.addElement(wsi);
710      }
711    
712      /**
713       * Get a "xsl:preserve-space" property.
714       * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
715       *
716       * @param i Index of WhiteSpaceInfo to get
717       *
718       * @return WhiteSpaceInfo at the given index
719       *
720       * @throws ArrayIndexOutOfBoundsException
721       */
722      public WhiteSpaceInfo getPreserveSpace(int i) throws ArrayIndexOutOfBoundsException
723      {
724    
725        if (null == m_whitespacePreservingElements)
726          throw new ArrayIndexOutOfBoundsException();
727    
728        return (WhiteSpaceInfo) m_whitespacePreservingElements.elementAt(i);
729      }
730    
731      /**
732       * Get the number of "xsl:preserve-space" properties.
733       * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
734       *
735       * @return the number of "xsl:preserve-space" properties.
736       */
737      public int getPreserveSpaceCount()
738      {
739        return (null != m_whitespacePreservingElements)
740               ? m_whitespacePreservingElements.size() : 0;
741      }
742    
743      /**
744       * The "xsl:output" properties.  This is a vector of OutputProperties objects.
745       * @serial
746       */
747      private Vector m_output;
748    
749      /**
750       * Set the "xsl:output" property.
751       * @see <a href="http://www.w3.org/TR/xslt#output">output in XSLT Specification</a>
752       *
753       * @param v non-null reference to the OutputProperties object to be 
754       *          added to the collection.
755       */
756      public void setOutput(OutputProperties v)
757      {
758        if (null == m_output)
759        {
760          m_output = new Vector();
761        }
762    
763        m_output.addElement(v);
764      }
765    
766      /**
767       * Get an "xsl:output" property.
768       * @see <a href="http://www.w3.org/TR/xslt#output">output in XSLT Specification</a>
769       *
770       * @param i Index of OutputFormatExtended to get
771       *
772       * @return non-null reference to an OutputProperties object.
773       *
774       * @throws ArrayIndexOutOfBoundsException
775       */
776      public OutputProperties getOutput(int i) throws ArrayIndexOutOfBoundsException
777      {
778    
779        if (null == m_output)
780          throw new ArrayIndexOutOfBoundsException();
781    
782        return (OutputProperties) m_output.elementAt(i);
783      }
784    
785      /**
786       * Get the number of "xsl:output" properties.
787       * @see <a href="http://www.w3.org/TR/xslt#output">output in XSLT Specification</a>
788       *
789       * @return The number of OutputProperties objects contained in this stylesheet.
790       */
791      public int getOutputCount()
792      {
793        return (null != m_output)
794               ? m_output.size() : 0;
795      }
796    
797      /**
798       * The "xsl:key" property.
799       * @serial
800       */
801      private Vector m_keyDeclarations;
802    
803      /**
804       * Set the "xsl:key" property.
805       * @see <a href="http://www.w3.org/TR/xslt#key">key in XSLT Specification</a>
806       *
807       * @param v KeyDeclaration element to add to the list of key declarations 
808       */
809      public void setKey(KeyDeclaration v)
810      {
811    
812        if (null == m_keyDeclarations)
813          m_keyDeclarations = new Vector();
814    
815        m_keyDeclarations.addElement(v);
816      }
817    
818      /**
819       * Get an "xsl:key" property.
820       * @see <a href="http://www.w3.org/TR/xslt#key">key in XSLT Specification</a>
821       *
822       * @param i Index of KeyDeclaration element to get
823       *
824       * @return KeyDeclaration element at given index in list 
825       *
826       * @throws ArrayIndexOutOfBoundsException
827       */
828      public KeyDeclaration getKey(int i) throws ArrayIndexOutOfBoundsException
829      {
830    
831        if (null == m_keyDeclarations)
832          throw new ArrayIndexOutOfBoundsException();
833    
834        return (KeyDeclaration) m_keyDeclarations.elementAt(i);
835      }
836    
837      /**
838       * Get the number of "xsl:key" properties.
839       * @see <a href="http://www.w3.org/TR/xslt#key">key in XSLT Specification</a>
840       *
841       * @return the number of "xsl:key" properties.
842       */
843      public int getKeyCount()
844      {
845        return (null != m_keyDeclarations) ? m_keyDeclarations.size() : 0;
846      }
847    
848      /**
849       * The "xsl:attribute-set" property.
850       * @serial
851       */
852      private Vector m_attributeSets;
853    
854      /**
855       * Set the "xsl:attribute-set" property.
856       * @see <a href="http://www.w3.org/TR/xslt#attribute-sets">attribute-sets in XSLT Specification</a>
857       *
858       * @param attrSet ElemAttributeSet to add to the list of attribute sets
859       */
860      public void setAttributeSet(ElemAttributeSet attrSet)
861      {
862    
863        if (null == m_attributeSets)
864        {
865          m_attributeSets = new Vector();
866        }
867    
868        m_attributeSets.addElement(attrSet);
869      }
870    
871      /**
872       * Get an "xsl:attribute-set" property.
873       * @see <a href="http://www.w3.org/TR/xslt#attribute-sets">attribute-sets in XSLT Specification</a>
874       *
875       * @param i Index of ElemAttributeSet to get in list
876       *
877       * @return ElemAttributeSet at the given index
878       *
879       * @throws ArrayIndexOutOfBoundsException
880       */
881      public ElemAttributeSet getAttributeSet(int i)
882              throws ArrayIndexOutOfBoundsException
883      {
884    
885        if (null == m_attributeSets)
886          throw new ArrayIndexOutOfBoundsException();
887    
888        return (ElemAttributeSet) m_attributeSets.elementAt(i);
889      }
890    
891      /**
892       * Get the number of "xsl:attribute-set" properties.
893       * @see <a href="http://www.w3.org/TR/xslt#attribute-sets">attribute-sets in XSLT Specification</a>
894       *
895       * @return the number of "xsl:attribute-set" properties.
896       */
897      public int getAttributeSetCount()
898      {
899        return (null != m_attributeSets) ? m_attributeSets.size() : 0;
900      }
901    
902      /**
903       * The "xsl:variable" and "xsl:param" properties.
904       * @serial
905       */
906      private Vector m_topLevelVariables;
907    
908      /**
909       * Set the "xsl:variable" property.
910       * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
911       *
912       * @param v ElemVariable object to add to list of top level variables
913       */
914      public void setVariable(ElemVariable v)
915      {
916    
917        if (null == m_topLevelVariables)
918          m_topLevelVariables = new Vector();
919    
920        m_topLevelVariables.addElement(v);
921      }
922      
923      /**
924       * Get an "xsl:variable" or "xsl:param" property.
925       * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
926       *
927       * @param qname non-null reference to the qualified name of the variable.
928       *
929       * @return The ElemVariable with the given name in the list or null
930       */
931      public ElemVariable getVariableOrParam(QName qname)
932      {
933    
934        if (null != m_topLevelVariables)
935        {
936          int n = getVariableOrParamCount();
937    
938          for (int i = 0; i < n; i++)
939          {
940            ElemVariable var = (ElemVariable) getVariableOrParam(i);
941    
942            if (var.getName().equals(qname))
943              return var;
944          }
945        }
946    
947        return null;
948      }
949    
950    
951      /**
952       * Get an "xsl:variable" property.
953       * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
954       *
955       * @param qname Qualified name of the xsl:variable to get 
956       *
957       * @return reference to the variable named by qname, or null if not found.
958       */
959      public ElemVariable getVariable(QName qname)
960      {
961    
962        if (null != m_topLevelVariables)
963        {
964          int n = getVariableOrParamCount();
965    
966          for (int i = 0; i < n; i++)
967          {
968            ElemVariable var = getVariableOrParam(i);
969            if((var.getXSLToken() == Constants.ELEMNAME_VARIABLE) &&
970               (var.getName().equals(qname)))
971              return var;
972          }
973        }
974    
975        return null;
976      }
977    
978      /**
979       * Get an "xsl:variable" property.
980       * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
981       *
982       * @param i Index of variable to get in the list
983       *
984       * @return ElemVariable at the given index in the list 
985       *
986       * @throws ArrayIndexOutOfBoundsException
987       */
988      public ElemVariable getVariableOrParam(int i) throws ArrayIndexOutOfBoundsException
989      {
990    
991        if (null == m_topLevelVariables)
992          throw new ArrayIndexOutOfBoundsException();
993    
994        return (ElemVariable) m_topLevelVariables.elementAt(i);
995      }
996    
997      /**
998       * Get the number of "xsl:variable" properties.
999       * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
1000       *
1001       * @return the number of "xsl:variable" properties.
1002       */
1003      public int getVariableOrParamCount()
1004      {
1005        return (null != m_topLevelVariables) ? m_topLevelVariables.size() : 0;
1006      }
1007    
1008      /**
1009       * Set an "xsl:param" property.
1010       * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
1011       *
1012       * @param v A non-null ElemParam reference.
1013       */
1014      public void setParam(ElemParam v)
1015      {
1016        setVariable(v);
1017      }
1018    
1019      /**
1020       * Get an "xsl:param" property.
1021       * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
1022       *
1023       * @param qname non-null reference to qualified name of the parameter.
1024       *
1025       * @return ElemParam with the given name in the list or null
1026       */
1027      public ElemParam getParam(QName qname)
1028      {
1029    
1030        if (null != m_topLevelVariables)
1031        {
1032          int n = getVariableOrParamCount();
1033    
1034          for (int i = 0; i < n; i++)
1035          {
1036            ElemVariable var = getVariableOrParam(i);
1037            if((var.getXSLToken() == Constants.ELEMNAME_PARAMVARIABLE) &&
1038               (var.getName().equals(qname)))
1039              return (ElemParam)var;
1040          }
1041        }
1042    
1043        return null;
1044      }
1045    
1046      /**
1047       * The "xsl:template" properties.
1048       * @serial
1049       */
1050      private Vector m_templates;
1051    
1052      /**
1053       * Set an "xsl:template" property.
1054       * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
1055       *
1056       * @param v ElemTemplate to add to list of templates
1057       */
1058      public void setTemplate(ElemTemplate v)
1059      {
1060    
1061        if (null == m_templates)
1062          m_templates = new Vector();
1063    
1064        m_templates.addElement(v);
1065        v.setStylesheet(this);
1066      }
1067    
1068      /**
1069       * Get an "xsl:template" property.
1070       * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
1071       *
1072       * @param i Index of ElemTemplate in the list to get
1073       *
1074       * @return ElemTemplate at the given index in the list
1075       *
1076       * @throws TransformerException
1077       */
1078      public ElemTemplate getTemplate(int i) throws TransformerException
1079      {
1080    
1081        if (null == m_templates)
1082          throw new ArrayIndexOutOfBoundsException();
1083    
1084        return (ElemTemplate) m_templates.elementAt(i);
1085      }
1086    
1087      /**
1088       * Get the number of "xsl:template" properties.
1089       * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
1090       *
1091       * @return the number of "xsl:template" properties.
1092       */
1093      public int getTemplateCount()
1094      {
1095        return (null != m_templates) ? m_templates.size() : 0;
1096      }
1097    
1098      /**
1099       * The "xsl:namespace-alias" properties.
1100       * @serial
1101       */
1102      private Vector m_prefix_aliases;
1103    
1104      /**
1105       * Set the "xsl:namespace-alias" property.
1106       * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
1107       *
1108       * @param na NamespaceAlias elemeent to add to the list
1109       */
1110      public void setNamespaceAlias(NamespaceAlias na)
1111      {
1112    
1113        if (m_prefix_aliases == null)
1114          m_prefix_aliases = new Vector();
1115    
1116        m_prefix_aliases.addElement(na);
1117      }
1118    
1119      /**
1120       * Get an "xsl:namespace-alias" property.
1121       * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
1122       *
1123       * @param i Index of NamespaceAlias element to get from the list 
1124       *
1125       * @return NamespaceAlias element at the given index in the list
1126       *
1127       * @throws ArrayIndexOutOfBoundsException
1128       */
1129      public NamespaceAlias getNamespaceAlias(int i)
1130              throws ArrayIndexOutOfBoundsException
1131      {
1132    
1133        if (null == m_prefix_aliases)
1134          throw new ArrayIndexOutOfBoundsException();
1135    
1136        return (NamespaceAlias) m_prefix_aliases.elementAt(i);
1137      }
1138    
1139      /**
1140       * Get the number of "xsl:namespace-alias" properties.
1141       * @see <a href="http://www.w3.org/TR/xslt#top-level-variables">top-level-variables in XSLT Specification</a>
1142       *
1143       * @return the number of "xsl:namespace-alias" properties.
1144       */
1145      public int getNamespaceAliasCount()
1146      {
1147        return (null != m_prefix_aliases) ? m_prefix_aliases.size() : 0;
1148      }
1149    
1150      /**
1151       * The "non-xsl-top-level" properties.
1152       * @serial
1153       */
1154      private Hashtable m_NonXslTopLevel;
1155    
1156      /**
1157       * Set found a non-xslt element.
1158       * @see <a href="http://www.w3.org/TR/xslt#stylesheet-element">stylesheet-element in XSLT Specification</a>
1159       *
1160       * @param name Qualified name of the element
1161       * @param obj The element object
1162       */
1163      public void setNonXslTopLevel(QName name, Object obj)
1164      {
1165    
1166        if (null == m_NonXslTopLevel)
1167          m_NonXslTopLevel = new Hashtable();
1168    
1169        m_NonXslTopLevel.put(name, obj);
1170      }
1171    
1172      /**
1173       * Get a non-xslt element.
1174       * @see <a href="http://www.w3.org/TR/xslt#stylesheet-element">stylesheet-element in XSLT Specification</a>
1175       *
1176       * @param name Qualified name of the element to get
1177       *
1178       * @return The object associate with the given name 
1179       */
1180      public Object getNonXslTopLevel(QName name)
1181      {
1182        return (null != m_NonXslTopLevel) ? m_NonXslTopLevel.get(name) : null;
1183      }
1184    
1185      // =========== End top-level XSLT properties ===========
1186    
1187      /**
1188       * The base URL of the XSL document.
1189       * @serial
1190       */
1191      private String m_href = null;
1192    
1193      /** The doctype-public element.
1194       *  @serial          */
1195      private String m_publicId;
1196    
1197      /** The doctype-system element.
1198       *  @serial          */
1199      private String m_systemId;
1200    
1201      /**
1202       * Get the base identifier with which this stylesheet is associated.
1203       *
1204       * @return the base identifier with which this stylesheet is associated.
1205       */
1206      public String getHref()
1207      {
1208        return m_href;
1209      }
1210    
1211      /**
1212       * Set the base identifier with which this stylesheet is associated.
1213       *
1214       * @param baseIdent the base identifier with which this stylesheet is associated.
1215       */
1216      public void setHref(String baseIdent)
1217      {
1218        m_href = baseIdent;
1219      }
1220    
1221      /**
1222       * Set the location information for this element.
1223       *
1224       * @param locator SourceLocator object with location information  
1225       */
1226      public void setLocaterInfo(SourceLocator locator)
1227      {
1228    
1229        if (null != locator)
1230        {
1231          m_publicId = locator.getPublicId();
1232          m_systemId = locator.getSystemId();
1233    
1234          if (null != m_systemId)
1235          {
1236            try
1237            {
1238              m_href = SystemIDResolver.getAbsoluteURI(m_systemId, null);
1239            }
1240            catch (TransformerException se)
1241            {
1242    
1243              // Ignore this for right now
1244            }
1245          }
1246    
1247          super.setLocaterInfo(locator);
1248        }
1249      }
1250    
1251      /**
1252       * The root of the stylesheet, where all the tables common
1253       * to all stylesheets are kept.
1254       * @serial
1255       */
1256      private StylesheetRoot m_stylesheetRoot;
1257    
1258      /**
1259       * Get the root of the stylesheet, where all the tables common
1260       * to all stylesheets are kept.
1261       *
1262       * @return the root of the stylesheet
1263       */
1264      public StylesheetRoot getStylesheetRoot()
1265      {
1266        return m_stylesheetRoot;
1267      }
1268    
1269      /**
1270       * Set the root of the stylesheet, where all the tables common
1271       * to all stylesheets are kept.
1272       *
1273       * @param v the root of the stylesheet
1274       */
1275      public void setStylesheetRoot(StylesheetRoot v)
1276      {
1277        m_stylesheetRoot = v;
1278      }
1279    
1280      /**
1281       * The parent of the stylesheet.  This will be null if this
1282       * is the root stylesheet.
1283       * @serial
1284       */
1285      private Stylesheet m_stylesheetParent;
1286    
1287      /**
1288       * Get the parent of the stylesheet.  This will be null if this
1289       * is the root stylesheet.
1290       *
1291       * @return the parent of the stylesheet.
1292       */
1293      public Stylesheet getStylesheetParent()
1294      {
1295        return m_stylesheetParent;
1296      }
1297    
1298      /**
1299       * Set the parent of the stylesheet.  This should be null if this
1300       * is the root stylesheet.
1301       *
1302       * @param v the parent of the stylesheet.
1303       */
1304      public void setStylesheetParent(Stylesheet v)
1305      {
1306        m_stylesheetParent = v;
1307      }
1308    
1309      /**
1310       * Get the owning aggregated stylesheet, or this
1311       * stylesheet if it is aggregated.
1312       *
1313       * @return the owning aggregated stylesheet or itself
1314       */
1315      public StylesheetComposed getStylesheetComposed()
1316      {
1317    
1318        Stylesheet sheet = this;
1319    
1320        while (!sheet.isAggregatedType())
1321        {
1322          sheet = sheet.getStylesheetParent();
1323        }
1324    
1325        return (StylesheetComposed) sheet;
1326      }
1327    
1328      /**
1329       * Get the type of the node.  We'll pretend we're a Document.
1330       *
1331       * @return the type of the node: document node.
1332       */
1333      public short getNodeType()
1334      {
1335        return DTM.DOCUMENT_NODE;
1336      }
1337    
1338      /**
1339       * Get an integer representation of the element type.
1340       *
1341       * @return An integer representation of the element, defined in the
1342       *     Constants class.
1343       * @see org.apache.xalan.templates.Constants
1344       */
1345      public int getXSLToken()
1346      {
1347        return Constants.ELEMNAME_STYLESHEET;
1348      }
1349    
1350      /**
1351       * Return the node name.
1352       *
1353       * @return The node name
1354       */
1355      public String getNodeName()
1356      {
1357        return Constants.ELEMNAME_STYLESHEET_STRING;
1358      }
1359    
1360      /**
1361       * Replace an "xsl:template" property.
1362       * This is a hook for CompilingStylesheetHandler, to allow
1363       * us to access a template, compile it, instantiate it,
1364       * and replace the original with the compiled instance.
1365       * ADDED 9/5/2000 to support compilation experiment
1366       *
1367       * @param v Compiled template to replace with
1368       * @param i Index of template to be replaced
1369       *
1370       * @throws TransformerException
1371       */
1372      public void replaceTemplate(ElemTemplate v, int i) throws TransformerException
1373      {
1374    
1375        if (null == m_templates)
1376          throw new ArrayIndexOutOfBoundsException();
1377    
1378        replaceChild(v, (ElemTemplateElement)m_templates.elementAt(i));
1379        m_templates.setElementAt(v, i);
1380        v.setStylesheet(this);
1381      }
1382      
1383        /**
1384         * Call the children visitors.
1385         * @param visitor The visitor whose appropriate method will be called.
1386         */
1387        protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
1388        {
1389          int s = getImportCount();
1390          for (int j = 0; j < s; j++)
1391          {
1392            getImport(j).callVisitors(visitor);
1393          }
1394       
1395          s = getIncludeCount();
1396          for (int j = 0; j < s; j++)
1397          {
1398            getInclude(j).callVisitors(visitor);
1399          }
1400    
1401          s = getOutputCount();
1402          for (int j = 0; j < s; j++)
1403          {
1404            visitor.visitTopLevelInstruction(getOutput(j));
1405          }
1406    
1407          // Next, add in the attribute-set elements
1408    
1409          s = getAttributeSetCount();
1410          for (int j = 0; j < s; j++)
1411          {
1412            ElemAttributeSet attrSet = getAttributeSet(j);
1413            if (visitor.visitTopLevelInstruction(attrSet))
1414            {
1415              attrSet.callChildVisitors(visitor);
1416            }
1417          }
1418          // Now the decimal-formats
1419    
1420          s = getDecimalFormatCount();
1421          for (int j = 0; j < s; j++)
1422          {
1423            visitor.visitTopLevelInstruction(getDecimalFormat(j));
1424          }
1425    
1426          // Now the keys
1427    
1428          s = getKeyCount();
1429          for (int j = 0; j < s; j++)
1430          {
1431            visitor.visitTopLevelInstruction(getKey(j));
1432          }
1433    
1434          // And the namespace aliases
1435    
1436          s = getNamespaceAliasCount();
1437          for (int j = 0; j < s; j++)
1438          {
1439            visitor.visitTopLevelInstruction(getNamespaceAlias(j));
1440          }
1441    
1442          // Next comes the templates
1443    
1444          s = getTemplateCount();
1445          for (int j = 0; j < s; j++)
1446          {
1447            try
1448            {
1449              ElemTemplate template = getTemplate(j);
1450              if (visitor.visitTopLevelInstruction(template))
1451              {
1452                template.callChildVisitors(visitor);
1453              }
1454            }
1455            catch (TransformerException te)
1456            {
1457              throw new org.apache.xml.utils.WrappedRuntimeException(te);
1458            }
1459          }
1460    
1461          // Then, the variables
1462    
1463          s = getVariableOrParamCount();
1464          for (int j = 0; j < s; j++)
1465          {
1466            ElemVariable var = getVariableOrParam(j);
1467            if (visitor.visitTopLevelVariableOrParamDecl(var))
1468            {
1469              var.callChildVisitors(visitor);
1470            }
1471          }
1472    
1473          // And lastly the whitespace preserving and stripping elements
1474    
1475          s = getStripSpaceCount();
1476          for (int j = 0; j < s; j++)
1477          {
1478            visitor.visitTopLevelInstruction(getStripSpace(j));
1479          }
1480    
1481          s = getPreserveSpaceCount();
1482          for (int j = 0; j < s; j++)
1483          {
1484            visitor.visitTopLevelInstruction(getPreserveSpace(j));
1485          }
1486          
1487          if(null != m_NonXslTopLevel)
1488          {
1489            java.util.Enumeration elements = m_NonXslTopLevel.elements();
1490            while(elements.hasMoreElements())
1491            {
1492              ElemTemplateElement elem = (ElemTemplateElement)elements.nextElement();
1493              if (visitor.visitTopLevelInstruction(elem))
1494              {
1495                elem.callChildVisitors(visitor);
1496              }
1497                    
1498            }
1499          }
1500        }
1501            
1502              
1503      /**
1504       * Accept a visitor and call the appropriate method 
1505       * for this class.
1506       * 
1507       * @param visitor The visitor whose appropriate method will be called.
1508       * @return true if the children of the object should be visited.
1509       */
1510      protected boolean accept(XSLTVisitor visitor)
1511      {
1512            return visitor.visitStylesheet(this);
1513      }
1514    
1515      
1516    }