@Override public final Expr compile(final QueryContext qc, final VarScope scp) throws QueryException { if (root != null) root = root.compile(qc, scp); // no steps if (steps.length == 0) return root == null ? new Context(info) : root; final Value init = qc.value, cv = initial(qc); final boolean doc = cv != null && cv.type == NodeType.DOC; qc.value = cv; try { final int sl = steps.length; for (int s = 0; s < sl; s++) { Expr e = steps[s]; // axis step: if input is a document, its type is temporarily generalized final boolean as = e instanceof Step; if (as && s == 0 && doc) cv.type = NodeType.NOD; e = e.compile(qc, scp); if (e.isEmpty()) return optPre(qc); steps[s] = e; // no axis step: invalidate context value if (!as) qc.value = null; } } finally { if (doc) cv.type = NodeType.DOC; qc.value = init; } // optimize path return optimize(qc, scp); }
@Override public Expr optimize(final QueryContext ctx, final VarScope scp) throws QueryException { if (root instanceof Context) { ctx.compInfo(OPTREMCTX); root = null; } for (final Expr e : steps) { // check for empty steps if (e.isEmpty()) return optPre(null, ctx); } return this; }
@Override public final Expr optimize(final QueryContext ctx, final VarScope scp) throws QueryException { // invalidate current context value (will be overwritten by filter) final Value cv = ctx.value; try { // return empty root if (root.isEmpty()) return optPre(null, ctx); // convert filters without numeric predicates to axis paths if (root instanceof AxisPath && !super.has(Flag.FCS)) return ((AxisPath) root.copy(ctx, scp)).addPreds(ctx, scp, preds); // no predicates.. return root; otherwise, do some advanced compilations return preds.length == 0 ? root : opt(ctx); } finally { ctx.value = cv; } }
/** * Returns true if at least one argument is empty or will yield 0 results. * * @return result of check */ protected final boolean oneIsEmpty() { for (final Expr e : exprs) if (e.isEmpty()) return true; return false; }