package org.hivedb.util.functional; import org.hivedb.util.PrimitiveUtils; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.Map; public class Amass { public static<C,R> R join(Joiner<C,R> joiner, Iterable<C> iterable, R initialValue) { R result = null; for (C item : iterable) { if (result == null) result = initialValue; result = joiner.f(item,result); } return result; } public static<C,R> R min(final Unary<C,R> unary, Iterable<C> iterable, final Class<R> primitiveType) { return Amass.join( new Joiner<C, R>() { public R f(C c, R result) { return (R) PrimitiveUtils.getMinFunction(primitiveType).f(result, unary.f(c)); }}, iterable, PrimitiveUtils.getMinValue(primitiveType)); } public static<C,R> R max(final Unary<C,R> unary, Iterable<C> iterable, final Class<R> primitiveType) { return Amass.join( new Joiner<C, R>() { public R f(C c, R result) { return (R) PrimitiveUtils.getMaxFunction(primitiveType).f(result, unary.f(c)); }}, iterable, PrimitiveUtils.getMaxValue(primitiveType)); } /** * Joins with the given function. The initial value is the first item of the iterable * Subsequent items of the iterable will be passed the join function along with the previous result of joiner or the initial value * @param <C> * @param joiner * @param iterable * @return */ public static<C> C join(Joiner<C,C> joiner, Iterable<C> iterable) { C result = null; for (C item : iterable) { result = (result == null) ? item : joiner.f(item,result); } return result; } public static<C> String joinByToString(Joiner<C,String> joiner, Iterable<C> iterable) { String result = ""; for (C item : iterable) { result = (result == null) ? item.toString() : joiner.f(item,result); } return result; } /** * * Joins with the given join function. The initial value is that of firstCall with the first item of the iterable passed to it. * Subsequent items of the iterable will be passed the join function along with the previous result of firstCall or joiner * * @param <C> * @param <R> * @param joiner * @param firstCall * @param iterable * @return */ public static<C,R> R join(Joiner<C,R> joiner, Unary<C,R> firstCall, Iterable<C> iterable) { R result = null; for (C item : iterable) { result = (result == null) ?firstCall.f(item) :joiner.f(item,result); } return result; } /** * Merges two equal size collections * @param <C1> * @param <C2> * @param <R> * @param merger * @param iterable1 * @param iterable2 * @param initialValue * @return */ public static<C1,C2,R> R merge(Merger<C1,C2,R> merger, Iterable<C1> iterable1, Iterable<C2> iterable2, R initialValue) { R result = null; Iterator<C1> iterator1 = iterable1.iterator(); Iterator<C2> iterator2 = iterable2.iterator(); while (iterator1.hasNext() && iterator2.hasNext()) { if (result == null) result = initialValue; result = merger.f(iterator1.next(), iterator2.next(), result); } return result; } /** * Perform 3 possible actions on depending on what set the merged itemes fall into. * @param <T> * @param leftOnly - run on items only in leftIterable * @param both - run on items in both * @param rightOnly - run on items only in rightIterable * @param leftIterable - "left" items to merge * @param rightIterable - "right" items to merge * @return 3 collections of the resulting items returned by the Unary functions */ @SuppressWarnings("unchecked") public static <T> MergeResult mergeTerciary(Unary<T,T> leftOnly, Unary<T,T> both, Unary<T,T> rightOnly, Iterable<T> leftIterable, Iterable<T> rightIterable) { // this should be optimized if ever used on large sets (i.e. O(n) not 3*O(n^2) ) return new MergeResult<T>( Transform.map(leftOnly, Filter.grepFalseAgainstList(rightIterable, leftIterable)), Transform.map(both, Filter.grepAgainstList(rightIterable, leftIterable)), Transform.map(rightOnly, Filter.grepFalseAgainstList(leftIterable, rightIterable))); } public static class MergeResult<T> { Collection<T> leftOnly, both, rightOnly; public MergeResult(Collection<T> leftOnly, Collection<T> both, Collection<T> rightOnly) { super(); this.leftOnly = leftOnly; this.both = both; this.rightOnly = rightOnly; } public Collection<T> getBoth() { return both; } public Collection<T> getLeftOnly() { return leftOnly; } public Collection<T> getRightOnly() { return rightOnly; } } public static int makeHashCode(Object[] objects) { return makeHashCode(Arrays.asList(objects)); } public static int makeHashCode(Collection<Object> objects) { final String join = Amass.join( new Joiner.ConcatHashCodesOfValues(), new Unary<Object, String>() { public String f(Object item) { return Joiner.hashItem(item); } }, objects); return join != null ? join.hashCode() : 0; } @SuppressWarnings("unchecked") static public <K, V> Map<K, V> concatOrderedMaps(Map<K,V> baseMap, Map<K,V> appendMap) { return Transform.toOrderedMap(Transform.flatten(new Collection[] { baseMap.entrySet(), appendMap.entrySet() })); } @SuppressWarnings("unchecked") static public <T> Collection<T> concatCollections(Collection<T> baseCollection, Collection<T> appendCollection) { return Transform.flatten(new Collection[] { baseCollection, appendCollection }); } }