KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > templates > ElemCallTemplate


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: ElemCallTemplate.java,v 1.27 2004/02/16 20:32:32 minchau Exp $
18  */

19 package org.apache.xalan.templates;
20
21 import javax.xml.transform.SourceLocator JavaDoc;
22 import javax.xml.transform.TransformerException JavaDoc;
23
24 import org.apache.xalan.res.XSLMessages;
25 import org.apache.xalan.res.XSLTErrorResources;
26 import org.apache.xalan.transformer.TransformerImpl;
27 import org.apache.xml.utils.QName;
28 import org.apache.xpath.VariableStack;
29 import org.apache.xpath.XPathContext;
30 import org.apache.xpath.objects.XObject;
31
32 /**
33  * Implement xsl:call-template.
34  * <pre>
35  * &amp;!ELEMENT xsl:call-template (xsl:with-param)*>
36  * &amp;!ATTLIST xsl:call-template
37  * name %qname; #REQUIRED
38  * &amp;
39  * </pre>
40  * @see <a HREF="http://www.w3.org/TR/xslt#named-templates">named-templates in XSLT Specification</a>
41  * @xsl.usage advanced
42  */

43 public class ElemCallTemplate extends ElemForEach
44 {
45
46   /**
47    * An xsl:call-template element invokes a template by name;
48    * it has a required name attribute that identifies the template to be invoked.
49    * @serial
50    */

51   public QName m_templateName = null;
52
53   /**
54    * Set the "name" attribute.
55    * An xsl:call-template element invokes a template by name;
56    * it has a required name attribute that identifies the template to be invoked.
57    *
58    * @param name Name attribute to set
59    */

60   public void setName(QName name)
61   {
62     m_templateName = name;
63   }
64
65   /**
66    * Get the "name" attribute.
67    * An xsl:call-template element invokes a template by name;
68    * it has a required name attribute that identifies the template to be invoked.
69    *
70    * @return Name attribute of this element
71    */

72   public QName getName()
73   {
74     return m_templateName;
75   }
76
77   /**
78    * The template which is named by QName.
79    * @serial
80    */

81   private ElemTemplate m_template = null;
82
83   /**
84    * Get an int constant identifying the type of element.
85    * @see org.apache.xalan.templates.Constants
86    *
87    * @return The token ID for this element
88    */

89   public int getXSLToken()
90   {
91     return Constants.ELEMNAME_CALLTEMPLATE;
92   }
93
94   /**
95    * Return the node name.
96    *
97    * @return The name of this element
98    */

99   public String JavaDoc getNodeName()
100   {
101     return Constants.ELEMNAME_CALLTEMPLATE_STRING;
102   }
103   
104   /**
105    * This function is called after everything else has been
106    * recomposed, and allows the template to set remaining
107    * values that may be based on some other property that
108    * depends on recomposition.
109    */

110   public void compose(StylesheetRoot sroot) throws TransformerException JavaDoc
111   {
112     super.compose(sroot);
113     
114     // Call compose on each param no matter if this is apply-templates
115
// or call templates.
116
int length = getParamElemCount();
117     for (int i = 0; i < length; i++)
118     {
119       ElemWithParam ewp = getParamElem(i);
120       ewp.compose(sroot);
121     }
122     
123     if ((null != m_templateName) && (null == m_template)) {
124         m_template =
125             this.getStylesheetRoot().getTemplateComposed(m_templateName);
126
127         if (null == m_template) {
128             String JavaDoc themsg =
129                 XSLMessages.createMessage(
130                     XSLTErrorResources.ER_ELEMTEMPLATEELEM_ERR,
131                     new Object JavaDoc[] { m_templateName });
132
133             throw new TransformerException JavaDoc(themsg, this);
134             //"Could not find template named: '"+templateName+"'");
135
}
136     
137       length = getParamElemCount();
138       for (int i = 0; i < length; i++)
139       {
140         ElemWithParam ewp = getParamElem(i);
141         ewp.m_index = -1;
142         // Find the position of the param in the template being called,
143
// and set the index of the param slot.
144
int etePos = 0;
145         for (ElemTemplateElement ete = m_template.getFirstChildElem();
146              null != ete; ete = ete.getNextSiblingElem())
147         {
148           if(ete.getXSLToken() == Constants.ELEMNAME_PARAMVARIABLE)
149           {
150             ElemParam ep = (ElemParam)ete;
151             if(ep.getName().equals(ewp.getName()))
152             {
153               ewp.m_index = etePos;
154             }
155           }
156           else
157             break;
158           etePos++;
159         }
160         
161       }
162     }
163   }
164   
165   /**
166    * This after the template's children have been composed.
167    */

168   public void endCompose(StylesheetRoot sroot) throws TransformerException JavaDoc
169   {
170     int length = getParamElemCount();
171     for (int i = 0; i < length; i++)
172     {
173       ElemWithParam ewp = getParamElem(i);
174       ewp.endCompose(sroot);
175     }
176     
177     super.endCompose(sroot);
178   }
179
180   /**
181    * Invoke a named template.
182    * @see <a HREF="http://www.w3.org/TR/xslt#named-templates">named-templates in XSLT Specification</a>
183    *
184    * @param transformer non-null reference to the the current transform-time state.
185    * @param sourceNode non-null reference to the <a HREF="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
186    * @param mode reference, which may be null, to the <a HREF="http://www.w3.org/TR/xslt#modes">current mode</a>.
187    *
188    * @throws TransformerException
189    */

190   public void execute(
191           TransformerImpl transformer)
192             throws TransformerException JavaDoc
193   {
194
195     if (TransformerImpl.S_DEBUG)
196       transformer.getTraceManager().fireTraceEvent(this);
197
198     if (null != m_template)
199     {
200       XPathContext xctxt = transformer.getXPathContext();
201       VariableStack vars = xctxt.getVarStack();
202
203       int thisframe = vars.getStackFrame();
204       int nextFrame = vars.link(m_template.m_frameSize);
205       
206       // We have to clear the section of the stack frame that has params
207
// so that the default param evaluation will work correctly.
208
if(m_template.m_inArgsSize > 0)
209       {
210         vars.clearLocalSlots(0, m_template.m_inArgsSize);
211       
212         if(null != m_paramElems)
213         {
214           int currentNode = xctxt.getCurrentNode();
215           vars.setStackFrame(thisframe);
216           int size = m_paramElems.length;
217           
218           for (int i = 0; i < size; i++)
219           {
220             ElemWithParam ewp = m_paramElems[i];
221             if(ewp.m_index >= 0)
222             {
223               if (TransformerImpl.S_DEBUG)
224                 transformer.getTraceManager().fireTraceEvent(ewp);
225               XObject obj = ewp.getValue(transformer, currentNode);
226               if (TransformerImpl.S_DEBUG)
227                 transformer.getTraceManager().fireTraceEndEvent(ewp);
228               
229               // Note here that the index for ElemWithParam must have been
230
// statically made relative to the xsl:template being called,
231
// NOT this xsl:template.
232
vars.setLocalVariable(ewp.m_index, obj, nextFrame);
233             }
234           }
235           vars.setStackFrame(nextFrame);
236         }
237       }
238       
239       SourceLocator JavaDoc savedLocator = xctxt.getSAXLocator();
240
241       try
242       {
243         xctxt.setSAXLocator(m_template);
244
245         // template.executeChildTemplates(transformer, sourceNode, mode, true);
246
transformer.pushElemTemplateElement(m_template);
247         m_template.execute(transformer);
248       }
249       finally
250       {
251         transformer.popElemTemplateElement();
252         xctxt.setSAXLocator(savedLocator);
253         // When we entered this function, the current
254
// frame buffer (cfb) index in the variable stack may
255
// have been manually set. If we just call
256
// unlink(), however, it will restore the cfb to the
257
// previous link index from the link stack, rather than
258
// the manually set cfb. So,
259
// the only safe solution is to restore it back
260
// to the same position it was on entry, since we're
261
// really not working in a stack context here. (Bug4218)
262
vars.unlink(thisframe);
263       }
264     }
265     else
266     {
267       transformer.getMsgMgr().error(this, XSLTErrorResources.ER_TEMPLATE_NOT_FOUND,
268                                     new Object JavaDoc[]{ m_templateName }); //"Could not find template named: '"+templateName+"'");
269
}
270     
271     if (TransformerImpl.S_DEBUG)
272       transformer.getTraceManager().fireTraceEndEvent(this);
273
274   }
275   
276   /** Vector of xsl:param elements associated with this element.
277    * @serial */

278   protected ElemWithParam[] m_paramElems = null;
279
280   /**
281    * Get the count xsl:param elements associated with this element.
282    * @return The number of xsl:param elements.
283    */

284   public int getParamElemCount()
285   {
286     return (m_paramElems == null) ? 0 : m_paramElems.length;
287   }
288
289   /**
290    * Get a xsl:param element associated with this element.
291    *
292    * @param i Index of element to find
293    *
294    * @return xsl:param element at given index
295    */

296   public ElemWithParam getParamElem(int i)
297   {
298     return m_paramElems[i];
299   }
300
301   /**
302    * Set a xsl:param element associated with this element.
303    *
304    * @param ParamElem xsl:param element to set.
305    */

306   public void setParamElem(ElemWithParam ParamElem)
307   {
308     if (null == m_paramElems)
309     {
310       m_paramElems = new ElemWithParam[1];
311       m_paramElems[0] = ParamElem;
312     }
313     else
314     {
315       // Expensive 1 at a time growth, but this is done at build time, so
316
// I think it's OK.
317
int length = m_paramElems.length;
318       ElemWithParam[] ewp = new ElemWithParam[length + 1];
319       System.arraycopy(m_paramElems, 0, ewp, 0, length);
320       m_paramElems = ewp;
321       ewp[length] = ParamElem;
322     }
323   }
324
325   /**
326    * Add a child to the child list.
327    * <!ELEMENT xsl:apply-templates (xsl:sort|xsl:with-param)*>
328    * <!ATTLIST xsl:apply-templates
329    * select %expr; "node()"
330    * mode %qname; #IMPLIED
331    * >
332    *
333    * @param newChild Child to add to this node's children list
334    *
335    * @return The child that was just added the children list
336    *
337    * @throws DOMException
338    */

339   public ElemTemplateElement appendChild(ElemTemplateElement newChild)
340   {
341
342     int type = ((ElemTemplateElement) newChild).getXSLToken();
343
344     if (Constants.ELEMNAME_WITHPARAM == type)
345     {
346       setParamElem((ElemWithParam) newChild);
347     }
348
349     // You still have to append, because this element can
350
// contain a for-each, and other elements.
351
return super.appendChild(newChild);
352   }
353   
354     /**
355      * Call the children visitors.
356      * @param visitor The visitor whose appropriate method will be called.
357      */

358     public void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
359     {
360 // if (null != m_paramElems)
361
// {
362
// int size = m_paramElems.length;
363
//
364
// for (int i = 0; i < size; i++)
365
// {
366
// ElemWithParam ewp = m_paramElems[i];
367
// ewp.callVisitors(visitor);
368
// }
369
// }
370

371       super.callChildVisitors(visitor, callAttrs);
372     }
373 }
374
Popular Tags