/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.foundation; /** * Iterator primitives (concat, map, reduce, filter, etc...). * * @exclude * * @sharpen.partial */ public class Iterators { /** * Constant indicating that the current element in a {@link #map} operation * should be skipped. */ public static final Object SKIP = new Object(); public static final Iterator4 EMPTY_ITERATOR = new Iterator4() { public Object current() { throw new IllegalStateException(); } public boolean moveNext() { return false; } public void reset() { // do nothing } }; public static final Iterable4 EMPTY_ITERABLE = new Iterable4() { public Iterator4 iterator() { return EMPTY_ITERATOR; } }; static final Object NO_ELEMENT = new Object(); /** * Generates {@link EnumerateIterator.Tuple} items with indexes starting at 0. * * @param iterable the iterable to be enumerated */ public static Iterable4 enumerate(final Iterable4 iterable) { return new Iterable4() { public Iterator4 iterator() { return new EnumerateIterator(iterable.iterator()); } }; } public static boolean any(Iterator4 iterator, Predicate4 condition) { while (iterator.moveNext()) { if (condition.match(iterator.current())) { return true; } } return false; } public static Iterator4 concat(Iterator4... array) { return concat(iterate((Object[])array)); } public static Iterator4 concat(Iterator4 iterators) { return new CompositeIterator4(iterators); } public static Iterable4 concat(Iterable4... iterables) { return concat(iterable(iterables)); } public static Iterable4 concat(final Iterable4 iterables) { return new CompositeIterable4(iterables); } public static Iterator4 concat(Iterator4 first, Iterator4 second) { return concat(new Iterator4[] { first, second }); } public static Iterable4 concatMap(Iterable4 iterable, Function4 function) { return concat(map(iterable, function)); } /** * Returns a new iterator which yields the result of applying the function * to every element in the original iterator. * * {@link Iterators#SKIP} can be returned from function to indicate the current * element should be skipped. * * @param iterator * @param function * @return */ public static Iterator4 map(Iterator4 iterator, Function4 function) { return new FunctionApplicationIterator(iterator, function); } public static Iterator4 map(Object[] array, Function4 function) { return map(new ArrayIterator4(array), function); } public static <T> Iterator4<T> filter(T[] array, Predicate4<T> predicate) { return filter(new ArrayIterator4(array), predicate); } public static Iterable4 filter(final Iterable4 source, final Predicate4 predicate) { return new Iterable4() { public Iterator4 iterator() { return filter(source.iterator(), predicate); } }; } public static Iterator4 filter(Iterator4 iterator, Predicate4 predicate) { return new FilteredIterator(iterator, predicate); } public static Iterable4 singletonIterable(final Object element) { return new Iterable4() { public Iterator4 iterator() { return singletonIterator(element); } }; } public static Iterable4 append(Iterable4 front, Object last) { return concat(iterable(new Object[] { front, singletonIterable(last) })); } /** * @sharpen.ignore */ @decaf.Ignore(decaf.Platform.JDK11) public static <T> Iterator4 iterator(java.util.Collection<T> c) { return new JdkCollectionIterator4(c); } public static Iterator4 iterator(Iterable4 iterable) { return iterable.iterator(); } /** * @sharpen.unwrap * @sharpen.ignore */ @decaf.ReplaceFirst(value="return iterator;", platform=decaf.Platform.JDK11) public static <T> java.util.Iterator<T> platformIterator(Iterator4 iterator) { return new Iterator4JdkIterator(iterator); } public static <T> Iterator4 iterate(T... array) { return new ArrayIterator4(array); } public static <T> Iterator4 revert(Iterator4<T> iterator) { iterator.reset(); List4 tail = null; while(iterator.moveNext()){ tail = new List4<T>(tail, iterator.current()); } return iterate(tail); } public static <T> Iterator4 iterate(List4 list) { if(list == null){ return EMPTY_ITERATOR; } Collection4 collection = new Collection4(); while(list != null){ collection.add(list._element); list = list._next; } return collection.iterator(); } public static int size(Iterable4 iterable) { return size(iterable.iterator()); } public static Object next(Iterator4 iterator) { if (!iterator.moveNext()) { throw new IllegalStateException(); } return iterator.current(); } public static int size(Iterator4 iterator) { int count=0; while (iterator.moveNext()) { ++count; } return count; } public static String toString(Iterable4 i) { return toString(i.iterator()); } public static String toString(Iterator4 i) { return join(i, "[", "]", ", "); } public static String join(Iterable4 i, String separator) { return join(i.iterator(), separator); } public static String join(Iterator4 i, String separator) { return join(i, "", "", separator); } public static String join(Iterator4 i, final String prefix, final String suffix, final String separator) { StringBuffer sb = new StringBuffer(); sb.append(prefix); if (i.moveNext()) { sb.append(i.current()); while (i.moveNext()) { sb.append(separator); sb.append(i.current()); } } sb.append(suffix); return sb.toString(); } public static Object[] toArray(Iterator4 tests) { return toArray(tests, new ArrayFactory() { public Object[] newArray(int size) { return new Object[size]; } }); } public static Object[] toArray(Iterator4 tests, ArrayFactory factory) { Collection4 elements = new Collection4(tests); return elements.toArray(factory.newArray(elements.size())); } /** * Yields a flat sequence of elements. Any {@link Iterable4} or {@link Iterator4} * found in the original sequence is recursively flattened. * * @param iterator original sequence */ public static Iterator4 flatten(Iterator4 iterator) { return new FlatteningIterator(iterator); } public static Iterable4 map(final Iterable4 iterable, final Function4 function) { return new Iterable4() { public Iterator4 iterator() { return map(iterable.iterator(), function); } }; } public static Iterable4 crossProduct(Iterable4 iterables) { return crossProduct((Iterable4[])toArray(iterables.iterator(), new ArrayFactory() { public Object[] newArray(int size) { return new Iterable4[size]; } })); } public static Iterable4 crossProduct(Iterable4... iterables) { return crossProduct(iterables, 0, Iterators.EMPTY_ITERABLE); } private static Iterable4 crossProduct(final Iterable4[] iterables, final int level, final Iterable4 row) { if (level == iterables.length - 1) { return map( iterables[level], new Function4() { public Object apply(Object arg) { return append(row, arg); } } ); } return concatMap(iterables[level], new Function4() { public Object apply(Object arg) { return crossProduct(iterables, level+1, append(row, arg)); } }); } public static <T> Iterable4 iterable(final T... objects) { return new Iterable4() { public Iterator4 iterator() { return iterate(objects); } }; } public static Iterator4 singletonIterator(final Object element) { return new SingleValueIterator(element); } public static Iterable4 iterable(final Iterator4 iterator) { return new Iterable4() { public Iterator4 iterator() { return iterator; } }; } public static Iterator4 copy(final Iterator4 iterator) { return new Collection4(iterator).iterator(); } public static <T> Iterator4<T> take(final int count, final Iterator4<T> iterator) { return new Iterator4<T>() { private int _taken = 0; public T current() { if (_taken > count) { throw new IllegalStateException(); } return iterator.current(); } public boolean moveNext() { if (_taken < count) { if (!iterator.moveNext()) { _taken = count; return false; } ++_taken; return true; } return false; } public void reset() { throw new NotImplementedException(); } }; } public static Iterator4<Integer> range(int fromInclusive, int toExclusive) { if (toExclusive < fromInclusive) { throw new IllegalArgumentException(); } return take( toExclusive - fromInclusive, series(fromInclusive - 1, new Function4<Integer, Integer>() { public Integer apply(Integer i) { return i + 1; }}).iterator()); } public static <T> Iterable4<T> series(final T seed, final Function4<T, T> function) { return new Iterable4() { public Iterator4<T> iterator() { return new Iterator4<T>() { private T _current = seed; public T current() { return _current; } public boolean moveNext() { _current = function.apply(_current); return true; } public void reset() { _current = seed; } }; } }; } }