/** * Adds a local function. * * @param fun function instance * @param ii input info * @return function id * @throws QueryException query exception */ public int add(final UserFunc fun, final InputInfo ii) throws QueryException { final QNm name = fun.name; final byte[] uri = name.uri(); if (uri.length == 0) FUNNONS.thrw(ii, name.string()); if (NSGlobal.reserved(uri)) { if (fun.declared) NAMERES.thrw(ii, name.string()); funError(name, ii); } final byte[] ln = name.local(); for (int l = 0; l < funcs.length; ++l) { final QNm qn = funcs[l].name; final byte[] u = qn.uri(); final byte[] nm = qn.local(); if (eq(ln, nm) && eq(uri, u) && fun.args.length == funcs[l].args.length) { // declare function that has been called before if (!funcs[l].declared) { funcs[l] = fun; return l; } // duplicate declaration FUNCDEFINED.thrw(ii, fun.name.string()); } } // add function skeleton funcs = Array.add(funcs, fun); calls = Array.add(calls, new UserFuncCall[0]); return funcs.length - 1; }
/** * Checks if the specified step will never yield results. * * @param rt root value * @param s index of step * @return {@code true} if steps will never yield results */ private boolean emptyPath(final Value rt, final int s) { final Step step = axisStep(s); if (step == null) return false; final Axis axis = step.axis; if (s == 0) { // first location step: if (root instanceof CAttr) { // @.../child:: / @.../descendant:: if (axis == CHILD || axis == DESC) return true; } else if (root instanceof Root || root instanceof CDoc || rt != null && rt.type == NodeType.DOC) { if (axis == SELF || axis == ANCORSELF) { if (step.test != Test.NOD && step.test != Test.DOC) return true; } else if (axis == CHILD || axis == DESC) { if (step.test == Test.DOC || step.test == Test.ATT) return true; } else if (axis == DESCORSELF) { if (step.test == Test.ATT) return true; } else { return true; } } } else { // remaining steps: final Step last = axisStep(s - 1); if (last == null) return false; // .../self:: / .../descendant-or-self:: if (axis == SELF || axis == DESCORSELF) { if (step.test == Test.NOD) return false; // @.../..., text()/... if (last.axis == ATTR && step.test.type != NodeType.ATT || last.test == Test.TXT && step.test != Test.TXT) return true; if (axis == DESCORSELF) return false; // .../self:: final QNm name = step.test.name, lastName = last.test.name; if (lastName == null || name == null || lastName.local().length == 0 || name.local().length == 0) return false; // ...X/...Y return !name.eq(lastName); } // .../following-sibling:: / .../preceding-sibling:: if (axis == FOLLSIBL || axis == PRECSIBL) return last.axis == ATTR; // .../descendant:: / .../child:: / .../attribute:: if (axis == DESC || axis == CHILD || axis == ATTR) return last.axis == ATTR || last.test == Test.TXT || last.test == Test.COM || last.test == Test.PI || axis == ATTR && step.test == Test.NSP; // .../parent:: / .../ancestor:: if (axis == PARENT || axis == ANC) return last.test == Test.DOC; } return false; }
/** * Parses a jar descriptor. * * @param io XML input * @return jar descriptor container * @throws QueryException query exception */ public JarDesc parse(final IO io) throws QueryException { final JarDesc desc = new JarDesc(); try { final ANode node = new DBNode(io).children().next(); for (final ANode next : node.children()) { if (next.type != NodeType.ELM) continue; final QNm name = next.qname(); // ignore namespace to improve compatibility if (eq(JAR, name.local())) desc.jars.add(next.string()); else if (eq(CLASS, name.local())) desc.classes.add(next.string()); // [CG] Packaging: add warning if unknown elements are encountered } if (desc.jars.isEmpty()) throw BXRE_JARDESC_X.get(info, NOJARS); else if (desc.classes.isEmpty()) throw BXRE_JARDESC_X.get(info, NOCLASSES); return desc; } catch (final IOException ex) { throw BXRE_JARFAIL_X.get(info, ex); } }
/** * Finds similar function names and throws an error message. * * @param name function name * @param ii input info * @throws QueryException query exception */ public void funError(final QNm name, final InputInfo ii) throws QueryException { // find global function Functions.get().error(name, ii); // find similar local function final Levenshtein ls = new Levenshtein(); final byte[] nm = lc(name.local()); for (final UserFunc f : funcs) { if (ls.similar(nm, lc(f.name.local()), 0)) { FUNSIMILAR.thrw(ii, name.string(), f.name.string()); } } }
/** * Checks if the location path contains steps that will never yield results. * * @param stps step array * @param ctx query context */ void voidStep(final Expr[] stps, final QueryContext ctx) { for (int l = 0; l < stps.length; ++l) { final Step s = axisStep(l); if (s == null) continue; final Axis sa = s.axis; if (l == 0) { if (root instanceof CAttr) { // @.../child:: / @.../descendant:: if (sa == CHILD || sa == DESC) { ctx.compInfo(WARNDESC, root); return; } } else if (root instanceof Root || root instanceof Value && ((Value) root).type == NodeType.DOC || root instanceof CDoc) { if (sa != CHILD && sa != DESC && sa != DESCORSELF && (sa != SELF && sa != ANCORSELF || s.test != Test.NOD && s.test != Test.DOC)) { ctx.compInfo(WARNDOC, root, sa); return; } } } else { final Step ls = axisStep(l - 1); if (ls == null) continue; final Axis lsa = ls.axis; boolean warning = true; if (sa == SELF || sa == DESCORSELF) { // .../self:: / .../descendant-or-self:: if (s.test == Test.NOD) continue; // @.../..., text()/... warning = lsa == ATTR && s.test.type != NodeType.ATT || ls.test == Test.TXT && s.test != Test.TXT; if (!warning) { if (sa == DESCORSELF) continue; // .../self:: final QNm n0 = ls.test.name; final QNm n1 = s.test.name; if (n0 == null || n1 == null || n0.local().length == 0 || n1.local().length == 0) continue; // ...X/...Y warning = !n1.eq(n0); } } else if (sa == FOLLSIBL || sa == PRECSIBL) { // .../following-sibling:: / .../preceding-sibling:: warning = lsa == ATTR; } else if (sa == DESC || sa == CHILD || sa == ATTR) { // .../descendant:: / .../child:: / .../attribute:: warning = lsa == ATTR || ls.test == Test.TXT || ls.test == Test.COM || ls.test == Test.PI || sa == ATTR && s.test == Test.NSP; } else if (sa == PARENT || sa == ANC) { // .../parent:: / .../ancestor:: warning = ls.test == Test.DOC; } if (warning) { ctx.compInfo(WARNSELF, s); return; } } } }