/* * Copyright 2013 Guidewire Software, Inc. */ package gw.util.diff.sorted; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; public class DiffIterator<T> implements Iterator<Diff<T>> { private final Iterator<T> _oldIterator; private final Iterator<T> _newIterator; private T _oldItem; private T _newItem; private final Comparator<? super T> _comparator; private Diff<T> _next; public DiffIterator(Iterator<T> oldIterator, Iterator<T> newIterator) { this(oldIterator, newIterator, new Comparator<T>() { @SuppressWarnings("unchecked") public int compare(T o1, T o2) { return ((Comparable<T>) o1).compareTo(o2); } }); } public DiffIterator(Iterable<T> oldIterable, Iterable<T> newIterable) { this(oldIterable.iterator(), newIterable.iterator()); } public DiffIterator(Iterable<T> oldIterable, Iterable<T> newIterable, Comparator<? super T> comparator) { this(oldIterable.iterator(), newIterable.iterator(), comparator); } public DiffIterator(Iterator<T> oldIterator, Iterator<T> newIterator, Comparator<? super T> comparator) { this._oldIterator = oldIterator; this._newIterator = newIterator; this._comparator = comparator; // prefetch first item from each iterator if (oldIterator.hasNext()) { _oldItem = oldIterator.next(); } if (newIterator.hasNext()) { _newItem = newIterator.next(); } calcNext(); } public boolean hasNext() { return _next != null; } public Diff<T> next() { if (_next == null) { throw new NoSuchElementException(); } Diff<T> lastNext = _next; calcNext(); return lastNext; } public void remove() { throw new UnsupportedOperationException(); } private void calcNext() { Integer compare = compare(); if (compare == null) { _next = null; } else if (compare > 0) { _next = new Diff<T>(null, _newItem); nextNew(); } else if (compare < 0) { _next = new Diff<T>(_oldItem, null); nextOld(); } else { _next = new Diff<T>(_oldItem, _newItem); nextOld(); nextNew(); } } private void nextOld() { _oldItem = _oldIterator.hasNext() ? _oldIterator.next() : null; } private void nextNew() { _newItem = _newIterator.hasNext() ? _newIterator.next() : null; } private Integer compare() { if (_oldItem == null) { if (_newItem == null) { return null; // no more items } return 1; } else if (_newItem == null) { return -1; } else { return _comparator.compare(_oldItem, _newItem); } } }