package jetbrains.mps.internal.collections.runtime.impl; /*Generated by MPS */ import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.ISequence; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.ArrayList; public class ComparingSequence<U> extends Sequence<U> implements Iterable<U> { private final ISequence<? extends U> left; private final ISequence<? extends U> right; private final ISequence<?> rightGeneric; private final ComparingSequence.Kind kind; public ComparingSequence(ISequence<? extends U> left, ISequence<? extends U> right, ComparingSequence.Kind kind) { if (left == null || right == null) { throw new NullPointerException(); } this.left = left; this.right = right; this.rightGeneric = right; this.kind = kind; } public ComparingSequence(ComparingSequence.Kind kind, ISequence<? extends U> left, ISequence<?> right) { if (left == null || right == null) { throw new NullPointerException(); } assert kind == ComparingSequence.Kind.SUBSTRACTION || kind == ComparingSequence.Kind.INTERSECTION; this.left = left; this.right = null; this.rightGeneric = right; this.kind = kind; } @Override public Iterator<U> iterator() { return new ComparingSequence.ComparingIterator(); } public enum Kind { UNION(), INTERSECTION(), SUBSTRACTION(), DISJUNCTION(); private Kind() { } } private class ComparingIterator implements Iterator<U> { private CardinalityMap<Object> cardMap = new CardinalityMap<Object>(); private List<U> cache; private Iterator<? extends U> leftIt; private Iterator<? extends U> rightIt; private U next; private HasNextState hasNext = HasNextState.UNKNOWN; private ComparingIterator() { } @Override public boolean hasNext() { if (leftIt == null && rightIt == null) { init(); } if (hasNext.unknown()) { moveToNext(); } return hasNext.hasNext(); } @Override public U next() { if (leftIt == null && rightIt == 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 (kind) { case SUBSTRACTION: case INTERSECTION: for (Object o : rightGeneric.toIterable()) { cardMap.postInc(o); } leftIt = left.toIterable().iterator(); break; case UNION: leftIt = left.toIterable().iterator(); rightIt = right.toIterable().iterator(); break; case DISJUNCTION: cache = new ArrayList<U>(); for (U o : right.toIterable()) { cardMap.postInc(o); cache.add(o); } leftIt = left.toIterable().iterator(); rightIt = cache.iterator(); break; default: break; } } private void destroy() { cardMap.clear(); if (cache != null) { cache.clear(); } } private void moveToNext() { next = null; hasNext = HasNextState.AT_END; loop: do { switch (kind) { case SUBSTRACTION: if (leftIt.hasNext()) { U tmp = leftIt.next(); if (cardMap.postDec(tmp) == 0) { setNext(tmp); break loop; } } else { break loop; } break; case INTERSECTION: if (leftIt.hasNext()) { U tmp = leftIt.next(); if (cardMap.postDec(tmp) > 0) { setNext(tmp); break loop; } } else { break loop; } break; case UNION: if (leftIt.hasNext()) { U tmp = leftIt.next(); cardMap.postInc(tmp); setNext(tmp); break loop; } if (rightIt.hasNext()) { U tmp = rightIt.next(); if (cardMap.postDec(tmp) == 0) { setNext(tmp); break loop; } } else { break loop; } break; case DISJUNCTION: if (leftIt.hasNext()) { U tmp = leftIt.next(); if (cardMap.postDec(tmp) == 0) { setNext(tmp); break loop; } } else if (rightIt.hasNext()) { U tmp = rightIt.next(); if (cardMap.postDec(tmp) > 0) { setNext(tmp); break loop; } } else { break loop; } break; default: break; } } while (true); if (!((hasNext.hasNext()))) { destroy(); } } private U clearNext() { U tmp = next; next = null; hasNext = HasNextState.UNKNOWN; return tmp; } private void setNext(U tmp) { next = tmp; hasNext = HasNextState.HAS_NEXT; } } }