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: ElemTemplate.java 468643 2006-10-28 06:56:03Z minchau $
020     */
021    package org.apache.xalan.templates;
022    
023    import javax.xml.transform.SourceLocator;
024    import javax.xml.transform.TransformerException;
025    
026    import org.apache.xalan.transformer.TransformerImpl;
027    import org.apache.xml.utils.QName;
028    import org.apache.xpath.XPath;
029    import org.apache.xpath.XPathContext;
030    
031    /**
032     * Implement xsl:template.
033     * <pre>
034     * <!ELEMENT xsl:template
035     *  (#PCDATA
036     *   %instructions;
037     *   %result-elements;
038     *   | xsl:param)
039     * >
040     *
041     * <!ATTLIST xsl:template
042     *   match %pattern; #IMPLIED
043     *   name %qname; #IMPLIED
044     *   priority %priority; #IMPLIED
045     *   mode %qname; #IMPLIED
046     *   %space-att;
047     * >
048     * </pre>
049     * @see <a href="http://www.w3.org/TR/xslt#section-Defining-Template-Rules">section-Defining-Template-Rules in XSLT Specification</a>
050     * @xsl.usage advanced
051     */
052    public class ElemTemplate extends ElemTemplateElement
053    {
054        static final long serialVersionUID = -5283056789965384058L;
055      /** The public identifier for the current document event.
056       *  @serial          */
057      private String m_publicId;
058    
059      /** The system identifier for the current document event.
060       *  @serial          */
061      private String m_systemId;
062    
063      /**
064       * Return the public identifier for the current document event.
065       * <p>This will be the public identifier
066       * @return A string containing the public identifier, or
067       *         null if none is available.
068       * @see #getSystemId
069       */
070      public String getPublicId()
071      {
072        return m_publicId;
073      }
074    
075      /**
076       * Return the system identifier for the current document event.
077       *
078       * <p>If the system identifier is a URL, the parser must resolve it
079       * fully before passing it to the application.</p>
080       *
081       * @return A string containing the system identifier, or null
082       *         if none is available.
083       * @see #getPublicId
084       */
085      public String getSystemId()
086      {
087        return m_systemId;
088      }
089    
090      /**
091       * Set the location information for this element.
092       *
093       * @param locator SourceLocator holding location information 
094       */
095      public void setLocaterInfo(SourceLocator locator)
096      {
097    
098        m_publicId = locator.getPublicId();
099        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        transformer.getStackGuard().checkForInfinateLoop();
385        
386        xctxt.pushRTFContext();
387    
388        if (transformer.getDebug())
389          transformer.getTraceManager().fireTraceEvent(this);
390    
391          // %REVIEW% commenting out of the code below.
392    //    if (null != sourceNode)
393    //    {
394          transformer.executeChildTemplates(this, true);
395    //    }
396    //    else  // if(null == sourceNode)
397    //    {
398    //      transformer.getMsgMgr().error(this,
399    //        this, sourceNode,
400    //        XSLTErrorResources.ER_NULL_SOURCENODE_HANDLEAPPLYTEMPLATES);
401    //
402    //      //"sourceNode is null in handleApplyTemplatesInstruction!");
403    //    }
404    
405        if (transformer.getDebug())
406          transformer.getTraceManager().fireTraceEndEvent(this);
407    
408        xctxt.popRTFContext();  
409        }
410    
411      /**
412       * This function is called during recomposition to
413       * control how this element is composed.
414       * @param root The root stylesheet for this transformation.
415       */
416      public void recompose(StylesheetRoot root)
417      {
418        root.recomposeTemplates(this);
419      }
420    
421    }