package com.appmetr.hercules.batch.iterator; import com.appmetr.hercules.profile.DataOperationsProfile; import java.util.ArrayList; import java.util.List; /** * This class designed for iterate through getting items by batches * * IMPORTANT * This class not designed for specific cases (e.g. when batch may contain less then batchSize items, * but data store has more elements, see TupleBatchIterator as an example) * * @param <E> entity for iterate * @param <K> entity key for iterate */ public abstract class RangeBatchIterator<E, K> extends AbstractBatchIterator<E, K> { protected K currentLowKey; protected K currentHighKey; //Override this method in child classes protected abstract List<E> getRange(K lowEnd, K highEnd, boolean reverse, int batchSize, DataOperationsProfile dataOperationsProfile); protected abstract K getKey(E item); public RangeBatchIterator() { super(); currentLowKey = lowEnd; currentHighKey = highEnd; } public RangeBatchIterator(int batchSize) { super(batchSize); currentLowKey = lowEnd; currentHighKey = highEnd; } public RangeBatchIterator(K lowEnd, K highEnd) { super(lowEnd, highEnd); currentLowKey = lowEnd; currentHighKey = highEnd; } public RangeBatchIterator(K lowEnd, K highEnd, int batchSize) { super(lowEnd, highEnd, batchSize); currentLowKey = lowEnd; currentHighKey = highEnd; } protected RangeBatchIterator(K lowEnd, K highEnd, boolean reverse, int batchSize) { super(lowEnd, highEnd, reverse, batchSize); currentLowKey = lowEnd; currentHighKey = highEnd; } @Override public List<E> next(DataOperationsProfile dataOperationsProfile) { List<E> batch = getRange(currentLowKey, currentHighKey, reverse, batchSize + 1, dataOperationsProfile); List<E> result = new ArrayList<E>(); if (batch.size() == 0) { hasNext = false; } else if (batch.size() < batchSize + 1) { result = batch; hasNext = false; } else { K lastKey = getKey(batch.get(batch.size() - 1)); if (reverse) { currentHighKey = lastKey; } else { currentLowKey = lastKey; } result = batch.subList(0, batch.size() - 1); } return result; } }