public class Shelly {

    private static final TargetCenter TARGET_CENTER = TargetCenter.getInstance();

    private static final DominoCenter DOMINO_CENTER = DominoCenter.getInstance();

    public static void register(Object object) {
        TARGET_CENTER.register(object);
    }

    public static boolean isRegistered(Object object) {
        return TARGET_CENTER.isRegistered(object);
    }

    public static void unregister(Object object) {
        TARGET_CENTER.unregister(object);
    }

    public static <T> Domino<T, T> createDomino(Object label) {
        return new Domino<T, T>(label);
    }

    public static <T> Domino<T, T> createAnonymousDomino() {
        return createDomino(null);
    }

    @SafeVarargs
    public static <T> void playDomino(Object label, T... input) {
        CopyOnWriteArrayList<T> newInput = new CopyOnWriteArrayList<T>();
        if (input == null) {
            newInput.add(null);
        } else if (input.length > 0) {
            newInput.addAll(Arrays.asList(input));
        }
        playDominoInternal(label, newInput);
    }

    public static void playDomino(Object label) {
        playDominoInternal(label, new CopyOnWriteArrayList<Object>());
    }

    private static <T> void playDominoInternal(Object label, CopyOnWriteArrayList<T> input) {
        DOMINO_CENTER.play(label, input);
    }

