/** * Copyright 2016 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.internal.functions; import java.util.*; import java.util.concurrent.*; import io.reactivex.*; import io.reactivex.functions.*; import io.reactivex.plugins.RxJavaPlugins; import io.reactivex.schedulers.Timed; /** * Utility methods to convert the Function3..Function9 instances to Function of Object array. */ public final class Functions { /** Utility class. */ private Functions() { throw new IllegalStateException("No instances!"); } @SuppressWarnings("unchecked") public static Function toFunction(final BiFunction biFunction) { ObjectHelper.requireNonNull(biFunction, "biFunction is null"); return new Function() { @Override public R apply(Object[] a) throws Exception { if (a.length != 2) { throw new IllegalArgumentException("Array of size 2 expected but got " + a.length); } return ((BiFunction)biFunction).apply(a[0], a[1]); } }; } public static Function toFunction(final Function3 f) { ObjectHelper.requireNonNull(f, "f is null"); return new Function() { @SuppressWarnings("unchecked") @Override public R apply(Object[] a) throws Exception { if (a.length != 3) { throw new IllegalArgumentException("Array of size 3 expected but got " + a.length); } return f.apply((T1)a[0], (T2)a[1], (T3)a[2]); } }; } public static Function toFunction(final Function4 f) { ObjectHelper.requireNonNull(f, "f is null"); return new Function() { @SuppressWarnings("unchecked") @Override public R apply(Object[] a) throws Exception { if (a.length != 4) { throw new IllegalArgumentException("Array of size 4 expected but got " + a.length); } return f.apply((T1)a[0], (T2)a[1], (T3)a[2], (T4)a[3]); } }; } public static Function toFunction(final Function5 f) { ObjectHelper.requireNonNull(f, "f is null"); return new Function() { @SuppressWarnings("unchecked") @Override public R apply(Object[] a) throws Exception { if (a.length != 5) { throw new IllegalArgumentException("Array of size 5 expected but got " + a.length); } return f.apply((T1)a[0], (T2)a[1], (T3)a[2], (T4)a[3], (T5)a[4]); } }; } public static Function toFunction( final Function6 f) { ObjectHelper.requireNonNull(f, "f is null"); return new Function() { @SuppressWarnings("unchecked") @Override public R apply(Object[] a) throws Exception { if (a.length != 6) { throw new IllegalArgumentException("Array of size 6 expected but got " + a.length); } return f.apply((T1)a[0], (T2)a[1], (T3)a[2], (T4)a[3], (T5)a[4], (T6)a[5]); } }; } public static Function toFunction( final Function7 f) { ObjectHelper.requireNonNull(f, "f is null"); return new Function() { @SuppressWarnings("unchecked") @Override public R apply(Object[] a) throws Exception { if (a.length != 7) { throw new IllegalArgumentException("Array of size 7 expected but got " + a.length); } return f.apply((T1)a[0], (T2)a[1], (T3)a[2], (T4)a[3], (T5)a[4], (T6)a[5], (T7)a[6]); } }; } public static Function toFunction( final Function8 f) { ObjectHelper.requireNonNull(f, "f is null"); return new Function() { @SuppressWarnings("unchecked") @Override public R apply(Object[] a) throws Exception { if (a.length != 8) { throw new IllegalArgumentException("Array of size 8 expected but got " + a.length); } return f.apply((T1)a[0], (T2)a[1], (T3)a[2], (T4)a[3], (T5)a[4], (T6)a[5], (T7)a[6], (T8)a[7]); } }; } public static Function toFunction( final Function9 f) { ObjectHelper.requireNonNull(f, "f is null"); return new Function() { @SuppressWarnings("unchecked") @Override public R apply(Object[] a) throws Exception { if (a.length != 9) { throw new IllegalArgumentException("Array of size 9 expected but got " + a.length); } return f.apply((T1)a[0], (T2)a[1], (T3)a[2], (T4)a[3], (T5)a[4], (T6)a[5], (T7)a[6], (T8)a[7], (T9)a[8]); } }; } /** A singleton identity function. */ static final Function IDENTITY = new Function() { @Override public Object apply(Object v) { return v; } @Override public String toString() { return "IdentityFunction"; } }; /** * Returns an identity function that simply returns its argument. * @param the input and output value type * @return the identity function */ @SuppressWarnings("unchecked") public static Function identity() { return (Function)IDENTITY; } public static final Runnable EMPTY_RUNNABLE = new Runnable() { @Override public void run() { } @Override public String toString() { return "EmptyRunnable"; } }; public static final Action EMPTY_ACTION = new Action() { @Override public void run() { } @Override public String toString() { return "EmptyAction"; } }; static final Consumer EMPTY_CONSUMER = new Consumer() { @Override public void accept(Object v) { } @Override public String toString() { return "EmptyConsumer"; } }; /** * Returns an empty consumer that does nothing. * @param the consumed value type, the value is ignored * @return an empty consumer that does nothing. */ @SuppressWarnings("unchecked") public static Consumer emptyConsumer() { return (Consumer)EMPTY_CONSUMER; } public static final Consumer ERROR_CONSUMER = new Consumer() { @Override public void accept(Throwable error) { RxJavaPlugins.onError(error); } }; public static final LongConsumer EMPTY_LONG_CONSUMER = new LongConsumer() { @Override public void accept(long v) { } }; static final Predicate ALWAYS_TRUE = new Predicate() { @Override public boolean test(Object o) { return true; } }; static final Predicate ALWAYS_FALSE = new Predicate() { @Override public boolean test(Object o) { return false; } }; static final Callable NULL_SUPPLIER = new Callable() { @Override public Object call() { return null; } }; static final Comparator NATURAL_COMPARATOR = new Comparator() { @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public int compare(Object a, Object b) { return ((Comparable)a).compareTo(b); } }; @SuppressWarnings("unchecked") public static Predicate alwaysTrue() { return (Predicate)ALWAYS_TRUE; } @SuppressWarnings("unchecked") public static Predicate alwaysFalse() { return (Predicate)ALWAYS_FALSE; } @SuppressWarnings("unchecked") public static Callable nullSupplier() { return (Callable)NULL_SUPPLIER; } /** * Returns a natural order comparator which casts the parameters to Comparable. * @param the value type * @return a natural order comparator which casts the parameters to Comparable */ @SuppressWarnings("unchecked") public static Comparator naturalOrder() { return (Comparator)NATURAL_COMPARATOR; } static final class FutureAction implements Action { final Future future; public FutureAction(Future future) { this.future = future; } @Override public void run() throws Exception { future.get(); } } /** * Wraps the blocking get call of the Future into an Action. * @param future the future to call get() on, not null * @return the new Action instance */ public static Action futureAction(Future future) { return new FutureAction(future); } static final class JustValue implements Callable, Function { final U value; public JustValue(U value) { this.value = value; } @Override public U call() throws Exception { return value; } @Override public U apply(T t) throws Exception { return value; } } /** * Returns a Callable that returns the given value. * @param the value type * @param value the value to return * @return the new Callable instance */ public static Callable justCallable(T value) { return new JustValue(value); } /** * Returns a Function that ignores its parameter and returns the given value. * @param the function's input type * @param the value and return type of the function * @param value the value to return * @return the new Function instance */ public static Function justFunction(U value) { return new JustValue(value); } static final class CastToClass implements Function { final Class clazz; public CastToClass(Class clazz) { this.clazz = clazz; } @Override public U apply(T t) throws Exception { return clazz.cast(t); } } /** * Returns a function that cast the incoming values via a Class object. * @param the input value type * @param the output and target type * @param target the target class * @return the new Function instance */ public static Function castFunction(Class target) { return new CastToClass(target); } static final class ArrayListCapacityCallable implements Callable> { final int capacity; public ArrayListCapacityCallable(int capacity) { this.capacity = capacity; } @Override public List call() throws Exception { return new ArrayList(capacity); } } public static Callable> createArrayList(int capacity) { return new ArrayListCapacityCallable(capacity); } static final class EqualsPredicate implements Predicate { final T value; public EqualsPredicate(T value) { this.value = value; } @Override public boolean test(T t) throws Exception { return ObjectHelper.equals(t, value); } } public static Predicate equalsWith(T value) { return new EqualsPredicate(value); } enum HashSetCallable implements Callable> { INSTANCE; @Override public Set call() throws Exception { return new HashSet(); } } @SuppressWarnings({ "rawtypes", "unchecked" }) public static Callable> createHashSet() { return (Callable)HashSetCallable.INSTANCE; } static final class NotificationOnNext implements Consumer { final Consumer> onNotification; public NotificationOnNext(Consumer> onNotification) { this.onNotification = onNotification; } @Override public void accept(T v) throws Exception { onNotification.accept(Notification.createOnNext(v)); } } static final class NotificationOnError implements Consumer { final Consumer> onNotification; public NotificationOnError(Consumer> onNotification) { this.onNotification = onNotification; } @Override public void accept(Throwable v) throws Exception { onNotification.accept(Notification.createOnError(v)); } } static final class NotificationOnComplete implements Action { final Consumer> onNotification; public NotificationOnComplete(Consumer> onNotification) { this.onNotification = onNotification; } @Override public void run() throws Exception { onNotification.accept(Notification.createOnComplete()); } } public static Consumer notificationOnNext(Consumer> onNotification) { return new NotificationOnNext(onNotification); } public static Consumer notificationOnError(Consumer> onNotification) { return new NotificationOnError(onNotification); } public static Action notificationOnComplete(Consumer> onNotification) { return new NotificationOnComplete(onNotification); } static final class ActionConsumer implements Consumer { final Action action; public ActionConsumer(Action action) { this.action = action; } @Override public void accept(T t) throws Exception { action.run(); } } public static Consumer actionConsumer(Action action) { return new ActionConsumer(action); } static final class ClassFilter implements Predicate { final Class clazz; public ClassFilter(Class clazz) { this.clazz = clazz; } @Override public boolean test(T t) throws Exception { return clazz.isInstance(t); } } public static Predicate isInstanceOf(Class clazz) { return new ClassFilter(clazz); } static final class BooleanSupplierPredicateReverse implements Predicate { final BooleanSupplier supplier; public BooleanSupplierPredicateReverse(BooleanSupplier supplier) { this.supplier = supplier; } @Override public boolean test(T t) throws Exception { return !supplier.getAsBoolean(); } } public static Predicate predicateReverseFor(BooleanSupplier supplier) { return new BooleanSupplierPredicateReverse(supplier); } static final class TimestampFunction implements Function> { final TimeUnit unit; final Scheduler scheduler; public TimestampFunction(TimeUnit unit, Scheduler scheduler) { this.unit = unit; this.scheduler = scheduler; } @Override public Timed apply(T t) throws Exception { return new Timed(t, scheduler.now(unit), unit); } } public static Function> timestampWith(TimeUnit unit, Scheduler scheduler) { return new TimestampFunction(unit, scheduler); } static final class ToMapKeySelector implements BiConsumer, T> { private final Function keySelector; ToMapKeySelector(Function keySelector) { this.keySelector = keySelector; } @Override public void accept(Map m, T t) throws Exception { K key = keySelector.apply(t); m.put(key, t); } } public static BiConsumer, T> toMapKeySelector(final Function keySelector) { return new ToMapKeySelector(keySelector); } static final class ToMapKeyValueSelector implements BiConsumer, T> { private final Function valueSelector; private final Function keySelector; ToMapKeyValueSelector(Function valueSelector, Function keySelector) { this.valueSelector = valueSelector; this.keySelector = keySelector; } @Override public void accept(Map m, T t) throws Exception { K key = keySelector.apply(t); V value = valueSelector.apply(t); m.put(key, value); } } public static BiConsumer, T> toMapKeyValueSelector(final Function keySelector, final Function valueSelector) { return new ToMapKeyValueSelector(valueSelector, keySelector); } static final class ToMultimapKeyValueSelector implements BiConsumer>, T> { private final Function> collectionFactory; private final Function valueSelector; private final Function keySelector; ToMultimapKeyValueSelector(Function> collectionFactory, Function valueSelector, Function keySelector) { this.collectionFactory = collectionFactory; this.valueSelector = valueSelector; this.keySelector = keySelector; } @SuppressWarnings("unchecked") @Override public void accept(Map> m, T t) throws Exception { K key = keySelector.apply(t); Collection coll = m.get(key); if (coll == null) { coll = (Collection)collectionFactory.apply(key); m.put(key, coll); } V value = valueSelector.apply(t); coll.add(value); } } public static BiConsumer>, T> toMultimapKeyValueSelector( final Function keySelector, final Function valueSelector, final Function> collectionFactory) { return new ToMultimapKeyValueSelector(collectionFactory, valueSelector, keySelector); } enum NaturalComparator implements Comparator { INSTANCE; @SuppressWarnings("unchecked") @Override public int compare(Object o1, Object o2) { return ((Comparable)o1).compareTo(o2); } } @SuppressWarnings("unchecked") public static Comparator naturalComparator() { return (Comparator)NaturalComparator.INSTANCE; } static final class ListSorter implements Function, List> { private final Comparator comparator; ListSorter(Comparator comparator) { this.comparator = comparator; } @Override public List apply(List v) { Collections.sort(v, comparator); return v; } } public static Function, List> listSorter(final Comparator comparator) { return new ListSorter(comparator); } }