/** * Create a sequence of nodes that iterates over the supplied node keys. Note that the supplied iterator is accessed lazily as * the resulting sequence's {@link #nextBatch() first batch} is {@link Batch#nextRow() used}. * * @param keys the iterator over the keys of the node keys to be returned; if null, an {@link #emptySequence empty instance} * is returned * @param keyCount the number of node keys in the iterator; must be -1 if not known, 0 if known to be empty, or a positive * number if the number of node keys is known * @param score the score to return for all of the nodes * @param workspaceName the name of the workspace in which all of the nodes exist * @param cache the node cache used to access the cached nodes; may be null only if the key sequence is null or empty * @return the sequence of nodes; never null */ public static NodeSequence withNodeKeys( final Iterator<NodeKey> keys, final long keyCount, final float score, final String workspaceName, final NodeCache cache ) { assert keyCount >= -1; if (keys == null) return emptySequence(1); return withBatch(batchOfKeys(keys, keyCount, score, workspaceName, cache)); }
/** * Create a sequence of nodes that iterates over the supplied nodes. Note that the supplied iterator is accessed lazily as the * resulting sequence's {@link #nextBatch() first batch} is {@link Batch#nextRow() used}. * * @param nodes the iterator over the node keys to be returned; if null, an {@link #emptySequence empty instance} is returned * @param nodeCount the number of nodes in the iterator; must be -1 if not known, 0 if known to be empty, or a positive number * if the number of nodes is known * @param score the score to return for all of the nodes * @param workspaceName the name of the workspace in which all of the nodes exist * @return the sequence of nodes; never null */ public static NodeSequence withNodes( final Iterator<CachedNode> nodes, final long nodeCount, final float score, final String workspaceName ) { assert nodeCount >= -1; if (nodes == null) return emptySequence(1); return withBatch(batchOf(nodes, nodeCount, score, workspaceName)); }
rows = NodeSequence.emptySequence(columns.getColumns().size()); } else { if (!rows.isEmpty() && !(rows instanceof DistinctSequence)) { boolean pack = false; boolean useHeap = false; if (0 >= right.getRowCount() && right.getRowCount() < 100) useHeap = true; ExtractFromRow leftExtractor = null; ExtractFromRow rightExtractor = null; for (Constraint constraint : constraints) { RowFilter constraintFilter = createRowFilter(constraint, context, columns, sources); filter = NodeSequence.requireBoth(filter, constraintFilter); rows = NodeSequence.filter(rows, filter); // even if filter is null break; case LIMIT: rows = NodeSequence.limit(rows, limit); rows = NodeSequence.emptySequence(columns.getColumns().size()); break; case PROJECT: Constraint constraint = plan.getProperty(Property.SELECT_CRITERIA, Constraint.class); filter = createRowFilter(constraint, context, columns, sources); rows = NodeSequence.filter(rows, filter); break;
@Test public void shouldCreateEmptySequenceOfVariousWidths() { for (int i = 0; i != 10; ++i) { NodeSequence seq = NodeSequence.emptySequence(i); assertThat("Incorrect width for empty sequence", seq.width(), is(i)); assertThat(seq.nextBatch(), is(nullValue())); seq.close(); } }
/** * Create a sequence of nodes that iterates over the supplied node keys. Note that the supplied iterator is accessed lazily as * the resulting sequence's {@link #nextBatch() first batch} is {@link Batch#nextRow() used}. * * @param keys the iterator over the keys of the nodes to be returned; if null, an {@link #emptySequence empty instance} is * returned * @param score the score to return for all of the nodes * @param workspaceName the name of the workspace in which all of the nodes exist * @param cache the cache used to access the cached nodes; may be null only if the key sequence is null or empty * @return the sequence of nodes; never null */ public static NodeSequence withNodeKeys( final Collection<NodeKey> keys, final float score, final String workspaceName, final NodeCache cache ) { if (keys == null || keys.isEmpty()) return emptySequence(1); return withNodeKeys(keys.iterator(), keys.size(), score, workspaceName, cache); }
@Override public int width() { return sequence.width(); }
/** * Create a sequence of nodes that skips a specified number of nodes before returning any nodes and that limits the number of * nodes returned. * * @param sequence the original sequence that is to be limited; may be null * @param limitAndOffset the specification of the offset and limit; if null this method simply returns <code>sequence</code> * @return the limitd sequence of nodes; never null */ public static NodeSequence limit( NodeSequence sequence, Limit limitAndOffset ) { if (sequence == null) return emptySequence(0); if (limitAndOffset != null && !limitAndOffset.isUnlimited()) { final int limit = limitAndOffset.getRowLimit(); // Perform the skip first ... if (limitAndOffset.isOffset()) { sequence = skip(sequence, limitAndOffset.getOffset()); } // And then the offset ... if (limit != Integer.MAX_VALUE) { sequence = limit(sequence, limit); } } return sequence; }
/** * Create a sequence of nodes that iterates over the supplied batches of nodes. Note that the supplied iterator is accessed * lazily as the resulting sequence instance is {@link #nextBatch() used}. * * @param batches the iterable container containing the node batches to be returned; if null, an {@link #emptySequence empty * instance} is returned * @param width the width of the batch; must be positive * @return the sequence of nodes; never null */ public static NodeSequence withBatches( final Collection<Batch> batches, final int width ) { if (batches == null || batches.isEmpty()) return emptySequence(width); if (batches.size() == 1) { Batch batch = batches.iterator().next(); assert width == batch.width(); return withBatch(batch); } // Tally the size of each batch ... long rowCount = 0L; for (Batch batch : batches) { long count = batch.rowCount(); rowCount = count < 0L ? -1L : rowCount + count; } return withBatches(batches.iterator(), width, rowCount); }
/** * Create a sequence of nodes that iterates over the supplied nodes. Note that the supplied iterator is accessed lazily as the * resulting sequence's {@link #nextBatch() first batch} is {@link Batch#nextRow() used}. * * @param nodes the iterator over the nodes to be returned; if null, an {@link #emptySequence empty instance} is returned * @param score the score to return for all of the nodes * @param workspaceName the name of the workspace in which all of the nodes exist * @return the sequence of nodes; never null */ public static NodeSequence withNodes( final Collection<CachedNode> nodes, final float score, final String workspaceName ) { if (nodes == null || nodes.isEmpty()) return emptySequence(1); return withNodes(nodes.iterator(), nodes.size(), score, workspaceName); }
/** * Create a batch of nodes around the supplied iterable container. Note that the supplied iterator is accessed lazily only * when the batch is {@link Batch#nextRow() used}. * * @param keys the iterator over the keys of the nodes to be returned; if null, an {@link #emptySequence empty instance} is * returned * @param score the score to return for all of the nodes * @param workspaceName the name of the workspace in which all of the nodes exist * @param repository the repository cache used to access the workspaces and cached nodes; may be null only if the key sequence * is null or empty * @return the batch of nodes; never null */ public static Batch batchOfKeys( final Collection<NodeKey> keys, final float score, final String workspaceName, final RepositoryCache repository ) { if (keys == null) return emptyBatch(workspaceName, 1); return batchOfKeys(keys.iterator(), keys.size(), score, workspaceName, repository); }
@Test public void shouldCreateFilteringSequenceThatIncludesOnlyNonSystemNodes() { RowFilter nonSysFilter = rowFilterOfNodesWithKeysHavingWorkspaceKey(0, NodeKey.keyForWorkspaceName(workspaceName())); NodeSequence seq = NodeSequence.filter(allNodes(), nonSysFilter); try { // Iterate over the batches ... Batch batch = null; while ((batch = seq.nextBatch()) != null) { while (batch.hasNext()) { batch.nextRow(); CachedNode node = batch.getNode(); if (node != null) { Path path = node.getPath(cache); boolean isSystem = path.getSegment(0).getName().equals(JcrLexicon.SYSTEM); assertTrue(path.isRoot() || !isSystem); } } } } finally { seq.close(); } } }
@SuppressWarnings( "unchecked" ) public CountableSequence( String workspaceName, NodeSequence original, BufferManager bufferMgr, CachedNodeSupplier nodeCache, boolean useHeap ) { this.original = original; this.workspaceName = workspaceName; this.width = original.width(); assert !original.isEmpty(); assert original.getRowCount() == -1; assert original.width() != 0; // Create the row factory ... this.rowFactory = BufferedRows.serializer(nodeCache, width); // Create the buffer into which we'll place the rows with null keys ... Serializer<BufferedRow> rowSerializer = (Serializer<BufferedRow>)BufferedRows.serializer(nodeCache, width); buffer = bufferMgr.createQueueBuffer(rowSerializer).useHeap(useHeap).make(); }
protected NodeSequence multipleBatchesOf( Iterator<NodeKey> keys, float score, int sizeOfBatches ) { List<NodeKey> listOfKeys = new ArrayList<>(); List<Batch> batches = new ArrayList<>(); while (keys.hasNext()) { for (int i = 0; i != sizeOfBatches; ++i) { if (!keys.hasNext()) break; listOfKeys.add(keys.next()); } batches.add(NodeSequence.batchOfKeys(listOfKeys.iterator(), listOfKeys.size(), score, workspaceName(), cache)); listOfKeys = new ArrayList<>(); } return NodeSequence.withBatches(batches, 1); }
/** * Obtain a {@link NodeSequence} that returns all (queryable) nodes in the workspace, where each node is assigned the given * score. * * @param score the score for each node * @param nodeCount the number of nodes (or an estimate) that will be returned * @return the sequence of nodes; never null */ public NodeSequence allNodes( float score, long nodeCount ) { // Use a single batch for the workspace content ... NodeCacheIterator iter = nodes(workspaceName, null); assert iter != null; Batch mainBatch = NodeSequence.batchOfKeys(iter, nodeCount, score, workspaceName, repo); // Nothing else to use ... return NodeSequence.withBatch(mainBatch); }
/** * Create an empty results object. */ private Results() { this.problems = NO_PROBLEMS; this.columns = IndexQueryEngine.ResultColumns.EMPTY; this.statistics = new Statistics(); this.plan = null; this.rows = NodeSequence.emptySequence(0); this.cachedNodes = null; }
@Test public void shouldCreateLimitedSequenceSmallerThanDelegate() { assertThat(countRows(NodeSequence.limit(allNodes(), 2)), is(2L)); }