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 }