/*
* ModeShape (http://www.modeshape.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.modeshape.jcr.query;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Before;
import org.modeshape.jcr.bus.RepositoryChangeBus;
import org.modeshape.jcr.cache.CachedNode;
import org.modeshape.jcr.cache.NodeCache;
import org.modeshape.jcr.cache.NodeKey;
import org.modeshape.jcr.cache.document.AbstractNodeCacheTest;
import org.modeshape.jcr.cache.document.DocumentStore;
import org.modeshape.jcr.cache.document.DocumentTranslator;
import org.modeshape.jcr.cache.document.LocalDocumentStore;
import org.modeshape.jcr.cache.document.WorkspaceCache;
import org.modeshape.jcr.query.NodeSequence.Batch;
import org.modeshape.jcr.query.NodeSequence.RowAccessor;
import org.modeshape.jcr.query.NodeSequence.RowFilter;
import org.modeshape.jcr.query.RowExtractors.ExtractFromRow;
/**
* An abstract base class for test classes that operate against {@link NodeSequence}.
*
* @author Randall Hauch (rhauch@redhat.com)
*/
public class AbstractNodeSequenceTest extends AbstractNodeCacheTest {
private ExecutorService executor;
private RepositoryChangeBus changeBus;
@Override
protected NodeCache createCache() {
executor = Executors.newCachedThreadPool();
changeBus = new RepositoryChangeBus("repo", executor);
ConcurrentMap<NodeKey, CachedNode> nodeCache = new ConcurrentHashMap<>();
DocumentStore documentStore = new LocalDocumentStore(schematicDb, repoEnv);
DocumentTranslator translator = new DocumentTranslator(context, documentStore, 100L);
WorkspaceCache workspaceCache = new WorkspaceCache(context, "repo", "ws", null, documentStore, translator, ROOT_KEY_WS1,
nodeCache, changeBus, null);
loadJsonDocuments(resource(resourceNameForWorkspaceContentDocument()));
return workspaceCache;
}
@Override
protected void shutdownCache( NodeCache cache ) {
super.shutdownCache(cache);
executor.shutdown();
}
@Override
@Before
public void beforeEach() {
super.beforeEach();
}
protected String workspaceName() {
return ((WorkspaceCache)cache).getWorkspaceName();
}
protected NodeSequence allNodes() {
return allNodes(1.0f);
}
protected long countRows( NodeSequence sequence ) {
try {
long count = 0;
Batch batch = null;
while ((batch = sequence.nextBatch()) != null) {
while (batch.hasNext()) {
batch.nextRow();
++count;
}
}
return count;
} finally {
sequence.close();
}
}
protected void print( String msg,
NodeSequence sequence,
ExtractFromRow firstExtractor,
ExtractFromRow... extractors ) {
if (!print()) return;
System.out.println(msg);
try {
Batch batch = null;
while ((batch = sequence.nextBatch()) != null) {
while (batch.hasNext()) {
batch.nextRow();
System.out.print(" ");
System.out.print(firstExtractor.getValueInRow(batch));
for (ExtractFromRow extractor : extractors) {
System.out.print(" ");
System.out.print(extractor.getValueInRow(batch));
}
System.out.println();
}
}
} finally {
sequence.close();
}
}
protected void printDetailed( String msg,
NodeSequence sequence,
ExtractFromRow... extractors ) {
if (!print()) return;
System.out.println(msg);
try {
Batch batch = null;
while ((batch = sequence.nextBatch()) != null) {
while (batch.hasNext()) {
batch.nextRow();
System.out.print(rowAsString(batch, " "));
for (ExtractFromRow extractor : extractors) {
System.out.print(" ");
System.out.print(extractor.getValueInRow(batch));
}
System.out.println();
}
}
} finally {
sequence.close();
}
}
protected NodeSequence allNodes( float score ) {
return NodeSequence.withNodeKeys(cache.getAllNodeKeys(), -1, score, workspaceName(), cache);
}
protected NodeSequence allNodes( float score,
int sizeOfBatches ) {
return multipleBatchesOf(cache.getAllNodeKeys(), score, sizeOfBatches);
}
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);
}
protected RowFilter rowFilterOfNodesWithKeysHavingWorkspaceKey( final int indexInRow,
final String workspaceKey ) {
return new RowFilter() {
@Override
public boolean isCurrentRowValid( Batch batch ) {
CachedNode node = batch.getNode(indexInRow);
if (node == null) return true;
return node.getKey().getWorkspaceKey().equals(workspaceKey);
}
};
}
protected static interface Verifier {
void verify( RowAccessor currentRow );
void complete();
}
protected void assertRowsSatisfy( NodeSequence nodeSequence,
Verifier verifier ) {
// Iterate over the batches ...
try {
Batch batch = null;
while ((batch = nodeSequence.nextBatch()) != null) {
while (batch.hasNext()) {
batch.nextRow();
verifier.verify(batch);
}
}
verifier.complete();
} finally {
nodeSequence.close();
}
}
protected String rowAsString( RowAccessor row ) {
return rowAsString(row, null);
}
protected String rowAsString( RowAccessor row,
String prefix ) {
StringBuilder sb = new StringBuilder();
if (prefix != null) sb.append(prefix);
sb.append('[');
for (int i = 0; i != row.width(); ++i) {
if (i != 0) sb.append(" | ");
CachedNode node = row.getNode(i);
sb.append(node != null ? node.getKey() : "null");
sb.append('(');
sb.append(row.getScore(i));
sb.append(')');
}
sb.append(']');
return sb.toString();
}
}