package org.hivedb.util.functional; import org.hivedb.util.functional.Transform.IdentityFunction; import java.util.*; public abstract class Filter { /** * Extend Filter to make an anoymouse filter function * @param <T> * @param iterable * @return */ public abstract<T> Collection<T> f(Iterable<? extends T> iterable); public static<T> Collection<T> grep(Predicate<T> filterer, Iterable<? extends T> iterable) { List<T> list = new ArrayList<T>(); for (T item : iterable) if (filterer.f(item)) list.add(item); return list; } public static<T> Collection<T> grep(Predicate<T> filterer, T[] array) { return grep(filterer, Arrays.asList(array)); } public static<T> T grepSingle(Predicate<T> filterer, Iterable<? extends T> iterable) throws NoSuchElementException { T match = grepSingleOrNull(filterer, iterable); if (match != null) return match; throw new NoSuchElementException("No match found"); } public static<T> T grepSingleOrNull(Predicate<T> filterer, Iterable<? extends T> iterable) throws NoSuchElementException { for (T item : iterable) if (filterer.f(item)) return item; return null; } /** * Return elements that are unique according to the results of a Unary function. The element returned among * matching elements is arbitrary. * @param <T> * @param filterer * @param iterable * @return * @throws NoSuchElementException */ public static<T,R> Collection<T> grepUnique(Unary<T,R> unary, Iterable<? extends T> iterable) { Map<R,T> results = new Hashtable<R, T>(); for (T item : iterable) { R result = unary.f(item); if (!results.containsKey(result)) results.put(result, item); } return results.values(); } public static<T,R> Collection<T> grepUnique(Iterable<? extends T> iterable) { return grepUnique(new IdentityFunction<T>(), iterable); } public static<T> T getFirst(Iterable<? extends T> iterable) throws NoSuchElementException { Iterator<? extends T> iterator = iterable.iterator(); if (iterator.hasNext()) return iterator.next(); throw new NoSuchElementException("No first element of the iterable exists"); } public static Boolean hasFirst(Iterable iterable) { return iterable.iterator().hasNext(); } public static<T> T getFirst(T[] array) throws NoSuchElementException { if (array.length > 0) return array[0]; throw new NoSuchElementException("No first element of the array exists"); } public static Boolean hasFirst(Object[] array) { return array.length > 0; } public static<T> Boolean isMatch(final Predicate<T> filterer, Iterable<? extends T> iterable) { for (T item : iterable) if (filterer.f(item)) return true; return false; } public static<T> Boolean isMatch(final Predicate<T> filterer, T[] array) { return isMatch(filterer, Arrays.asList(array)); } // Passes through all superset items that match a subset item // The match is determined by calling the equals method of either the superset or subset item. // Therefore the type of both Iterable must match (probably need wildcards here actually) // If you need to pass in an array, use Arrays.asList() to make it iterable public static<T> Collection<T> grepAgainstList(final Iterable<? extends T> subset, Iterable<? extends T> superset) { Predicate<T> doesThisSupersetItemMatchAnySubsetItem = makeDoesSupersetItemMatchAnySubsetItem(subset, new EqualFunction<T>()); return grep(doesThisSupersetItemMatchAnySubsetItem, superset); } public static<T> boolean grepItemAgainstList(final T subItem, Iterable<? extends T> superset) { List<T> list = new ArrayList<T>(1); list.add(subItem); Predicate<T> doesThisSupersetItemMatchAnySubsetItem = makeDoesSupersetItemMatchAnySubsetItem(list, new EqualFunction<T>()); return isMatch(doesThisSupersetItemMatchAnySubsetItem, superset); } // Passes through all superset items that match a subset item // The match is determined by passing all permutations needed of subset and superset item to CompareFunction, which returns true to indicate a match and false otherwise. // Using Grep.EqualsFunction is the same as not passing in any CompareFunction // If you need to pass in an array, use Arrays.asList() to make it iterable public static<SUP,SUB> Collection<SUP> grepAgainstList(final Iterable<? extends SUB> subset, Iterable<? extends SUP> superset, BinaryPredicate<SUB, SUP> compareFunction) { Predicate<SUP> doesThisSupersetItemMatchAnySubsetItem = makeDoesSupersetItemMatchAnySubsetItem(subset, compareFunction); return grep(doesThisSupersetItemMatchAnySubsetItem, superset); } public static<SUP,SUB> boolean grepItemAgainstList(final SUB subItem, Iterable<? extends SUP> superset, BinaryPredicate<SUB, SUP> compareFunction) { List<SUB> list = new ArrayList<SUB>(1); list.add(subItem); Predicate<SUP> doesThisSupersetItemMatchAnySubsetItem = makeDoesSupersetItemMatchAnySubsetItem(list,compareFunction); return isMatch(doesThisSupersetItemMatchAnySubsetItem, superset); } public static<T> Collection<T> grepFalseAgainstList(final Iterable<? extends T> subset, Iterable<? extends T> superset) { Predicate<T> doesThisSupersetItemNotMatchAnySubsetItem = makeDoesSupersetItemNotMatchAnySubsetItem(subset, new EqualFunction<T>()); return grep(doesThisSupersetItemNotMatchAnySubsetItem, superset); } public static<T> Collection<T> grepItemFalseAgainstList(final T subItem, Iterable<? extends T> superset) { List<T> list = new ArrayList<T>(); list.add(subItem); Predicate<T> doesThisSupersetItemNotMatchAnySubsetItem = makeDoesSupersetItemNotMatchAnySubsetItem(list, new EqualFunction<T>()); return grep(doesThisSupersetItemNotMatchAnySubsetItem, superset); } public static<SUP,SUB> Collection<SUP> grepFalseAgainstList(final Iterable<? extends SUB> subset, Iterable<? extends SUP> superset, BinaryPredicate<SUB, SUP> compareFunction) { Predicate<SUP> doesThisSupersetItemNotMatchAnySubsetItem = makeDoesSupersetItemNotMatchAnySubsetItem(subset, compareFunction); return grep(doesThisSupersetItemNotMatchAnySubsetItem, superset); } public static<SUP,SUB> Collection<SUP> grepItemFalseAgainstList(final SUB subItem, Iterable<SUP> superset, BinaryPredicate<SUB, SUP> compareFunction) { List<SUB> list = new ArrayList<SUB>(); list.add(subItem); Predicate<SUP> doesThisSupersetItemNotMatchAnySubsetItem = makeDoesSupersetItemNotMatchAnySubsetItem(list, compareFunction); return grep(doesThisSupersetItemNotMatchAnySubsetItem, superset); } // Returns true if all superset items match a subset item // The match is determined by callin the equals method of either the superset or subset item // If you need to pass in an array, use Arrays.asList() to make it iterable public static<T> Boolean allMatch(final Iterable<? extends T> subset, Iterable<? extends T> superset) { Predicate<T> doesThisSupersetItemMatchAnySubsetItem = makeDoesSupersetItemMatchAnySubsetItem(subset, new EqualFunction<T>()); for (T supersetItem : superset) if (!doesThisSupersetItemMatchAnySubsetItem.f(supersetItem)) return false; return true; } private static <SUB,SUP> Predicate<SUP> makeDoesSupersetItemMatchAnySubsetItem(final Iterable<? extends SUB> subset, final BinaryPredicate<SUB, SUP> compareFunction) { Predicate<SUP> doesThisSupersetItemMatchAnySubsetItem = new Predicate<SUP>() { public boolean f(final SUP supersetItem) { Predicate<SUB> doesEnlosedSupersetItemMatchThisSubsetItem = new Predicate<SUB>() { public boolean f(final SUB subsetItem) { return compareFunction.f(subsetItem, supersetItem); } }; return isMatch(doesEnlosedSupersetItemMatchThisSubsetItem,subset); } }; return doesThisSupersetItemMatchAnySubsetItem; } private static <SUB,SUP> Predicate<SUP> makeDoesSupersetItemNotMatchAnySubsetItem(final Iterable<? extends SUB> subset, final BinaryPredicate<SUB, SUP> compareFunction) { Predicate<SUP> doesThisSupersetItemMatchAnySubsetItem = new Predicate<SUP>() { public boolean f(final SUP supersetItem) { Predicate<SUB> doesEnlosedSupersetItemMatchThisSubsetItem = new Predicate<SUB>() { public boolean f(final SUB subsetItem) { return compareFunction.f(subsetItem, supersetItem); } }; return !isMatch(doesEnlosedSupersetItemMatchThisSubsetItem,subset); } }; return doesThisSupersetItemMatchAnySubsetItem; } public static<T> Collection<T> getUnique(Iterable<? extends T> iterable) { Map<T,Boolean> map = new Hashtable<T,Boolean>(); for (T item : iterable) map.put(item, true); return map.keySet(); } public static<T,R> Collection<T> getUnique(Iterable<? extends T> iterable, Unary<T, R> accessor) { Map<R,T> map = new Hashtable<R,T>(); for (T item : iterable) map.put(accessor.f(item), item); return map.values(); } public static class TruePredicate implements Predicate<Object> { public boolean f(Object item) { return true; } } public static class FalsePredicate implements Predicate<Object> { public boolean f(Object item) { return false; } } public static class UniquePredicate<T> implements Predicate<T> { private Map<T, Boolean> map = new Hashtable<T, Boolean>(); public boolean f(T item) { if (map.containsKey(item)) return false; map.put(item, true); return true; } } public static class FirstOnlyFilter extends Filter { public <T> Collection<T> f(Iterable<? extends T> iterable) { return grep(new FirstOnlyPredicate<T>(), iterable); } } public static class FirstOnlyPredicate<T> implements Predicate<T> { private boolean first; public boolean f(T item) { if (first) return false; first = true; return true; } } public static class NullPredicate<T> implements Predicate<T> { public boolean f(T item) { return item == null; } } public static class NotNullPredicate<T> implements Predicate<T> { public boolean f(T item) { return item != null; } } public static class AllowAllFilter extends Filter { @SuppressWarnings("unchecked") public <T> Collection<T> f(Iterable<? extends T> iterable) { return (Collection<T>)grep(new TruePredicate(), iterable); } } public static class BlockAllFilter extends Filter { public <T> Collection<T> f(Iterable<? extends T> iterable) { return new ArrayList<T>(); } } public static<T> Collection<T> removeItemAtIndex(int index, Collection<T> collection) { List<T>list = new ArrayList<T>(collection); list.remove(index); return list; } public static<T> Object getItemAtIndex(int index, Collection<T> collection) { return new ArrayList<T>(collection).get(index); } public static abstract class BinaryPredicate<T,S> {public abstract boolean f(final T item1, S item2 );} public static class EqualFunction<T> extends BinaryPredicate<T,T> { public boolean f(final Object item1, Object item2 ) { return item1.equals(item2); } } public static class UnequalFunction<T> extends BinaryPredicate<T,T> { public boolean f(final T item1, T item2 ) { return !item1.equals(item2); } } public static class ClassPredicate implements Predicate<Class<?>> { Class<?> clazz; public ClassPredicate(Class<?> clazz) { this.clazz = clazz; } public boolean f(Class<?> clazz) { return clazz.equals(this.clazz); } } }