KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > query > XQueryFunction


1 package net.sf.saxon.query;
2
3 import net.sf.saxon.event.LocationProvider;
4 import net.sf.saxon.expr.*;
5 import net.sf.saxon.functions.ExecutableFunctionLibrary;
6 import net.sf.saxon.instruct.*;
7 import net.sf.saxon.om.NamePool;
8 import net.sf.saxon.om.NamespaceResolver;
9 import net.sf.saxon.style.StandardNames;
10 import net.sf.saxon.trace.InstructionInfo;
11 import net.sf.saxon.trace.Location;
12 import net.sf.saxon.trans.StaticError;
13 import net.sf.saxon.trans.XPathException;
14 import net.sf.saxon.value.SequenceType;
15
16 import java.util.ArrayList JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19
20 public class XQueryFunction implements InstructionInfo, Container, Declaration {
21     private int nameCode;
22     List JavaDoc arguments; // A list of RangeVariableDeclaration objects
23
SequenceType resultType;
24     Expression body = null;
25     List JavaDoc references = new ArrayList JavaDoc(10);
26     int lineNumber;
27     int columnNumber;
28     String JavaDoc systemId;
29     private Executable executable;
30     private UserFunction compiledFunction = null;
31     NamespaceResolver namespaceResolver;
32     private StaticContext staticContext;
33
34     public XQueryFunction() {}
35
36     public void setNameCode(int nameCode) {
37         this.nameCode = nameCode;
38     }
39
40     public int getNameCode() {
41         return nameCode;
42     }
43
44     public String JavaDoc getFunctionDisplayName(NamePool pool) {
45         return pool.getDisplayName(nameCode);
46     }
47
48     public int getFunctionFingerprint() {
49         return nameCode & 0xfffff;
50     }
51
52     public SequenceType getResultType() {
53         return resultType;
54     }
55
56     public void setExecutable(Executable exec) {
57         executable = exec;
58     }
59
60     public Executable getExecutable() {
61         return executable;
62     }
63
64     /**
65      * Get the LocationProvider allowing location identifiers to be resolved.
66      */

67
68     public LocationProvider getLocationProvider() {
69         return executable.getLocationMap();
70     }
71
72     public StaticContext getStaticContext() {
73         return staticContext;
74     }
75
76     public SequenceType[] getArgumentTypes() {
77         SequenceType[] types = new SequenceType[arguments.size()];
78         for (int i=0; i<arguments.size(); i++) {
79             types[i] = ((RangeVariableDeclaration)arguments.get(i)).getRequiredType();
80         }
81         return types;
82     }
83
84     public UserFunctionParameter[] getParameterDefinitions() {
85         UserFunctionParameter[] params = new UserFunctionParameter[arguments.size()];
86         for (int i=0; i<arguments.size(); i++) {
87             SequenceType type = ((RangeVariableDeclaration)arguments.get(i)).getRequiredType();
88             UserFunctionParameter param = new UserFunctionParameter();
89             param.setRequiredType(type);
90             params[i] = param;
91         }
92         return params;
93     }
94
95     public int getNumberOfArguments() {
96         return arguments.size();
97     }
98
99     public void registerReference(UserFunctionCall ufc) {
100         references.add(ufc);
101     }
102
103     public UserFunction compile(StaticQueryContext env) throws StaticError {
104         staticContext = env;
105         try {
106             // If a query function is imported into several modules, then the compile()
107
// method will be called once for each importing module. If the compiled
108
// function already exists, then this is a repeat call, and the only thing
109
// needed is to fix up references to the function from within the importing
110
// module.
111

112             if (compiledFunction == null) {
113                 // first get the UserFunctionParameter object for each declared
114
// argument of the function, and bind the references to that argument
115
SlotManager map = env.getConfiguration().makeSlotManager();
116                 UserFunctionParameter[] params = getParameterDefinitions();
117                 Iterator JavaDoc iter = arguments.iterator();
118                 int slot = 0;
119                 while (iter.hasNext()) {
120                     RangeVariableDeclaration decl = (RangeVariableDeclaration)iter.next();
121                     UserFunctionParameter param = params[slot];
122                     param.setSlotNumber(slot++);
123                     param.setRequiredType(decl.getRequiredType());
124                     map.allocateSlotNumber(decl.getNameCode() & 0xfffff);
125                     decl.fixupReferences(param);
126                 }
127
128                 // type-check the body of the function
129

130                 body = body.simplify(env).typeCheck(env, null);
131                 body = body.optimize(env.getConfiguration().getOptimizer(), env, null);
132                 if (body instanceof ComputedExpression) {
133                     ((ComputedExpression)body).setParentExpression(this);
134                 }
135                 RoleLocator role =
136                         new RoleLocator(RoleLocator.FUNCTION_RESULT, new Integer JavaDoc(nameCode), 0, env.getNamePool());
137                 role.setSourceLocator(this);
138                 body = TypeChecker.staticTypeCheck(body, resultType, false, role, env);
139                 if (body instanceof ComputedExpression) {
140                     ((ComputedExpression)body).setParentExpression(this);
141                 }
142                 ExpressionTool.allocateSlots(body, slot, map);
143
144                 if (env.getConfiguration().getTraceListener() != null) {
145                     namespaceResolver = env.getNamespaceResolver();
146                     TraceExpression trace = new TraceExpression(body);
147                     trace.setLineNumber(lineNumber);
148                     trace.setColumnNumber(columnNumber);
149                     trace.setSystemId(env.getBaseURI());
150                     trace.setConstructType(StandardNames.XSL_FUNCTION);
151                     trace.setObjectNameCode(nameCode);
152                     trace.setLocationId(env.getLocationMap().allocateLocationId(systemId, lineNumber));
153                     body = trace;
154                 }
155
156                 compiledFunction = new UserFunction(body);
157                 compiledFunction.setFunctionNameCode(nameCode);
158                 compiledFunction.setParameterDefinitions(params);
159                 //compiledFunction.setArgumentTypes(getArgumentTypes());
160
compiledFunction.setResultType(getResultType());
161                 compiledFunction.setLineNumber(lineNumber);
162                 compiledFunction.setSystemId(systemId);
163                 compiledFunction.setExecutable(executable);
164                 compiledFunction.setStackFrameMap(map);
165
166                 // mark tail calls within the function body
167

168                 boolean tailCalls = ExpressionTool.markTailFunctionCalls(body);
169                 compiledFunction.setTailRecursive(tailCalls);
170
171                 for (int i=0; i<params.length; i++) {
172                     RangeVariableDeclaration decl = (RangeVariableDeclaration)arguments.get(i);
173                     UserFunctionParameter param = params[i];
174                     int refs = decl.getReferenceCount(param);
175                     param.setReferenceCount(refs);
176                 }
177
178             }
179
180             // bind all references to this function to the UserFunction object
181

182             fixupReferences(env);
183
184             // register this function with the function library available at run-time (e.g. for saxon:evaluate())
185

186             if (executable.getFunctionLibrary() instanceof ExecutableFunctionLibrary) {
187                 ExecutableFunctionLibrary lib = (ExecutableFunctionLibrary)executable.getFunctionLibrary();
188                 lib.addFunction(compiledFunction);
189             } else {
190                 throw new AssertionError JavaDoc("executable.getFunctionLibrary() is an instance of " +
191                         executable.getFunctionLibrary().getClass().getName());
192             }
193
194             return compiledFunction;
195         } catch (XPathException e) {
196             if (e.getLocator()==null) {
197                 e.setLocator(this);
198             }
199             if (e instanceof StaticError) {
200                 throw (StaticError)e;
201             } else {
202                 throw new StaticError(e);
203             }
204         }
205     }
206
207     /**
208      * Fix up references to this function
209      */

210
211     public void fixupReferences(StaticContext env) throws XPathException {
212         Iterator JavaDoc iter = references.iterator();
213         while (iter.hasNext()) {
214             UserFunctionCall ufc = (UserFunctionCall)iter.next();
215             ufc.setFunction(compiledFunction, env);
216         }
217     }
218
219     /**
220      * Type-check references to this function
221      */

222
223     public void checkReferences(StaticContext env) throws XPathException {
224         Iterator JavaDoc iter = references.iterator();
225         while (iter.hasNext()) {
226             UserFunctionCall ufc = (UserFunctionCall)iter.next();
227             ufc.checkFunctionCall(compiledFunction, env);
228         }
229
230         // clear the list of references, so that more can be added in another module
231
references = new ArrayList JavaDoc(0);
232
233     }
234
235     /**
236      * Produce diagnostic output showing the compiled and optimized expression tree for a function
237      * @param pool the namepool to be used
238      */

239     public void explain(NamePool pool) {
240         System.err.println("declare function " + pool.getDisplayName(nameCode) + " {");
241         body.display(4, pool, System.err);
242         System.err.println("}");
243     }
244
245     /**
246      * Get the callable compiled function contained within this XQueryFunction definition.
247      */

248
249     public UserFunction getUserFunction() {
250         return compiledFunction;
251     }
252
253     /**
254      * Get the type of construct. This will be a constant in
255      * class {@link Location}.
256      */

257
258     public int getConstructType() {
259         return StandardNames.XSL_FUNCTION;
260     }
261
262     /**
263      * Get a description of the instruction for use in error messages. For an XSLT instruction this
264      * will be the display name
265      */

266
267 // public String getDescription(NamePool pool) {
268
// return "declare function";
269
// }
270

271     /**
272      * Get a name identifying the object of the expression, for example a function name, template name,
273      * variable name, key name, element name, etc. This is used only where the name is known statically.
274      */

275
276     public int getObjectNameCode() {
277         return nameCode;
278     }
279
280     /**
281      * Get the system identifier (URI) of the source module containing
282      * the instruction. This will generally be an absolute URI. If the system
283      * identifier is not known, the method may return null. In some cases, for example
284      * where XML external entities are used, the correct system identifier is not
285      * always retained.
286      */

287
288     public String JavaDoc getSystemId() {
289         return systemId;
290     }
291
292     /**
293      * Get the line number of the instruction in the source stylesheet module.
294      * If this is not known, or if the instruction is an artificial one that does
295      * not relate to anything in the source code, the value returned may be -1.
296      */

297
298     public int getLineNumber() {
299         return lineNumber;
300     }
301
302     /**
303      * Return the public identifier for the current document event.
304      * @return A string containing the public identifier, or
305      * null if none is available.
306      * @see #getSystemId
307      */

308     public String JavaDoc getPublicId() {
309         return null;
310     }
311
312     /**
313      * Return the column number
314      * @return The column number, or -1 if none is available.
315      * @see #getLineNumber
316      */

317
318     public int getColumnNumber() {
319         return -1;
320     }
321
322     public String JavaDoc getSystemId(int locationId) {
323         return getSystemId();
324     }
325
326     public int getLineNumber(int locationId) {
327         return getLineNumber();
328     }
329
330     /**
331      * Get the namespace context of the instruction. This will not always be available, in which
332      * case the method returns null.
333      */

334
335     public NamespaceResolver getNamespaceResolver() {
336         return namespaceResolver;
337     }
338
339     /**
340      * Get the value of a particular property of the instruction. Properties
341      * of XSLT instructions are generally known by the name of the stylesheet attribute
342      * that defines them.
343      * @param name The name of the required property
344      * @return The value of the requested property, or null if the property is not available
345      */

346
347     public Object JavaDoc getProperty(String JavaDoc name) {
348         if ("name".equals(name)) {
349             return staticContext.getNamePool().getDisplayName(nameCode);
350         } else if ("as".equals(name)) {
351             return resultType.toString();
352         } else {
353             return null;
354         }
355     }
356
357     /**
358      * Get an iterator over all the properties available. The values returned by the iterator
359      * will be of type String, and each string can be supplied as input to the getProperty()
360      * method to retrieve the value of the property.
361      */

362
363     public Iterator JavaDoc getProperties() {
364         return new PairIterator("name", "as");
365     }
366
367
368 }
369
370
371 //
372
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
373
// you may not use this file except in compliance with the License. You may obtain a copy of the
374
// License at http://www.mozilla.org/MPL/
375
//
376
// Software distributed under the License is distributed on an "AS IS" basis,
377
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
378
// See the License for the specific language governing rights and limitations under the License.
379
//
380
// The Original Code is: all this file.
381
//
382
// The Initial Developer of the Original Code is Michael H. Kay
383
//
384
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
385
//
386
// Contributor(s): none
387
//
Popular Tags