package org.infinispan.query.impl; import java.util.NoSuchElementException; import org.hibernate.search.query.engine.spi.EntityInfo; import org.infinispan.query.ResultIterator; /** * This is the abstract superclass of the 2 iterators. Since some of the methods have the same implementations they have * been put onto a separate class. * * @author Navin Surtani * @author Marko Luksa * @see org.infinispan.query.impl.EagerIterator * @see org.infinispan.query.impl.LazyIterator * @since 4.0 */ public abstract class AbstractIterator<E> implements ResultIterator<E> { private final Object[] buffer; /** * Index of the element that will be returned by next() */ private int index = 0; /** * The index at which the buffer starts (the global index of the element at buffer[0]) */ private int bufferIndex = -1; /** * The index of the last element that will be returned by this iterator. */ private final int lastIndex; private final QueryResultLoader resultLoader; protected AbstractIterator(QueryResultLoader resultLoader, int firstIndex, int lastIndex, int fetchSize) { if (fetchSize < 1) { throw new IllegalArgumentException("Incorrect value for fetchSize passed. Your fetchSize is less than 1"); } this.resultLoader = resultLoader; this.index = firstIndex; this.lastIndex = lastIndex; int resultCount = lastIndex == -1 ? 0 : (lastIndex + 1 - firstIndex); this.buffer = new Object[Math.min(fetchSize, resultCount)]; // don't allocate more than necessary } @Override public boolean hasNext() { return index <= lastIndex; } /** * This method is not supported and should not be used. Use cache.remove() instead. */ @Override public void remove() { throw new UnsupportedOperationException("Not supported as you are trying to change something in the cache. Please use searchableCache.put()"); } @Override public E next() { if (!hasNext()) throw new NoSuchElementException("Out of boundaries. There is no next"); if (mustInitializeBuffer()) { fillBuffer(index); } int indexToReturn = index - bufferIndex; index++; return (E) buffer[indexToReturn]; } private boolean mustInitializeBuffer() { return bufferIndex == -1 // buffer init check || index < bufferIndex // lower boundary || index >= (bufferIndex + buffer.length); // upper boundary } private void fillBuffer(int startIndex) { bufferIndex = startIndex; int resultsToLoad = Math.min(buffer.length, lastIndex + 1 - bufferIndex); for (int i = 0; i < resultsToLoad; i++) { buffer[i] = loadResult(bufferIndex + i); } } private Object loadResult(int index) { EntityInfo entityInfo = loadEntityInfo(index); return resultLoader.load(entityInfo); } protected abstract EntityInfo loadEntityInfo(int index); }