KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > style > XSLCallTemplate


1 package com.icl.saxon.style;
2 import com.icl.saxon.tree.AttributeCollection;
3 import com.icl.saxon.tree.NodeImpl;
4 import com.icl.saxon.*;
5 import com.icl.saxon.om.*;
6 import com.icl.saxon.expr.*;
7 import javax.xml.transform.*;
8 import java.util.*;
9 import java.io.*;
10
11 /**
12 * An xsl:call-template element in the stylesheet
13 */

14
15 public class XSLCallTemplate extends StyleElement {
16
17     private int calledTemplateFingerprint = -1; // the fingerprint of the called template
18
private XSLTemplate template = null;
19     private boolean useTailRecursion = false;
20     private Expression calledTemplateExpression; // allows name to be an AVT
21
private String JavaDoc calledTemplateName = null; // used only for diagnostics
22

23     /**
24     * Determine whether this node is an instruction.
25     * @return true - it is an instruction
26     */

27
28     public boolean isInstruction() {
29         return true;
30     }
31
32     /**
33     * Determine whether this element does any processing after instantiating any children.
34     * This implementation says it doesn't, thus enabling tail recursion.
35     */

36
37     public boolean doesPostProcessing() {
38         return false;
39     }
40
41     public void prepareAttributes() throws TransformerConfigurationException {
42
43         StandardNames sn = getStandardNames();
44         AttributeCollection atts = getAttributeList();
45
46         String JavaDoc allowAVTatt = null;
47         String JavaDoc nameAttribute = null;
48         
49         for (int a=0; a<atts.getLength(); a++) {
50             int nc = atts.getNameCode(a);
51             int f = nc & 0xfffff;
52             if (f==sn.NAME) {
53                 nameAttribute = atts.getValue(a);
54             } else if (f==sn.SAXON_ALLOW_AVT) {
55                 allowAVTatt = atts.getValue(a);
56             } else {
57                 checkUnknownAttribute(nc);
58             }
59         }
60
61         if (nameAttribute==null) {
62             reportAbsence("name");
63             return;
64         }
65         
66         boolean allowAVT = (allowAVTatt != null && allowAVTatt.equals("yes"));
67         if (allowAVT) {
68             calledTemplateExpression = makeAttributeValueTemplate(nameAttribute);
69         } else {
70             if (!Name.isQName(nameAttribute)) {
71                 compileError("Name of called template must be a valid QName");
72             }
73             calledTemplateName = nameAttribute;
74             try {
75                 calledTemplateFingerprint =
76                     makeNameCode(nameAttribute, false) & 0xfffff;
77             } catch (NamespaceException err) {
78                 compileError(err.getMessage());
79             }
80         }
81     }
82
83     public void validate() throws TransformerConfigurationException {
84         checkWithinTemplate();
85
86         if (calledTemplateExpression==null) {
87             template = findTemplate(calledTemplateFingerprint);
88
89             // Use tail recursion if the template is calling itself, and if neither this instruction
90
// nor any ancestor instruction has a following sibling. Avoid tail recursion if called
91
// within any element that needs to do further processing after instantiating its children,
92
// e.g. a literal result element, which needs to write out the end tag
93

94             if (Navigator.isAncestor(template, this)) {
95                 useTailRecursion = true;
96                 StyleElement n = this;
97                 while (n!=template) {
98                     if ((n.isInstruction() && n.getNextSibling()!=null) ||
99                              n.doesPostProcessing()) {
100                         useTailRecursion = false;
101                         break;
102                     }
103                     n = (StyleElement)n.getParentNode();
104                 }
105                 // System.err.println((useTailRecursion ? "" : "NOT ") + "Using tail recursion at line " + getLineNumber());
106
}
107         }
108
109     }
110
111     private XSLTemplate findTemplate(int fingerprint)
112     throws TransformerConfigurationException {
113         
114         XSLStyleSheet stylesheet = getPrincipalStyleSheet();
115         Vector toplevel = stylesheet.getTopLevel();
116     
117         // search for a matching template name, starting at the end in case of duplicates.
118
// this also ensures we get the one with highest import precedence.
119

120         for (int i=toplevel.size()-1; i>=0; i--) {
121             if (toplevel.elementAt(i) instanceof XSLTemplate) {
122                 XSLTemplate t = (XSLTemplate)toplevel.elementAt(i);
123                 if (t.getTemplateFingerprint() == fingerprint) {
124                     return t;
125                 }
126             }
127         }
128         compileError("No template exists named " + calledTemplateName);
129         return null;
130     }
131
132     public void process(Context context) throws TransformerException
133     {
134         // if name is determined dynamically, determine it now
135

136         XSLTemplate target = template;
137         if (calledTemplateExpression != null) {
138             String JavaDoc qname = calledTemplateExpression.evaluateAsString(context);
139             if (!Name.isQName(qname)) {
140                 throw styleError("Invalid template name: " + qname);
141             }
142             int fprint;
143             try {
144                 fprint = makeNameCode(qname, false) & 0xfffff;
145             } catch (NamespaceException err) {
146                 throw styleError(err.getMessage());
147             }
148             target = findTemplate(fprint);
149             if (target==null) {
150                 throw styleError("Template " + qname + " has not been defined");
151             }
152         }
153
154         // handle parameters if any
155

156         ParameterSet params = null;
157         
158         if (hasChildNodes()) {
159             NodeImpl child = (NodeImpl)getFirstChild();
160             params = new ParameterSet();
161             while (child != null) {
162                 if (child instanceof XSLWithParam) { // currently always true
163
XSLWithParam param = (XSLWithParam)child;
164                     params.put(param.getVariableFingerprint(), param.getParamValue(context));
165                 }
166                 child = (NodeImpl)child.getNextSibling();
167             }
168         }
169
170         // Call the named template
171

172         if (useTailRecursion) {
173             if (params==null) { // bug 490967
174
params = new ParameterSet();
175             }
176             context.setTailRecursion(params);
177             // we now just let the stack unwind until we get back to the xsl:template element;
178
// at that point the template will detect that there has been a tail-recursive call,
179
// and iterate to achieve the effect of calling itself.
180
} else {
181             Bindery bindery = context.getBindery();
182             bindery.openStackFrame(params);
183
184             if (context.getController().isTracing()) { // e.g. FIXME: trace tail recursion
185
target.traceExpand(context);
186             } else {
187                 target.expand(context);
188             }
189             
190             bindery.closeStackFrame();
191         }
192
193     }
194
195 }
196
197 //
198
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
199
// you may not use this file except in compliance with the License. You may obtain a copy of the
200
// License at http://www.mozilla.org/MPL/
201
//
202
// Software distributed under the License is distributed on an "AS IS" basis,
203
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
204
// See the License for the specific language governing rights and limitations under the License.
205
//
206
// The Original Code is: all this file.
207
//
208
// The Initial Developer of the Original Code is
209
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
210
//
211
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
212
//
213
// Contributor(s): none.
214
//
215
Popular Tags