/** * 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; }
/** * Returns the specified function. * * @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 TypedFunc get( final QNm name, final Expr[] args, final boolean dyn, final QueryContext ctx, final InputInfo ii) throws QueryException { // find function final byte[] uri = name.uri(); final byte[] ln = name.local(); // parse data type constructors if (eq(uri, XSURI)) { final Type type = AtomType.find(name, true); if (type == null || type == AtomType.NOT || type == AtomType.AAT) { final Levenshtein ls = new Levenshtein(); for (final AtomType t : AtomType.values()) { if (t.par != null && ls.similar(lc(ln), lc(t.string()), 0)) FUNSIMILAR.thrw(ii, name.string(), t.string()); } FUNCUNKNOWN.thrw(ii, name.string()); } if (args.length != 1) FUNCTYPE.thrw(ii, name.string()); final SeqType to = SeqType.get(type, SeqType.Occ.ZO); return TypedFunc.constr(new Cast(ii, args[0], to), to); } // check Java functions - only allowed with administrator permissions if (startsWith(uri, JAVAPRE) && ctx.context.user.perm(User.ADMIN)) { final String c = string(substring(uri, JAVAPRE.length)); // convert dashes to upper-case initials final TokenBuilder tb = new TokenBuilder().add(c).add('.'); boolean dash = false; for (int p = 0; p < ln.length; p += cl(ln, p)) { final int ch = cp(ln, p); if (dash) { tb.add(Character.toUpperCase(ch)); dash = false; } else { dash = ch == '-'; if (!dash) tb.add(ch); } } final String java = tb.toString(); final int i = java.lastIndexOf("."); final Class<?> cls = Reflect.find(java.substring(0, i)); if (cls == null) FUNCJAVA.thrw(ii, java); final String mth = java.substring(i + 1); return TypedFunc.java(new JavaFunc(ii, cls, mth, args)); } // check predefined functions final FuncCall fun = Functions.get().get(ln, uri, args, ctx, ii); if (fun != null) { for (final Function f : Function.UPDATING) { if (fun.def == f) { ctx.updating = true; break; } } return new TypedFunc(fun, fun.def.type(args.length)); } // find local function for (int l = 0; l < func.length; ++l) { final QNm qn = func[l].name; if (eq(ln, qn.local()) && eq(uri, qn.uri()) && args.length == func[l].args.length) return new TypedFunc(add(ii, qn, l, args), FuncType.get(func[l])); } // add function call for function that has not been defined yet if (!dyn && Types.find(name, false) == null) { return new TypedFunc( add(ii, name, add(new UserFunc(ii, name, new Var[args.length], null, false), ii), args), FuncType.arity(args.length)); } return null; }