package com.gffny.ldrbrd.common.utils; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Random; public class CollectionUtils extends org.apache.commons.collections.CollectionUtils { private static final Random random = new Random(System.currentTimeMillis()); public static <O> O getFirstElement(Collection<O> c) { return getElementAt(c, 0); } public static <O> O getLastElement(Collection<O> c) { return getElementAt(c, safeSize(c) - 1); } public static <O> O getRandomElement(Collection<O> c) { return getElementAt(c, random.nextInt(size(c))); } @SuppressWarnings("unchecked") public static <O> O getElementAt(Collection<O> c, int index) { if (isEmpty(c)) { return null; } try { return (O) get(c, index); } catch (Throwable ex) { return null; } } public static <O> O getCircularElementAt(Collection<O> c, int index) { if (index < 0) { index += safeSize(c); } return getElementAt(c, index); } public static <O> O getFirstElement(List<O> l) { if (CollectionUtils.isEmpty(l)) { return null; } return l.get(0); } public static <O> O getLastElement(List<O> l) { if (CollectionUtils.isEmpty(l)) { return null; } int index = l.size() - 1; return l.get(index); } public static <O> O getRandomElement(List<O> l) { if (CollectionUtils.isEmpty(l)) { return null; } if (l.size() == 1) { return l.get(0); } int index = random.nextInt(l.size()); return l.get(index); } public static <O> List<O> sort(List<O> collection, Comparator<? super O> comparator) { return sort(collection, comparator, false); } public static <O> List<O> sort(List<O> collection, Comparator<? super O> comparator, boolean clone) { if (collection == null) return collection; if (clone) { collection = new ArrayList<O>(collection); } Collections.sort(collection, comparator); return collection; } public static <O> List<O> sort(Collection<O> collection, Comparator<? super O> comparator) { if (collection == null) return null; return sort(new ArrayList<O>(collection), comparator); } public static <O> boolean isEmpty(O[] arr) { return arr == null || arr.length == 0; } public static <O> boolean isNotEmpty(O[] arr) { return !CollectionUtils.isEmpty(arr); } public static <O> List<O> asList(O... a) { return a == null ? new ArrayList<O>() : Arrays.asList(a); } public static <O> boolean isSingular(Collection<O> c) { return safeSize(c) == 1; } public static <O> boolean isSingular(O[] arr) { return safeSize(arr) == 1; } public static <O> List<List<O>> split(List<O> l, int targetSize) { List<List<O>> groups = new ArrayList<List<O>>(); for (int i = 0; i < l.size(); i += targetSize) { groups.add(l.subList(i, Math.min(i + targetSize, l.size()))); } return groups; } /** * Used for dividing an original list into two lists. * * @param <T> * @param list * @param i * @return */ public static <T> List<T> divide(List<T> list, int i) { List<T> x = new ArrayList<T>(list.subList(i, list.size())); // Remove items from end of original list for (int j = list.size() - 1; j >= i; --j) { list.remove(j); } return x; } /** * Used to return list1 - list2 * */ public static <T> List<T> subtract(List<T> list1, List<T> list2) { try { if (list1 == null || list1.isEmpty()) return list1; if (list2 == null || list2.isEmpty()) return list1; List<T> x = new ArrayList<T>(); for (T o : list1) { if (!list2.contains(o)) { x.add(o); } } return x; } catch (Throwable ex) { return list1; } } public static <O> O safeGet(List<O> l, int index) { try { return l.get(index); } catch (Throwable ex) { return null; } } public static <O> O safeRemove(List<O> l, int index) { try { return l.remove(index); } catch (Throwable ex) { return null; } } public static <O> boolean safeAdd(Collection<O> c, O item) { try { return c.add(item); } catch (Throwable ex) { return false; } } public static <O> boolean safeAddAll(Collection<O> c, Collection<O> items) { try { return c.addAll(items); } catch (Throwable ex) { return false; } } public static <O> List<O> safeSubList(List<O> l, int size) { try { if (l.size() < size) { return l; } return l.subList(0, size); } catch (Throwable ex) { return l; } } public static int safeSize(Collection<?> c) { return c != null ? c.size() : 0; } public static <O> int safeSize(O[] arr) { return arr != null ? arr.length : 0; } public static <O> boolean contains(O[] a, O e) { if (CollectionUtils.isEmpty(a)) { return false; } for (O i : a) { if (i == e) { return true; } else if (i != null && i.equals(e)) { return true; } else if (e != null && e.equals(i)) { return true; } } return false; } public static <O> boolean doesNotContain(O[] a, O e) { return !contains(a, e); } public static <O> boolean contains(Collection<O> c, O e) { if (CollectionUtils.isEmpty(c)) { return false; } return c.contains(e); } public static <O> boolean doesNotContain(Collection<O> c, O e) { return !contains(c, e); } public static <O> boolean contains(Collection<O> c, O e, Comparator<O> comparator) { if (CollectionUtils.isNotEmpty(c)) { for (O item : c) { try { if (comparator.compare(item, e) == 0) { return true; } } catch (Throwable ex) { // assume not equals } } } return false; } public static <O> boolean doesNotContain(Collection<O> c, O e, Comparator<O> comparator) { return !contains(c, e, comparator); } public static <O> List<O> clone(Collection<O> c) { return c == null ? null : new ArrayList<O>(c); } public static <O> List<O> cloneToEmpty(Collection<O> l) { return l == null ? new ArrayList<O>() : clone(l); } public static <O> boolean toggleExistence(Collection<O> c, O e, boolean toggle) { if (toggle) { if (CollectionUtils.doesNotContain(c, e)) { return c.add(e); } } else { if (CollectionUtils.contains(c, e)) { return c.remove(e); } } return false; } public static <O> List<O> concat(Collection<O>... collections) { return concatInto(new ArrayList<O>(), collections); } public static <O, C extends Collection<O>> C concatInto(C concatInto, Collection<O>... collections) { if (CollectionUtils.isNotEmpty(collections)) { for (Collection<O> collection : collections) { CollectionUtils.safeAddAll(concatInto, collection); } } return concatInto; } public static <O> void pruneAllThatDoNotExist(final Collection<O> source, Collection<O> subset) { if (CollectionUtils.isEmpty(subset)) { return; } if (CollectionUtils.isEmpty(source)) { subset.clear(); return; } for (Iterator<O> iter = subset.iterator(); iter.hasNext();) { O item = iter.next(); if (CollectionUtils.doesNotContain(source, item)) { iter.remove(); } } } public static <O> List<O> nullAsEmpty(List<O> list) { return (list != null) ? list : new ArrayList<O>(); } public static <O> ListIterator<O> getReverseIterator(List<O> list) { if (list != null) { return list.listIterator(list.size()); } else { return null; } } public static <O> O getFirstElement(O[] a) { return getElementAt(a, 0); } public static <O> O getLastElement(O[] a) { return getElementAt(a, safeSize(a) - 1); } public static <O> O getRandomElement(O[] a) { return getElementAt(a, random.nextInt(safeSize(a))); } @SuppressWarnings("unchecked") public static <O> O getElementAt(O[] a, int index) { if (isEmpty(a)) { return null; } try { return (O) get(a, index); } catch (Throwable ex) { return null; } } public static <O> boolean isNotSingular(O[] arr) { return !isSingular(arr); } public static <O> boolean isNotSingular(Collection<O> c) { return !isSingular(c); } /** * Used for dividing an original list into two lists. * * @param <T> * @param list * @param i * @return */ public static <O, P extends O> boolean safeAddAll(Collection<O> c, P[] items) { try { for (O item : items) { c.add(item); } return true; } catch (Throwable ex) { return false; } } public static <O> List<O> safeSubList(List<O> l, int offset, int count) { if (l == null) { return null; } if (offset >= l.size()) return Collections.emptyList(); if (count == 0) count = l.size(); return l.subList(offset, Math.min(offset + count, l.size())); } public static int safeSize(Object object) { try { return CollectionUtils.size(object); } catch (Throwable ex) { return 0; } } public static <O> boolean containsAll(Collection<O> c, Collection<O> i) { if (c == null || i == null) { return false; } for (O obj : i) { if (doesNotContain(c, obj)) { return false; } } return true; } public static <O> boolean doesNotContainAll(Collection<O> c, Collection<O> i) { if (c == null || i == null) { return false; } return !containsAll(c, i); } public static <O> Collection<O> nullAsEmpty(Collection<O> c) { return c == null ? new ArrayList<O>() : c; } public static <O> O[] nullAsEmpty(O[] a, O[] empty) { return a == null ? empty : a; } public static <O> List<O> emptyAsNull(List<O> l) { return isEmpty(l) ? null : l; } public static <O> O[] emptyAsNull(O[] a) { return isEmpty(a) ? null : a; } public static <O> List<O> cast(Collection<O> c, Class<O> clazz) { if (c == null) { return null; } List<O> casted = new ArrayList<O>(); CollectionUtils.safeAddAll(casted, c); return casted; } @SuppressWarnings("unchecked") public static <O> List<O> convert(List<?> list, Class<O> clazz) { if (list == null) { return null; } List<O> converted = new ArrayList<O>(); for (Object item : list) { if (clazz.isInstance(item)) { converted.add((O) item); } } return converted; } public static <INPUT, OUTPUT> OUTPUT transform(final INPUT source, Transformer<INPUT, OUTPUT> transformer) { return transformer.transform(source); } public static <INPUT, OUTPUT> List<OUTPUT> transform( final Collection<INPUT> source, Transformer<INPUT, OUTPUT> transformer) { if (source == null) { return null; } if (CollectionUtils.isEmpty(source)) { return new ArrayList<OUTPUT>(); } List<OUTPUT> output = new ArrayList<OUTPUT>(); for (INPUT input : source) { output.add(transformer.transform(input)); } return output; } public static <INPUT, OUTPUT> List<OUTPUT> transformAndReduce( final Collection<INPUT> source, Transformer<INPUT, OUTPUT> transformer) { List<OUTPUT> output = transform(source, transformer); return stripNull(output); } public static <T> Collection<T> each(Collection<T> c, Statement<? super T> statement) { if (isEmpty(c) || statement == null) { return c; } Iterator<T> iter = c.iterator(); while (iter.hasNext()) { T item = iter.next(); statement.run(item); } return c; } public static <T> Collection<T> each(Collection<T> c, Collection<Statement<? super T>> statements) { if (isEmpty(c) || isEmpty(statements)) { return c; } Iterator<T> iter = c.iterator(); while (iter.hasNext()) { T item = iter.next(); for (Statement<? super T> statement : statements) { if (statement != null) { statement.run(item); } } } return c; } public static <T> Collection<T> each(Collection<T> c, Statement<? super T>... statements) { return each(c, Arrays.asList(statements)); } public static interface Transformer<INPUT, OUTPUT> { OUTPUT transform(INPUT item); } public static interface Predicate<T> { boolean evaluate(T object); } public static interface Statement<T> { void run(T object); } public static <O> List<O> filter(Collection<O> c, Predicate<O> predicate) { if (c == null || predicate == null) { return null; } List<O> clone = CollectionUtils.clone(c); Iterator<O> iter = clone.iterator(); while (iter.hasNext()) { O object = iter.next(); if (!predicate.evaluate(object)) { iter.remove(); } } return clone; } public static <O> O firstOrDefault(Collection<O> c, Predicate<O> predicate) { if (c == null || predicate == null) { return null; } Iterator<O> iter = c.iterator(); while (iter.hasNext()) { O object = iter.next(); if (predicate.evaluate(object)) { return object; } } return null; } public static <O> O singleOrDefault(Collection<O> c, Predicate<O> predicate) { Collection<O> filtered = filter(c, predicate); if (CollectionUtils.isSingular(filtered)) { return CollectionUtils.getFirstElement(filtered); } else { if (CollectionUtils.isEmpty(filtered)) { return null; } else { throw new RuntimeException( "Expected one or zero results, received: " + CollectionUtils.safeSize(filtered)); } } } public static <O> List<O> stripNull(Collection<O> c) { if (c == null) { return null; } List<O> response = CollectionUtils.clone(c); Iterator<O> iter = response.iterator(); while (iter.hasNext()) { O item = iter.next(); if (item == null) { iter.remove(); } } return response; } }