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: ElemTemplate.java 468643 2006-10-28 06:56:03Z minchau $
20 */
21package org.apache.xalan.templates;
22
23import javax.xml.transform.SourceLocator;
24import javax.xml.transform.TransformerException;
25
26import org.apache.xalan.transformer.TransformerImpl;
27import org.apache.xml.utils.QName;
28import org.apache.xpath.XPath;
29import org.apache.xpath.XPathContext;
30
31/**
32 * Implement xsl:template.
33 * <pre>
34 * <!ELEMENT xsl:template
35 *  (#PCDATA
36 *   %instructions;
37 *   %result-elements;
38 *   | xsl:param)
39 * >
40 *
41 * <!ATTLIST xsl:template
42 *   match %pattern; #IMPLIED
43 *   name %qname; #IMPLIED
44 *   priority %priority; #IMPLIED
45 *   mode %qname; #IMPLIED
46 *   %space-att;
47 * >
48 * </pre>
49 * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
50 * @xsl.usage advanced
51 */
52public class ElemTemplate extends ElemTemplateElement
53{
54    static final long serialVersionUID = -5283056789965384058L;
55  /** The public identifier for the current document event.
56   *  @serial          */
57  private String m_publicId;
58
59  /** The system identifier for the current document event.
60   *  @serial          */
61  private String m_systemId;
62
63  /**
64   * Return the public identifier for the current document event.
65   * <p>This will be the public identifier
66   * @return A string containing the public identifier, or
67   *         null if none is available.
68   * @see #getSystemId
69   */
70  public String getPublicId()
71  {
72    return m_publicId;
73  }
74
75  /**
76   * Return the system identifier for the current document event.
77   *
78   * <p>If the system identifier is a URL, the parser must resolve it
79   * fully before passing it to the application.</p>
80   *
81   * @return A string containing the system identifier, or null
82   *         if none is available.
83   * @see #getPublicId
84   */
85  public String getSystemId()
86  {
87    return m_systemId;
88  }
89
90  /**
91   * Set the location information for this element.
92   *
93   * @param locator SourceLocator holding location information
94   */
95  public void setLocaterInfo(SourceLocator locator)
96  {
97
98    m_publicId = locator.getPublicId();
99    m_systemId = locator.getSystemId();
100
101    super.setLocaterInfo(locator);
102  }
103
104  /**
105   * The owning stylesheet.
106   * (Should this only be put on the template element, to
107   * conserve space?)
108   * @serial
109   */
110  private Stylesheet m_stylesheet;
111
112  /**
113   * Get the stylesheet composed (resolves includes and
114   * imports and has methods on it that return "composed" properties.
115   *
116   * @return The stylesheet composed.
117   */
118  public StylesheetComposed getStylesheetComposed()
119  {
120    return m_stylesheet.getStylesheetComposed();
121  }
122
123  /**
124   * Get the owning stylesheet.
125   *
126   * @return The owning stylesheet.
127   */
128  public Stylesheet getStylesheet()
129  {
130    return m_stylesheet;
131  }
132
133  /**
134   * Set the owning stylesheet.
135   *
136   * @param sheet The owning stylesheet for this element
137   */
138  public void setStylesheet(Stylesheet sheet)
139  {
140    m_stylesheet = sheet;
141  }
142
143  /**
144   * Get the root stylesheet.
145   *
146   * @return The root stylesheet for this element
147   */
148  public StylesheetRoot getStylesheetRoot()
149  {
150    return m_stylesheet.getStylesheetRoot();
151  }
152
153  /**
154   * The match attribute is a Pattern that identifies the source
155   * node or nodes to which the rule applies.
156   * @serial
157   */
158  private XPath m_matchPattern = null;
159
160  /**
161   * Set the "match" attribute.
162   * The match attribute is a Pattern that identifies the source
163   * node or nodes to which the rule applies. The match attribute
164   * is required unless the xsl:template element has a name
165   * attribute (see [6 Named Templates]). It is an error for the
166   * value of the match attribute to contain a VariableReference.
167   * @see <a href="http://www.w3.org/TR/xslt#patterns">patterns in XSLT Specification</a>
168   *
169   * @param v Value to set for the "match" attribute
170   */
171  public void setMatch(XPath v)
172  {
173    m_matchPattern = v;
174  }
175
176  /**
177   * Get the "match" attribute.
178   * The match attribute is a Pattern that identifies the source
179   * node or nodes to which the rule applies. The match attribute
180   * is required unless the xsl:template element has a name
181   * attribute (see [6 Named Templates]). It is an error for the
182   * value of the match attribute to contain a VariableReference.
183   * @see <a href="http://www.w3.org/TR/xslt#patterns">patterns in XSLT Specification</a>
184   *
185   * @return Value of the "match" attribute
186   */
187  public XPath getMatch()
188  {
189    return m_matchPattern;
190  }
191
192  /**
193   * An xsl:template element with a name attribute specifies a named template.
194   * @serial
195   */
196  private QName m_name = null;
197
198  /**
199   * Set the "name" attribute.
200   * An xsl:template element with a name attribute specifies a named template.
201   * If an xsl:template element has a name attribute, it may, but need not,
202   * also have a match attribute.
203   * @see <a href="http://www.w3.org/TR/xslt#named-templates">named-templates in XSLT Specification</a>
204   *
205   * @param v Value to set the "name" attribute
206   */
207  public void setName(QName v)
208  {
209    m_name = v;
210  }
211
212  /**
213   * Get the "name" attribute.
214   * An xsl:template element with a name attribute specifies a named template.
215   * If an xsl:template element has a name attribute, it may, but need not,
216   * also have a match attribute.
217   * @see <a href="http://www.w3.org/TR/xslt#named-templates">named-templates in XSLT Specification</a>
218   *
219   * @return Value of the "name" attribute
220   */
221  public QName getName()
222  {
223    return m_name;
224  }
225
226  /**
227   * Modes allow an element to be processed multiple times,
228   * each time producing a different result.
229   * @serial
230   */
231  private QName m_mode;
232
233  /**
234   * Set the "mode" attribute.
235   * Modes allow an element to be processed multiple times,
236   * each time producing a different result.  If xsl:template
237   * does not have a match attribute, it must not have a mode attribute.
238   * @see <a href="http://www.w3.org/TR/xslt#modes">modes in XSLT Specification</a>
239   *
240   * @param v Value to set the "mode" attribute
241   */
242  public void setMode(QName v)
243  {
244    m_mode = v;
245  }
246
247  /**
248   * Get the "mode" attribute.
249   * Modes allow an element to be processed multiple times,
250   * each time producing a different result.  If xsl:template
251   * does not have a match attribute, it must not have a mode attribute.
252   * @see <a href="http://www.w3.org/TR/xslt#modes">modes in XSLT Specification</a>
253   *
254   * @return Value of the "mode" attribute
255   */
256  public QName getMode()
257  {
258    return m_mode;
259  }
260
261  /**
262   * The priority of a template rule is specified by the priority
263   * attribute on the template rule.
264   * @serial
265   */
266  private double m_priority = XPath.MATCH_SCORE_NONE;
267
268  /**
269   * Set the "priority" attribute.
270   * The priority of a template rule is specified by the priority
271   * attribute on the template rule. The value of this must be a
272   * real number (positive or negative), matching the production
273   * Number with an optional leading minus sign (-).
274   * @see <a href="http://www.w3.org/TR/xslt#conflict">conflict in XSLT Specification</a>
275   *
276   * @param v The value to set for the "priority" attribute
277   */
278  public void setPriority(double v)
279  {
280    m_priority = v;
281  }
282
283  /**
284   * Get the "priority" attribute.
285   * The priority of a template rule is specified by the priority
286   * attribute on the template rule. The value of this must be a
287   * real number (positive or negative), matching the production
288   * Number with an optional leading minus sign (-).
289   * @see <a href="http://www.w3.org/TR/xslt#conflict">conflict in XSLT Specification</a>
290   *
291   * @return The value of the "priority" attribute
292   */
293  public double getPriority()
294  {
295    return m_priority;
296  }
297
298  /**
299   * Get an int constant identifying the type of element.
300   * @see org.apache.xalan.templates.Constants
301   *
302   * @return The token ID for the element
303   */
304  public int getXSLToken()
305  {
306    return Constants.ELEMNAME_TEMPLATE;
307  }
308
309  /**
310   * Return the node name.
311   *
312   * @return The element's name
313   */
314  public String getNodeName()
315  {
316    return Constants.ELEMNAME_TEMPLATE_STRING;
317  }
318
319  /**
320   * The stack frame size for this template, which is equal to the maximum number
321   * of params and variables that can be declared in the template at one time.
322   */
323  public int m_frameSize;
324
325  /**
326   * The size of the portion of the stack frame that can hold parameter
327   * arguments.
328   */
329  int m_inArgsSize;
330
331  /**
332   * List of namespace/local-name pairs, DTM style, that are unique
333   * qname identifiers for the arguments.  The position of a given qname
334   * in the list is the argument ID, and thus the position in the stack
335   * frame.
336   */
337  private int[] m_argsQNameIDs;
338
339  /**
340   * This function is called after everything else has been
341   * recomposed, and allows the template to set remaining
342   * values that may be based on some other property that
343   * depends on recomposition.
344   */
345  public void compose(StylesheetRoot sroot) throws TransformerException
346  {
347    super.compose(sroot);
348    StylesheetRoot.ComposeState cstate = sroot.getComposeState();
349    java.util.Vector vnames = cstate.getVariableNames();
350    if(null != m_matchPattern)
351      m_matchPattern.fixupVariables(vnames, sroot.getComposeState().getGlobalsSize());
352
353    cstate.resetStackFrameSize();
354    m_inArgsSize = 0;
355  }
356
357  /**
358   * This after the template's children have been composed.
359   */
360  public void endCompose(StylesheetRoot sroot) throws TransformerException
361  {
362    StylesheetRoot.ComposeState cstate = sroot.getComposeState();
363    super.endCompose(sroot);
364    m_frameSize = cstate.getFrameSize();
365
366    cstate.resetStackFrameSize();
367  }
368
369  /**
370   * Copy the template contents into the result tree.
371   * The content of the xsl:template element is the template
372   * that is instantiated when the template rule is applied.
373   *
374   * @param transformer non-null reference to the the current transform-time state.
375   *
376   * @throws TransformerException
377   */
378  public void execute(
379          TransformerImpl transformer)
380            throws TransformerException
381  {
382    XPathContext xctxt = transformer.getXPathContext();
383
384    xctxt.pushRTFContext();
385
386      // %REVIEW% commenting out of the code below.
387//    if (null != sourceNode)
388//    {
389      transformer.executeChildTemplates(this, true);
390//    }
391//    else  // if(null == sourceNode)
392//    {
393//      transformer.getMsgMgr().error(this,
394//        this, sourceNode,
395//        XSLTErrorResources.ER_NULL_SOURCENODE_HANDLEAPPLYTEMPLATES);
396//
397//      //"sourceNode is null in handleApplyTemplatesInstruction!");
398//    }
399
400    xctxt.popRTFContext();
401    }
402
403  /**
404   * This function is called during recomposition to
405   * control how this element is composed.
406   * @param root The root stylesheet for this transformation.
407   */
408  public void recompose(StylesheetRoot root)
409  {
410    root.recomposeTemplates(this);
411  }
412
413}
414