package fr.openwide.core.commons.util.functional;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import org.javatuples.Pair;
import org.javatuples.valueintf.IValue0;
import org.javatuples.valueintf.IValue1;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Table;
import com.google.common.collect.Tables;
public final class Functions2 {
private Functions2() { }
public static <T1, T2> Function<Iterable<? extends T1>, Iterable<T2>> transformedIterable(Function<? super T1, T2> function) {
return new TransformedIterableFunction<>(function);
}
private static final class TransformedIterableFunction<T1, T2> implements Function<Iterable<? extends T1>, Iterable<T2>>, Serializable {
private static final long serialVersionUID = -3456570157416618375L;
private final Function<? super T1, T2> function;
public TransformedIterableFunction(Function<? super T1, T2> function) {
super();
this.function = function;
}
@Override
public Iterable<T2> apply(Iterable<? extends T1> input) {
return input == null ? null : Iterables.transform(input, function);
}
@Override
public String toString() {
return "transform(" + function + ")";
}
}
public static <T1, T2> Function<Collection<? extends T1>, Collection<T2>> transformedCollection(Function<? super T1, T2> function) {
return new TransformedCollectionFunction<>(function);
}
private static final class TransformedCollectionFunction<T1, T2> implements Function<Collection<? extends T1>, Collection<T2>>, Serializable {
private static final long serialVersionUID = -3456570157416618375L;
private final Function<? super T1, T2> function;
public TransformedCollectionFunction(Function<? super T1, T2> function) {
super();
this.function = function;
}
@Override
public Collection<T2> apply(Collection<? extends T1> input) {
return input == null ? null : Collections2.transform(input, function);
}
@Override
public String toString() {
return "transform(" + function + ")";
}
}
public static <T1, T2> Function<List<? extends T1>, List<T2>> transformedList(Function<? super T1, T2> function) {
return new TransformedListFunction<>(function);
}
private static final class TransformedListFunction<T1, T2> implements Function<List<? extends T1>, List<T2>>, Serializable {
private static final long serialVersionUID = -3456570157416618375L;
private final Function<? super T1, T2> function;
public TransformedListFunction(Function<? super T1, T2> function) {
super();
this.function = function;
}
@Override
public List<T2> apply(List<? extends T1> input) {
return input == null ? null : Lists.transform(input, function);
}
@Override
public String toString() {
return "transform(" + function + ")";
}
}
public static <T> Function<Collection<? extends T>, Collection<T>> unmodifiableCollection() {
return new UnmodifiableCollectionFunction<T>();
}
private static final class UnmodifiableCollectionFunction<T> implements Function<Collection<? extends T>, Collection<T>>, Serializable {
private static final long serialVersionUID = -3456570157416618375L;
@Override
public Collection<T> apply(Collection<? extends T> input) {
return input == null ? null : Collections.unmodifiableCollection(input);
}
@Override
public String toString() {
return "unmodifiableCollection";
}
}
public static <T> Function<List<? extends T>, List<T>> unmodifiableList() {
return new UnmodifiableListFunction<T>();
}
private static final class UnmodifiableListFunction<T> implements Function<List<? extends T>, List<T>>, Serializable {
private static final long serialVersionUID = -4973967075781864935L;
@Override
public List<T> apply(List<? extends T> input) {
return input == null ? null : Collections.unmodifiableList(input);
}
@Override
public String toString() {
return "unmodifiableList";
}
}
public static <T> Function<Set<? extends T>, Set<T>> unmodifiableSet() {
return new UnmodifiableSetFunction<T>();
}
private static final class UnmodifiableSetFunction<T> implements Function<Set<? extends T>, Set<T>>, Serializable {
private static final long serialVersionUID = 3544407931818217873L;
@Override
public Set<T> apply(Set<? extends T> input) {
return input == null ? null : Collections.unmodifiableSet(input);
}
@Override
public String toString() {
return "unmodifiableSet";
}
}
public static <T> Function<SortedSet<T>, SortedSet<T>> unmodifiableSortedSet() {
return new UnmodifiableSortedSetFunction<T>();
}
private static final class UnmodifiableSortedSetFunction<T> implements Function<SortedSet<T>, SortedSet<T>>, Serializable {
private static final long serialVersionUID = -1090617064751406961L;
@Override
public SortedSet<T> apply(SortedSet<T> input) {
return input == null ? null : Collections.unmodifiableSortedSet(input);
}
@Override
public String toString() {
return "unmodifiableSortedSet";
}
}
public static <K, V> Function<Map<? extends K, ? extends V>, Map<K, V>> unmodifiableMap() {
return new UnmodifiableMapFunction<K, V>();
}
private static final class UnmodifiableMapFunction<K, V> implements Function<Map<? extends K, ? extends V>, Map<K, V>>, Serializable {
private static final long serialVersionUID = 5952443669998059686L;
@Override
public Map<K, V> apply(Map<? extends K, ? extends V> input) {
return input == null ? null : Collections.unmodifiableMap(input);
}
@Override
public String toString() {
return "unmodifiableMap";
}
}
public static <R, C, V> Function<Table<? extends R, ? extends C, ? extends V>, Table<R, C, V>> unmodifiableTable() {
return new UnmodifiableTableFunction<>();
}
private static final class UnmodifiableTableFunction<R, C, V> implements Function<Table<? extends R, ? extends C, ? extends V>, Table<R, C, V>>, Serializable {
private static final long serialVersionUID = 5952443669998059686L;
@Override
public Table<R, C, V> apply(Table<? extends R, ? extends C, ? extends V> input) {
return input == null ? null : Tables.unmodifiableTable(input);
}
@Override
public String toString() {
return "unmodifiableTable";
}
}
public static <T> Function<Iterable<T>, T> first() {
return new IterableFirstFunction<T>();
}
private static final class IterableFirstFunction<T> implements Function<Iterable<T>, T>, Serializable {
private static final long serialVersionUID = -8259072136500802108L;
@Override
public T apply(Iterable<T> input) {
return input == null ? null : Iterables.getFirst(input, null);
}
@Override
public String toString() {
return "first";
}
}
/**
* Same as {@link Functions#forMap(Map, Object)}, except that the default value is defined as a function of the unknown key.
*/
public static <K, V> Function<K, V> forMap(Map<? super K, ? extends V> map, Function<? super K, ? extends V> defaultValueFunction) {
return new ForMapFunction<>(map, defaultValueFunction);
}
private static final class ForMapFunction<K, V> implements Function<K, V>, Serializable {
private static final long serialVersionUID = 1409896188722279336L;
private final Map<? super K, ? extends V> map;
private final Function<? super K, ? extends V> defaultValueFunction;
public ForMapFunction(Map<? super K, ? extends V> map, Function<? super K, ? extends V> defaultValueFunction) {
super();
this.map = map;
this.defaultValueFunction = defaultValueFunction;
}
@Override
public V apply(K key) {
if (map.containsKey(key)) {
return map.get(key);
} else {
return defaultValueFunction.apply(key);
}
}
@Override
public String toString() {
return "forMap(" + map + ", " + defaultValueFunction + ")";
}
}
/**
* @return A function that returns its argument if {@code validValuePredicate.apply(argument)} and {@code defaultValueFunction.apply(argument)} otherwise.
*/
public static <T> Function<T, T> defaultValue(Predicate<? super T> validValuePredicate, Function<? super T, ? extends T> defaultValueFunction) {
return new DefaultValueFunction<T>(validValuePredicate, defaultValueFunction);
}
/**
* Shorthand for {@code defaulValue(Predicates.notNull(), Functions.constant(valueIfInvalid))}
*/
public static <T> Function<T, T> defaultValue(T valueIfInvalid) {
return defaultValue(Predicates.notNull(), Functions.constant(valueIfInvalid));
}
private static final class DefaultValueFunction<T> implements Function<T, T>, Serializable {
private static final long serialVersionUID = 5952443669998059686L;
private final Predicate<? super T> validValuePredicate;
private final Function<? super T, ? extends T> defaultValueFunction;
public DefaultValueFunction(Predicate<? super T> validValuePredicate, Function<? super T, ? extends T> defaultValueFunction) {
super();
this.validValuePredicate = validValuePredicate;
this.defaultValueFunction = defaultValueFunction;
}
@Override
public T apply(T input) {
return validValuePredicate.apply(input) ? input : defaultValueFunction.apply(input);
}
@Override
public String toString() {
return "default(if not " + validValuePredicate + ", then " + defaultValueFunction + ")";
}
}
@SuppressWarnings({ "unchecked", "rawtypes" }) // Works for any K, since it is read-only
public static <K> Function<Entry<? extends K, ?>, K> entryKey() {
return (Function) EntryFunction.KEY;
}
@SuppressWarnings({ "unchecked", "rawtypes" }) // Works for any V, since it is read-only
public static <V> Function<Entry<?, ? extends V>, V> entryValue() {
return (Function) EntryFunction.VALUE;
}
private enum EntryFunction implements Function<Entry<?, ?>, Object> {
KEY {
@Override
public Object apply(Entry<?, ?> entry) {
return entry == null ? null : entry.getKey();
}
@Override
public String toString() {
return "key";
}
},
VALUE {
@Override
public Object apply(Entry<?, ?> entry) {
return entry == null ? null : entry.getValue();
}
@Override
public String toString() {
return "value";
}
};
}
@SuppressWarnings({ "unchecked", "rawtypes" }) // Works for any K and V, since it is read-only and Pair is immutable
public static <K, V> Function<Entry<? extends K, ? extends V>, Pair<K, V>> entryToPair() {
return (Function) EntryToJavaTuplesPairFunction.INSTANCE;
}
private enum EntryToJavaTuplesPairFunction implements Function<Entry<?, ?>, Pair<?, ?>> {
INSTANCE {
@Override
public Pair<?, ?> apply(Entry<?, ?> entry) {
return entry == null ? null : Pair.with(entry.getKey(), entry.getValue());
}
@Override
public String toString() {
return "entryToPair";
}
};
}
@SuppressWarnings({ "unchecked", "rawtypes" }) // Works for any T, since it is read-only
public static <T> Function<IValue0<? extends T>, T> tupleValue0() {
return (Function) JavaTuplesValue0Function.INSTANCE;
}
private enum JavaTuplesValue0Function implements Function<IValue0<?>, Object> {
INSTANCE {
@Override
public Object apply(IValue0<?> entry) {
return entry == null ? null : entry.getValue0();
}
@Override
public String toString() {
return "value0";
}
}
}
@SuppressWarnings({ "unchecked", "rawtypes" }) // Works for any T, since it is read-only
public static <T> Function<IValue1<? extends T>, T> tupleValue1() {
return (Function) JavaTuplesValue1Function.INSTANCE;
}
private enum JavaTuplesValue1Function implements Function<IValue1<?>, Object> {
INSTANCE {
@Override
public Object apply(IValue1<?> entry) {
return entry == null ? null : entry.getValue1();
}
@Override
public String toString() {
return "value1";
}
};
}
}