package me.prettyprint.cassandra.service; import com.google.common.collect.Iterators; import com.google.common.collect.PeekingIterator; import java.util.Iterator; import me.prettyprint.cassandra.service.template.SliceFilter; import me.prettyprint.hector.api.beans.Row; import me.prettyprint.hector.api.query.RangeSlicesQuery; /** * Iterates over the range slices, automatically refreshing the query until all matching rows are returned. * * @author thrykol */ public class RangeSlicesIterator<K, N, V> implements Iterator<Row<K, N, V>> { private RangeSlicesQuery<K, N, V> query; private K startKey; private K endKey; private PeekingIterator<Row<K, N, V>> iterator; private SliceFilter<Row<K, N, V>> filter = null; private int rows = 0; public RangeSlicesIterator(RangeSlicesQuery<K, N, V> query, K startKey, K endKey) { this.query = query; this.startKey = startKey; this.endKey = endKey; this.query.setKeys(startKey, endKey); } @Override public boolean hasNext() { if (iterator == null) { // First time through iterator = Iterators.peekingIterator(query.execute().get().getList().iterator()); } else if (!iterator.hasNext() && rows == query.getRowCount()) { // only need to do another query if maximum rows were retrieved query.setKeys(startKey, endKey); iterator = Iterators.peekingIterator(query.execute().get().getList().iterator()); rows = 0; if (iterator.hasNext()) { // First element is startKey which was the last element on the previous query result - skip it next(); } } while(filter != null && iterator != null && iterator.hasNext() && !filter.accept(iterator.peek())) { next(); if(!iterator.hasNext() && rows == query.getRowCount()) { refresh(); } } return iterator.hasNext(); } @Override public Row<K, N, V> next() { Row<K, N, V> row = iterator.next(); startKey = row.getKey(); rows++; return row; } @Override public void remove() { iterator.remove(); } public RangeSlicesIterator<K, N, V> setFilter(SliceFilter<Row<K, N, V>> filter) { this.filter = filter; return this; } private void refresh() { query.setKeys(startKey, endKey); iterator = Iterators.peekingIterator(query.execute().get().getList().iterator()); rows = 0; if (iterator.hasNext()) { // First element is startKey which was the last element on the previous query result - skip it next(); } } }