KickJava   Java API By Example, From Geeks To Geeks.

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


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: ElemApplyTemplates.java,v 1.33 2004/02/16 20:32:32 minchau Exp $
18  */

19 package org.apache.xalan.templates;
20
21 import java.util.Vector JavaDoc;
22
23 import javax.xml.transform.TransformerException JavaDoc;
24
25 import org.apache.xalan.transformer.StackGuard;
26 import org.apache.xalan.transformer.TransformerImpl;
27 import org.apache.xml.dtm.DTM;
28 import org.apache.xml.dtm.DTMIterator;
29 import org.apache.xml.serializer.SerializationHandler;
30 import org.apache.xml.utils.IntStack;
31 import org.apache.xml.utils.QName;
32 import org.apache.xpath.VariableStack;
33 import org.apache.xpath.XPath;
34 import org.apache.xpath.XPathContext;
35 import org.apache.xpath.objects.XObject;
36 import org.xml.sax.SAXException JavaDoc;
37
38 /**
39  * Implement xsl:apply-templates.
40  * <pre>
41  * &amp;!ELEMENT xsl:apply-templates (xsl:sort|xsl:with-param)*>
42  * &amp;!ATTLIST xsl:apply-templates
43  * select %expr; "node()"
44  * mode %qname; #IMPLIED
45  * &amp;
46  * </pre>
47  * @see <a HREF="http://www.w3.org/TR/xslt#section-Applying-Template-Rules">section-Applying-Template-Rules in XSLT Specification</a>
48  * @xsl.usage advanced
49  */

