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: Stylesheet.java 468643 2006-10-28 06:56:03Z minchau $
20 */
21package org.apache.xalan.templates;
22
23import java.io.IOException;
24import java.io.ObjectInputStream;
25import java.io.ObjectOutputStream;
26import java.util.Hashtable;
27import java.util.Stack;
28import java.util.Vector;
29
30import javax.xml.transform.SourceLocator;
31import javax.xml.transform.TransformerException;
32
33import org.apache.xml.dtm.DTM;
34import org.apache.xml.utils.QName;
35import org.apache.xml.utils.StringVector;
36import org.apache.xml.utils.SystemIDResolver;
37
38/**
39 * Represents a stylesheet element.
40 * <p>All properties in this class have a fixed form of bean-style property
41 * accessors for all properties that represent XSL attributes or elements.
42 * These properties have setter method names accessed generically by the
43 * processor, and so these names must be fixed according to the system
44 * defined in the <a href="XSLTAttributeDef#getSetterMethodName">getSetterMethodName</a>
45 * function.</p>
46 * <p><pre>
47 * <!ENTITY % top-level "
48 *  (xsl:import*,
49 *   (xsl:include
50 *   | xsl:strip-space
51 *   | xsl:preserve-space
52 *   | xsl:output
53 *   | xsl:key
54 *   | xsl:decimal-format
55 *   | xsl:attribute-set
56 *   | xsl:variable
57 *   | xsl:param
58 *   | xsl:template
59 *   | xsl:namespace-alias
60 *   %non-xsl-top-level;)*)
61 * ">
62 *
63 * <!ENTITY % top-level-atts '
64 *   extension-element-prefixes CDATA #IMPLIED
65 *   exclude-result-prefixes CDATA #IMPLIED
66 *   id ID #IMPLIED
67 *   version NMTOKEN #REQUIRED
68 *   xmlns:xsl CDATA #FIXED "http://www.w3.org/1999/XSL/Transform"
69 *   %space-att;
70 * '>
71 *
72 * <!ELEMENT xsl:stylesheet %top-level;>
73 * <!ATTLIST xsl:stylesheet %top-level-atts;>
74 *
75 * <!ELEMENT xsl:transform %top-level;>
76 * <!ATTLIST xsl:transform %top-level-atts;>
77 *
78 * </p></pre>
79 * @see <a href="http://www.w3.org/TR/xslt#section-Stylesheet-Structure">section-Stylesheet-Structure in XSLT Specification</a>
80 */
81public class Stylesheet extends ElemTemplateElement
82        implements java.io.Serializable /* , Document */
83{
84    static final long serialVersionUID = 2085337282743043776L;
85
86  /**
87   * Constructor for a Stylesheet.
88   * @param parent  The including or importing stylesheet.
89   */
90  public Stylesheet(Stylesheet parent)
91  {
92
93    if (null != parent)
94    {
95      m_stylesheetParent = parent;
96      m_stylesheetRoot = parent.getStylesheetRoot();
97    }
98  }
99
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}
1517