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

import java.util.function.Predicate;

import com.github.phantomthief.failover.Failover;
import com.github.phantomthief.failover.exception.NoAvailableResourceException;
import com.github.phantomthief.util.ThrowableConsumer;
import com.github.phantomthief.util.ThrowableFunction;
import com.google.common.base.Throwables;

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

    private FailoverUtils() {
        throw new UnsupportedOperationException();
    }

    public static <T, R, X extends Throwable> R run(Failover<T> failover,
            ThrowableFunction<T, R, X> func, Predicate<Throwable> failChecker) {
        T oneAvailable = failover.getOneAvailable();
        if (oneAvailable != null) {
            try {
                R result = func.apply(oneAvailable);
                failover.success(oneAvailable);
                return result;
            } catch (Throwable e) {
                if (failChecker == null || failChecker.test(e)) {
                    failover.fail(oneAvailable);
                } else {
                    failover.success(oneAvailable);
                }
                throw Throwables.propagate(e);
            }
        } else {
            throw new NoAvailableResourceException();
        }
    }

    public static <T, X extends Throwable> void call(Failover<T> failover,
            ThrowableConsumer<T, X> func, Predicate<Throwable> failChecker) {
        T oneAvailable = failover.getOneAvailable();
        if (oneAvailable != null) {
            try {
                func.accept(oneAvailable);
                failover.success(oneAvailable);
            } catch (Throwable e) {
                if (failChecker == null || failChecker.test(e)) {
                    failover.fail(oneAvailable);
                } else {
                    failover.success(oneAvailable);
                }
                throw Throwables.propagate(e);
            }
        } else {
            throw new NoAvailableResourceException();
        }
    }
}

@@ -372,16 +372,61 @@
 owables;
+%0Aimport com.google.common.reflect.Reflection;
 %0A%0A/**%0A *
@@ -2096,11 +2096,299 @@
  %7D%0A    %7D
+%0A%0A    public static %3CT, E%3E T proxy(Class%3CT%3E iface, T toProxyObject, Failover%3CE%3E failover,%0A            Predicate%3CThrowable%3E failChecker) %7B%0A        return Reflection.newProxy(iface, (proxy, method, args) -%3E run(failover,%0A                res -%3E method.invoke(res, args), failChecker));%0A    %7D
 %0A%7D%0A

add proxy mode for failover utils.