KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.style;
2 import net.sf.saxon.expr.*;
3 import net.sf.saxon.instruct.*;
4 import net.sf.saxon.om.*;
5 import net.sf.saxon.pattern.NodeKindTest;
6 import net.sf.saxon.trans.XPathException;
7 import net.sf.saxon.type.ItemType;
8 import net.sf.saxon.type.Type;
9 import net.sf.saxon.value.Cardinality;
10 import net.sf.saxon.value.EmptySequence;
11 import net.sf.saxon.value.SequenceType;
12 import net.sf.saxon.value.StringValue;
13
14 /**
15 * This class defines common behaviour across xsl:variable, xsl:param, and xsl:with-param
16 */

17
18 public abstract class XSLGeneralVariable extends StyleElement {
19
20     protected Expression select = null;
21     protected SequenceType requiredType = null;
22     protected String JavaDoc constantText = null;
23     protected boolean global;
24     protected SlotManager slotManager = null; // used only for global variable declarations
25
protected boolean assignable = false;
26     protected boolean redundant = false;
27     protected boolean requiredParam = false;
28     protected boolean tunnel = false;
29     private boolean textonly;
30
31     /**
32      * Determine the type of item returned by this instruction (only relevant if
33      * it is an instruction).
34      * @return the item type returned. This is null for a variable: we are not
35      * interested in the type of the variable, but in what the xsl:variable constributes
36      * to the result of the sequence constructor it is part of.
37      */

38
39     protected ItemType getReturnedItemType() {
40         return null;
41     }
42     /**
43     * Determine whether this type of element is allowed to contain a template-body
44     * @return true: yes, it may contain a template-body
45     */

46
47     public boolean mayContainSequenceConstructor() {
48         return true;
49     }
50
51     protected boolean allowsAsAttribute() {
52         return true;
53     }
54
55     protected boolean allowsTunnelAttribute() {
56         return false;
57     }
58
59     protected boolean allowsValue() {
60         return true;
61     }
62
63     protected boolean allowsRequired() {
64         return false;
65     }
66
67     /**
68     * Test whether it is permitted to assign to the variable using the saxon:assign
69     * extension element. This will only be true if the extra attribute saxon:assignable="yes"
70     * is present.
71     */

72
73     public boolean isAssignable() {
74         return assignable;
75     }
76
77     public boolean isTunnelParam() {
78         return tunnel;
79     }
80
81     public boolean isRequiredParam() {
82         return requiredParam;
83     }
84
85     public boolean isGlobal() {
86         return isTopLevel();
87             // might be called before the "global" field is initialized
88
}
89
90     /**
91     * Get the display name of the variable.
92     */

93
94     public String JavaDoc getVariableName() {
95         return getAttributeValue(StandardNames.NAME);
96     }
97
98     /**
99     * Mark this global variable as redundant. This is done before prepareAttributes is called.
100     */

101
102     public void setRedundant() {
103         redundant = true;
104     }
105
106     /**
107     * Get the fingerprint of the variable name
108     */

109
110     public int getVariableFingerprint() {
111
112         // if an expression has a forwards reference to this variable, getVariableFingerprint() can be
113
// called before prepareAttributes() is called. We need to allow for this. But we'll
114
// deal with any errors when we come round to processing this attribute, to avoid
115
// duplicate error messages
116

117         if (getObjectNameCode()==-1) {
118             String JavaDoc nameAttribute = getAttributeValue(StandardNames.NAME);
119             if (nameAttribute==null) {
120                 return -1; // we'll report the error later
121
}
122             try {
123                 setObjectNameCode(makeNameCode(nameAttribute.trim()));
124             } catch (NamespaceException err) {
125                 setObjectNameCode(-1);
126             } catch (XPathException err) {
127                 setObjectNameCode(-1);
128             }
129         }
130         return getObjectFingerprint();
131     }
132
133     public void prepareAttributes() throws XPathException {
134
135         getVariableFingerprint();
136
137         AttributeCollection atts = getAttributeList();
138
139         String JavaDoc selectAtt = null;
140         String JavaDoc assignAtt = null;
141         String JavaDoc nameAtt = null;
142         String JavaDoc asAtt = null;
143         String JavaDoc requiredAtt = null;
144         String JavaDoc tunnelAtt = null;
145
146         for (int a=0; a<atts.getLength(); a++) {
147             int nc = atts.getNameCode(a);
148             String JavaDoc f = getNamePool().getClarkName(nc);
149             if (f==StandardNames.NAME) {
150                 nameAtt = atts.getValue(a).trim();
151             } else if (f==StandardNames.SELECT) {
152                 selectAtt = atts.getValue(a);
153             } else if (f==StandardNames.AS && allowsAsAttribute()) {
154                 asAtt = atts.getValue(a);
155             } else if (f==StandardNames.REQUIRED && allowsRequired()) {
156                 requiredAtt = atts.getValue(a).trim();
157             } else if (f==StandardNames.TUNNEL && allowsTunnelAttribute()) {
158                 tunnelAtt = atts.getValue(a).trim();
159             } else if (f==StandardNames.SAXON_ASSIGNABLE && this instanceof XSLVariableDeclaration) {
160                 assignAtt = atts.getValue(a).trim();
161             } else {
162                 checkUnknownAttribute(nc);
163             }
164         }
165
166         if (nameAtt==null) {
167             reportAbsence("name");
168         } else {
169             try {
170                 setObjectNameCode(makeNameCode(nameAtt.trim()));
171             } catch (NamespaceException err) {
172                 compileError(err.getMessage());
173             } catch (XPathException err) {
174                 compileError(err);
175             }
176         }
177
178         if (selectAtt!=null) {
179             if (!allowsValue()) {
180                 compileError("Function parameters cannot have a default value", "XTSE0760");
181             }
182             select = makeExpression(selectAtt);
183         }
184
185         if (assignAtt!=null && assignAtt.equals("yes")) {
186             assignable=true;
187         }
188
189         if (requiredAtt!=null) {
190             if (requiredAtt.equals("yes")) {
191                 requiredParam = true;
192             } else if (requiredAtt.equals("no")) {
193                 requiredParam = false;
194             } else {
195                 compileError("The attribute 'required' must be set to 'yes' or 'no'", "XTSE0020");
196             }
197         }
198
199         if (tunnelAtt!=null) {
200             if (tunnelAtt.equals("yes")) {
201                 tunnel = true;
202             } else if (tunnelAtt.equals("no")) {
203                 tunnel = false;
204             } else {
205                 compileError("The attribute 'tunnel' must be set to 'yes' or 'no'", "XTSE0020");
206             }
207         }
208
209         if (asAtt!=null) {
210             requiredType = makeSequenceType(asAtt);
211         }
212     }
213
214     public void validate() throws XPathException {
215         global = isTopLevel();
216
217         if (global) {
218             slotManager = getConfiguration().makeSlotManager();
219         }
220         if (select!=null && hasChildNodes()) {
221             compileError("An " + getDisplayName() + " element with a select attribute must be empty", "XTSE0620");
222         }
223
224         if (assignable && !global) {
225             compileError("saxon:assignable='yes' is no longer permitted for local variables");
226         }
227
228         checkAgainstRequiredType(requiredType);
229
230         if (select==null && allowsValue()) {
231             textonly = true;
232             AxisIterator kids = iterateAxis(Axis.CHILD);
233             NodeInfo first = (NodeInfo)kids.next();
234             if (first == null) {
235                 if (requiredType == null) {
236                     select = StringValue.EMPTY_STRING;
237                 } else {
238                     if (this instanceof XSLParam) {
239                         if (!requiredParam) {
240                             if (Cardinality.allowsZero(requiredType.getCardinality())) {
241                                 select = EmptySequence.getInstance();
242                             } else {
243                                 // The implicit default value () is not valid for the required type, so
244
// it is treated as if there is no default
245
requiredParam = true;
246                             }
247                         }
248                     } else {
249                         if (Cardinality.allowsZero(requiredType.getCardinality())) {
250                             select = EmptySequence.getInstance();
251                         } else {
252                             compileError("The implicit value () is not valid for the declared type", "XTTE0570");
253                         }
254                     }
255                 }
256             } else {
257                 if (kids.next() == null) {
258                     // there is exactly one child node
259
if (first.getNodeKind() == Type.TEXT) {
260                         // it is a text node: optimize for this case
261
constantText = first.getStringValue();
262                     }
263                 }
264
265                 // Determine if the temporary tree can only contain text nodes
266
textonly = (getCommonChildItemType() == NodeKindTest.TEXT);
267             }
268         }
269         select = typeCheck("select", select);
270     }
271
272     /**
273      * Check the supplied select expression against the required type.
274      * @param required The type required by the variable declaration, or in the case
275      * of xsl:with-param, the signature of the called template
276      */

277
278     protected void checkAgainstRequiredType(SequenceType required)
279     throws XPathException {
280         try {
281
282             if (required!=null) {
283                 // check that the expression is consistent with the required type
284
if (select != null) {
285                     RoleLocator role = new RoleLocator(RoleLocator.VARIABLE, getVariableName(), 0, null);
286                     role.setSourceLocator(new ExpressionLocation(this));
287                     role.setErrorCode("XTTE0570");
288                     select = TypeChecker.staticTypeCheck(select, required, false, role, getStaticContext());
289                 } else {
290                     // do the check later
291
}
292             }
293         } catch (XPathException err) {
294             err.setLocator(this); // because the expression wasn't yet linked into the module
295
compileError(err);
296             select = new ErrorExpression(err);
297         }
298     }
299
300     /**
301     * Initialize - common code called from the compile() method of all subclasses
302     */

303
304     protected void initializeInstruction(Executable exec, GeneralVariable var)
305     throws XPathException {
306
307         var.init(select, getObjectNameCode());
308         var.setAssignable(assignable);
309         var.setRequiredParam(requiredParam);
310         var.setRequiredType(requiredType);
311         var.setTunnel(tunnel);
312
313         // handle the "temporary tree" case by creating a Document sub-instruction
314
// to construct and return a document node.
315
if (hasChildNodes()) {
316             if (requiredType==null) {
317                 DocumentInstr doc = new DocumentInstr(textonly, constantText, getBaseURI());
318                 doc.setParentExpression(var);
319                 Expression b = compileSequenceConstructor(exec, iterateAxis(Axis.CHILD), true);
320                 if (b == null) {
321                     b = EmptySequence.getInstance();
322                 }
323                 doc.setContentExpression(b);
324                 select = doc;
325                 var.setSelectExpression(doc);
326             } else {
327                 select = compileSequenceConstructor(exec, iterateAxis(Axis.CHILD), true);
328                 if (select == null) {
329                     select = EmptySequence.getInstance();
330                 }
331                 try {
332                     if (requiredType != null) {
333                         RoleLocator role =
334                                 new RoleLocator(RoleLocator.VARIABLE, getVariableName(), 0, null);
335                         role.setErrorCode("XTTE0570");
336                         role.setSourceLocator(new ExpressionLocation(this));
337                         select = select.simplify(getStaticContext());
338                         select = TypeChecker.staticTypeCheck(select, requiredType, false, role, getStaticContext());
339                     }
340                 } catch (XPathException err) {
341                     err.setLocator(this);
342                     compileError(err);
343                     select = new ErrorExpression(err);
344                 }
345                 var.setSelectExpression(select);
346             }
347         }
348         if (global) {
349             Expression exp2 = select;
350             if (exp2 != null) {
351                 try {
352                     exp2 = select.simplify(staticContext).typeCheck(staticContext, Type.NODE_TYPE);
353                     exp2 = exp2.optimize(getConfiguration().getOptimizer(), staticContext, Type.NODE_TYPE);
354                 } catch (XPathException err) {
355                     compileError(err);
356                 }
357
358                 if (getConfiguration().getTraceListener() != null) {
359                     TraceWrapper trace = new TraceInstruction(exp2, this);
360                     trace.setLocationId(allocateLocationId(getSystemId(), getLineNumber()));
361                     exp2 = trace;
362                 }
363
364                 allocateSlots(exp2);
365             }
366             if (slotManager != null && slotManager.getNumberOfVariables() > 0) {
367                 ((GlobalVariable)var).setContainsLocals(slotManager);
368             }
369             exec.registerGlobalVariable(var);
370             if (exp2 != select) {
371                 var.setSelectExpression(exp2);
372             }
373         }
374     }
375
376     /**
377      * Get the type of construct. This will be a constant in
378      * class {@link net.sf.saxon.trace.Location}. This method is part of the
379      * {@link net.sf.saxon.trace.InstructionInfo} interface
380      */

381
382     public int getConstructType() {
383         return StandardNames.XSL_VARIABLE;
384     }
385
386 }
387
388 //
389
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
390
// you may not use this file except in compliance with the License. You may obtain a copy of the
391
// License at http://www.mozilla.org/MPL/
392
//
393
// Software distributed under the License is distributed on an "AS IS" basis,
394
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
395
// See the License for the specific language governing rights and limitations under the License.
396
//
397
// The Original Code is: all this file.
398
//
399
// The Initial Developer of the Original Code is Michael H. Kay.
400
//
401
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
402
//
403
// Contributor(s): none.
404
//
405
Popular Tags