KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > style > XSLCallTemplate


1 package net.sf.saxon.style;
2 import net.sf.saxon.Err;
3 import net.sf.saxon.expr.Expression;
4 import net.sf.saxon.expr.ExpressionTool;
5 import net.sf.saxon.instruct.CallTemplate;
6 import net.sf.saxon.instruct.Executable;
7 import net.sf.saxon.instruct.Template;
8 import net.sf.saxon.om.*;
9 import net.sf.saxon.trans.XPathException;
10 import net.sf.saxon.type.AnyItemType;
11 import net.sf.saxon.type.ItemType;
12 import net.sf.saxon.type.Type;
13 import net.sf.saxon.value.SequenceType;
14 import net.sf.saxon.value.Whitespace;
15
16 import java.util.List JavaDoc;
17
18 /**
19 * An xsl:call-template element in the stylesheet
20 */

21
22 public class XSLCallTemplate extends StyleElement {
23
24     private int calledTemplateFingerprint = -1; // the fingerprint of the called template
25
private XSLTemplate template = null;
26     private boolean useTailRecursion = false;
27     private String JavaDoc calledTemplateName = null; // used only for diagnostics
28
private Expression calledTemplateExpression; // allows name to be an AVT
29

30     /**
31      * Determine whether the called template can be specified as an AVT
32      */

33
34     protected boolean allowAVT() {
35         return false;
36     }
37
38     /**
39     * Determine whether this node is an instruction.
40     * @return true - it is an instruction
41     */

42
43     public boolean isInstruction() {
44         return true;
45     }
46
47     /**
48      * Determine the type of item returned by this instruction (only relevant if
49      * it is an instruction).
50      * @return the item type returned
51      */

52
53     protected ItemType getReturnedItemType() {
54         if (template==null) {
55             return AnyItemType.getInstance();
56         } else {
57             return template.getReturnedItemType();
58         }
59     }
60
61     public void prepareAttributes() throws XPathException {
62
63         AttributeCollection atts = getAttributeList();
64
65         String JavaDoc nameAttribute = null;
66
67         for (int a=0; a<atts.getLength(); a++) {
68             int nc = atts.getNameCode(a);
69             String JavaDoc f = getNamePool().getClarkName(nc);
70             if (f==StandardNames.NAME) {
71                 nameAttribute = atts.getValue(a).trim();
72             } else {
73                 checkUnknownAttribute(nc);
74             }
75         }
76
77         if (nameAttribute==null) {
78             reportAbsence("name");
79             return;
80         }
81
82         if (allowAVT() && nameAttribute.indexOf('{')>=0) {
83             calledTemplateExpression = makeAttributeValueTemplate(nameAttribute);
84         } else {
85             calledTemplateName = nameAttribute;
86             try {
87                 calledTemplateFingerprint =
88                     makeNameCode(nameAttribute.trim()) & 0xfffff;
89             } catch (NamespaceException err) {
90                 compileError(err.getMessage(), "XTSE0280");
91             } catch (XPathException err) {
92                 compileError(err.getMessage(), "XTSE0280");
93             }
94         }
95     }
96
97     public void validate() throws XPathException {
98         checkWithinTemplate();
99
100         AxisIterator kids = iterateAxis(Axis.CHILD);
101         while (true) {
102             NodeInfo child = (NodeInfo)kids.next();
103             if (child == null) {
104                 break;
105             }
106             if (child instanceof XSLWithParam) {
107                 // OK;
108
} else if (child instanceof XSLFallback && mayContainFallback()) {
109                 // xsl:fallback is not allowed on xsl:call-template, but is allowed on saxon:call-template (cheat!)
110
} else if (child.getNodeKind() == Type.TEXT) {
111                     // with xml:space=preserve, white space nodes may still be there
112
if (!Whitespace.isWhite(child.getStringValueCS())) {
113                     compileError("No character data is allowed within xsl:call-template", "XTSE0010");
114                 }
115             } else {
116                 compileError("Child element " + Err.wrap(child.getDisplayName(), Err.ELEMENT) +
117                         " is not allowed within xsl:call-template", "XTSE0010");
118             }
119         }
120         if (calledTemplateExpression==null) {
121             template = findTemplate(calledTemplateFingerprint);
122             if (template==null) {
123                 return;
124             }
125         }
126         calledTemplateExpression = typeCheck("name", calledTemplateExpression);
127     }
128
129     public void postValidate() throws XPathException {
130         // check that a parameter is supplied for each required parameter
131
// of the called template
132

133         if (template != null) {
134             AxisIterator declaredParams = template.iterateAxis(Axis.CHILD);
135             while(true) {
136                 NodeInfo param = (NodeInfo)declaredParams.next();
137                 if (param == null) {
138                     break;
139                 }
140                 if (param instanceof XSLParam && ((XSLParam)param).isRequiredParam()
141                                               && !((XSLParam)param).isTunnelParam()) {
142                     AxisIterator actualParams = iterateAxis(Axis.CHILD);
143                     boolean ok = false;
144                     while(true) {
145                         NodeInfo withParam = (NodeInfo)actualParams.next();
146                         if (withParam == null) {
147                             break;
148                         }
149                         if (withParam instanceof XSLWithParam &&
150                                 ((XSLWithParam)withParam).getVariableFingerprint() ==
151                                     ((XSLParam)param).getVariableFingerprint()) {
152                             ok = true;
153                             break;
154                         }
155                     }
156                     if (!ok) {
157                         compileError("No value supplied for required parameter " +
158                                 Err.wrap(((XSLParam)param).getVariableName(), Err.VARIABLE), "XTSE0690");
159                     }
160                 }
161             }
162
163
164             // check that every supplied parameter is declared in the called
165
// template
166

167             AxisIterator actualParams = iterateAxis(Axis.CHILD);
168             while(true) {
169                 NodeInfo w = (NodeInfo)actualParams.next();
170                 if (w == null) {
171                     break;
172                 }
173                 if (w instanceof XSLWithParam && !((XSLWithParam)w).isTunnelParam()) {
174                     XSLWithParam withParam = (XSLWithParam)w;
175                     AxisIterator formalParams = template.iterateAxis(Axis.CHILD);
176                     boolean ok = false;
177                     while(true) {
178                         NodeInfo param = (NodeInfo)formalParams.next();
179                         if (param == null) {
180                             break;
181                         }
182                         if (param instanceof XSLParam &&
183                                 ((XSLParam)param).getVariableFingerprint() ==
184                                     withParam.getVariableFingerprint()) {
185                             ok = true;
186                             SequenceType required = ((XSLParam)param).getRequiredType();
187                             withParam.checkAgainstRequiredType(required);
188                             break;
189                         }
190                     }
191                     if (!ok) {
192                         if (!backwardsCompatibleModeIsEnabled()) {
193                             compileError("Parameter " +
194                                     withParam.getVariableName() +
195                                     " is not declared in the called template", "XTSE0680");
196                         }
197                     }
198                 }
199             }
200         }
201     }
202
203     private XSLTemplate findTemplate(int fingerprint)
204     throws XPathException {
205
206         XSLStylesheet stylesheet = getPrincipalStylesheet();
207         List JavaDoc toplevel = stylesheet.getTopLevel();
208
209         // search for a matching template name, starting at the end in case of duplicates.
210
// this also ensures we get the one with highest import precedence.
211

212         for (int i=toplevel.size()-1; i>=0; i--) {
213             if (toplevel.get(i) instanceof XSLTemplate) {
214                 XSLTemplate t = (XSLTemplate)toplevel.get(i);
215                 if (t.getTemplateFingerprint() == fingerprint) {
216                     return t;
217                 }
218             }
219         }
220         compileError("No template exists named " + calledTemplateName, "XTSE0650");
221         return null;
222     }
223
224     /**
225      * Mark tail-recursive calls on templates and functions.
226      * For most instructions, this does nothing.
227     */

228
229     public void markTailCalls() {
230         useTailRecursion = true;
231     }
232
233
234     public Expression compile(Executable exec) throws XPathException {
235         Template target = null;
236         NamespaceResolver nsContext = null;
237
238         if (calledTemplateExpression==null) {
239             if (template==null) {
240                 return null; // error already reported
241
}
242             target = template.getCompiledTemplate();
243         } else {
244             //getPrincipalStyleSheet().setRequireRuntimeTemplateMap(true);
245
nsContext = makeNamespaceContext();
246         }
247
248         CallTemplate call = new CallTemplate (
249                                     target,
250                                     useTailRecursion,
251                                     calledTemplateExpression,
252                                     nsContext );
253         call.setActualParameters(getWithParamInstructions(exec, false, call),
254                                  getWithParamInstructions(exec, true, call));
255         ExpressionTool.makeParentReferences(call);
256         return call;
257     }
258
259 }
260
261 //
262
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
263
// you may not use this file except in compliance with the License. You may obtain a copy of the
264
// License at http://www.mozilla.org/MPL/
265
//
266
// Software distributed under the License is distributed on an "AS IS" basis,
267
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
268
// See the License for the specific language governing rights and limitations under the License.
269
//
270
// The Original Code is: all this file.
271
//
272
// The Initial Developer of the Original Code is Michael H. Kay.
273
//
274
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
275
//
276
// Contributor(s): none.
277
//
278
Popular Tags