/** * Returns the specified function literal. * * @param name function name * @param arity number of arguments * @param dyn dynamic invocation flag * @param ctx query context * @param ii input info * @return literal function expression * @throws QueryException query exception */ public static FItem get( final QNm name, final long arity, final boolean dyn, final QueryContext ctx, final InputInfo ii) throws QueryException { final Expr[] args = new Expr[(int) arity]; final Var[] vars = new Var[args.length]; for (int i = 0; i < args.length; i++) { vars[i] = ctx.uniqueVar(ii, null); args[i] = new VarRef(ii, vars[i]); } final TypedFunc f = get(name, args, dyn, ctx, ii); if (f == null) { if (!dyn) FUNCUNKNOWN.thrw(ii, name + "#" + arity); return null; } // compile the function if it hasn't been done statically if (dyn && f.fun instanceof UserFuncCall) { final UserFunc usf = ((UserFuncCall) f.fun).func(); if (usf != null && usf.declared) usf.compile(ctx); } final FuncType ft = f.type; return new FuncItem(name, vars, f.fun, ft, false); }
/** * Checks if all functions have been correctly declared, and initializes all function calls. * * @throws QueryException query exception */ public void check() throws QueryException { // initialize function calls for (int i = 0; i < funcs.length; ++i) { for (final UserFuncCall c : calls[i]) c.init(funcs[i]); } for (final UserFunc f : funcs) { if (f.expr == null) EXTERNALFUNC.thrw(f.info, f.name.string()); if (!f.declared) { // function has not been declared yet for (final UserFunc uf : funcs) { // check if another function with same name exists if (f != uf && f.name.eq(uf.name)) FUNCTYPE.thrw(f.info, uf.name.string()); } // if not, indicate that function is unknown FUNCUNKNOWN.thrw(f.info, f.name.string()); } } }
/** * Returns an instance of a with the specified name and number of arguments, or {@code null}. * * @param name name of the function * @param args optional arguments * @param dyn compile-/run-time flag * @param ctx query context * @param ii input info * @return function instance * @throws QueryException query exception */ public static TypedFunc get( final QNm name, final Expr[] args, final boolean dyn, final QueryContext ctx, final InputInfo ii) throws QueryException { // get namespace and local name // parse data type constructors if (eq(name.uri(), XSURI)) { final byte[] ln = name.local(); final AtomType type = AtomType.find(name, false); if (type == null) { final Levenshtein ls = new Levenshtein(); for (final AtomType t : AtomType.values()) { if (t.par != null && t != AtomType.NOT && t != AtomType.AAT && t != AtomType.BIN && ls.similar(lc(ln), lc(t.string()), 0)) FUNSIMILAR.thrw(ii, name.string(), t.string()); } } // no constructor function found, or abstract type specified if (type == null || type == AtomType.NOT || type == AtomType.AAT) { FUNCUNKNOWN.thrw(ii, name.string()); } if (args.length != 1) FUNCTYPE.thrw(ii, name.string()); final SeqType to = SeqType.get(type, Occ.ZERO_ONE); return TypedFunc.constr(new Cast(ii, args[0], to), to); } // pre-defined functions final StandardFunc fun = Functions.get().get(name, args, ii); if (fun != null) { if (!ctx.sc.xquery3 && fun.xquery3()) FEATURE30.thrw(ii); for (final Function f : Function.UPDATING) { if (fun.sig == f) { ctx.updating(true); break; } } return new TypedFunc(fun, fun.sig.type(args.length)); } // user-defined function final TypedFunc tf = ctx.funcs.get(name, args, ii); if (tf != null) return tf; // Java function (only allowed with administrator permissions) final JavaMapping jf = JavaMapping.get(name, args, ctx, ii); if (jf != null) return TypedFunc.java(jf); // add user-defined function that has not been declared yet if (!dyn && FuncType.find(name) == null) return ctx.funcs.add(name, args, ii, ctx); // no function found return null; }