/** * Computes the number of results. * * @param qc query context (may be @code null) * @return number of results */ private long size(final QueryContext qc) { final Value rt = initial(qc); // skip computation if value is not a document node if (rt == null || rt.type != NodeType.DOC) return -1; final Data data = rt.data(); // skip computation if no database instance is available, is out-of-date or // if context does not contain all database nodes if (data == null || !data.meta.uptodate || data.resources.docs().size() != rt.size()) return -1; ArrayList<PathNode> nodes = data.paths.root(); long m = 1; final int sl = steps.length; for (int s = 0; s < sl; s++) { final Step curr = axisStep(s); if (curr != null) { nodes = curr.nodes(nodes, data); if (nodes == null) return -1; } else if (s + 1 == sl) { m = steps[s].size(); } else { // stop if a non-axis step is not placed last return -1; } } long sz = 0; for (final PathNode pn : nodes) sz += pn.stats.count; return sz * m; }
/** * Returns the root of the current context or {@code null}. * * @param ctx query context * @return root */ final Value root(final QueryContext ctx) { final Value v = ctx != null ? ctx.value : null; // no root specified: return context, if it does not reference a document // as e.g. happens in //a(b|c) if (root == null) return v == null || v.type != NodeType.DOC ? v : null; // root is value: return root if (root.isValue()) return (Value) root; // no root reference, no context: return null if (!(root instanceof Root) || v == null) return null; // return context sequence or root of current context return v.size() == 1 ? Root.root(v) : v; }