package jetbrains.mps.internal.collections.runtime.impl; /*Generated by MPS */ import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.AbstractSequence; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.ArrayList; public class PagingSequence<U> extends Sequence<U> implements Iterable<U> { private final AbstractSequence<U> input; private final PagingSequence.Page page; private final int length; public PagingSequence(AbstractSequence<U> input, PagingSequence.Page page, int length) { if (input == null) { throw new NullPointerException(); } if (length < 0) { throw new IllegalArgumentException("Negative page length"); } this.input = input; this.page = page; this.length = length; } @Override public Iterator<U> iterator() { return new PagingSequence.PagingIterator(); } public enum Page { TAKE(), SKIP(), TAIL(), CUT(); private Page() { } } private class PagingIterator implements Iterator<U> { private Iterator<U> inputIt; private HasNextState hasNext = HasNextState.UNKNOWN; private U next; private int countDown; private List<U> cache; private PagingIterator() { } @Override public boolean hasNext() { if (inputIt == null) { init(); } if (hasNext.unknown()) { moveToNext(); } return hasNext.hasNext(); } @Override public U next() { if (inputIt == null) { init(); } if (hasNext.unknown()) { moveToNext(); } if (!((hasNext.hasNext()))) { throw new NoSuchElementException(); } return clearNext(); } @Override public void remove() { throw new UnsupportedOperationException(); } private void init() { switch (page) { case TAKE: case SKIP: inputIt = input.toIterable().iterator(); countDown = length; break; case TAIL: case CUT: cache = new ArrayList<U>(); for (U o : input) { cache.add(o); } inputIt = cache.iterator(); countDown = Math.max(0, cache.size() - length); break; default: break; } } private void destroy() { switch (page) { case TAKE: case SKIP: break; case TAIL: case CUT: cache.clear(); break; default: break; } } @SuppressWarnings(value = "unused") private void moveToNext() { if (countDown > 0) { skipping: do { --countDown; switch (page) { case TAKE: case CUT: takeNext(); return; case SKIP: case TAIL: if (!(skipNext())) { return; } break; default: break; } } while (countDown > 0); } switch (page) { case TAKE: case CUT: stop(); break; case SKIP: case TAIL: takeNext(); break; default: break; } } private U clearNext() { U tmp = next; next = null; hasNext = HasNextState.UNKNOWN; return tmp; } private boolean skipNext() { if (inputIt.hasNext()) { inputIt.next(); next = null; return true; } else { stop(); return false; } } private void stop() { hasNext = HasNextState.AT_END; next = null; destroy(); } private void takeNext() { if (inputIt.hasNext()) { next = inputIt.next(); hasNext = HasNextState.HAS_NEXT; } else { stop(); } } } }