package pl.net.bluesoft.util.lang.cquery; import pl.net.bluesoft.util.lang.Lang; import pl.net.bluesoft.util.lang.cquery.func.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import static pl.net.bluesoft.util.lang.cquery.CQuery.from; import static pl.net.bluesoft.util.lang.cquery.Selectors.identity; /** * User: POlszewski * Date: 2011-07-29 */ public abstract class CQueryCollection<T> implements Collection<T> { @Override public boolean add(T t) { throw new UnsupportedOperationException(); } @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } @Override public boolean addAll(Collection<? extends T> c) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } public abstract Iterator<T> iterator(); public <R> CQueryCollection<R> select(final F<? super T, R> selector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new CQueryIterator<T, R>(CQueryCollection.this) { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public R next() { return selector.invoke(iterator.next()); } }; } }; } public <R> CQueryCollection<R> select(final FI<? super T, R> selector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new CQueryIterator<T, R>(CQueryCollection.this) { private int index = 0; @Override public boolean hasNext() { return iterator.hasNext(); } @Override public R next() { return selector.invoke(iterator.next(), index++); } }; } }; } public <R> CQueryCollection<R> selectMany(final F<? super T, ? extends Iterable<R>> selector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new SelectManyIterator<T, R>(CQueryCollection.this) { @Override protected Iterable<R> selectSubElements(T element) { return selector.invoke(element); } }; } }; } public <R> CQueryCollection<R> selectMany(final FI<? super T, ? extends Iterable<R>> selector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new SelectManyIterator<T, R>(CQueryCollection.this) { private int pos = 0; @Override protected Iterable<R> selectSubElements(T element) { return selector.invoke(element, pos++); } }; } }; } public <R, TCollection> CQueryCollection<R> selectMany( final F<? super T, ? extends Iterable<TCollection>> collectionSelector, final F2<? super T, ? super TCollection, R> resultSelector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new SelectManyCollectionsIterator<T, R, TCollection>(CQueryCollection.this, resultSelector) { @Override protected Iterable<TCollection> selectCollection(T t) { return collectionSelector.invoke(t); } }; } }; } public <R, TCollection> CQueryCollection<R> selectMany( final FI<? super T, ? extends Iterable<TCollection>> collectionSelector, final F2<? super T, ? super TCollection, R> resultSelector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new SelectManyCollectionsIterator<T, R, TCollection>(CQueryCollection.this, resultSelector) { private int pos = 0; @Override protected Iterable<TCollection> selectCollection(T t) { return collectionSelector.invoke(t, pos++); } }; } }; } public CQueryCollection<T> where(final P<? super T> pred) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new WhereIterator<T>(CQueryCollection.this) { @Override protected boolean meetsPredicate(T t) { return pred.invoke(t); } }; } }; } public CQueryCollection<T> where(final PI<? super T> pred) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new WhereIterator<T>(CQueryCollection.this) { private int pos = 0; @Override protected boolean meetsPredicate(T t) { return pred.invoke(t, pos++); } }; } }; } public CQueryCollection<T> notNull() { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new CQueryIterator<T, T>(CQueryCollection.this) { private T nextValue; @Override public boolean hasNext() { if (nextValue != null) { return true; } while (iterator.hasNext()) { T t = iterator.next(); if (t != null) { nextValue = t; return true; } } return false; } @Override public T next() { if (nextValue == null) { throw new IllegalStateException(); } T r = nextValue; nextValue = null; return r; } }; } }; } private abstract static class DistinctIterator<T> extends CQueryIterator<T, T> { private final Set<T> alreadyReturned; private T nextValue; private boolean hasNext = false; public DistinctIterator(Iterator<T> iterator) { super(iterator); this.alreadyReturned = createIndexSet(); } @Override public boolean hasNext() { if (hasNext) { return true; } while (iterator.hasNext()) { T t = iterator.next(); if (!alreadyReturned.contains(t)) { alreadyReturned.add(t); nextValue = t; hasNext = true; return true; } } return false; } @Override public T next() { if (!hasNext) { throw new IllegalStateException(); } hasNext = false; return nextValue; } protected abstract Set<T> createIndexSet(); } public CQueryCollection<T> distinct() { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new DistinctIterator<T>(CQueryCollection.this.iterator()) { @Override protected Set<T> createIndexSet() { return new HashSet<T>(); } }; } }; } public CQueryCollection<T> distinct(final EqualityComparer<? super T> comparer) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new DistinctIterator<T>(CQueryCollection.this.iterator()) { @Override protected Set<T> createIndexSet() { return new CustomEqualitySet<T>(comparer); } }; } }; } public CQueryCollection<T> skip(final int n) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new CQueryIterator<T, T>(CQueryCollection.this) { private int skip = 0; @Override public boolean hasNext() { while (skip < n && iterator.hasNext()) { iterator.next(); ++skip; } return iterator.hasNext(); } @Override public T next() { if (skip < n) { throw new IllegalStateException(); } return iterator.next(); } }; } }; } public CQueryCollection<T> skipWhile(final P<? super T> pred) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new SkipWhileIterator<T>(CQueryCollection.this) { @Override protected boolean meetsPredicate(T value) { return pred.invoke(value); } }; } }; } public CQueryCollection<T> skipWhile(final PI<? super T> pred) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new SkipWhileIterator<T>(CQueryCollection.this) { private int index = 0; @Override protected boolean meetsPredicate(T value) { return pred.invoke(value, index++); } }; } }; } public CQueryCollection<T> take(final int n) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new CQueryIterator<T, T>(CQueryCollection.this) { private int i = 0; @Override public boolean hasNext() { return i < n && iterator.hasNext(); } @Override public T next() { if (i < n) { return iterator.next(); } throw new IllegalStateException(); } }; } }; } public CQueryCollection<T> takeWhile(final P<? super T> pred) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new TakeWhileIterator<T>(CQueryCollection.this) { @Override protected boolean meetsPredicate(T value) { return pred.invoke(value); } }; } }; } public CQueryCollection<T> takeWhile(final PI<? super T> pred) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new TakeWhileIterator<T>(CQueryCollection.this) { private int index = 0; @Override protected boolean meetsPredicate(T value) { return pred.invoke(value, index++); } }; } }; } public <R extends Comparable<R>> OrderByCollection<T> orderBy(F<? super T, R> selector) { return new OrderByCollection<T>(this, new AscendingComparator<T, R>(selector)); } public <R extends Comparable<R>> OrderByCollection<T> orderByDescending(F<? super T, R> selector) { return new OrderByCollection<T>(this, new DescendingComparator<T, R>(selector)); } public <R> OrderByCollection<T> orderBy(F<? super T, R> selector, Comparator<? super R> comparator) { return new OrderByCollection<T>(this, new CustomAscentingComparator<T, R>(selector, comparator)); } public <R> OrderByCollection<T> orderByDescending(F<? super T, R> selector, Comparator<? super R> comparator) { return new OrderByCollection<T>(this, new CustomDescendingComparator<T, R>(selector, comparator)); } @SuppressWarnings({ "rawtypes", "unchecked" }) public CQueryCollection<T> ordered() { return new OrderByCollection<T>(this, new SimpleAscendingComparator()); } @SuppressWarnings({ "rawtypes", "unchecked" }) public CQueryCollection<T> orderedDescending() { return new OrderByCollection<T>(this, new SimpleDescendingComparator()); } public CQueryCollection<T> reverse() { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new CQueryIterator<T, T>(CQueryCollection.this) { private List<T> reversed; private int i = 0; @Override public boolean hasNext() { if (reversed != null) { return i < reversed.size(); } else { return iterator.hasNext(); } } @Override public T next() { if (reversed == null) { reversed = new ArrayList<T>(); while (iterator.hasNext()) { reversed.add(iterator.next()); } Collections.reverse(reversed); } return reversed.get(i++); } }; } }; } public CQueryCollection<T> concat(final Iterable<? extends T> iterable2) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new CQueryIterator<T, T>(CQueryCollection.this) { private boolean usingIt2 = false; @Override public boolean hasNext() { if (iterator.hasNext()) { return true; } if (!usingIt2) { iterator = iterable2.iterator(); usingIt2 = true; return iterator.hasNext(); } return false; } @Override public T next() { return iterator.next(); } }; } }; } public <Q extends T> CQueryCollection<T> concat(Q... array) { return concat(from(array)); } public String toString() { return toString(",", "[", "]"); } public String toString(String separator) { StringBuilder sb = new StringBuilder(); toStringHelper(sb, separator); return sb.toString(); } public String toString(String separator, String prefix, String suffix) { StringBuilder sb = new StringBuilder(); if (prefix != null) { sb.append(prefix); } toStringHelper(sb, separator); if (suffix != null) { sb.append(suffix); } return sb.toString(); } private void toStringHelper(StringBuilder sb, String separator) { boolean first = true; Iterator<T> it = iterator(); while (it.hasNext()) { if (!first) { sb.append(separator); } else { first = false; } T t = it.next(); sb.append(t); } } public String toString(String separator, String prefix, String suffix, String format) { StringBuilder sb = new StringBuilder(); if (prefix != null) { sb.append(prefix); } boolean first = true; Iterator<T> it = iterator(); while (it.hasNext()) { if (!first) { sb.append(separator); } else { first = false; } T t = it.next(); sb.append(String.format(format, t)); } if (suffix != null) { sb.append(suffix); } return sb.toString(); } @Override public Object[] toArray() { return toList().toArray(); // Object[] t = new Object[size()]; // int i = 0; // Iterator<T> it = iterator(); // while (it.hasNext()) { // t[i++] = it.next(); // } // return t; } //@SuppressWarnings("unchecked") @Override public <R> R[] toArray(R[] t) { return toList().toArray(t); // int size = size(); // if (t.length < size) { // t = (T[])Array.newInstance(t.getClass().getComponentType(), size); // } // else if (t.length > size) { // t[size] = null; // } // int i = 0; // Iterator<T> it = iterator(); // while (it.hasNext()) { // t[i++] = it.next(); // } // return t; } public void iterate() { for (Iterator<T> i = iterator(); i.hasNext(); i.next()) /* VOID */; } public <R> CQueryCollection<R> cast(final Class<R> clazz) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new CQueryIterator<T, R>(CQueryCollection.this) { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public R next() { T t = iterator.next(); return clazz.cast(t); } }; } }; } public <R> CQueryCollection<R> ofType(final Class<R> clazz) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new CQueryIterator<T, R>(CQueryCollection.this) { private R nextValue; @SuppressWarnings("unchecked") @Override public boolean hasNext() { if (nextValue != null) { return true; } while (iterator.hasNext()) { T t = iterator.next(); if (clazz.isInstance(t)) { nextValue = (R)t; return true; } } return false; } @Override public R next() { if (nextValue == null) { throw new IllegalStateException(); } R r = nextValue; nextValue = null; return r; } }; } }; } public List<T> toList() { //return new ArrayList<T>(this); List<T> list = new ArrayList<T>(); Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); list.add(t); } return list; } public Set<T> toSet() { // return new HashSet<T>(this); Set<T> set = new HashSet<T>(); Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); set.add(t); } return set; } public <K> Map<K, T> toMap(F<? super T, K> keySelector) { Map<K, T> map = new HashMap<K, T>(); Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); K key = keySelector.invoke(t); if (map.containsKey(key)) { throw new RuntimeException("Duplicate key " + key); } map.put(key, t); } return map; } public <K, V> Map<K, V> toMap(F<? super T, K> keySelector, F<? super T, V> valueSelector) { Map<K, V> map = new HashMap<K, V>(); Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); K key = keySelector.invoke(t); if (map.containsKey(key)) { throw new RuntimeException("Duplicate key " + key); } map.put(key, valueSelector.invoke(t)); } return map; } public <V> Map<T, V> mapTo(F<? super T, V> valueSelector) { Map<T, V> map = new HashMap<T, V>(); Iterator<T> it = iterator(); while (it.hasNext()) { T key = it.next(); V value = valueSelector.invoke(key); if (map.containsKey(key)) { throw new RuntimeException("Duplicate key " + key); } map.put(key, value); } return map; } @SuppressWarnings("unchecked") public CQueryCollection<T> defaultIfEmpty(T defaultValue) { Iterator<T> it = iterator(); if (it.hasNext()) { return this; } return from(Arrays.asList(defaultValue)); } public T first() { Iterator<T> it = iterator(); if (it.hasNext()) { return it.next(); } throw new IllegalArgumentException("Selecting first element of empty collection"); } public T firstOrDefault(T defaultValue) { Iterator<T> it = iterator(); if (it.hasNext()) { return it.next(); } return defaultValue; } public T firstOrDefault() { return firstOrDefault((T)null); } public T first(P<? super T> pred) { Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); if (pred.invoke(t)) { return t; } } throw new IllegalArgumentException("Selecting first element of empty collection"); } public T firstOrDefault(P<? super T> pred, T defaultValue) { Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); if (pred.invoke(t)) { return t; } } return defaultValue; } public T firstOrDefault(P<? super T> pred) { return firstOrDefault(pred, null); } public T last() { Iterator<T> it = iterator(); if (!it.hasNext()) { throw new IllegalArgumentException("Selecting last element of empty collection"); } T last = null; while (it.hasNext()) { last = it.next(); } return last; } public T lastOrDefault(T defaultValue) { Iterator<T> it = iterator(); if (!it.hasNext()) { return defaultValue; } T last = null; while (it.hasNext()) { last = it.next(); } return last; } public T lastOrDefault() { return lastOrDefault((T)null); } public T last(P<? super T> pred) { Iterator<T> it = iterator(); T last = null; boolean found = false; while (it.hasNext()) { T t = it.next(); if (pred.invoke(t)) { last = t; found = true; } } if (found) { return last; } throw new IllegalArgumentException("Selecting last element of empty collection"); } public T lastOrDefault(P<? super T> pred, T defaultValue) { Iterator<T> it = iterator(); T last = null; boolean found = false; while (it.hasNext()) { T t = it.next(); if (pred.invoke(t)) { last = t; found = true; } } if (found) { return last; } return defaultValue; } public T lastOrDefault(P<? super T> pred) { return lastOrDefault(pred, null); } public T single() { Iterator<T> it = iterator(); if (!it.hasNext()) { throw new IllegalStateException(); } T t = it.next(); if (it.hasNext()) { throw new IllegalStateException(); } return t; } public T single(P<? super T> pred) { Iterator<T> it = iterator(); T result = null; boolean hasResult = false; while (it.hasNext()) { T t = it.next(); if (pred.invoke(t)) { if (!hasResult) { result = t; hasResult = true; } else { throw new IllegalStateException(); } } } if (hasResult) { return result; } else { throw new IllegalStateException(); } } public T singleOrDefault(T defaultValue) { Iterator<T> it = iterator(); if (!it.hasNext()) { return defaultValue; } T t = it.next(); if (it.hasNext()) { throw new IllegalStateException(); } return t; } public T singleOrDefault() { return singleOrDefault((T)null); } public T singleOrDefault(P<? super T> pred, T defaultValue) { Iterator<T> it = iterator(); T result = null; boolean hasResult = false; while (it.hasNext()) { T t = it.next(); if (pred.invoke(t)) { if (!hasResult) { result = t; hasResult = true; } else { throw new IllegalStateException(); } } } if (hasResult) { return result; } else { return defaultValue; } } public T singleOrDefault(P<? super T> pred) { return singleOrDefault(pred, null); } public T elementAt(int index) { int i = 0; Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); if (i++ == index) { return t; } } throw new IllegalArgumentException("There is no element at index: " + index); } public T elementAtOrDefault(int index, T defaultValue) { int i = 0; Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); if (i++ == index) { return t; } } return defaultValue; } public T elementAtOrDefault(int index) { return elementAtOrDefault(index, null); } public int indexOf(T element) { int pos = 0; for (T t : this) { if (Lang.equals(t, element)) { return pos; } ++pos; } return -1; } public int indexOf(P<? super T> pred) { int pos = 0; for (T t : this) { if (pred.invoke(t)) { return pos; } ++pos; } return -1; } @Override public int size() { return count(); } public int count() { Iterator<T> it = iterator(); int size = 0; while (it.hasNext()) { it.next(); ++size; } return size; } public int count(P<? super T> pred) { Iterator<T> it = iterator(); int size = 0; while (it.hasNext()) { T t = it.next(); if (pred.invoke(t)) { ++size; } } return size; } @Override public boolean isEmpty() { return !iterator().hasNext(); } public boolean any() { return iterator().hasNext(); } public boolean any(P<? super T> pred) { Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); if (pred.invoke(t)) { return true; } } return false; } public boolean all(P<? super T> pred) { Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); if (!pred.invoke(t)) { return false; } } return true; } @Override public boolean contains(Object value) { Iterator<T> it = iterator(); if (value == null) { while (it.hasNext()) { T t = it.next(); if (t == null) { return true; } } } else { while (it.hasNext()) { Object t = it.next(); if (value.equals(t)) { return true; } } } return false; } public boolean contains(T value, EqualityComparer<? super T> comparer) { Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); if (comparer.equals(value, t)) { return true; } } return false; } public boolean containsAny(T... values) { Set<T> index = toSet(); for (T t : values) { if (index.contains(t)) { return true; } } return false; } public boolean containsAny(T[] values, EqualityComparer<T> comparer) { Set<T> index = new CustomEqualitySet<T>(comparer); for (T t : this) { index.add(t); } for (T t : values) { if (index.contains(t)) { return true; } } return false; } public boolean containsAny(Iterable<T> values) { Set<T> index = toSet(); for (T t : values) { if (index.contains(t)) { return true; } } return false; } public boolean containsAny(Iterable<T> values, EqualityComparer<T> comparer) { Set<T> index = new CustomEqualitySet<T>(comparer); for (T t : this) { index.add(t); } for (T t : values) { if (index.contains(t)) { return true; } } return false; } public boolean containsAll(T... values) { Set<T> index = toSet(); for (T t : values) { if (!index.contains(t)) { return false; } } return true; } public boolean containsAll(T[] values, EqualityComparer<T> comparer) { Set<T> index = new CustomEqualitySet<T>(comparer); for (T t : this) { index.add(t); } for (T t : values) { if (!index.contains(t)) { return false; } } return true; } public boolean containsAll(Iterable<T> values) { Set<T> index = toSet(); for (T t : values) { if (!index.contains(t)) { return false; } } return true; } @Override public boolean containsAll(Collection<?> c) { Set<?> index = toSet(); for (Object t : c) { if (!index.contains(t)) { return false; } } return true; } public boolean containsAll(Iterable<T> values, EqualityComparer<T> comparer) { Set<T> index = new CustomEqualitySet<T>(comparer); for (T t : this) { index.add(t); } for (T t : values) { if (!index.contains(t)) { return false; } } return true; } // wy element jest seedem public T aggregate(F2<? super T, ? super T, ? extends T> func) { Iterator<T> it = iterator(); if (!it.hasNext()) { return null; } T acc = it.next(); while (it.hasNext()) { acc = func.invoke(acc, it.next()); } return acc; } public <R> R aggregate(R seed, F2<? super R, ? super T, ? extends R> func) { Iterator<T> it = iterator(); R acc = seed; while (it.hasNext()) { acc = func.invoke(acc, it.next()); } return acc; } public <R, S> S aggregate(R seed, F2<? super R, ? super T, ? extends R> func, F<? super R, S> resultSelector) { Iterator<T> it = iterator(); R acc = seed; while (it.hasNext()) { acc = func.invoke(acc, it.next()); } return resultSelector.invoke(acc); } public <K, R> Map<K, R> groupAggregate(F<? super T, K> keySelector, R seed, F2<? super R, ? super T, ? extends R> aggregateFunc) { Iterator<T> it = iterator(); HashMap<K, R> result = new HashMap<K, R>(); while (it.hasNext()) { T t = it.next(); K k = keySelector.invoke(t); R acc = result.containsKey(k) ? result.get(k) : seed; result.put(k, aggregateFunc.invoke(acc, t)); } return result; } @SuppressWarnings({ "unchecked", "rawtypes" }) public <K, R> Map<K, R> groupAggregate(F<? super T, K> keySelector, F<? extends Collection<? super T>, R> aggregateFunc) { Map<K, List<T>> groups = new HashMap<K, List<T>>(); groupByHelper(groups, keySelector); for (Map.Entry<K, List<T>> e : groups.entrySet()) { ((Map.Entry)e).setValue(((F)aggregateFunc).invoke(e.getValue())); } return (Map)groups; } @SuppressWarnings("unchecked") public T min() { T min = null; for (T t : this) { if (t != null) { if (min != null) { if (((Comparable<T>)t).compareTo(min) < 0) { min = t; } } else { min = t; } } } return min; } public T min(Comparator<? super T> comparator) { T min = null; for (T t : this) { if (t != null) { if (min != null) { if (comparator.compare(t, min) < 0) { min = t; } } else { min = t; } } } return min; } public <R extends Comparable<R>> R min(F<? super T, R> selector){ R min = null; for (T t : this) { R v = selector.invoke(t); if (v != null) { if (min != null) { if (v.compareTo(min) < 0) { min = v; } } else { min = v; } } } return min; } @SuppressWarnings("unchecked") public T max() { T max = null; for (T t : this) { if (t != null) { if (max != null) { if (((Comparable<T>)t).compareTo(max) > 0) { max = t; } } else { max = t; } } } return max; } public T max(Comparator<? super T> comparator) { T max = null; for (T t : this) { if (t != null) { if (max != null) { if (comparator.compare(t, max) > 0) { max = t; } } else { max = t; } } } return max; } public <R extends Comparable<R>> R max(F<? super T, R> selector){ R max = null; for (T t : this) { R v = selector.invoke(t); if (v != null) { if (max != null) { if (v.compareTo(max) > 0) { max = v; } } else { max = v; } } } return max; } @SuppressWarnings("unchecked") public T sum() { return (T)sum((F)identity()); } @SuppressWarnings("unchecked") public <R extends Number> R sum(F<? super T, R> selector) { Iterator<T> it = iterator(); while (it.hasNext()) { R r = selector.invoke(it.next()); if (r != null) { if (r instanceof Integer) { int sum = (Integer)r; while (it.hasNext()) { r = selector.invoke(it.next()); if (r != null) { sum += (Integer)r; } } return (R)new Integer(sum); } if (r instanceof Long) { long sum = (Long)r; while (it.hasNext()) { r = selector.invoke(it.next()); if (r != null) { sum += (Long)r; } } return (R)new Long(sum); } if (r instanceof Double) { double sum = (Double)r; while (it.hasNext()) { r = selector.invoke(it.next()); if (r != null) { sum += (Double)r; } } return (R)new Double(sum); } if (r instanceof Float) { float sum = (Float)r; while (it.hasNext()) { r = selector.invoke(it.next()); if (r != null) { sum += (Float)r; } } return (R)new Float(sum); } if (r instanceof BigDecimal) { BigDecimal sum = (BigDecimal)r; while (it.hasNext()) { r = selector.invoke(it.next()); if (r != null) { sum = sum.add((BigDecimal)r); } } return (R)sum; } if (r instanceof BigInteger) { BigInteger sum = (BigInteger)r; while (it.hasNext()) { r = selector.invoke(it.next()); if (r != null) { sum = sum.add((BigInteger)r); } } return (R)sum; } throw new UnsupportedOperationException(r.getClass().getName() + " can not be sumed up"); } } return null; } @SuppressWarnings("unchecked") public T average() { return (T)average((F)identity()); } @SuppressWarnings("unchecked") public <R extends Number> R average(F<? super T, R> selector) { Iterator<T> it = iterator(); int cnt = 0; while (it.hasNext()) { R r = selector.invoke(it.next()); ++cnt; if (r != null) { if (r instanceof Integer) { int sum = (Integer)r; while (it.hasNext()) { r = selector.invoke(it.next()); ++cnt; if (r != null) { sum += (Integer)r; } } return (R)new Integer(sum/cnt); } if (r instanceof Long) { long sum = (Long)r; while (it.hasNext()) { r = selector.invoke(it.next()); ++cnt; if (r != null) { sum += (Long)r; } } return (R)new Long(sum/cnt); } if (r instanceof Double) { double sum = (Double)r; while (it.hasNext()) { r = selector.invoke(it.next()); ++cnt; if (r != null) { sum += (Double)r; } } return (R)new Double(sum/cnt); } if (r instanceof Float) { float sum = (Float)r; while (it.hasNext()) { r = selector.invoke(it.next()); ++cnt; if (r != null) { sum += (Float)r; } } return (R)new Float(sum/cnt); } if (r instanceof BigDecimal) { BigDecimal sum = (BigDecimal)r; while (it.hasNext()) { r = selector.invoke(it.next()); ++cnt; if (r != null) { sum = sum.add((BigDecimal)r); } } return (R)sum.divide(new BigDecimal(cnt)); } if (r instanceof BigInteger) { BigInteger sum = (BigInteger)r; while (it.hasNext()) { r = selector.invoke(it.next()); ++cnt; if (r != null) { sum = sum.add((BigInteger)r); } } return (R)sum.divide(new BigInteger(String.valueOf(cnt))); } throw new UnsupportedOperationException(r.getClass().getName() + " can not be sumed up"); } } return null; } private abstract static class ExceptIterator<T> extends CQueryIterator<T, T> { private final Iterable<? extends T> second; private Set<T> secondIndex; private Set<T> returned; private T toReturn; boolean hasResult = false; public ExceptIterator(Iterable<T> first, Iterable<? extends T> second) { super(first); this.second = second; } @Override public boolean hasNext() { if (hasResult) { return true; } if (secondIndex == null) { secondIndex = createIndexSet(); returned = createIndexSet(); for (T t : second) { secondIndex.add(t); } } while (iterator.hasNext()) { toReturn = iterator.next(); if (!secondIndex.contains(toReturn) && !returned.contains(toReturn)) { hasResult = true; return true; } } hasResult = false; return false; } @Override public T next() { if (hasResult) { hasResult = false; returned.add(toReturn); return toReturn; } throw new IllegalStateException(); } protected abstract Set<T> createIndexSet(); } public CQueryCollection<T> except(final Iterable<? extends T> second) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new ExceptIterator<T>(CQueryCollection.this, second) { @Override protected Set<T> createIndexSet() { return new HashSet<T>(); } }; } }; } public CQueryCollection<T> except(final Iterable<? extends T> second, final EqualityComparer<? super T> comparer) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new ExceptIterator<T>(CQueryCollection.this, second) { @Override protected Set<T> createIndexSet() { return new CustomEqualitySet<T>(comparer); } }; } }; } public <Q extends T> CQueryCollection<T> except(Q... second) { return except(from(second)); } public <Q extends T> CQueryCollection<T> except(Q[] second, final EqualityComparer<? super T> comparer) { return except(from(second), comparer); } private abstract static class IntersectIterator<T> extends CQueryIterator<T, T> { private Set<T> secondIndex; private Set<T> returned; private final Iterable<? extends T> second; private T toReturn; private boolean hasResult = false; public IntersectIterator(Iterable<T> first, Iterable<? extends T> second) { super(first); this.second = second; } @Override public boolean hasNext() { if (hasResult) { return true; } if (secondIndex == null) { secondIndex = createIndexSet(); returned = createIndexSet(); for (T t : second) { secondIndex.add(t); } } while (iterator.hasNext()) { toReturn = iterator.next(); if (secondIndex.contains(toReturn) && !returned.contains(toReturn)) { hasResult = true; return true; } } hasResult = false; return false; } @Override public T next() { if (hasResult) { hasResult = false; returned.add(toReturn); return toReturn; } throw new IllegalStateException(); } protected abstract Set<T> createIndexSet(); } public CQueryCollection<T> intersect(final Iterable<? extends T> second) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new IntersectIterator<T>(CQueryCollection.this, second) { @Override protected Set<T> createIndexSet() { return new HashSet<T>(); } }; } }; } public CQueryCollection<T> intersect(final Iterable<? extends T> second, final EqualityComparer<? super T> comparer) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new IntersectIterator<T>(CQueryCollection.this, second) { @Override protected Set<T> createIndexSet() { return new CustomEqualitySet<T>(comparer); } }; } }; } public <Q extends T> CQueryCollection<T> intersect(Q... second) { return intersect(from(second)); } public <Q extends T> CQueryCollection<T> intersect(Q[] second, final EqualityComparer<? super T> comparer) { return intersect(from(second), comparer); } private abstract static class UnionIterator<T> extends CQueryIterator<T, T> { private final Iterable<? extends T> second; private Set<T> returned; private T toReturn; private boolean hasResult = false; private boolean usingIt2 = false; public UnionIterator(Iterable<T> first, Iterable<? extends T> second) { super(first); this.second = second; this.returned = createIndexSet(); } @Override public boolean hasNext() { if (hasResult) { return true; } while (iterator.hasNext()) { toReturn = iterator.next(); if (!returned.contains(toReturn)) { hasResult = true; return true; } } if (!usingIt2) { iterator = second.iterator(); while (iterator.hasNext()) { toReturn = iterator.next(); if (!returned.contains(toReturn)) { hasResult = true; return true; } } } hasResult = false; return false; } @Override public T next() { if (hasResult) { hasResult = false; returned.add(toReturn); return toReturn; } throw new IllegalStateException(); } protected abstract Set<T> createIndexSet(); } public CQueryCollection<T> union(final Iterable<? extends T> second) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new UnionIterator<T>(CQueryCollection.this, second) { @Override protected Set<T> createIndexSet() { return new HashSet<T>(); } }; } }; } public CQueryCollection<T> union(final Iterable<? extends T> second, final EqualityComparer<? super T> comparer) { return new CQueryCollection<T>() { @Override public Iterator<T> iterator() { return new UnionIterator<T>(CQueryCollection.this, second) { @Override protected Set<T> createIndexSet() { return new CustomEqualitySet<T>(comparer); } }; } }; } public <Q extends T> CQueryCollection<T> union(Q... second) { return union(from(second)); } public <Q extends T> CQueryCollection<T> union(Q[] second, final EqualityComparer<? super T> comparer) { return union(from(second), comparer); } private abstract static class JoinIteratorBase<Outer, Inner, K, R> extends CQueryIterator<Outer, R> { protected final Iterable<? extends Inner> innerIterable; protected Map<K, List<Inner>> innerIndex; protected Outer outer; protected List<Inner> innerList; protected int innerListIndex; protected final F<? super Outer, K> outerKeySelector; protected final F<? super Inner, K> innerKeySelector; protected final F2<? super Outer,? super Inner,R> resultSelector; public JoinIteratorBase(Iterable<Outer> outer, Iterable<? extends Inner> inner, F<? super Outer, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super Outer,? super Inner,R> resultSelector) { super(outer); this.outerKeySelector = outerKeySelector; this.innerKeySelector = innerKeySelector; this.resultSelector = resultSelector; this.innerIterable = inner; } protected void createIndex() { innerIndex = createInnerIndexMap(); for (Inner i : innerIterable) { K k = innerKeySelector.invoke(i); List<Inner> list = innerIndex.get(k); if (list != null) { list.add(i); } else { list = new ArrayList<Inner>(); list.add(i); innerIndex.put(k, list); } } } protected abstract Map<K, List<Inner>> createInnerIndexMap(); } private abstract static class JoinIterator<Outer, Inner, K, R> extends JoinIteratorBase<Outer, Inner, K, R> { public JoinIterator(Iterable<Outer> outer, Iterable<? extends Inner> inner, F<? super Outer, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super Outer,? super Inner,R> resultSelector) { super(outer, inner, outerKeySelector, innerKeySelector, resultSelector); } @Override public boolean hasNext() { if (innerList != null && innerListIndex < innerList.size()) { return true; } if (innerIndex == null && iterator.hasNext()) { createIndex(); } while (iterator.hasNext()) { outer = iterator.next(); K k = outerKeySelector.invoke(outer); innerList = innerIndex.get(k); if (innerList != null) { innerListIndex = 0; return true; } } return false; } @Override public R next() { return resultSelector.invoke(outer, innerList.get(innerListIndex++)); } } public <Inner, K, R> CQueryCollection<R> join(final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super Inner,R> resultSelector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new JoinIterator<T, Inner, K, R>(CQueryCollection.this, inner, outerKeySelector, innerKeySelector, resultSelector) { @Override protected Map<K, List<Inner>> createInnerIndexMap() { return new HashMap<K, List<Inner>>(); } }; } }; } public <Inner, K, R> CQueryCollection<R> join(final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super Inner,R> resultSelector, final EqualityComparer<? super K> keyComparer) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new JoinIterator<T, Inner, K, R>(CQueryCollection.this, inner, outerKeySelector, innerKeySelector, resultSelector) { @Override protected Map<K, List<Inner>> createInnerIndexMap() { return new CustomEqualityMap<K, List<Inner>>(keyComparer); } }; } }; } public <Inner, K, R> CQueryCollection<R> join(Inner[] inner, F<? super T, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super T,? super Inner,R> resultSelector) { return join(from(inner), outerKeySelector, innerKeySelector, resultSelector); } public <Inner, K, R> CQueryCollection<R> join(Inner[] inner, F<? super T, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super T,? super Inner,R> resultSelector, EqualityComparer<? super K> keyComparer) { return join(from(inner), outerKeySelector, innerKeySelector, resultSelector, keyComparer); } public <K, R> CQueryCollection<R> join(final Iterable<T> inner, final F<? super T, K> keySelector, final F2<? super T,? super T,R> resultSelector) { return join(inner, keySelector, keySelector, resultSelector); } public <K, R> CQueryCollection<R> join(final Iterable<T> inner, final F<? super T, K> keySelector, final F2<? super T,? super T, R> resultSelector, final EqualityComparer<? super K> keyComparer) { return join(inner, keySelector, keySelector, resultSelector, keyComparer); } public <K, R> CQueryCollection<R> join(T[] inner, F<? super T, K> keySelector, F2<? super T,? super T,R> resultSelector) { return join(from(inner), keySelector, keySelector, resultSelector); } public <K, R> CQueryCollection<R> join(T[] inner, F<? super T, K> keySelector, F2<? super T,? super T, R> resultSelector, EqualityComparer<? super K> keyComparer) { return join(from(inner), keySelector, keySelector, resultSelector, keyComparer); } private abstract static class LeftJoinIterator<Outer, Inner, K, R> extends JoinIteratorBase<Outer, Inner, K, R> { public LeftJoinIterator(Iterable<Outer> outer, Iterable<? extends Inner> inner, F<? super Outer, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super Outer,? super Inner,R> resultSelector) { super(outer, inner, outerKeySelector, innerKeySelector, resultSelector); } @Override public boolean hasNext() { if (innerList != null && innerListIndex < innerList.size() || innerListIndex == -1) { return true; } if (innerIndex == null && iterator.hasNext()) { createIndex(); } while (iterator.hasNext()) { outer = iterator.next(); K k = outerKeySelector.invoke(outer); innerList = innerIndex.get(k); if (innerList != null) { innerListIndex = 0; } else { innerListIndex = -1; } return true; } return false; } @Override public R next() { if (innerListIndex >= 0) { return resultSelector.invoke(outer, innerList.get(innerListIndex++)); } else { innerListIndex = 0; return resultSelector.invoke(outer, null); } } } public <Inner, K, R> CQueryCollection<R> leftJoin(final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super Inner,R> resultSelector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new LeftJoinIterator<T, Inner, K, R>(CQueryCollection.this, inner, outerKeySelector, innerKeySelector, resultSelector) { @Override protected Map<K, List<Inner>> createInnerIndexMap() { return new HashMap<K, List<Inner>>(); } }; } }; } public <Inner, K, R> CQueryCollection<R> leftJoin(final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super Inner,R> resultSelector, final EqualityComparer<? super K> keyComparer) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new LeftJoinIterator<T, Inner, K, R>(CQueryCollection.this, inner, outerKeySelector, innerKeySelector, resultSelector) { @Override protected Map<K, List<Inner>> createInnerIndexMap() { return new CustomEqualityMap<K, List<Inner>>(keyComparer); } }; } }; } public <Inner, K, R> CQueryCollection<R> leftJoin(Inner[] inner, F<? super T, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super T,? super Inner,R> resultSelector) { return leftJoin(from(inner), outerKeySelector, innerKeySelector, resultSelector); } public <Inner, K, R> CQueryCollection<R> leftJoin(Inner[] inner, F<? super T, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super T,? super Inner,R> resultSelector, EqualityComparer<? super K> keyComparer) { return leftJoin(from(inner), outerKeySelector, innerKeySelector, resultSelector, keyComparer); } public <K, R> CQueryCollection<R> leftJoin(final Iterable<T> inner, final F<? super T, K> keySelector, final F2<? super T,? super T,R> resultSelector) { return leftJoin(inner, keySelector, keySelector, resultSelector); } public <K, R> CQueryCollection<R> leftJoin(final Iterable<T> inner, final F<? super T, K> keySelector, final F2<? super T,? super T, R> resultSelector, final EqualityComparer<? super K> keyComparer) { return leftJoin(inner, keySelector, keySelector, resultSelector, keyComparer); } public <K, R> CQueryCollection<R> leftJoin(T[] inner, F<? super T, K> keySelector, F2<? super T,? super T,R> resultSelector) { return leftJoin(from(inner), keySelector, keySelector, resultSelector); } public <K, R> CQueryCollection<R> leftJoin(T[] inner, F<? super T, K> keySelector, F2<? super T,? super T, R> resultSelector, EqualityComparer<? super K> keyComparer) { return leftJoin(from(inner), keySelector, keySelector, resultSelector, keyComparer); } private static class ReverseArguments<X, Y, R> implements F2<Y, X, R> { private final F2<? super X, ? super Y, R> f; public ReverseArguments(F2<? super X, ? super Y, R> f) { this.f = f; } @Override public R invoke(Y y, X x) { return f.invoke(x, y); } } public <Inner, K, R> CQueryCollection<R> rightJoin(final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super Inner,R> resultSelector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new LeftJoinIterator<Inner, T, K, R>(inner, CQueryCollection.this, innerKeySelector, outerKeySelector, new ReverseArguments<T, Inner, R>(resultSelector)) { @Override protected Map<K, List<T>> createInnerIndexMap() { return new HashMap<K, List<T>>(); } }; } }; } public <Inner, K, R> CQueryCollection<R> rightJoin(final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super Inner,R> resultSelector, final EqualityComparer<? super K> keyComparer) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new LeftJoinIterator<Inner, T, K, R>(inner, CQueryCollection.this, innerKeySelector, outerKeySelector, new ReverseArguments<T, Inner, R>(resultSelector)) { @Override protected Map<K, List<T>> createInnerIndexMap() { return new CustomEqualityMap<K, List<T>>(keyComparer); } }; } }; } public <Inner, K, R> CQueryCollection<R> rightJoin(Inner[] inner, F<? super T, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super T,? super Inner,R> resultSelector) { return rightJoin(from(inner), outerKeySelector, innerKeySelector, resultSelector); } public <Inner, K, R> CQueryCollection<R> rightJoin(Inner[] inner, F<? super T, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super T,? super Inner,R> resultSelector, EqualityComparer<? super K> keyComparer) { return rightJoin(from(inner), outerKeySelector, innerKeySelector, resultSelector, keyComparer); } public <K, R> CQueryCollection<R> rightJoin(final Iterable<T> inner, final F<? super T, K> keySelector, final F2<? super T,? super T,R> resultSelector) { return rightJoin(inner, keySelector, keySelector, resultSelector); } public <K, R> CQueryCollection<R> rightJoin(final Iterable<T> inner, final F<? super T, K> keySelector, final F2<? super T,? super T, R> resultSelector, final EqualityComparer<? super K> keyComparer) { return rightJoin(inner, keySelector, keySelector, resultSelector, keyComparer); } public <K, R> CQueryCollection<R> rightJoin(T[] inner, F<? super T, K> keySelector, F2<? super T,? super T,R> resultSelector) { return rightJoin(from(inner), keySelector, keySelector, resultSelector); } public <K, R> CQueryCollection<R> rightJoin(T[] inner, F<? super T, K> keySelector, F2<? super T,? super T, R> resultSelector, EqualityComparer<? super K> keyComparer) { return rightJoin(from(inner), keySelector, keySelector, resultSelector, keyComparer); } private abstract static class FullJoinIterator<Outer, Inner, K, R> extends JoinIteratorBase<Outer, Inner, K, R> { private Iterator<K> remainingIterator; private Set<K> remainingInnerKeys; public FullJoinIterator(Iterable<Outer> outer, Iterable<? extends Inner> inner, F<? super Outer, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super Outer,? super Inner,R> resultSelector) { super(outer, inner, outerKeySelector, innerKeySelector, resultSelector); } @Override public boolean hasNext() { if (remainingIterator != null) { if (innerList != null && innerListIndex < innerList.size()) { return true; } while (remainingIterator.hasNext()) { innerList = innerIndex.get(remainingIterator.next()); innerListIndex = 0; return true; } return false; } if (innerList != null && innerListIndex < innerList.size() || innerListIndex == -1) { return true; } if (innerIndex == null) { createIndex(); remainingInnerKeys = new HashSet<K>(innerIndex.keySet()); } while (iterator.hasNext()) { outer = iterator.next(); K k = outerKeySelector.invoke(outer); innerList = innerIndex.get(k); if (innerList != null) { innerListIndex = 0; remainingInnerKeys.remove(k); } else { innerListIndex = -1; } return true; } remainingIterator = remainingInnerKeys.iterator(); return hasNext(); } @Override public R next() { if (remainingIterator != null) { return resultSelector.invoke(null, innerList.get(innerListIndex++)); } if (innerListIndex >= 0) { R result = resultSelector.invoke(outer, innerList.get(innerListIndex++)); return result; } else { innerListIndex = -1000; return resultSelector.invoke(outer, null); } } } public <Inner, K, R> CQueryCollection<R> fullJoin(final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super Inner,R> resultSelector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new FullJoinIterator<T, Inner, K, R>(CQueryCollection.this, inner, outerKeySelector, innerKeySelector, resultSelector) { @Override protected Map<K, List<Inner>> createInnerIndexMap() { return new HashMap<K, List<Inner>>(); } }; } }; } public <Inner, K, R> CQueryCollection<R> fullJoin(final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super Inner,R> resultSelector, final EqualityComparer<? super K> keyComparer) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new FullJoinIterator<T, Inner, K, R>(CQueryCollection.this, inner, outerKeySelector, innerKeySelector, resultSelector) { @Override protected Map<K, List<Inner>> createInnerIndexMap() { return new CustomEqualityMap<K, List<Inner>>(keyComparer); } }; } }; } public <Inner, K, R> CQueryCollection<R> fullJoin(Inner[] inner, F<? super T, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super T,? super Inner,R> resultSelector) { return fullJoin(from(inner), outerKeySelector, innerKeySelector, resultSelector); } public <Inner, K, R> CQueryCollection<R> fullJoin(Inner[] inner, F<? super T, K> outerKeySelector, F<? super Inner, K> innerKeySelector, F2<? super T,? super Inner,R> resultSelector, EqualityComparer<? super K> keyComparer) { return fullJoin(from(inner), outerKeySelector, innerKeySelector, resultSelector, keyComparer); } public <K, R> CQueryCollection<R> fullJoin(final Iterable<T> inner, final F<? super T, K> keySelector, final F2<? super T,? super T,R> resultSelector) { return fullJoin(inner, keySelector, keySelector, resultSelector); } public <K, R> CQueryCollection<R> fullJoin(final Iterable<T> inner, final F<? super T, K> keySelector, final F2<? super T,? super T, R> resultSelector, final EqualityComparer<? super K> keyComparer) { return fullJoin(inner, keySelector, keySelector, resultSelector, keyComparer); } public <K, R> CQueryCollection<R> fullJoin(T[] inner, F<? super T, K> keySelector, F2<? super T,? super T,R> resultSelector) { return fullJoin(from(inner), keySelector, keySelector, resultSelector); } public <K, R> CQueryCollection<R> fullJoin(T[] inner, F<? super T, K> keySelector, F2<? super T,? super T, R> resultSelector, EqualityComparer<? super K> keyComparer) { return fullJoin(from(inner), keySelector, keySelector, resultSelector, keyComparer); } public <Inner, R> CQueryCollection<R> crossJoin(final Iterable<Inner> inner, final F2<? super T,? super Inner,R> resultSelector) { return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return new CQueryIterator<T, R>(CQueryCollection.this) { private int innerIndex = 0; private List<Inner> innerList; private boolean hasOuter; private T outer; @Override public boolean hasNext() { if (!hasOuter) { if (!iterator.hasNext()) { return false; } outer = iterator.next(); hasOuter = true; } if (innerList == null) { innerList = from(inner).toList(); } if (innerIndex >= innerList.size()) { innerIndex = 0; if (innerList.isEmpty()) { return false; } if (!iterator.hasNext()) { hasOuter = false; return false; } outer = iterator.next(); hasOuter = true; } return true; } @Override public R next() { return resultSelector.invoke(outer, innerList.get(innerIndex++)); } }; } }; } public <Inner, R> CQueryCollection<R> crossJoin(Inner[] inner, F2<? super T,? super Inner,R> resultSelector) { return crossJoin(from(inner), resultSelector); } public <K> GroupByCollection<K, T> groupBy(F<? super T, K> keySelector) { Map<K, List<T>> groups = new HashMap<K, List<T>>(); groupByHelper(groups, keySelector); return new GroupByCollection<K, T>(groups); } public <K> GroupByCollection<K, T> groupBy(F<? super T, K> keySelector, EqualityComparer<K> keyComparer) { Map<K, List<T>> groups = new CustomEqualityMap<K, List<T>>(keyComparer); groupByHelper(groups, keySelector); return new GroupByCollection<K, T>(groups); } public <K, E> GroupByCollection<K, E> groupBy(F<? super T, K> keySelector, F<? super T, E> elementSelector) { Map<K, List<E>> groups = new HashMap<K, List<E>>(); groupByHelper(groups, keySelector, elementSelector); return new GroupByCollection<K, E>(groups); } public <K, E> GroupByCollection<K, E> groupBy(F<? super T, K> keySelector, F<? super T, E> elementSelector, EqualityComparer<? super K> keyComparer) { Map<K, List<E>> groups = new CustomEqualityMap<K, List<E>>(keyComparer); groupByHelper(groups, keySelector, elementSelector); return new GroupByCollection<K, E>(groups); } public <K, E, R> CQueryCollection<R> groupBy(F<? super T, K> keySelector, F<? super T, E> elementSelector, F<? super CQueryCollection<E>, R> resultSelector) { Map<K, List<E>> groups = new HashMap<K, List<E>>(); groupByHelper(groups, keySelector, elementSelector); return transform(groups, resultSelector); } public <K, E, R> CQueryCollection<R> groupBy(F<? super T, K> keySelector, F<? super T, E> elementSelector, F<? super CQueryCollection<E>, R> resultSelector, EqualityComparer<? super K> keyComparer) { Map<K, List<E>> groups = new CustomEqualityMap<K, List<E>>(keyComparer); groupByHelper(groups, keySelector, elementSelector); return transform(groups, resultSelector); } private <K> void groupByHelper(Map<K, List<T>> groups, F<? super T, K> keySelector) { Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); K k = keySelector.invoke(t); List<T> list = groups.get(k); if (list != null) { list.add(t); } else { list = new ArrayList<T>(); list.add(t); groups.put(k, list); } } } private <K, E> void groupByHelper(Map<K, List<E>> groups, F<? super T, K> keySelector, F<? super T, E> elementSelector) { Iterator<T> it = iterator(); while (it.hasNext()) { T t = it.next(); K k = keySelector.invoke(t); E e = elementSelector.invoke(t); List<E> list = groups.get(k); if (list != null) { list.add(e); } else { list = new ArrayList<E>(); list.add(e); groups.put(k, list); } } } private <K, E, R> CQueryCollection<R> transform(Map<K, List<E>> grouping, F<? super CQueryCollection<E>, R> resultSelector) { final List<R> result = new ArrayList<R>(); for (Map.Entry<K, List<E>> group : grouping.entrySet()) { result.add(resultSelector.invoke(from(group.getValue()))); } return new CQueryCollection<R>() { @Override public Iterator<R> iterator() { return result.iterator(); } @Override public List<R> toList() { return result; } }; } @SuppressWarnings("rawtypes") public <Inner, K, R> CQueryCollection<R> groupJoin(final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super CQueryCollection<Inner>,R> resultSelector) { return groupJoinHelper(new HashMap<K, List[]>(), inner, outerKeySelector, innerKeySelector, resultSelector); } @SuppressWarnings("rawtypes") public <Inner, K, R> CQueryCollection<R> groupJoin(final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super CQueryCollection<Inner>,R> resultSelector, EqualityComparer<? super K> keyComparer) { return groupJoinHelper(new CustomEqualityMap<K, List[]>(keyComparer), inner, outerKeySelector, innerKeySelector, resultSelector); } public <Inner, K, R> CQueryCollection<R> groupJoin(Inner[] inner, final F<T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T, CQueryCollection<? super Inner>,R> resultSelector) { return groupJoin(from(inner), outerKeySelector, innerKeySelector, resultSelector); } public <Inner, K, R> CQueryCollection<R> groupJoin(Inner[] inner, final F<T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T, CQueryCollection<? super Inner>,R> resultSelector, EqualityComparer<? super K> keyComparer) { return groupJoin(from(inner), outerKeySelector, innerKeySelector, resultSelector, keyComparer); } @SuppressWarnings({ "rawtypes", "unchecked" }) private <Inner, K, R> CQueryCollection<R> groupJoinHelper(Map<K, List[]> groups, final Iterable<Inner> inner, final F<? super T, K> outerKeySelector, final F<? super Inner, K> innerKeySelector, final F2<? super T,? super CQueryCollection<Inner>,R> resultSelector) { for (T t : this) { K k = outerKeySelector.invoke(t); List[] lists = groups.get(k); if (lists != null) { lists[0].add(t); } else { lists = new List[]{ new ArrayList<T>(), new ArrayList<Inner>() }; lists[0].add(t); groups.put(k, lists); } } for (Inner in : inner) { List[] lists = groups.get(innerKeySelector.invoke(in)); if (lists != null) { if (lists[1] == null) { lists[1] = new ArrayList<Inner>(); } lists[1].add(in); } } List<R> result = new ArrayList<R>(); for (List[] lists : groups.values()) { for (T outerElem : (List<T>)lists[0]) { result.add(resultSelector.invoke(outerElem, from((List<Inner>)lists[1]))); } } return from(result); } public boolean sequenceEqual(Iterable<? extends T> second) { return sequenceEqual(second, EqualityComparer.DEFAULT); } public boolean sequenceEqual(Iterable<? extends T> second, EqualityComparer<? super T> comparer) { Iterator<T> it1 = iterator(); Iterator<? extends T> it2 = second.iterator(); while (it1.hasNext() && it2.hasNext()) { T t1 = it1.next(), t2 = it2.next(); if (!comparer.equals(t1, t2)) { return false; } } return !it1.hasNext() && !it2.hasNext(); } public <Q extends T> boolean sequenceEqual(Q... second) { return sequenceEqual(from(second)); } public <Q extends T> boolean sequenceEqual(Q[] second, EqualityComparer<? super T> comparer) { return sequenceEqual(from(second), comparer); } private abstract static class TakeWhileIterator<T> extends CQueryIterator<T, T> { private T toReturn; private boolean take; private boolean stop; public TakeWhileIterator(CQueryCollection<T> collection) { super(collection); take = true; stop = false; } protected abstract boolean meetsPredicate(T value); @Override public boolean hasNext() { if (stop) { return true; } if (!take) { return true; } take = false; if (iterator.hasNext() && meetsPredicate(toReturn = iterator.next())) { return true; } else { stop = true; return false; } } @Override public T next() { if (!take) { take = true; return toReturn; } throw new IllegalStateException(); } } private abstract static class SkipWhileIterator<T> extends CQueryIterator<T, T> { private boolean skip; private boolean firstNonskipped; private T toReturn; public SkipWhileIterator(CQueryCollection<T> collection) { super(collection); skip = true; } protected abstract boolean meetsPredicate(T value); @Override public boolean hasNext() { while (skip) { if (!iterator.hasNext()) { return false; } T t = iterator.next(); if (!meetsPredicate(t)) { skip = false; firstNonskipped = true; toReturn = t; return true; } } return iterator.hasNext(); } @Override public T next() { if (skip) { throw new IllegalStateException(); } if (firstNonskipped) { firstNonskipped = false; return toReturn; } return iterator.next(); } } private abstract static class SelectManyIterator<T, R> extends CQueryIterator<T, R> { private Iterator<R> innerIterator; public SelectManyIterator(CQueryCollection<T> collection) { super(collection); } protected abstract Iterable<R> selectSubElements(T element); @Override public boolean hasNext() { if (innerIterator != null && innerIterator.hasNext()) { return true; } while (iterator.hasNext()) { Iterable<R> col = selectSubElements(iterator.next()); if (col != null) { innerIterator = col.iterator(); if (innerIterator.hasNext()) { return true; } } } return false; } @Override public R next() { return innerIterator.next(); } } private abstract static class SelectManyCollectionsIterator<T, R, TCollection> extends CQueryIterator<T, R> { private Iterator<TCollection> innerIterator; private T t; private final F2<? super T, ? super TCollection, R> resultSelector; public SelectManyCollectionsIterator(CQueryCollection<T> collection, F2<? super T, ? super TCollection, R> resultSelector) { super(collection); this.resultSelector = resultSelector; } protected abstract Iterable<TCollection> selectCollection(T t); @Override public boolean hasNext() { if (innerIterator != null && innerIterator.hasNext()) { return true; } while (iterator.hasNext()) { t = iterator.next(); Iterable<TCollection> col = selectCollection(t); if (col != null) { innerIterator = col.iterator(); if (innerIterator.hasNext()) { return true; } } } return false; } @Override public R next() { return resultSelector.invoke(t, innerIterator.next()); } } private abstract static class WhereIterator<T> extends CQueryIterator<T, T> { private T nextValue; private boolean hasNext; public WhereIterator(CQueryCollection<T> collection) { super(collection); hasNext = false; } protected abstract boolean meetsPredicate(T t); @Override public boolean hasNext() { if (hasNext) { return true; } while (iterator.hasNext()) { T t = iterator.next(); if (meetsPredicate(t)) { nextValue = t; hasNext = true; return true; } } return false; } @Override public T next() { if (!hasNext) { throw new IllegalStateException(); } hasNext = false; return nextValue; } } }