001: package net.sf.saxon.functions;
002:
003: import net.sf.saxon.Configuration;
004: import net.sf.saxon.expr.Expression;
005: import net.sf.saxon.expr.UserFunctionCall;
006: import net.sf.saxon.instruct.UserFunction;
007: import net.sf.saxon.trans.IndependentContext;
008: import net.sf.saxon.trans.XPathException;
009:
010: import java.util.HashMap;
011:
012: /**
013: * An ExecutableFunctionLibrary is a function library that contains definitions of functions for use at
014: * run-time. Normally functions are bound at compile-time; however there are various situations in which
015: * the information is needed dynamically, for example (a) to support the XSLT function-available() call
016: * (in the pathological case where the argument is not known statically), (b) to allow functions to be
017: * called from saxon:evaluate(), (c) to allow functions to be called from a debugging breakpoint.
018: *
019: * The objects actually held in the ExecutableFunctionLibrary are UserFunctionCall objects that have been
020: * prepared at compile time. These are function calls that do full dynamic type checking: that is, they
021: * are prepared on the basis that the static types of the arguments are all "item()*", meaning that full
022: * type checking is needed at run-time.
023: */
024:
025: public class ExecutableFunctionLibrary implements FunctionLibrary {
026:
027: private Configuration config;
028: private HashMap functions = new HashMap(20);
029:
030: // The key of the hash table is a Long containing the arity in the top half, and the
031: // fingerprint of the function name in the bottom half. The value is a UserFunction object.
032:
033: public ExecutableFunctionLibrary(Configuration config) {
034: this .config = config;
035: }
036:
037: /**
038: * Register a function with the function library
039: */
040:
041: public void addFunction(UserFunction fn) {
042: long key = ((long) fn.getNumberOfArguments()) << 32
043: | (fn.getFunctionNameCode() & 0xfffff);
044: functions.put(new Long(key), fn);
045: }
046:
047: /**
048: * Test whether a function with a given name and arity is available. This supports
049: * the function-available() function in XSLT.
050: * @param uri The URI of the function name
051: * @param local The local part of the function name
052: * @param arity The number of arguments. This is set to -1 in the case of the single-argument
053: * function-available() function; in this case the method should return true if there is some
054: * matching extension function, regardless of its arity.
055: */
056:
057: public boolean isAvailable(int fingerprint, String uri,
058: String local, int arity) {
059: if (arity == -1) {
060: for (int i = 0; i <= 20; i++) {
061: if (isAvailable(fingerprint, uri, local, i)) {
062: return true;
063: }
064: }
065: return false;
066: }
067: long key = ((long) arity) << 32 | fingerprint;
068: return functions.get(new Long(key)) != null;
069: }
070:
071: /**
072: * Bind a function, given the URI and local parts of the function name,
073: * and the list of expressions supplied as arguments. This method is called at compile
074: * time.
075: * @param nameCode The namepool nameCode of the function name. The uri and local name are also
076: * supplied (redundantly) to avoid fetching them from the name pool.
077: * @param uri The URI of the function name
078: * @param local The local part of the function name
079: * @param staticArgs The expressions supplied statically in the function call. The intention is
080: * that the static type of the arguments (obtainable via getItemType() and getCardinality() may
081: * be used as part of the binding algorithm.
082: * @return An object representing the extension function to be called, if one is found;
083: * null if no extension function was found matching the required name and arity.
084: * @throws net.sf.saxon.trans.XPathException if a function is found with the required name and arity, but
085: * the implementation of the function cannot be loaded or used; or if an error occurs
086: * while searching for the function; or if this function library "owns" the namespace containing
087: * the function call, but no function was found.
088: */
089:
090: public Expression bind(int nameCode, String uri, String local,
091: Expression[] staticArgs) throws XPathException {
092: long key = ((long) staticArgs.length) << 32
093: | (nameCode & 0xfffff);
094: UserFunction fn = (UserFunction) functions.get(new Long(key));
095: if (fn == null) {
096: return null;
097: }
098: IndependentContext env = new IndependentContext(config); // this is needed only for the name pool
099: UserFunctionCall fc = new UserFunctionCall();
100: fc.setFunctionNameCode(nameCode);
101: fc.setArguments(staticArgs);
102: fc.setFunction(fn, env);
103: fc.checkFunctionCall(fn, env);
104: fc.setStaticType(fn.getResultType());
105: return fc;
106: }
107:
108: /**
109: * This method creates a copy of a FunctionLibrary: if the original FunctionLibrary allows
110: * new functions to be added, then additions to this copy will not affect the original, or
111: * vice versa.
112: *
113: * @return a copy of this function library. This must be an instance of the original class.
114: */
115:
116: public FunctionLibrary copy() {
117: ExecutableFunctionLibrary efl = new ExecutableFunctionLibrary(
118: config);
119: efl.functions = new HashMap(functions);
120: return efl;
121: }
122:
123: }
124:
125: //
126: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
127: // you may not use this file except in compliance with the License. You may obtain a copy of the
128: // License at http://www.mozilla.org/MPL/
129: //
130: // Software distributed under the License is distributed on an "AS IS" basis,
131: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
132: // See the License for the specific language governing rights and limitations under the License.
133: //
134: // The Original Code is: all this file.
135: //
136: // The Initial Developer of the Original Code is Michael H. Kay.
137: //
138: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
139: //
140: // Contributor(s): none.
141: //
|