KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > expr > FunctionCall


1 package net.sf.saxon.expr;
2 import net.sf.saxon.om.NamePool;
3 import net.sf.saxon.trans.StaticError;
4 import net.sf.saxon.trans.XPathException;
5 import net.sf.saxon.type.ItemType;
6 import net.sf.saxon.value.Value;
7
8 import java.io.PrintStream JavaDoc;
9 import java.util.Arrays JavaDoc;
10 import java.util.Iterator JavaDoc;
11
12 /**
13 * Abstract superclass for calls to system-defined and user-defined functions
14 */

15
16 public abstract class FunctionCall extends ComputedExpression {
17
18     /**
19      * The name of the function
20      */

21
22     private int nameCode;
23
24     /**
25     * The array of expressions representing the actual parameters
26     * to the function call
27     */

28
29     protected Expression[] argument;
30
31     /**
32      * Set the name code of the function being called
33      */

34
35     public final void setFunctionNameCode(int nc) {
36         nameCode = nc;
37     }
38
39     /**
40      * Get the name code of the function being called
41      * @return the name code as recorded in the name pool
42      */

43
44     public final int getFunctionNameCode() {
45         return nameCode;
46     }
47
48     /**
49     * Determine the number of actual arguments supplied in the function call
50     */

51
52     public final int getNumberOfArguments() {
53         return argument.length;
54     }
55
56     /**
57     * Method called by the expression parser when all arguments have been supplied
58     */

59
60     public void setArguments(Expression[] args) {
61         argument = args;
62         for (int a=0; a<args.length; a++) {
63             adoptChildExpression(args[a]);
64         }
65     }
66
67     /**
68     * Simplify the function call. Default method is to simplify each of the supplied arguments and
69     * evaluate the function if all are now known.
70     */

71
72      public Expression simplify(StaticContext env) throws XPathException {
73         return simplifyArguments(env);
74     }
75
76     /**
77     * Simplify the arguments of the function.
78     * Called from the simplify() method of each function.
79     * @return the result of simplifying the arguments of the expression
80     */

81
82     protected final Expression simplifyArguments(StaticContext env) throws XPathException {
83         for (int i=0; i<argument.length; i++) {
84             Expression exp = argument[i].simplify(env);
85             if (exp != argument[i]) {
86                 adoptChildExpression(exp);
87                 argument[i] = exp;
88             }
89         }
90         return this;
91     }
92
93     /**
94     * Type-check the expression. This also calls preEvaluate() to evaluate the function
95     * if all the arguments are constant; functions that do not require this behavior
96     * can override the preEvaluate method.
97     */

98
99     public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException {
100         boolean fixed = true;
101         for (int i=0; i<argument.length; i++) {
102             Expression exp = argument[i].typeCheck(env, contextItemType);
103             if (exp != argument[i]) {
104                 adoptChildExpression(exp);
105                 argument[i] = exp;
106             }
107             if (!(argument[i] instanceof Value)) {
108                 fixed = false;
109             }
110         }
111         checkArguments(env);
112         if (fixed) {
113             return preEvaluate(env);
114         } else {
115             return this;
116         }
117     }
118
119     /**
120      * Perform optimisation of an expression and its subexpressions.
121      * <p/>
122      * <p>This method is called after all references to functions and variables have been resolved
123      * to the declaration of the function or variable, and after all type checking has been done.</p>
124      *
125      * @param opt the optimizer in use. This provides access to supporting functions; it also allows
126      * different optimization strategies to be used in different circumstances.
127      * @param env the static context of the expression
128      * @param contextItemType the static type of "." at the point where this expression is invoked.
129      * The parameter is set to null if it is known statically that the context item will be undefined.
130      * If the type of the context item is not known statically, the argument is set to
131      * {@link net.sf.saxon.type.Type#ITEM_TYPE}
132      * @return the original expression, rewritten if appropriate to optimize execution
133      * @throws net.sf.saxon.trans.StaticError if an error is discovered during this phase
134      * (typically a type error)
135      */

136
137     public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException {
138         boolean fixed = true;
139         for (int i=0; i<argument.length; i++) {
140             Expression exp = argument[i].optimize(opt, env, contextItemType);
141             if (exp != argument[i]) {
142                 adoptChildExpression(exp);
143                 argument[i] = exp;
144             }
145             if (!(argument[i] instanceof Value)) {
146                 fixed = false;
147             }
148         }
149         checkArguments(env);
150         if (fixed) {
151             return preEvaluate(env);
152         } else {
153             return this;
154         }
155     }
156
157     /**
158     * Pre-evaluate a function at compile time. Functions that do not allow
159     * pre-evaluation, or that need access to context information, can override this method.
160     */

161
162     public Expression preEvaluate(StaticContext env) throws XPathException {
163         return ExpressionTool.eagerEvaluate(this, null);
164     }
165
166     /**
167     * Promote this expression if possible
168     */

169
170     public Expression promote(PromotionOffer offer) throws XPathException {
171         Expression exp = offer.accept(this);
172         if (exp != null) {
173             return exp;
174         } else {
175             if (offer.action != PromotionOffer.UNORDERED) {
176                 for (int i=0; i<argument.length; i++) {
177                     argument[i] = doPromotion(argument[i], offer);
178                 }
179             }
180             return this;
181         }
182     }
183
184     /**
185     * Method supplied by each class of function to check arguments during parsing, when all
186     * the argument expressions have been read
187     */

188
189     protected abstract void checkArguments(StaticContext env) throws XPathException;
190
191     /**
192     * Check number of arguments. <BR>
193     * A convenience routine for use in subclasses.
194     * @param min the minimum number of arguments allowed
195     * @param max the maximum number of arguments allowed
196     * @return the actual number of arguments
197     * @throws net.sf.saxon.trans.XPathException if the number of arguments is out of range
198     */

199
200     protected int checkArgumentCount(int min, int max, StaticContext env) throws XPathException {
201         int numArgs = argument.length;
202         if (min==max && numArgs != min) {
203             throw new StaticError("Function " + getDisplayName(env.getNamePool()) + " must have "
204                     + min + pluralArguments(min),
205                     ExpressionTool.getLocator(this));
206         }
207         if (numArgs < min) {
208             throw new StaticError("Function " + getDisplayName(env.getNamePool()) + " must have at least "
209                     + min + pluralArguments(min),
210                     ExpressionTool.getLocator(this));
211         }
212         if (numArgs > max) {
213             throw new StaticError("Function " + getDisplayName(env.getNamePool()) + " must have no more than "
214                     + max + pluralArguments(max),
215                     ExpressionTool.getLocator(this));
216         }
217         return numArgs;
218     }
219
220     /**
221     * Utility routine used in constructing error messages
222     */

223
224     private static String JavaDoc pluralArguments(int num) {
225         if (num==1) return " argument";
226         return " arguments";
227     }
228
229     /**
230     * Get the immediate subexpressions of this expression
231     */

232
233     public Iterator JavaDoc iterateSubExpressions() {
234         return Arrays.asList(argument).iterator();
235     }
236
237     /**
238     * Diagnostic print of expression structure
239     */

240
241     public final String JavaDoc getDisplayName(NamePool pool) {
242         return pool.getDisplayName(getFunctionNameCode());
243     }
244
245     public void display(int level, NamePool pool, PrintStream JavaDoc out) {
246         out.println(ExpressionTool.indent(level) + "function " + getDisplayName(pool));
247         for (int a=0; a<argument.length; a++) {
248             argument[a].display(level+1, pool, out);
249         }
250     }
251
252 }
253
254 //
255
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
256
// you may not use this file except in compliance with the License. You may obtain a copy of the
257
// License at http://www.mozilla.org/MPL/
258
//
259
// Software distributed under the License is distributed on an "AS IS" basis,
260
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
261
// See the License for the specific language governing rights and limitations under the License.
262
//
263
// The Original Code is: all this file.
264
//
265
// The Initial Developer of the Original Code is Michael H. Kay.
266
//
267
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
268
//
269
// Contributor(s): none.
270
//
271
Popular Tags