/** * Optimizes descendant-or-self steps and static types. * * @param ctx query context */ void optSteps(final QueryContext ctx) { boolean opt = false; Expr[] st = steps; for (int l = 1; l < st.length; ++l) { if (!(st[l - 1] instanceof Step && st[l] instanceof Step)) continue; final Step prev = (Step) st[l - 1]; final Step curr = (Step) st[l]; if (!prev.simple(DESCORSELF, false)) continue; if (curr.axis == CHILD && !curr.has(Flag.FCS)) { // descendant-or-self::node()/child::X -> descendant::X final int sl = st.length; final Expr[] tmp = new Expr[sl - 1]; System.arraycopy(st, 0, tmp, 0, l - 1); System.arraycopy(st, l, tmp, l - 1, sl - l); st = tmp; curr.axis = DESC; opt = true; } else if (curr.axis == ATTR && !curr.has(Flag.FCS)) { // descendant-or-self::node()/@X -> descendant-or-self::*/@X prev.test = new NameTest(false); opt = true; } } if (opt) ctx.compInfo(OPTDESC); // set atomic type for single attribute steps to speedup predicate tests if (root == null && st.length == 1 && st[0] instanceof Step) { final Step curr = (Step) st[0]; if (curr.axis == ATTR && curr.test.mode == Mode.STD) curr.type = SeqType.NOD_ZO; } steps = st; }
/** * Gathers all declared variables. * * @param gs grouping specs * @param vs non-grouping variables * @return declared variables */ private static Var[] vars(final Spec[] gs, final Var[] vs) { final int gl = gs.length, vl = vs.length; final Var[] res = new Var[gl + vl]; for (int g = 0; g < gl; g++) res[g] = gs[g].var; System.arraycopy(vs, 0, res, gl, vl); return res; }
/** * Constructor. * * @param specs grouping specs * @param pre references to pre-grouping variables * @param post post-grouping variables * @param info input info */ public GroupBy(final Spec[] specs, final VarRef[] pre, final Var[] post, final InputInfo info) { super(info, vars(specs, post)); this.specs = specs; this.post = post; preExpr = new Expr[pre.length]; System.arraycopy(pre, 0, preExpr, 0, pre.length); int n = 0; for (final Spec spec : specs) if (!spec.occluded) n++; nonOcc = n; }