Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.util;
     18 
     19 import android.os.RemoteException;
     20 import android.util.ExceptionUtils;
     21 
     22 import java.util.function.Consumer;
     23 import java.util.function.Supplier;
     24 
     25 /**
     26  * Utilities specific to functional programming
     27  */
     28 public class FunctionalUtils {
     29     private FunctionalUtils() {}
     30 
     31     /**
     32      * Converts a lambda expression that throws a checked exception(s) into a regular
     33      * {@link Consumer} by propagating any checked exceptions as {@link RuntimeException}
     34      */
     35     public static <T> Consumer<T> uncheckExceptions(ThrowingConsumer<T> action) {
     36         return action;
     37     }
     38 
     39     /**
     40      * Wraps a given {@code action} into one that ignores any {@link RemoteException}s
     41      */
     42     public static <T> Consumer<T> ignoreRemoteException(RemoteExceptionIgnoringConsumer<T> action) {
     43         return action;
     44     }
     45 
     46     /**
     47      * Wraps the given {@link ThrowingRunnable} into one that handles any exceptions using the
     48      * provided {@code handler}
     49      */
     50     public static Runnable handleExceptions(ThrowingRunnable r, Consumer<Throwable> handler) {
     51         return () -> {
     52             try {
     53                 r.run();
     54             } catch (Throwable t) {
     55                 handler.accept(t);
     56             }
     57         };
     58     }
     59 
     60     /**
     61      * An equivalent of {@link Runnable} that allows throwing checked exceptions
     62      *
     63      * This can be used to specify a lambda argument without forcing all the checked exceptions
     64      * to be handled within it
     65      */
     66     @FunctionalInterface
     67     @SuppressWarnings("FunctionalInterfaceMethodChanged")
     68     public interface ThrowingRunnable extends Runnable {
     69         void runOrThrow() throws Exception;
     70 
     71         @Override
     72         default void run() {
     73             try {
     74                 runOrThrow();
     75             } catch (Exception ex) {
     76                 throw ExceptionUtils.propagate(ex);
     77             }
     78         }
     79     }
     80 
     81     /**
     82      * An equivalent of {@link Supplier} that allows throwing checked exceptions
     83      *
     84      * This can be used to specify a lambda argument without forcing all the checked exceptions
     85      * to be handled within it
     86      */
     87     @FunctionalInterface
     88     public interface ThrowingSupplier<T> {
     89         T getOrThrow() throws Exception;
     90     }
     91 
     92     /**
     93      * A {@link Consumer} that allows throwing checked exceptions from its single abstract method.
     94      *
     95      * Can be used together with {@link #uncheckExceptions} to effectively turn a lambda expression
     96      * that throws a checked exception into a regular {@link Consumer}
     97      */
     98     @FunctionalInterface
     99     @SuppressWarnings("FunctionalInterfaceMethodChanged")
    100     public interface ThrowingConsumer<T> extends Consumer<T> {
    101         void acceptOrThrow(T t) throws Exception;
    102 
    103         @Override
    104         default void accept(T t) {
    105             try {
    106                 acceptOrThrow(t);
    107             } catch (Exception ex) {
    108                 throw ExceptionUtils.propagate(ex);
    109             }
    110         }
    111     }
    112 
    113     /**
    114      * A {@link Consumer} that automatically ignores any {@link RemoteException}s.
    115      *
    116      * Used by {@link #ignoreRemoteException}
    117      */
    118     @FunctionalInterface
    119     @SuppressWarnings("FunctionalInterfaceMethodChanged")
    120     public interface RemoteExceptionIgnoringConsumer<T> extends Consumer<T> {
    121         void acceptOrThrow(T t) throws RemoteException;
    122 
    123         @Override
    124         default void accept(T t) {
    125             try {
    126                 acceptOrThrow(t);
    127             } catch (RemoteException ex) {
    128                 // ignore
    129             }
    130         }
    131     }
    132 }
    133