package org.basex.query.path; import org.basex.data.Data; import org.basex.data.Nodes; import org.basex.query.QueryContext; import org.basex.query.item.DBNode; import org.basex.query.item.DBNodeSeq; import org.basex.query.item.Item; import org.basex.query.item.ANode; import org.basex.query.item.NodeType; import org.basex.query.iter.ValueIter; import org.basex.util.TokenBuilder; import org.basex.util.list.IntList; /** * Document test for database nodes. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ final class DocTest extends Test { /** Database nodes. */ private final Nodes nodes; /** * Constructor. * @param n database document nodes */ private DocTest(final Nodes n) { type = NodeType.DOC; nodes = n; } /** * Returns a document test. This test will only be utilized by * {@link AxisPath#index} if all context values are database nodes. * @param ctx query context * @param data data reference * @return document test */ static Test get(final QueryContext ctx, final Data data) { // use simple test if database contains only one node if(data.single()) return Test.DOC; // adopt nodes from existing sequence if(ctx.value instanceof DBNodeSeq) { final DBNodeSeq seq = (DBNodeSeq) ctx.value; return seq.complete ? Test.DOC : new DocTest(new Nodes(seq.pres, data)); } // loop through all documents and add pre values of documents // not more than 2^31 documents supported final IntList il = new IntList((int) ctx.value.size()); final ValueIter ir = ctx.value.iter(); for(Item it; (it = ir.next()) != null;) il.add(((DBNode) it).pre); return new DocTest(new Nodes(il.toArray(), data)); } @Override public boolean eval(final ANode node) { // no document node, or no database instance if(node.type != type || !(node instanceof DBNode)) return false; // ensure that the pre value is contained in the target documents final DBNode db = (DBNode) node; return nodes.data == db.data && nodes.contains(db.pre); } @Override public String toString() { return new TokenBuilder(NodeType.DOC.string()).add("(...)").toString(); } }