/**
 * 
 */
package com.github.phantomthief.util;

import static com.google.common.base.Throwables.propagate;

import java.util.concurrent.Callable;

/**
 * @author w.vela
 */
public class MoreFunctions {

    public static <R> R catching(Callable<R> callable) {
        return catching(callable, (Class<Throwable>) null);
    }

    @SafeVarargs
    public static <R> R catching(Callable<R> callable,
            Class<? extends Throwable>... catchThrowables) {
        try {
            return callable.call();
        } catch (Throwable e) {
            if (catchThrowables != null) {
                for (Class<? extends Throwable> throwable : catchThrowables) {
                    if (throwable != null) {
                        if (!throwable.isInstance(e)) {
                            throw propagate(e);
                        }
                    }
                }
            }
            return null;
        }
    }

    public static <T, R> R catching(FunctionWithThrowable<T, R, Throwable> function, T t) {
        return catching(function, t, (Class<Throwable>) null);
    }

    @SafeVarargs
    public static <T, R> R catching(FunctionWithThrowable<T, R, Throwable> function, T t,
            Class<? extends Throwable>... catchThrowables) {
        try {
            return function.apply(t);
        } catch (Throwable e) {
            if (catchThrowables != null) {
                for (Class<? extends Throwable> throwable : catchThrowables) {
                    if (throwable != null) {
                        if (!throwable.isInstance(e)) {
                            throw propagate(e);
                        }
                    }
                }
            }
            return null;
        }
    }

    public interface FunctionWithThrowable<T, R, X extends Throwable> {

        R apply(T t) throws X;
    }
}

@@ -103,16 +103,88 @@
 pagate;%0A
+import static java.util.Optional.ofNullable;%0A%0Aimport java.util.Optional;
 %0Aimport 
@@ -297,100 +297,436 @@
 %3CR%3E 
-R catching(Callable%3CR%3E callable) %7B%0A        return catching(callable, (Class%3CThrowable%3E) null
+Optional%3CR%3E safe(Callable%3CR%3E callable) %7B%0A        return safe(callable, (Class%3CThrowable%3E) null);%0A    %7D%0A%0A    public static %3CR%3E R catching(Callable%3CR%3E callable) %7B%0A        return catching(callable, (Class%3CThrowable%3E) null);%0A    %7D%0A%0A    @SafeVarargs%0A    public static %3CR%3E Optional%3CR%3E safe(Callable%3CR%3E callable,%0A            Class%3C? extends Throwable%3E... catchThrowables) %7B%0A        return ofNullable(catching(callable, catchThrowables)
 );%0A 
@@ -1368,135 +1368,547 @@
  R%3E 
-R catching(FunctionWithThrowable%3CT, R, Throwable%3E function, T t) %7B%0A        return catching(function, t, (Class%3CThrowable%3E) null
+Optional%3CR%3E safe(FunctionWithThrowable%3CT, R, Throwable%3E function, T t) %7B%0A        return safe(function, t, (Class%3CThrowable%3E) null);%0A    %7D%0A%0A    public static %3CT, R%3E R catching(FunctionWithThrowable%3CT, R, Throwable%3E function, T t) %7B%0A        return catching(function, t, (Class%3CThrowable%3E) null);%0A    %7D%0A%0A    @SafeVarargs%0A    public static %3CT, R%3E Optional%3CR%3E safe(FunctionWithThrowable%3CT, R, Throwable%3E function, T t,%0A            Class%3C? extends Throwable%3E... catchThrowables) %7B%0A        return ofNullable(catching(function, t, catchThrowables)
 );%0A 

add safe.