KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > functions > VendorFunctionLibrary


1 package net.sf.saxon.functions;
2
3 import net.sf.saxon.expr.Expression;
4 import net.sf.saxon.expr.StaticContext;
5 import net.sf.saxon.expr.StaticProperty;
6 import net.sf.saxon.om.NamespaceConstant;
7 import net.sf.saxon.pattern.NodeKindTest;
8 import net.sf.saxon.trans.StaticError;
9 import net.sf.saxon.trans.XPathException;
10 import net.sf.saxon.type.ItemType;
11 import net.sf.saxon.type.Type;
12 import net.sf.saxon.Err;
13
14 import java.util.HashMap JavaDoc;
15
16 /**
17  * The VendorFunctionLibrary represents specially-recognized functions in the Saxon namespace. It doesn't
18  * handle Saxon extension functions that are implemented as normal extension functions, which are bound using
19  * the {@link JavaExtensionLibrary}.
20  */

21
22 public class VendorFunctionLibrary implements FunctionLibrary {
23
24     private HashMap JavaDoc functionTable;
25
26     public VendorFunctionLibrary() {
27         init();
28     }
29
30     /**
31      * Register an extension function in the table of function details.
32      * @param name the function name
33      * @param implementationClass the class used to implement the function
34      * @param opcode identifies the function when a single class implements several functions
35      * @param minArguments the minimum number of arguments required
36      * @param maxArguments the maximum number of arguments allowed
37      * @param itemType the item type of the result of the function
38      * @param cardinality the cardinality of the result of the function
39      * @return the entry describing the function. The entry is incomplete, it does not yet contain information
40      * about the function arguments.
41     */

42
43     protected StandardFunction.Entry register( String JavaDoc name,
44                                  Class JavaDoc implementationClass,
45                                  int opcode,
46                                  int minArguments,
47                                  int maxArguments,
48                                  ItemType itemType,
49                                  int cardinality ) {
50         StandardFunction.Entry e = StandardFunction.makeEntry(
51                 name, implementationClass, opcode, minArguments, maxArguments, itemType, cardinality);
52         functionTable.put(name, e);
53         return e;
54     }
55
56     protected void init() {
57         functionTable = new HashMap JavaDoc(30);
58         StandardFunction.Entry e;
59         e = register("evaluate", Evaluate.class, Evaluate.EVALUATE, 1, 10, Type.ITEM_TYPE, StaticProperty.ALLOWS_ZERO_OR_MORE);
60             StandardFunction.arg(e, 0, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
61
62         e = register("evaluate-node", Evaluate.class, Evaluate.EVALUATE_NODE, 1, 1, Type.ITEM_TYPE, StaticProperty.ALLOWS_ZERO_OR_MORE);
63             StandardFunction.arg(e, 0, Type.NODE_TYPE, StaticProperty.EXACTLY_ONE);
64
65         e = register("eval", Evaluate.class, Evaluate.EVAL, 1, 10, Type.ITEM_TYPE, StaticProperty.ALLOWS_ZERO_OR_MORE);
66             StandardFunction.arg(e, 0, Type.ANY_ATOMIC_TYPE, StaticProperty.EXACTLY_ONE);
67
68         e = register("expression", Evaluate.class, Evaluate.EXPRESSION, 1, 1, Type.ANY_ATOMIC_TYPE, StaticProperty.EXACTLY_ONE);
69             StandardFunction.arg(e, 0, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
70
71         e = register("parse", Parse.class, 0, 1, 1, NodeKindTest.DOCUMENT, StaticProperty.EXACTLY_ONE);
72             StandardFunction.arg(e, 0, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
73
74         e = register("serialize", Serialize.class, 0, 2, 2, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
75             StandardFunction.arg(e, 0, Type.NODE_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
76             StandardFunction.arg(e, 1, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
77
78     }
79
80     /**
81      * Test whether a Saxon function with a given name and arity is available. This supports
82      * the function-available() function in XSLT. This method may be called either at compile time
83      * or at run time.
84      * @param uri The URI of the function name
85      * @param local The local part of the function name
86      * @param arity The number of arguments. This is set to -1 in the case of the single-argument
87      * function-available() function; in this case the method should return true if there is some
88      * matching extension function, regardless of its arity.
89      */

90
91     public boolean isAvailable(int fingerprint, String JavaDoc uri, String JavaDoc local, int arity) {
92         if (uri.equals(NamespaceConstant.SAXON)) {
93             StandardFunction.Entry entry = (StandardFunction.Entry)functionTable.get(local);
94             if (entry == null) {
95                 return false;
96             }
97             return (arity == -1 ||
98                     (arity >= entry.minArguments && arity <= entry.maxArguments));
99         } else {
100             return false;
101         }
102     }
103
104     /**
105      * Bind an extension function, given the URI and local parts of the function name,
106      * and the list of expressions supplied as arguments. This method is called at compile
107      * time.
108      * @param uri The URI of the function name
109      * @param local The local part of the function name
110      * @param staticArgs The expressions supplied statically in the function call. The intention is
111      * that the static type of the arguments (obtainable via getItemType() and getCardinality() may
112      * be used as part of the binding algorithm.
113      * @return An object representing the extension function to be called, if one is found;
114      * null if no extension function was found matching the required name and arity.
115      * @throws net.sf.saxon.trans.XPathException if a function is found with the required name and arity, but
116      * the implementation of the function cannot be loaded or used; or if an error occurs
117      * while searching for the function; or if this function library "owns" the namespace containing
118      * the function call, but no function was found.
119      */

120
121     public Expression bind(int nameCode, String JavaDoc uri, String JavaDoc local, Expression[] staticArgs)
122             throws XPathException {
123         if (uri.equals(NamespaceConstant.SAXON)) {
124             StandardFunction.Entry entry = (StandardFunction.Entry)functionTable.get(local);
125             if (entry == null) {
126                 return null;
127             }
128             Class JavaDoc functionClass = entry.implementationClass;
129             SystemFunction f;
130             try {
131                 f = (SystemFunction)functionClass.newInstance();
132             } catch (Exception JavaDoc err) {
133                 throw new AssertionError JavaDoc("Failed to load Saxon extension function: " + err.getMessage());
134             }
135             f.setDetails(entry);
136             f.setFunctionNameCode(nameCode);
137             f.setArguments(staticArgs);
138             checkArgumentCount(staticArgs.length, entry.minArguments, entry.maxArguments, local);
139             return f;
140         } else {
141             return null;
142         }
143     }
144
145     /**
146      * Make a Saxon function with a given name
147      */

148
149     public Expression makeSaxonFunction(String JavaDoc localName, StaticContext env, Expression[] arguments)
150     throws XPathException {
151         String JavaDoc uri = NamespaceConstant.SAXON;
152         int nameCode = env.getNamePool().allocate("saxon", uri, localName);
153         return bind(nameCode, uri, localName, arguments);
154     }
155
156     /**
157     * Check number of arguments. <BR>
158     * A convenience routine for use in subclasses.
159     * @param min the minimum number of arguments allowed
160     * @param max the maximum number of arguments allowed
161     * @return the actual number of arguments
162     * @throws net.sf.saxon.trans.XPathException if the number of arguments is out of range
163     */

164
165     private int checkArgumentCount(int numArgs, int min, int max, String JavaDoc local) throws XPathException {
166         if (min==max && numArgs != min) {
167             throw new StaticError("Function " + Err.wrap("saxon:"+local, Err.FUNCTION) + " must have "
168                     + min + pluralArguments(min));
169         }
170         if (numArgs < min) {
171             throw new StaticError("Function " + Err.wrap("saxon:"+local, Err.FUNCTION) + " must have at least "
172                     + min + pluralArguments(min));
173         }
174         if (numArgs > max) {
175             throw new StaticError("Function " + Err.wrap("saxon:"+local, Err.FUNCTION) + " must have no more than "
176                     + max + pluralArguments(max));
177         }
178         return numArgs;
179     }
180
181     /**
182     * Utility routine used in constructing error messages
183     */

184
185     public static String JavaDoc pluralArguments(int num) {
186         if (num==1) return " argument";
187         return " arguments";
188     }
189
190     /**
191      * This method creates a copy of a FunctionLibrary: if the original FunctionLibrary allows
192      * new functions to be added, then additions to this copy will not affect the original, or
193      * vice versa.
194      *
195      * @return a copy of this function library. This must be an instance of the original class.
196      */

197
198     public FunctionLibrary copy() {
199         return this;
200     }
201 }
202 //
203
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
204
// you may not use this file except in compliance with the License. You may obtain a copy of the
205
// License at http://www.mozilla.org/MPL/
206
//
207
// Software distributed under the License is distributed on an "AS IS" basis,
208
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
209
// See the License for the specific language governing rights and limitations under the License.
210
//
211
// The Original Code is: all this file.
212
//
213
// The Initial Developer of the Original Code is Michael H. Kay.
214
//
215
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
216
//
217
// Contributor(s): none.
218
//
Popular Tags