package speiger.src.collections.PACKAGE.utils; import java.util.Iterator; import java.util.NoSuchElementException; #if TYPE_OBJECT import java.util.function.Function; #endif import speiger.src.collections.PACKAGE.collections.ITERATOR; import speiger.src.collections.PACKAGE.lists.ARRAY_LIST; import speiger.src.collections.PACKAGE.lists.LIST; import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR; import speiger.src.collections.PACKAGE.collections.BI_ITERATOR; import speiger.src.collections.PACKAGE.collections.COLLECTION; /** * A Helper class for Iterators */ public class ITERATORS { /** * Empty Iterator Reference */ public static final EmptyIterator NO_GENERIC_TYPE EMPTY = new EmptyIteratorBRACES(); /** * Returns a Immutable EmptyIterator instance that is automatically casted. * @Type(T) * @return an empty iterator */ public static GENERIC_KEY_BRACES EmptyIterator KEY_GENERIC_TYPE empty() { #if TYPE_OBJECT return (EmptyIterator)EMPTY; #else return EMPTY; #endif } /** * Inverter function for Bidirectional Iterators * @param it the iterator that should be inverted * @Type(T) * @return a Inverted Bidirectional Iterator. If it was inverted then it just gives back the original reference */ public static GENERIC_KEY_BRACES BI_ITERATOR KEY_GENERIC_TYPE invert(BI_ITERATOR KEY_GENERIC_TYPE it) { return it instanceof ReverseBiIterator ? ((ReverseBiIterator KEY_GENERIC_TYPE)it).it : new ReverseBiIteratorBRACES(it); } /** * Inverter function for List Iterators * @param it the iterator that should be inverted * @Type(T) * @return a Inverted List Iterator. If it was inverted then it just gives back the original reference */ public static GENERIC_KEY_BRACES LIST_ITERATOR KEY_GENERIC_TYPE invert(LIST_ITERATOR KEY_GENERIC_TYPE it) { return it instanceof ReverseListIterator ? ((ReverseListIterator KEY_GENERIC_TYPE)it).it : new ReverseListIteratorBRACES(it); } /** * Returns a Immutable Iterator instance based on the instance given. * @param iterator that should be made immutable/unmodifiable * @Type(T) * @return a unmodifiable iterator wrapper. If the Iterator already a unmodifiable wrapper then it just returns itself. */ public static GENERIC_KEY_BRACES ITERATOR KEY_GENERIC_TYPE unmodifiable(ITERATOR KEY_GENERIC_TYPE iterator) { return iterator instanceof UnmodifiableIterator ? iterator : new UnmodifiableIteratorBRACES(iterator); } /** * Returns a Immutable Iterator instance based on the instance given. * @param iterator that should be made immutable/unmodifiable * @Type(T) * @return a unmodifiable iterator wrapper. If the Iterator already a unmodifiable wrapper then it just returns itself. */ public static GENERIC_KEY_BRACES BI_ITERATOR KEY_GENERIC_TYPE unmodifiable(BI_ITERATOR KEY_GENERIC_TYPE iterator) { return iterator instanceof UnmodifiableBiIterator ? iterator : new UnmodifiableBiIteratorBRACES(iterator); } /** * Returns a Immutable ListIterator instance based on the instance given. * @param iterator that should be made immutable/unmodifiable * @Type(T) * @return a unmodifiable listiterator wrapper. If the ListIterator already a unmodifiable wrapper then it just returns itself. */ public static GENERIC_KEY_BRACES LIST_ITERATOR KEY_GENERIC_TYPE unmodifiable(LIST_ITERATOR KEY_GENERIC_TYPE iterator) { return iterator instanceof UnmodifiableListIterator ? iterator : new UnmodifiableListIteratorBRACES(iterator); } #if TYPE_OBJECT /** * A Helper function that maps a Iterator into a new Type. * @param iterator that should be mapped * @param mapper the function that decides what the result turns into. * @Type(T) * @Type(E) * @return a iterator that is mapped to a new result */ public static ITERATOR map(ITERATOR iterator, Function mapper) { return new MappedIteratorBRACES(iterator, mapper); } /** * A Helper function that flatMaps a Iterator into a new Type. * @param iterator that should be flatMapped * @param mapper the function that decides what the result turns into. * @Type(T) * @Type(V) * @Type(E) * @return a iterator that is flatMapped to a new result */ public static > ITERATOR flatMap(ITERATOR iterator, Function mapper) { return new FlatMappedIteratorBRACES(iterator, mapper); } /** * A Helper function that flatMaps a Iterator into a new Type. * @param iterator that should be flatMapped * @param mapper the function that decides what the result turns into. * @Type(T) * @Type(E) * @return a iterator that is flatMapped to a new result */ public static ITERATOR arrayFlatMap(ITERATOR iterator, Function mapper) { return new FlatMappedArrayIteratorBRACES(iterator, mapper); } #endif /** * Helper function to convert a Object Iterator into a Primitive Iterator * @param iterator that should be converted to a unboxing iterator * @ArrayType(T) * @return a primitive iterator */ public static GENERIC_KEY_BRACES ITERATOR KEY_GENERIC_TYPE wrap(Iterator iterator) { return iterator instanceof ITERATOR ? (ITERATOR KEY_GENERIC_TYPE)iterator : new IteratorWrapperBRACES(iterator); } /** * Returns a Array Wrapping iterator * @param a the array that should be wrapped * @ArrayType(T) * @return a Iterator that is wrapping a array. */ public static GENERIC_KEY_BRACES ArrayIterator KEY_GENERIC_TYPE wrap(KEY_TYPE[] a) { return wrap(a, 0, a.length); } /** * Returns a Array Wrapping iterator * @param a the array that should be wrapped. * @param start the index to be started from. * @param end the index that should be ended. * @ArrayType(T) * @return a Iterator that is wrapping a array. */ public static GENERIC_KEY_BRACES ArrayIterator KEY_GENERIC_TYPE wrap(KEY_TYPE[] a, int start, int end) { return new ArrayIteratorBRACES(a, start, end); } /** * Iterates over a iterator and inserts the values into the array and returns the amount that was inserted * @param a where the elements should be inserted * @param i the source iterator * @ArrayType(T) * @return the amount of elements that were inserted into the array. */ public static GENERIC_KEY_BRACES int unwrap(KEY_TYPE[] a, Iterator i) { return unwrap(a, i, 0, a.length); } /** * Iterates over a iterator and inserts the values into the array and returns the amount that was inserted * @param a where the elements should be inserted * @param i the source iterator * @param offset the array offset where the start should be * @ArrayType(T) * @return the amount of elements that were inserted into the array. */ public static GENERIC_KEY_BRACES int unwrap(KEY_TYPE[] a, Iterator i, int offset) { return unwrap(a, i, offset, a.length - offset); } /** * Iterates over a iterator and inserts the values into the array and returns the amount that was inserted * @param a where the elements should be inserted * @param i the source iterator * @param offset the array offset where the start should be * @param max the maximum values that should be extracted from the source * @ArrayType(T) * @return the amount of elements that were inserted into the array. * @throws IllegalStateException if max is smaller the 0 or if the maximum index is larger then the array */ public static GENERIC_KEY_BRACES int unwrap(KEY_TYPE[] a, Iterator i, int offset, int max) { if(max < 0) throw new IllegalStateException("The max size is smaller then 0"); if(offset + max > a.length) throw new IllegalStateException("largest array index exceeds array size"); int index = 0; for(;index a.length) throw new IllegalStateException("largest array index exceeds array size"); int index = 0; for(;index a.length) throw new IllegalStateException("largest array index exceeds array size"); int index = 0; for(;index iter; public IteratorWrapper(Iterator iter) { this.iter = iter; } @Override public boolean hasNext() { return iter.hasNext(); } @Override public KEY_TYPE NEXT() { return OBJ_TO_KEY(iter.next()); } #if !TYPE_OBJECT @Override @Deprecated public CLASS_TYPE next() { return iter.next(); } #endif } private static class ConcatIterator KEY_GENERIC_TYPE implements ITERATOR KEY_GENERIC_TYPE { ITERATOR KEY_GENERIC_TYPE[] iters; int offset; int lastOffset = -1; int length; public ConcatIterator(ITERATOR KEY_GENERIC_TYPE[] iters, int offset, int length) { this.iters = iters; this.offset = offset; this.length = length; find(); } private void find() { for(;length != 0 && !iters[offset].hasNext();length--, offset++); } @Override public boolean hasNext() { return length > 0; } @Override public KEY_TYPE NEXT() { if(!hasNext()) throw new NoSuchElementException(); KEY_TYPE result = iters[lastOffset = offset].NEXT(); find(); return result; } @Override public void remove() { if(lastOffset == -1) throw new IllegalStateException(); iters[lastOffset].remove(); lastOffset = -1; } } private static class ReverseBiIterator KEY_GENERIC_TYPE implements BI_ITERATOR KEY_GENERIC_TYPE { BI_ITERATOR KEY_GENERIC_TYPE it; ReverseBiIterator(BI_ITERATOR KEY_GENERIC_TYPE it) { this.it = it; } @Override public KEY_TYPE NEXT() { return it.PREVIOUS(); } @Override public boolean hasNext() { return it.hasPrevious(); } @Override public boolean hasPrevious() { return it.hasNext(); } @Override public KEY_TYPE PREVIOUS() { return it.NEXT(); } @Override public void remove() { it.remove(); } } private static class ReverseListIterator KEY_GENERIC_TYPE implements LIST_ITERATOR KEY_GENERIC_TYPE { LIST_ITERATOR KEY_GENERIC_TYPE it; ReverseListIterator(LIST_ITERATOR KEY_GENERIC_TYPE it) { this.it = it; } @Override public KEY_TYPE NEXT() { return it.PREVIOUS(); } @Override public boolean hasNext() { return it.hasPrevious(); } @Override public boolean hasPrevious() { return it.hasNext(); } @Override public KEY_TYPE PREVIOUS() { return it.NEXT(); } @Override public void remove() { it.remove(); } @Override public int nextIndex() { return it.previousIndex(); } @Override public int previousIndex() { return it.nextIndex(); } @Override public void set(KEY_TYPE e) { it.set(e); } @Override public void add(KEY_TYPE e) { it.add(e); } } private static class UnmodifiableListIterator KEY_GENERIC_TYPE implements LIST_ITERATOR KEY_GENERIC_TYPE { LIST_ITERATOR KEY_GENERIC_TYPE iter; UnmodifiableListIterator(LIST_ITERATOR KEY_GENERIC_TYPE iter) { this.iter = iter; } @Override public boolean hasNext() { return iter.hasNext(); } @Override public boolean hasPrevious() { return iter.hasPrevious(); } @Override public int nextIndex() { return iter.nextIndex(); } @Override public int previousIndex() { return iter.previousIndex(); } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public KEY_TYPE PREVIOUS() { return iter.PREVIOUS(); } @Override public KEY_TYPE NEXT() { return iter.NEXT(); } @Override public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); } @Override public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); } } private static class UnmodifiableBiIterator KEY_GENERIC_TYPE implements BI_ITERATOR KEY_GENERIC_TYPE { BI_ITERATOR KEY_GENERIC_TYPE iter; UnmodifiableBiIterator(BI_ITERATOR KEY_GENERIC_TYPE iter) { this.iter = iter; } @Override public KEY_TYPE NEXT() { return iter.NEXT(); } @Override public boolean hasNext() { return iter.hasNext(); } @Override public boolean hasPrevious() { return iter.hasPrevious(); } @Override public KEY_TYPE PREVIOUS() { return iter.PREVIOUS(); } } private static class UnmodifiableIterator KEY_GENERIC_TYPE implements ITERATOR KEY_GENERIC_TYPE { ITERATOR KEY_GENERIC_TYPE iterator; UnmodifiableIterator(ITERATOR KEY_GENERIC_TYPE iterator) { this.iterator = iterator; } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public KEY_TYPE NEXT() { return iterator.NEXT(); } } private static class EmptyIterator KEY_GENERIC_TYPE implements LIST_ITERATOR KEY_GENERIC_TYPE { @Override public boolean hasNext() { return false; } @Override public KEY_TYPE NEXT() { return EMPTY_KEY_VALUE; } @Override public boolean hasPrevious() { return false; } @Override public KEY_TYPE PREVIOUS() { return EMPTY_KEY_VALUE; } @Override public int nextIndex() { return 0; } @Override public int previousIndex() { return 0; } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); } @Override public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); } } private static class ArrayIterator KEY_GENERIC_TYPE implements ITERATOR KEY_GENERIC_TYPE { KEY_TYPE[] a; int from; int to; ArrayIterator(KEY_TYPE[] a, int from, int to) { this.a = a; this.from = from; this.to = to; } @Override public boolean hasNext() { return from < to; } @Override public KEY_TYPE NEXT() { return a[from++]; } @Override public int skip(int amount) { if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed"); int left = Math.min(amount, to - from); from += left; return amount - left; } } #if TYPE_OBJECT private static class MappedIterator implements ITERATOR { ITERATOR iterator; Function mapper; MappedIterator(ITERATOR iterator, Function mapper) { this.iterator = iterator; this.mapper = mapper; } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public KEY_TYPE NEXT() { return mapper.apply(iterator.NEXT()); } @Override public int skip(int amount) { return iterator.skip(amount); } } private static class FlatMappedIterator> implements ITERATOR { ITERATOR iterator; Iterator last = null; Function mapper; boolean foundNext = false; FlatMappedIterator(ITERATOR iterator, Function mapper) { this.iterator = iterator; this.mapper = mapper; } void compute() { if(foundNext) return; foundNext = true; while(iterator.hasNext()) { if(last != null && last.hasNext()) return; last = mapper.apply(iterator.next()).iterator(); } } @Override public boolean hasNext() { compute(); return last != null && last.hasNext(); } @Override public KEY_TYPE NEXT() { if(!hasNext()) throw new IllegalStateException("End of Iterator"); KEY_TYPE result = last.next(); foundNext = false; return result; } } private static class FlatMappedArrayIterator implements ITERATOR { ITERATOR iterator; Iterator last = null; Function mapper; boolean foundNext = false; FlatMappedArrayIterator(ITERATOR iterator, Function mapper) { this.iterator = iterator; this.mapper = mapper; } void compute() { if(foundNext) return; foundNext = true; while(iterator.hasNext()) { if(last != null && last.hasNext()) return; last = wrap(mapper.apply(iterator.next())); } } @Override public boolean hasNext() { compute(); return last != null && last.hasNext(); } @Override public T next() { if(!hasNext()) throw new IllegalStateException("End of Iterator"); KEY_TYPE result = last.next(); foundNext = false; return result; } } #endif }