    public static <T, R> Domino<T, R> getDominoByLabel(Object label) {
        return DOMINO_CENTER.getDomino(label);
    }
} public interface Action0 extends Action {
    void call();
} public interface Action1<T> extends Action {
    void call(T input);
} public interface Function1<T, R> extends Function {
    R call(T input);
} public interface Function2<T, R, S> extends Function {
    S call(T input1, R input2);
} public interface TargetAction0<T> extends Action {
    void call(T t);
} public interface TargetAction1<T, R> extends Action {
    void call(T t, R input);
} public interface TargetAction2<T, R, S> extends Action {
    void call(T t, R input1, S input2);
} public abstract class StashAction1<T> extends StashAction implements Action1<T> {
} public abstract class RetrofitTask<T, R> extends AbstractRetrofitTask<T, R> {
    @Override
    protected void call(Call<R> call) {
        call.enqueue(getCallback());
    }

} public abstract class Task<T, R, S> {

    private TaskListener<R, S> mListener;

    public Task() {
    }

    public void setListener(TaskListener<R, S> listener) {
        mListener = listener;
    }

    protected abstract void onExecute(T input);

    public final void execute(T input) {
        onExecute(input);
    }

    public final void notifySuccess(R result) {
        if (mListener != null) {
            mListener.onSuccess(result);
        }
    }

    public final void notifyFailure(S error) {
        if (mListener != null) {
            mListener.onFailure(error);
        }
    }

    public interface TaskListener<R, S> {
        void onSuccess(R result);
        void onFailure(S error);
    }

} public class Pair<T1, T2> {
    public final T1 first;
    public final T2 second;

    @Deprecated
    public Pair(T1 first, T2 second) {
        this.first = first;
        this.second = second;
    }

    public static <T1, T2> Pair<T1, T2> create(T1 first, T2 second) {
        return new Pair<T1, T2>(first, second);
    }
} public class Triple<T1, T2, T3> {
    public final T1 first;
    public final T2 second;
    public final T3 third;

    @Deprecated
    public Triple(T1 first, T2 second, T3 third) {
        this.first = first;
        this.second = second;
        this.third = third;
    }

    public static <T1, T2, T3> Triple<T1, T2, T3> create(T1 first, T2 second, T3 third) {
        return new Triple<T1, T2, T3>(first, second, third);
    }
}
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Response;
import xiaofei.library.shelly.Shelly;
import xiaofei.library.shelly.function.Action0;
import xiaofei.library.shelly.function.Action1;
import xiaofei.library.shelly.function.Function1;
import xiaofei.library.shelly.function.Function2;
import xiaofei.library.shelly.function.TargetAction0;
import xiaofei.library.shelly.function.TargetAction1;
import xiaofei.library.shelly.function.TargetAction2;
import xiaofei.library.shelly.function.stashfunction.StashAction1;
import xiaofei.library.shelly.task.RetrofitTask;
import xiaofei.library.shelly.task.Task;
import xiaofei.library.shelly.tuple.Pair;
import xiaofei.library.shelly.tuple.Triple;
                // If the execution of the above task succeeds,
                // perform an action on all registered instances of ImageView.
                .onSuccess(ImageView.class, new TargetAction1<ImageView, Pair<String,Bitmap>>() {
                    @Override
                    public void call(ImageView imageView, Pair<String, Bitmap> input) {

                    }
                })
                // The following actions will be performed in background.
                .background()
                // If the execution of the above task fails, perform an action.
                .onFailure(new Action0() {
                    @Override
                    public void call() {
                        // Do something.
                    }
                })
                // If the execution of the above task fails, print the stack trace fo the exception.
                .onFailure(new Action1<Exception>() {
                    @Override
                    public void call(Exception input) {
                        input.printStackTrace();
                    }
                })
                // If the execution of the above task fails,
                // perform an action on all registered instances of ImageView.
                .onFailure(ImageView.class, new TargetAction1<ImageView, Exception>() {
                    @Override
                    public void call(ImageView imageView, Exception input) {
                        // Do something.
                    }
                })
                .endTask()
                .perform(new Action1<Pair<String, Bitmap>>() {
                    @Override
                    public void call(Pair<String, Bitmap> input) {

                    }
                })
                .commit();
        final Network network = null;

        Shelly.<String>createDomino("GETTING_USER")
                .background()
                // Return a call for the Retrofit task.
                .beginRetrofitTask(new RetrofitTask<String, User>() {
                    @Override
                    protected Call<User> getCall(String s) {
                        return network.getUser(s);
                    }
                })
                .uiThread()
                // If the request succeed and we get the user information,
                // perform an action.
                .onSuccessResult(new Action0() {
                    @Override
                    public void call() {

                    }
                })
                // If the request succeed and we get the user information,
                // perform an action on MyActivity.
                .onSuccessResult(MyActivity.class, new TargetAction1<MyActivity, User>() {
                    @Override
                    public void call(MyActivity mainActivity, User input) {

                    }
                })
                // If the request succeed but we get an error from the server,
                // perform an action.
                .onResponseFailure(new Action0() {
                    @Override
                    public void call() {

                    }
                })
                // If the request succeed but we get an error from the server,
                // perform an action on MyActivity.
                .onResponseFailure(MyActivity.class, new TargetAction1<MyActivity, Response<User>>() {
                    @Override
                    public void call(MyActivity myActivity, Response<User> input) {

                    }
                })
                // If the request fails, perform an action.
                .onFailure(new Action1<Throwable>() {
                    @Override
                    public void call(Throwable input) {

                    }
                })
                // If the request fails, perform an action on MyActivity.
                .onFailure(MyActivity.class, new TargetAction1<MyActivity, Throwable>() {
                    @Override
                    public void call(MyActivity myActivity, Throwable input) {

                    }
                })
                .endTask()
                .commit();
        Shelly.<String>createDomino("GETTING_USER")
                .background()
                // Return a call for the Retrofit task.
                .beginRetrofitTaskKeepingInput(new RetrofitTask<String, User>() {
                    @Override
                    protected Call<User> getCall(String s) {
                        return network.getUser(s);
                    }
                })
                .uiThread()
                // If the request succeed and we get the user information,
                // perform an action.
                .onSuccessResult(new Action0() {
                    @Override
                    public void call() {

                    }
                })
                // If the request succeed and we get the user information,
                // perform an action on MyActivity.
                .onSuccessResult(MyActivity.class, new TargetAction2<MyActivity, String, User>() {