50 public class ElemApplyTemplates extends ElemCallTemplate
51 {
52
53   /**
54    * mode %qname; #IMPLIED
55    * @serial
56    */

57   private QName m_mode = null;
58
59   /**
60    * Set the mode attribute for this element.
61    *
62    * @param mode reference, which may be null, to the <a HREF="http://www.w3.org/TR/xslt#modes">current mode</a>.
63    */

64   public void setMode(QName mode)
65   {
66     m_mode = mode;
67   }
68
69   /**
70    * Get the mode attribute for this element.
71    *
72    * @return The mode attribute for this element
73    */

74   public QName getMode()
75   {
76     return m_mode;
77   }
78
79   /**
80    * Tells if this belongs to a default template,
81    * in which case it will act different with
82    * regard to processing modes.
83    * @see <a HREF="http://www.w3.org/TR/xslt#built-in-rule">built-in-rule in XSLT Specification</a>
84    * @serial
85    */

86   private boolean m_isDefaultTemplate = false;
87   
88 // /**
89
// * List of namespace/localname IDs, for identification of xsl:with-param to
90
// * xsl:params. Initialized in the compose() method.
91
// */
92
// private int[] m_paramIDs;
93

94   /**
95    * Set if this belongs to a default template,
96    * in which case it will act different with
97    * regard to processing modes.
98    * @see <a HREF="http://www.w3.org/TR/xslt#built-in-rule">built-in-rule in XSLT Specification</a>
99    *
100    * @param b boolean value to set.
101    */

102   public void setIsDefaultTemplate(boolean b)
103   {
104     m_isDefaultTemplate = b;
105   }
106
107   /**
108    * Get an int constant identifying the type of element.
109    * @see org.apache.xalan.templates.Constants
110    *
111    * @return Token ID for this element types
112    */

113   public int getXSLToken()
114   {
115     return Constants.ELEMNAME_APPLY_TEMPLATES;
116   }
117   
118   /**
119    * This function is called after everything else has been
120    * recomposed, and allows the template to set remaining
121    * values that may be based on some other property that
122    * depends on recomposition.
123    */

124   public void compose(StylesheetRoot sroot) throws TransformerException JavaDoc
125   {
126     super.compose(sroot);
127   }
128
129   /**
130    * Return the node name.
131    *
132    * @return Element name
133    */

134   public String JavaDoc getNodeName()
135   {
136     return Constants.ELEMNAME_APPLY_TEMPLATES_STRING;
137   }
138
139   /**
140    * Apply the context node to the matching templates.
141    * @see <a HREF="http://www.w3.org/TR/xslt#section-Applying-Template-Rules">section-Applying-Template-Rules in XSLT Specification</a>
142    *
143    * @param transformer non-null reference to the the current transform-time state.
144    * @param sourceNode non-null reference to the <a HREF="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
145    * @param mode reference, which may be null, to the <a HREF="http://www.w3.org/TR/xslt#modes">current mode</a>.
146    *
147    * @throws TransformerException
148    */

149   public void execute(TransformerImpl transformer) throws TransformerException JavaDoc
150   {
151
152     transformer.pushCurrentTemplateRuleIsNull(false);
153
154     boolean pushMode = false;
155
156     try
157     {
158       // %REVIEW% Do we need this check??
159
// if (null != sourceNode)
160
// {
161
// boolean needToTurnOffInfiniteLoopCheck = false;
162
QName mode = transformer.getMode();
163
164       if (!m_isDefaultTemplate)
165       {
166         if (((null == mode) && (null != m_mode))
167                 || ((null != mode) &&!mode.equals(m_mode)))
168         {
169           pushMode = true;
170
171           transformer.pushMode(m_mode);
172         }
173       }
174       if (TransformerImpl.S_DEBUG)
175         transformer.getTraceManager().fireTraceEvent(this);
176
177       transformSelectedNodes(transformer);
178     }
179     finally
180     {
181       if (TransformerImpl.S_DEBUG)
182         transformer.getTraceManager().fireTraceEndEvent(this);
183
184       if (pushMode)
185         transformer.popMode();
186
187       transformer.popCurrentTemplateRuleIsNull();
188     }
189   }
190
191   
192   /**
193    * Perform a query if needed, and call transformNode for each child.
194    *
195    * @param transformer non-null reference to the the current transform-time state.
196    * @param template The owning template context.
197    *
198    * @throws TransformerException Thrown in a variety of circumstances.
199    * @xsl.usage advanced
200    */

201   public void transformSelectedNodes(TransformerImpl transformer)
202             throws TransformerException JavaDoc
203   {
204
205     final XPathContext xctxt = transformer.getXPathContext();
206     final int sourceNode = xctxt.getCurrentNode();
207     DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);
208     VariableStack vars = xctxt.getVarStack();
209     int nParams = getParamElemCount();
210     int thisframe = vars.getStackFrame();
211     StackGuard guard = transformer.getStackGuard();
212     boolean check = (guard.getRecursionLimit() > -1) ? true : false;
213     
214     boolean pushContextNodeListFlag = false;
215       
216     try
217     {
218
219             xctxt.pushCurrentNode(DTM.NULL);
220             xctxt.pushCurrentExpressionNode(DTM.NULL);
221             xctxt.pushSAXLocatorNull();
222             transformer.pushElemTemplateElement(null);
223       final Vector JavaDoc keys = (m_sortElems == null)
224                           ? null
225                           : transformer.processSortKeys(this, sourceNode);
226
227       // Sort if we need to.
228
if (null != keys)
229         sourceNodes = sortNodes(xctxt, keys, sourceNodes);
230             
231       if (TransformerImpl.S_DEBUG)
232       {
233         transformer.getTraceManager().fireSelectedEvent(sourceNode, this,
234                 "select", new XPath(m_selectExpression),
235                 new org.apache.xpath.objects.XNodeSet(sourceNodes));
236       }
237
238       final SerializationHandler rth = transformer.getSerializationHandler();
239 // ContentHandler chandler = rth.getContentHandler();
240
final StylesheetRoot sroot = transformer.getStylesheet();
241       final TemplateList tl = sroot.getTemplateListComposed();
242       final boolean quiet = transformer.getQuietConflictWarnings();
243       
244       // Should be able to get this from the iterator but there must be a bug.
245
DTM dtm = xctxt.getDTM(sourceNode);
246       
247       int argsFrame = -1;
248       if(nParams > 0)
249       {
250         // This code will create a section on the stack that is all the
251
// evaluated arguments. These will be copied into the real params
252
// section of each called template.
253
argsFrame = vars.link(nParams);
254         vars.setStackFrame(thisframe);
255         
256         for (int i = 0; i < nParams; i++)
257         {
258           ElemWithParam ewp = m_paramElems[i];
259           if (TransformerImpl.S_DEBUG)
260             transformer.getTraceManager().fireTraceEvent(ewp);
261           XObject obj = ewp.getValue(transformer, sourceNode);
262           if (TransformerImpl.S_DEBUG)
263             transformer.getTraceManager().fireTraceEndEvent(ewp);
264           
265           vars.setLocalVariable(i, obj, argsFrame);
266         }
267         vars.setStackFrame(argsFrame);
268       }
269       
270       xctxt.pushContextNodeList(sourceNodes);
271       pushContextNodeListFlag = true;
272       
273       IntStack currentNodes = xctxt.getCurrentNodeStack();
274       
275       IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();
276       
277       // pushParams(transformer, xctxt);
278

279       int child;
280       while (DTM.NULL != (child = sourceNodes.nextNode()))
281       {
282         currentNodes.setTop(child);
283         currentExpressionNodes.setTop(child);
284
285         if(xctxt.getDTM(child) != dtm)
286         {
287           dtm = xctxt.getDTM(child);
288         }
289         
290         final int exNodeType = dtm.getExpandedTypeID(child);
291
292         final int nodeType = dtm.getNodeType(child);
293
294         final QName mode = transformer.getMode();
295
296         ElemTemplate template = tl.getTemplateFast(xctxt, child, exNodeType, mode,
297                                       -1, quiet, dtm);
298
299         // If that didn't locate a node, fall back to a default template rule.
300
// See http://www.w3.org/TR/xslt#built-in-rule.
301
if (null == template)
302         {
303           switch (nodeType)
304           {
305           case DTM.DOCUMENT_FRAGMENT_NODE :
306           case DTM.ELEMENT_NODE :
307             template = sroot.getDefaultRule();
308             // %OPT% direct faster?
309
break;
310           case DTM.ATTRIBUTE_NODE :
311           case DTM.CDATA_SECTION_NODE :
312           case DTM.TEXT_NODE :
313             // if(rth.m_elemIsPending || rth.m_docPending)
314
// rth.flushPending(true);
315
transformer.pushPairCurrentMatched(sroot.getDefaultTextRule(), child);
316             transformer.setCurrentElement(sroot.getDefaultTextRule());
317             // dtm.dispatchCharactersEvents(child, chandler, false);
318
dtm.dispatchCharactersEvents(child, rth, false);
319             transformer.popCurrentMatched();
320             continue;
321           case DTM.DOCUMENT_NODE :
322             template = sroot.getDefaultRootRule();
323             break;
324           default :
325
326             // No default rules for processing instructions and the like.
327
continue;
328           }
329         }
330         else
331         {
332             transformer.setCurrentElement(template);
333         }
334                 
335         transformer.pushPairCurrentMatched(template, child);
336         if (check)
337             guard.checkForInfinateLoop();
338
339         int currentFrameBottom; // See comment with unlink, below
340
if(template.m_frameSize > 0)
341         {
342           xctxt.pushRTFContext();
343           currentFrameBottom = vars.getStackFrame(); // See comment with unlink, below
344
vars.link(template.m_frameSize);
345           // You can't do the check for nParams here, otherwise the
346
// xsl:params might not be nulled.
347
if(/* nParams > 0 && */ template.m_inArgsSize > 0)
348           {
349             int paramIndex = 0;
350             for (ElemTemplateElement elem = template.getFirstChildElem();
351                  null != elem; elem = elem.getNextSiblingElem())
352             {
353               if(Constants.ELEMNAME_PARAMVARIABLE == elem.getXSLToken())
354               {
355                 ElemParam ep = (ElemParam)elem;
356                 
357                 int i;
358                 for (i = 0; i < nParams; i++)
359                 {
360                   ElemWithParam ewp = m_paramElems[i];
361                   if(ewp.m_qnameID == ep.m_qnameID)
362                   {
363                     XObject obj = vars.getLocalVariable(i, argsFrame);
364                     vars.setLocalVariable(paramIndex, obj);
365                     break;
366                   }
367                 }
368                 if(i == nParams)
369                   vars.setLocalVariable(paramIndex, null);
370               }
371               else
372                 break;
373               paramIndex++;
374             }
375             
376           }
377         }
378         else
379             currentFrameBottom = 0;
380
381         // Fire a trace event for the template.
382
if (TransformerImpl.S_DEBUG)
383           transformer.getTraceManager().fireTraceEvent(template);
384
385         // And execute the child templates.
386
// Loop through the children of the template, calling execute on
387
// each of them.
388
for (ElemTemplateElement t = template.m_firstChild;
389              t != null; t = t.m_nextSibling)
390         {
391           xctxt.setSAXLocator(t);
392           try
393           {
394             transformer.pushElemTemplateElement(t);
395             t.execute(transformer);
396           }
397           finally
398           {
399             transformer.popElemTemplateElement();
400           }
401         }
402         
403         if (TransformerImpl.S_DEBUG)
404           transformer.getTraceManager().fireTraceEndEvent(template);
405         
406         if(template.m_frameSize > 0)
407         {
408           // See Frank Weiss bug around 03/19/2002 (no Bugzilla report yet).
409
// While unlink will restore to the proper place, the real position
410
// may have been changed for xsl:with-param, so that variables
411
// can be accessed.
412
// of right now.
413
// More:
414
// When we entered this function, the current
415
// frame buffer (cfb) index in the variable stack may
416
// have been manually set. If we just call
417
// unlink(), however, it will restore the cfb to the
418
// previous link index from the link stack, rather than
419
// the manually set cfb. So,
420
// the only safe solution is to restore it back
421
// to the same position it was on entry, since we're
422
// really not working in a stack context here. (Bug4218)
423
vars.unlink(currentFrameBottom);
424           xctxt.popRTFContext();
425         }
426           
427         transformer.popCurrentMatched();
428         
429       } // end while (DTM.NULL != (child = sourceNodes.nextNode()))
430
}
431     catch (SAXException JavaDoc se)
432     {
433       transformer.getErrorListener().fatalError(new TransformerException JavaDoc(se));
434     }
435     finally
436     {
437       if (TransformerImpl.S_DEBUG)
438         transformer.getTraceManager().fireSelectedEndEvent(sourceNode, this,
439                 "select", new XPath(m_selectExpression),
440                 new org.apache.xpath.objects.XNodeSet(sourceNodes));
441       
442       // Unlink to the original stack frame
443
if(nParams > 0)
444         vars.unlink(thisframe);
445       xctxt.popSAXLocator();
446       if (pushContextNodeListFlag) xctxt.popContextNodeList();
447       transformer.popElemTemplateElement();
448       xctxt.popCurrentExpressionNode();
449       xctxt.popCurrentNode();
450       sourceNodes.detach();
451     }
452   }
453
454 }
455
Popular Tags