package speiger.src.collections.PACKAGE.utils; import java.util.Collection; import java.util.Objects; import java.util.Random; import java.util.RandomAccess; import java.util.function.Consumer; import speiger.src.collections.PACKAGE.collections.COLLECTION; #if !TYPE_OBJECT import speiger.src.collections.PACKAGE.functions.CONSUMER; #endif import speiger.src.collections.PACKAGE.lists.ABSTRACT_LIST; import speiger.src.collections.PACKAGE.lists.LIST; import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR; import speiger.src.collections.PACKAGE.utils.ARRAYS; import speiger.src.collections.utils.SanityChecks; /** * A Helper class for Lists */ public class LISTS { /** * Empty List reference */ public static final EmptyList NO_GENERIC_TYPE EMPTY = new EmptyListBRACES(); /** * Returns a Immutable EmptyList instance that is automatically casted. * @Type(T) * @return an empty list */ public static GENERIC_KEY_BRACES EmptyList KEY_GENERIC_TYPE empty() { #if TYPE_OBJECT return (EmptyList)EMPTY; #else return EMPTY; #endif } /** * Returns a Immutable List instance based on the instance given. * @param l that should be made immutable/unmodifiable * @Type(T) * @return a unmodifiable list wrapper. If the list is implementing RandomAccess that is also transferred. If the List already a unmodifiable wrapper then it just returns itself. */ public static GENERIC_KEY_BRACES LIST KEY_GENERIC_TYPE unmodifiable(LIST KEY_GENERIC_TYPE l) { return l instanceof UnmodifiableList ? l : l instanceof RandomAccess ? new UnmodifiableRandomListBRACES(l) : new UnmodifiableListBRACES(l); } /** * Returns a synchronized List instance based on the instance given. * @param l that should be synchronized * @Type(T) * @return a synchronized list wrapper. If the list is implementing RandomAccess or IARRAY that is also transferred. If the List already a synchronized wrapper then it just returns itself. */ public static GENERIC_KEY_BRACES LIST KEY_GENERIC_TYPE synchronize(LIST KEY_GENERIC_TYPE l) { return l instanceof SynchronizedList ? l : (l instanceof IARRAY ? new SynchronizedArrayListBRACES(l) : (l instanceof RandomAccess ? new SynchronizedRandomAccessListBRACES(l) : new SynchronizedListBRACES(l))); } /** * Returns a synchronized List instance based on the instance given. * @param l that should be synchronized * @param mutex is the controller of the synchronization block. * @Type(T) * @return a synchronized list wrapper. If the list is implementing RandomAccess or IARRAY that is also transferred. If the List already a synchronized wrapper then it just returns itself. */ public static GENERIC_KEY_BRACES LIST KEY_GENERIC_TYPE synchronize(LIST KEY_GENERIC_TYPE l, Object mutex) { return l instanceof SynchronizedList ? l : (l instanceof IARRAY ? new SynchronizedArrayListBRACES(l, mutex) : (l instanceof RandomAccess ? new SynchronizedRandomAccessListBRACES(l, mutex) : new SynchronizedListBRACES(l, mutex))); } /** * Creates a Unmodifiable Singleton list * @param element that should be used in the Singleton * @Type(T) * @return a singleton list that is unmodifiable */ public static GENERIC_KEY_BRACES LIST KEY_GENERIC_TYPE singleton(KEY_TYPE element) { return new SingletonListBRACES(element); } /** * Reverses the list * @param list that should be reversed. * @Type(T) * @return the input list */ public static GENERIC_KEY_BRACES LIST KEY_GENERIC_TYPE reverse(LIST KEY_GENERIC_TYPE list) { int size = list.size(); if(list instanceof IARRAY) { IARRAY KEY_GENERIC_TYPE array = (IARRAY KEY_GENERIC_TYPE)list; #if TYPE_OBJECT if(array.isCastable()) { if(list instanceof SynchronizedArrayList) array.elements(T -> ARRAYS.reverse(T, size)); else ARRAYS.reverse(array.elements(), size); return list; } #else if(list instanceof SynchronizedArrayList) array.elements(T -> ARRAYS.reverse(T, size)); else ARRAYS.reverse(array.elements(), size); return list; #endif } if(list instanceof RandomAccess) { for (int i = 0, mid = size >> 1, j = size - 1; i < mid; i++, j--) { KEY_TYPE t = list.GET_KEY(i); list.set(i, list.GET_KEY(j)); list.set(j, t); } return list; } LIST_ITERATOR KEY_GENERIC_TYPE fwd = list.listIterator(); LIST_ITERATOR KEY_GENERIC_TYPE rev = list.listIterator(size); for(int i = 0, mid = size >> 1; i < mid; i++) { KEY_TYPE tmp = fwd.NEXT(); fwd.set(rev.PREVIOUS()); rev.set(tmp); } return list; } /** * Shuffles the list * @param list that should be Shuffled. * @Type(T) * @return the input list */ public static GENERIC_KEY_BRACES LIST KEY_GENERIC_TYPE shuffle(LIST KEY_GENERIC_TYPE list) { return shuffle(list, SanityChecks.getRandom()); } /** * Shuffles the list * @param list that should be Shuffled. * @param random the random that should be used * @Type(T) * @return the input list */ public static GENERIC_KEY_BRACES LIST KEY_GENERIC_TYPE shuffle(LIST KEY_GENERIC_TYPE list, Random random) { int size = list.size(); if(list instanceof IARRAY) { IARRAY KEY_GENERIC_TYPE array = (IARRAY KEY_GENERIC_TYPE)list; #if TYPE_OBJECT if(array.isCastable()) { if(list instanceof SynchronizedArrayList) array.elements(T -> ARRAYS.shuffle(T, size, random)); else ARRAYS.shuffle(array.elements(), size, random); } else { for(int i = list.size(); i-- != 0;) { int p = random.nextInt(i + 1); KEY_TYPE t = list.GET_KEY(i); list.set(i, list.GET_KEY(p)); list.set(p, t); } } #else if(list instanceof SynchronizedArrayList) array.elements(T -> ARRAYS.shuffle(T, size, random)); else ARRAYS.shuffle(array.elements(), size, random); #endif return list; } for(int i = list.size(); i-- != 0;) { int p = random.nextInt(i + 1); KEY_TYPE t = list.GET_KEY(i); list.set(i, list.GET_KEY(p)); list.set(p, t); } return list; } private static class SingletonList KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE { KEY_TYPE element; SingletonList(KEY_TYPE element) { this.element = element; } @Override public void add(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); } @Override public boolean addAll(int index, Collection c) { throw new UnsupportedOperationException(); } @Override public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); } @Override public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); } @Override public KEY_TYPE GET_KEY(int index) { if(index == 0) return element; throw new IndexOutOfBoundsException(); } @Override public KEY_TYPE set(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); } @Override public KEY_TYPE REMOVE(int index) { throw new UnsupportedOperationException(); } @Override public void addElements(int from, KEY_TYPE[] a, int offset, int length) { throw new UnsupportedOperationException(); } @Override public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) { if(from != 0 || length != 1) throw new IndexOutOfBoundsException(); a[offset] = element; return a; } @Override public void removeElements(int from, int to) { throw new UnsupportedOperationException(); } #if TYPE_OBJECT @Override public K[] extractElements(int from, int to, Class type) { throw new UnsupportedOperationException(); } #else @Override public KEY_TYPE[] extractElements(int from, int to) { throw new UnsupportedOperationException(); } #endif @Override public int size() { return 1; } } private static class SynchronizedArrayList KEY_GENERIC_TYPE extends SynchronizedList KEY_GENERIC_TYPE implements IARRAY KEY_GENERIC_TYPE { IARRAY KEY_GENERIC_TYPE l; SynchronizedArrayList(LIST KEY_GENERIC_TYPE l) { super(l); this.l = (IARRAY KEY_GENERIC_TYPE)l; } SynchronizedArrayList(LIST KEY_GENERIC_TYPE l, Object mutex) { super(l, mutex); this.l = (IARRAY KEY_GENERIC_TYPE)l; } @Override public void ensureCapacity(int size) { synchronized(mutex) { l.ensureCapacity(size); } } @Override public boolean trim(int size) { synchronized(mutex) { return l.trim(size); } } @Override public void clearAndTrim(int size) { synchronized(mutex) { l.clearAndTrim(size); } } @Override public KEY_TYPE[] elements() { synchronized(mutex) { return l.elements(); } } #if TYPE_OBJECT @Override public boolean isCastable() { synchronized(mutex) { return l.isCastable(); } } #endif @Override public void elements(Consumer action) { Objects.requireNonNull(action); synchronized(mutex) { l.elements(action); } } } private static class SynchronizedRandomAccessList KEY_GENERIC_TYPE extends SynchronizedList KEY_GENERIC_TYPE implements RandomAccess { SynchronizedRandomAccessList(LIST KEY_GENERIC_TYPE l) { super(l); } SynchronizedRandomAccessList(LIST KEY_GENERIC_TYPE l, Object mutex) { super(l, mutex); } } private static class SynchronizedList KEY_GENERIC_TYPE extends COLLECTIONS.SynchronizedCollection KEY_GENERIC_TYPE implements LIST KEY_GENERIC_TYPE { LIST KEY_GENERIC_TYPE l; SynchronizedList(LIST KEY_GENERIC_TYPE l) { super(l); this.l = l; } SynchronizedList(LIST KEY_GENERIC_TYPE l, Object mutex) { super(l, mutex); this.l = l; } @Override public boolean addAll(int index, Collection c) { synchronized(mutex) { return l.addAll(index, c); } } @Override public void add(int index, CLASS_TYPE element) { synchronized(mutex) { l.add(index, element); } } #if !TYPE_OBJECT @Override public void add(int index, KEY_TYPE e) { synchronized(mutex) { l.add(index, e); } } #endif @Override public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) { synchronized(mutex) { return l.addAll(index, c); } } @Override public boolean addAll(LIST KEY_GENERIC_TYPE c) { synchronized(mutex) { return l.addAll(c); } } @Override public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) { synchronized(mutex) { return l.addAll(index, c); } } @Override public KEY_TYPE GET_KEY(int index) { synchronized(mutex) { return l.GET_KEY(index); } } #if !TYPE_OBJECT @Override public void forEach(CONSUMER action) { synchronized(mutex) { l.forEach(action); } } #else @Override public void forEach(Consumer action) { synchronized(mutex) { l.forEach(action); } } #endif @Override public KEY_TYPE set(int index, KEY_TYPE e) { synchronized(mutex) { return l.set(index, e); } } @Override public KEY_TYPE REMOVE(int index) { synchronized(mutex) { return l.REMOVE(index); } } @Override @Primitive public int indexOf(Object e) { synchronized(mutex) { return l.indexOf(e); } } @Override @Primitive public int lastIndexOf(Object e) { synchronized(mutex) { return l.lastIndexOf(e); } } #if !TYPE_OBJECT @Override public int indexOf(KEY_TYPE e) { synchronized(mutex) { return l.indexOf(e); } } @Override public int lastIndexOf(KEY_TYPE e) { synchronized(mutex) { return l.lastIndexOf(e); } } #endif @Override public void addElements(int from, KEY_TYPE[] a, int offset, int length) { synchronized(mutex) { addElements(from, a, offset, length); } } @Override public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) { synchronized(mutex) { return l.getElements(from, a, offset, length); } } @Override public void removeElements(int from, int to) { synchronized(mutex) { l.removeElements(from, to); } } #if !TYPE_OBJECT @Override public KEY_TYPE[] extractElements(int from, int to) { synchronized(mutex) { return l.extractElements(from, to); } } #else @Override public K[] extractElements(int from, int to, Class clz) { synchronized(mutex) { return l.extractElements(from, to, clz); } } #endif @Override public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() { return l.listIterator(); } @Override public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) { return l.listIterator(index); } @Override public LIST KEY_GENERIC_TYPE subList(int from, int to) { return synchronize(l.subList(from, to)); } @Override public void size(int size) { synchronized(mutex) { l.size(size); } } } private static class UnmodifiableRandomList KEY_GENERIC_TYPE extends UnmodifiableList KEY_GENERIC_TYPE implements RandomAccess { UnmodifiableRandomList(LIST KEY_GENERIC_TYPE l) { super(l); } } private static class UnmodifiableList KEY_GENERIC_TYPE extends COLLECTIONS.UnmodifiableCollection KEY_GENERIC_TYPE implements LIST KEY_GENERIC_TYPE { final LIST KEY_GENERIC_TYPE l; UnmodifiableList(LIST KEY_GENERIC_TYPE l) { super(l); this.l = l; } @Override public boolean addAll(int index, Collection c) { throw new UnsupportedOperationException(); } @Override public void add(int index, CLASS_TYPE element) { throw new UnsupportedOperationException(); } #if !TYPE_OBJECT @Override public void add(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); } #endif @Override public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); } @Override public boolean addAll(LIST KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); } @Override public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); } @Override public KEY_TYPE GET_KEY(int index) { return l.GET_KEY(index); } #if !TYPE_OBJECT @Override public void forEach(CONSUMER action) { l.forEach(action); } #else @Override public void forEach(Consumer action) { l.forEach(action); } #endif @Override public KEY_TYPE set(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); } @Override public KEY_TYPE REMOVE(int index) { throw new UnsupportedOperationException(); } @Override @Primitive public int indexOf(Object e) { return l.indexOf(e); } @Override @Primitive public int lastIndexOf(Object e) { return l.lastIndexOf(e); } #if !TYPE_OBJECT @Override public int indexOf(KEY_TYPE e) { return l.indexOf(e); } @Override public int lastIndexOf(KEY_TYPE e) { return l.lastIndexOf(e); } #endif @Override public void addElements(int from, KEY_TYPE[] a, int offset, int length) { throw new UnsupportedOperationException(); } @Override public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) { return l.getElements(from, a, offset, length); } @Override public void removeElements(int from, int to) { throw new UnsupportedOperationException(); } #if !TYPE_OBJECT @Override public KEY_TYPE[] extractElements(int from, int to) { throw new UnsupportedOperationException(); } #else @Override public K[] extractElements(int from, int to, Class clz) { throw new UnsupportedOperationException(); } #endif @Override public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() { return ITERATORS.unmodifiable(l.listIterator()); } @Override public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) { return ITERATORS.unmodifiable(l.listIterator(index)); } @Override public LIST KEY_GENERIC_TYPE subList(int from, int to) { return unmodifiable(l.subList(from, to)); } @Override public void size(int size) { throw new UnsupportedOperationException(); } } private static class EmptyList KEY_GENERIC_TYPE extends COLLECTIONS.EmptyCollection KEY_GENERIC_TYPE implements LIST KEY_GENERIC_TYPE { @Override public boolean addAll(int index, Collection c) { throw new UnsupportedOperationException(); } @Override public void add(int index, CLASS_TYPE element) { throw new UnsupportedOperationException(); } #if !TYPE_OBJECT @Override public void add(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); } #endif @Override public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); } @Override public boolean addAll(LIST KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); } @Override public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); } @Override public KEY_TYPE GET_KEY(int index) { throw new IndexOutOfBoundsException(); } @Override public KEY_TYPE set(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); } @Override public KEY_TYPE REMOVE(int index) { throw new UnsupportedOperationException(); } @Override public int indexOf(Object e) { return -1; } @Override public int lastIndexOf(Object e) { return -1; } #if !TYPE_OBJECT @Override public int indexOf(KEY_TYPE e) { return -1; } @Override public int lastIndexOf(KEY_TYPE e) { return -1; } #endif @Override public void addElements(int from, KEY_TYPE[] a, int offset, int length){ throw new UnsupportedOperationException(); } @Override public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) { throw new IndexOutOfBoundsException(); } @Override public void removeElements(int from, int to) { throw new UnsupportedOperationException(); } #if !TYPE_OBJECT @Override public KEY_TYPE[] extractElements(int from, int to) { throw new UnsupportedOperationException(); } #else @Override public K[] extractElements(int from, int to, Class clz) { throw new UnsupportedOperationException(); } #endif @Override public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() { return ITERATORS.empty(); } @Override public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) { if(index != 0) throw new IndexOutOfBoundsException(); return ITERATORS.empty(); } @Override public LIST KEY_GENERIC_TYPE subList(int from, int to) { throw new UnsupportedOperationException(); } @Override public void size(int size) { throw new UnsupportedOperationException(); } } }