1 package net.sf.saxon.query; 2 import net.sf.saxon.Configuration; 3 import net.sf.saxon.expr.Expression; 4 import net.sf.saxon.expr.ExpressionTool; 5 import net.sf.saxon.expr.UserFunctionCall; 6 import net.sf.saxon.functions.FunctionLibrary; 7 import net.sf.saxon.instruct.UserFunction; 8 import net.sf.saxon.om.NamePool; 9 import net.sf.saxon.trans.StaticError; 10 import net.sf.saxon.trans.XPathException; 11 12 import java.util.ArrayList ; 13 import java.util.HashMap ; 14 import java.util.Iterator ; 15 import java.util.List ; 16 17 23 24 public class XQueryFunctionLibrary implements FunctionLibrary { 25 26 private Configuration config; 27 private HashMap functions = new HashMap (20); 28 private List unboundFunctionCalls = new ArrayList (20); 29 private boolean allowForwardsReferences = false; 30 31 34 35 public XQueryFunctionLibrary(Configuration config, boolean allowForwardsReferences) { 36 this.config = config; 37 this.allowForwardsReferences = allowForwardsReferences; 38 } 39 40 43 44 public void setConfiguration(Configuration config) { 45 this.config = config; 46 } 47 48 51 52 public Configuration getConfiguration() { 53 return config; 54 } 55 56 private NamePool getNamePool() { 57 return config.getNamePool(); 58 } 59 60 63 64 public void setAllowForwardsReferences(boolean allow) { 65 allowForwardsReferences = allow; 66 } 67 68 71 72 public void declareFunction(XQueryFunction function) throws StaticError { 73 int fp = function.getFunctionFingerprint(); 74 int arity = function.getNumberOfArguments(); 75 Long keyObj = functionKey(fp, arity); 76 if (functions.get(keyObj) != null) { 77 XQueryFunction old = (XQueryFunction)functions.get(keyObj); 78 StaticError err = new StaticError("Duplicate definition of function " + 79 getNamePool().getDisplayName(fp) + 80 " (see line " + old.getLineNumber() + " in " + old.getSystemId() + ')'); 81 err.setErrorCode("XQST0034"); 82 err.setLocator(function); 83 throw err; 84 } 85 functions.put(keyObj, function); 86 } 87 88 94 private static Long functionKey(int fp, int arity) { 95 return new Long ((((long)arity)<<32) + (long)fp); 96 } 97 98 108 109 public boolean isAvailable(int fingerprint, String uri, String local, int arity) { 110 if (arity == -1) { 111 for (int i=0; i<20; i++) { 114 if (isAvailable(fingerprint, uri, local, i)) { 115 return true; 116 } 117 } 118 return false; 119 } 120 121 return (functions.get(functionKey(fingerprint, arity)) != null); 122 } 123 124 144 145 public Expression bind(int nameCode, String uri, String local, Expression[] arguments) throws XPathException { 146 int fp = getNamePool().allocate("", uri, local) & 0xfffff; 147 XQueryFunction fd = (XQueryFunction)functions.get(functionKey(fp, arguments.length)); 148 if (fd != null) { 149 UserFunctionCall ufc = new UserFunctionCall(); 150 ufc.setFunctionNameCode(nameCode); 151 ufc.setArguments(arguments); 152 ufc.setStaticType(fd.getResultType()); 153 UserFunction fn = fd.getUserFunction(); 154 if (fn == null) { 155 fd.registerReference(ufc); 157 ufc.setConfirmed(true); 158 } else { 159 ufc.setFunction(fn, fd.getStaticContext()); 160 ufc.checkFunctionCall(fn, fd.getStaticContext()); 161 } 162 return ufc; 163 } else if (allowForwardsReferences) { 164 UserFunctionCall ufc = new UserFunctionCall(); 165 ufc.setFunctionNameCode(nameCode); 166 ufc.setArguments(arguments); 167 unboundFunctionCalls.add(ufc); 168 return ufc; 169 } else { 170 return null; 171 } 172 } 173 174 175 182 183 public void bindUnboundFunctionCalls() throws StaticError { 184 Iterator iter = unboundFunctionCalls.iterator(); 185 while (iter.hasNext()) { 186 UserFunctionCall ufc = (UserFunctionCall)iter.next(); 187 int fp = ufc.getFunctionNameCode() & 0xfffff; 188 int arity = ufc.getNumberOfArguments(); 189 190 XQueryFunction fd = (XQueryFunction)functions.get(functionKey(fp, arity)); 191 if (fd != null) { 192 ufc.setStaticType(fd.getResultType()); 193 fd.registerReference(ufc); 194 } else { 195 String msg = "Cannot find a matching " + arity + 196 "-argument function named " + getNamePool().getClarkName(fp) + "()"; 197 if (!config.isAllowExternalFunctions()) { 198 msg += ". Note: external function calls have been disabled"; 199 } 200 StaticError err = new StaticError(msg, 201 ExpressionTool.getLocator(ufc)); 202 err.setErrorCode("XPST0017"); 203 throw err; 204 } 205 } 206 } 207 208 214 215 public Iterator getFunctionDefinitions() { 216 return functions.values().iterator(); 217 } 218 219 227 228 protected void fixupGlobalFunctions(StaticQueryContext env) throws XPathException { 229 Iterator iter = functions.values().iterator(); 230 while (iter.hasNext()) { 231 XQueryFunction fn = (XQueryFunction)iter.next(); 232 fn.compile(env); 233 } 234 iter = functions.values().iterator(); 235 while (iter.hasNext()) { 236 XQueryFunction fn = (XQueryFunction)iter.next(); 237 fn.checkReferences(env); 238 } 239 } 240 241 244 245 public void explainGlobalFunctions() throws XPathException { 246 Iterator iter = functions.values().iterator(); 247 while (iter.hasNext()) { 248 XQueryFunction fn = (XQueryFunction)iter.next(); 249 fn.explain(getNamePool()); 250 } 251 } 252 253 262 263 public UserFunction getUserDefinedFunction(String uri, String localName, int arity) { 264 int fp = getNamePool().allocate("", uri, localName) & 0xfffff; 265 XQueryFunction function = (XQueryFunction)functions.get(functionKey(fp, arity)); 266 if (function==null) { 267 return null; 268 } 269 return function.getUserFunction(); 270 } 271 272 279 280 public FunctionLibrary copy() { 281 XQueryFunctionLibrary qfl = new XQueryFunctionLibrary(config, allowForwardsReferences); 282 qfl.functions = new HashMap (functions); 283 qfl.unboundFunctionCalls = new ArrayList (unboundFunctionCalls); 284 return qfl; 285 } 286 287 } 288 289 | Popular Tags |