package org.gridkit.jvmtool.event;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Subtract one {@link Iterator} from another.
* <br/>
* Each of nested {@link Iterator}s MUST produce ordered, duplicate free
* sequence of values.
* <br/>
* Result would be ordered, duplicate free sequence of values present
* in iterator A, but not present in V.
*
* @author Alexey Ragozin (alexey.ragozin@gmail.com)
*/
public class ExcludeIterator<T> implements Iterator<T> {
@SuppressWarnings("rawtypes")
private static final Comparator NATURAL = new NaturalComaprator();
@SuppressWarnings("unchecked")
public static <T> Iterator<T> exclude(Iterator<T> a, Iterator<T> b) {
return exclude(a, b, NATURAL);
}
public static <T> Iterator<T> exclude(Iterator<T> a, Iterator<T> b, Comparator<T> cmp) {
return new ExcludeIterator<T>(a, b, cmp);
}
@SuppressWarnings("unchecked")
public static <T> Iterable<T> exclude(final Iterable<T> a, final Iterable<T> b) {
return exclude(a, b, NATURAL);
}
public static <T> Iterable<T> exclude(final Iterable<T> a, final Iterable<T> b, final Comparator<T> cmp) {
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return exclude(a.iterator(), b.iterator(), cmp);
}
};
}
private final Iterator<T> a;
private final Iterator<T> b;
private final Comparator<T> comparator;
private T peekA;
private T peekB;
@SuppressWarnings("unchecked")
public ExcludeIterator(Iterator<T> a, Iterator<T> b, Comparator<T> cmp) {
this.a = a;
this.b = b;
this.comparator = cmp == null ? NATURAL : cmp;
peekA = a.hasNext() ? next(a) : null;
peekB = b.hasNext() ? next(b) : null;
seek();
}
private T next(Iterator<T> it) {
T v = it.next();
if (v == null) {
throw new NullPointerException("null element is not allowed");
}
return v;
}
private void seek() {
while(peekA != null && peekB != null) {
int c = comparator.compare(peekA, peekB);
if (c > 0) {
peekB = b.hasNext() ? b.next() : null;
continue;
}
else if (c == 0) {
peekA = a.hasNext() ? a.next() : null;
peekB = b.hasNext() ? b.next() : null;
continue;
}
else {
break;
}
}
}
@Override
public boolean hasNext() {
return peekA != null;
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
T result = peekA;
peekA = a.hasNext() ? a.next() : null;
seek();
return result;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
private static class NaturalComaprator implements Comparator<Comparable<Object>> {
@Override
public int compare(Comparable<Object> o1, Comparable<Object> o2) {
return o1.compareTo(o2);
}
}
}