1cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla/*
2cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla * Copyright (C) 2017 The Android Open Source Project
3cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla *
4cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla * Licensed under the Apache License, Version 2.0 (the "License");
5cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla * you may not use this file except in compliance with the License.
6cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla * You may obtain a copy of the License at
7cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla *
8cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla *      http://www.apache.org/licenses/LICENSE-2.0
9cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla *
10cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla * Unless required by applicable law or agreed to in writing, software
11cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla * distributed under the License is distributed on an "AS IS" BASIS,
12cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla * See the License for the specific language governing permissions and
14cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla * limitations under the License.
15cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla */
16cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla
17cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Suslapackage com.android.internal.util;
18cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla
194b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Suslaimport android.os.RemoteException;
207b24b2bc3eeb1313e275f73fe62055ead408745cEugene Suslaimport android.util.ExceptionUtils;
214b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla
224b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Suslaimport java.util.function.Consumer;
23cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Suslaimport java.util.function.Supplier;
24cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla
25cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla/**
26cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla * Utilities specific to functional programming
27cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla */
28cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Suslapublic class FunctionalUtils {
29cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla    private FunctionalUtils() {}
30cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla
31cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla    /**
324b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     * Converts a lambda expression that throws a checked exception(s) into a regular
334b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     * {@link Consumer} by propagating any checked exceptions as {@link RuntimeException}
344b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     */
354b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    public static <T> Consumer<T> uncheckExceptions(ThrowingConsumer<T> action) {
364b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        return action;
374b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    }
384b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla
394b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    /**
407b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla     * Wraps a given {@code action} into one that ignores any {@link RemoteException}s
414b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     */
424b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    public static <T> Consumer<T> ignoreRemoteException(RemoteExceptionIgnoringConsumer<T> action) {
434b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        return action;
444b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    }
454b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla
464b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    /**
477b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla     * Wraps the given {@link ThrowingRunnable} into one that handles any exceptions using the
487b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla     * provided {@code handler}
497b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla     */
507b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla    public static Runnable handleExceptions(ThrowingRunnable r, Consumer<Throwable> handler) {
517b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla        return () -> {
527b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla            try {
537b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla                r.run();
547b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla            } catch (Throwable t) {
557b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla                handler.accept(t);
567b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla            }
577b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla        };
587b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla    }
597b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla
607b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla    /**
61cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla     * An equivalent of {@link Runnable} that allows throwing checked exceptions
62cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla     *
63cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla     * This can be used to specify a lambda argument without forcing all the checked exceptions
64cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla     * to be handled within it
65cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla     */
66cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla    @FunctionalInterface
677b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla    @SuppressWarnings("FunctionalInterfaceMethodChanged")
687b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla    public interface ThrowingRunnable extends Runnable {
692f5ee71ec851b1149b4e10ec211ad520cd73776eEugene Susla        void runOrThrow() throws Exception;
707b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla
717b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla        @Override
727b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla        default void run() {
737b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla            try {
747b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla                runOrThrow();
757b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla            } catch (Exception ex) {
767b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla                throw ExceptionUtils.propagate(ex);
777b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla            }
787b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla        }
79cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla    }
80cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla
81cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla    /**
82cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla     * An equivalent of {@link Supplier} that allows throwing checked exceptions
83cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla     *
84cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla     * This can be used to specify a lambda argument without forcing all the checked exceptions
85cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla     * to be handled within it
86cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla     */
87cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla    @FunctionalInterface
88cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla    public interface ThrowingSupplier<T> {
892f5ee71ec851b1149b4e10ec211ad520cd73776eEugene Susla        T getOrThrow() throws Exception;
90cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla    }
91612311ef41ea2304c7d487b321b88c60fbfe9d6cEugene Susla
92612311ef41ea2304c7d487b321b88c60fbfe9d6cEugene Susla    /**
934b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     * A {@link Consumer} that allows throwing checked exceptions from its single abstract method.
94612311ef41ea2304c7d487b321b88c60fbfe9d6cEugene Susla     *
954b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     * Can be used together with {@link #uncheckExceptions} to effectively turn a lambda expression
964b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     * that throws a checked exception into a regular {@link Consumer}
974b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     */
984b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    @FunctionalInterface
994b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    @SuppressWarnings("FunctionalInterfaceMethodChanged")
1004b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    public interface ThrowingConsumer<T> extends Consumer<T> {
1014b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        void acceptOrThrow(T t) throws Exception;
1024b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla
1034b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        @Override
1044b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        default void accept(T t) {
1054b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla            try {
1064b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla                acceptOrThrow(t);
1074b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla            } catch (Exception ex) {
1087b24b2bc3eeb1313e275f73fe62055ead408745cEugene Susla                throw ExceptionUtils.propagate(ex);
1094b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla            }
1104b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        }
1114b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    }
1124b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla
1134b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    /**
1144b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     * A {@link Consumer} that automatically ignores any {@link RemoteException}s.
1154b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     *
1164b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     * Used by {@link #ignoreRemoteException}
117612311ef41ea2304c7d487b321b88c60fbfe9d6cEugene Susla     */
118612311ef41ea2304c7d487b321b88c60fbfe9d6cEugene Susla    @FunctionalInterface
1194b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    @SuppressWarnings("FunctionalInterfaceMethodChanged")
1204b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    public interface RemoteExceptionIgnoringConsumer<T> extends Consumer<T> {
1214b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        void acceptOrThrow(T t) throws RemoteException;
1224b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla
1234b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        @Override
1244b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        default void accept(T t) {
1254b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla            try {
1264b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla                acceptOrThrow(t);
1274b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla            } catch (RemoteException ex) {
1284b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla                // ignore
1294b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla            }
1304b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        }
131612311ef41ea2304c7d487b321b88c60fbfe9d6cEugene Susla    }
132cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla}
133