KickJava   Java API By Example, From Geeks To Geeks.

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


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 com.icl.saxon.pattern.Pattern;
8 import com.icl.saxon.trace.*; // e.g.
9

10 import javax.xml.transform.*;
11
12 /**
13 * An xsl:template element in the style sheet.
14 */

15     
16 public class XSLTemplate extends StyleElement implements NodeHandler {
17
18     protected int modeNameCode = -1;
19     protected int templateFingerprint = -1;
20     protected Pattern match;
21     protected boolean prioritySpecified;
22     protected double priority;
23     protected Procedure procedure = new Procedure();
24     protected boolean needsStackFrame;
25
26     /**
27     * Determine whether this type of element is allowed to contain a template-body
28     * @return true: yes, it may contain a template-body
29     */

30
31     public boolean mayContainTemplateBody() {
32         return true;
33     }
34
35     /**
36     * Return the fingerprint for the name of this template
37     */

38
39     public int getTemplateFingerprint() {
40         
41         //We use -1 to mean "not yet evaluated"
42

43         try {
44             if (templateFingerprint==-1) {
45                 // allow for forwards references
46
StandardNames sn = getStandardNames();
47                 String JavaDoc nameAtt = getAttributeList().getValue(sn.NAME);
48                 if (nameAtt!=null) {
49                     templateFingerprint =
50                         makeNameCode(nameAtt, false) & 0xfffff;
51                 }
52             }
53             return templateFingerprint;
54         } catch (NamespaceException err) {
55             return -1; // the error will be picked up later
56
}
57     }
58
59     public int getMinImportPrecedence() {
60         return ((XSLStyleSheet)getDocumentElement()).getMinImportPrecedence();
61     }
62
63     public boolean needsStackFrame() {
64         return this.needsStackFrame;
65     }
66
67     public void prepareAttributes() throws TransformerConfigurationException {
68
69         String JavaDoc modeAtt = null;
70         String JavaDoc nameAtt = null;
71         String JavaDoc priorityAtt = null;
72         String JavaDoc matchAtt = null;
73
74         StandardNames sn = getStandardNames();
75         AttributeCollection atts = getAttributeList();
76
77         for (int a=0; a<atts.getLength(); a++) {
78             int nc = atts.getNameCode(a);
79             int f = nc & 0xfffff;
80             if (f==sn.MODE) {
81                 modeAtt = atts.getValue(a);
82             } else if (f==sn.NAME) {
83                 nameAtt = atts.getValue(a);
84             } else if (f==sn.MATCH) {
85                 matchAtt = atts.getValue(a);
86             } else if (f==sn.PRIORITY) {
87                 priorityAtt = atts.getValue(a);
88             } else {
89                 checkUnknownAttribute(nc);
90             }
91         }
92         try {
93             if (modeAtt!=null) {
94                 if (!Name.isQName(modeAtt)) {
95                     compileError("Mode name is not a valid QName");
96                 }
97                 modeNameCode = makeNameCode(modeAtt, false);
98             }
99             
100             if (nameAtt!=null) {
101                 if (!Name.isQName(nameAtt)) {
102                     compileError("Template name is not a valid QName");
103                 }
104                 templateFingerprint = makeNameCode(nameAtt, false) & 0xfffff;
105             }
106         } catch (NamespaceException err) {
107             compileError(err.getMessage());
108         }
109         
110         prioritySpecified = (priorityAtt != null);
111         if (prioritySpecified) {
112             try {
113                 priority = new Double JavaDoc(priorityAtt.trim()).doubleValue();
114             } catch (NumberFormatException JavaDoc err) {
115                 compileError("Invalid numeric value for priority (" + priority + ")");
116             }
117         }
118
119         if (matchAtt != null) {
120             match = makePattern(matchAtt);
121         }
122         
123         if (match==null && nameAtt==null)
124             compileError("xsl:template must have a a name or match attribute (or both)");
125
126     }
127     
128
129     public void validate() throws TransformerConfigurationException {
130         checkTopLevel();
131
132         // it is in error if there is another template with the same name and precedence
133

134         if (templateFingerprint!=-1) {
135             // TODO: this check only looks at others in the same stylesheet module
136
NodeImpl node = (NodeImpl)getPreviousSibling();
137             while (node!=null) {
138                 if (node instanceof XSLTemplate) {
139                     XSLTemplate t = (XSLTemplate)node;
140                     if (t.getTemplateFingerprint()==templateFingerprint &&
141                             t.getPrecedence()==this.getPrecedence()) {
142                         compileError("There is another template with the same name and precedence");
143                     }
144                 }
145                 node = (NodeImpl)node.getPreviousSibling();
146             }
147         }
148                     
149     }
150
151     /**
152     * Preprocess: this registers the template with the rule manager, and ensures
153     * space is available for local variables
154     */

155
156     public void preprocess() throws TransformerConfigurationException
157     {
158         RuleManager mgr = getPrincipalStyleSheet().getRuleManager();
159         Mode mode = mgr.getMode(modeNameCode);
160         
161         if (match!=null) {
162             NodeHandler handler = this;
163             if (getFirstChild()==null) {
164                 // template is empty: use a no-op handler instead
165
handler = new NoOpHandler();
166             }
167             if (prioritySpecified) {
168                 mgr.setHandler(match, handler, mode, getPrecedence(), priority);
169             } else {
170                 mgr.setHandler(match, handler, mode, getPrecedence());
171             }
172         }
173
174         getPrincipalStyleSheet().allocateLocalSlots(procedure.getNumberOfVariables());
175         needsStackFrame = (procedure.getNumberOfVariables() > 0);
176       
177     }
178
179     /**
180     * Process template. This is called while all the top-level nodes are being processed in order,
181     * so it does nothing.
182     */

183
184     public void process(Context context) throws TransformerException {
185     }
186
187     /**
188     * Process a node in the source document. This is called when the template
189     * is invoked using xsl:apply-templates.
190     */

191    
192     public void start( NodeInfo e, Context context ) throws TransformerException {
193         context.setCurrentTemplate(this);
194
195         if (context.getController().isTracing()) { // e.g. FIXME: trace tail recursion
196
traceExpand(context);
197         } else {
198             expand(context);
199         }
200     }
201
202     /**
203     * Expand the template, with tracing. Called when the template is invoked either
204     * by xsl:apply-templates or from xsl:call-template
205     */

206
207     protected void traceExpand(Context context) throws TransformerException {
208
209         TraceListener listener = context.getController().getTraceListener();
210
211         listener.enter(this, context);
212         expand(context);
213         listener.leave(this, context);
214     }
215
216     /**
217     * Expand the template. Called when the template is invoked either
218     * by xsl:apply-templates or from xsl:call-template
219     */

220
221     protected void expand(Context context) throws TransformerException {
222         ParameterSet p = null;
223         do {
224             context.setTailRecursion(null);
225             processChildren(context);
226             p = context.getTailRecursion();
227             if (p!=null) {
228                 context.getBindery().closeStackFrame();
229                 context.getBindery().openStackFrame(p);
230             }
231         } while (p!=null);
232     }
233
234     /**
235     * Disallow variable references in the match pattern
236     */

237
238     public Binding bindVariable(int fingerprint) throws XPathException {
239         throw new XPathException("The match pattern in xsl:template may not contain references to variables");
240     }
241
242     /**
243     * Get associated Procedure (for details of stack frame)
244     */

245
246     public Procedure getProcedure() {
247         return procedure;
248     }
249
250     /**
251     * Inner class: a no-op handler to provide a fast path for empty templates
252     */

253     
254     private final class NoOpHandler implements NodeHandler {
255         public void start( NodeInfo e, Context context ) {}
256         public boolean needsStackFrame() {
257             return false;
258         }
259     }
260 }
261
262 //
263
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
264
// you may not use this file except in compliance with the License. You may obtain a copy of the
265
// License at http://www.mozilla.org/MPL/
266
//
267
// Software distributed under the License is distributed on an "AS IS" basis,
268
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
269
// See the License for the specific language governing rights and limitations under the License.
270
//
271
// The Original Code is: all this file.
272
//
273
// The Initial Developer of the Original Code is
274
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
275
//
276
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
277
//
278
// Contributor(s):
279
// Portions marked "e.g." are from Edwin Glaser (edwin@pannenleiter.de)
280
//
281
Popular Tags