public interface AlwaysCallback {

    void onAlways();

} public interface CancelCallback {

    void onCancel();

} public interface DoneCallback<T> {

    void onDone(T result);

} public interface FailCallback {

    void onFail(Exception exception);

} public interface ProgressCallback<Progress> {

    void onProgress(Progress progress);

} public interface ThenCallback<Arg, Result, Progress> {

    Promise<Result, Progress> then(Arg arg);

} public interface UIAlwaysCallback extends AlwaysCallback {
} public interface UICancelCallback extends CancelCallback {
} public interface UIDoneCallback<T> extends DoneCallback<T> {
} public interface UIFailCallback extends FailCallback {
} public interface UIProgressCallback<Progress> extends ProgressCallback<Progress> {
} public interface Filter<T> {
    boolean filter(T value);
} public interface Mapper<T, U> {
    U map(T value);
} public class ObjectPool<T> {
    private final Object mLock = new Object();
    private final Object[] mPool;

    private int mPoolSize;

    /**
     * Creates a new instance.
     *
     * @param maxPoolSize The max pool size.
     * @throws IllegalArgumentException If the max pool size is less than zero.
     */
    public ObjectPool(int maxPoolSize) {
        if (maxPoolSize <= 0) {
            throw new IllegalArgumentException("The max pool size must be > 0");
        }
        mPool = new Object[maxPoolSize];
    }

    @SuppressWarnings("unchecked")
    public T acquire() {
        synchronized (mLock) {
            if (mPoolSize > 0) {
                final int lastPooledIndex = mPoolSize - 1;
                T instance = (T) mPool[lastPooledIndex];
                mPool[lastPooledIndex] = null;
                mPoolSize--;
                return instance;
            }
            return null;
        }
    }

    public boolean release(T element) {
        synchronized (mLock) {
            if (isInPool(element)) {
                throw new IllegalStateException("Already in the pool!");
            }
            if (mPoolSize < mPool.length) {
                mPool[mPoolSize] = element;
                mPoolSize++;
                return true;
            }
            return false;
        }
    }

    private boolean isInPool(T element) {
        for (int i = 0; i < mPoolSize; i++) {
            if (mPool[i] == element) {
                return true;
            }
        }
        return false;
    }
}
import com.raycoarana.awex.callbacks.AlwaysCallback;
import com.raycoarana.awex.callbacks.CancelCallback;
import com.raycoarana.awex.callbacks.DoneCallback;
import com.raycoarana.awex.callbacks.FailCallback;
import com.raycoarana.awex.callbacks.ProgressCallback;
import com.raycoarana.awex.callbacks.ThenCallback;
import com.raycoarana.awex.callbacks.UIAlwaysCallback;
import com.raycoarana.awex.callbacks.UICancelCallback;
import com.raycoarana.awex.callbacks.UIDoneCallback;
import com.raycoarana.awex.callbacks.UIFailCallback;
import com.raycoarana.awex.callbacks.UIProgressCallback;
import com.raycoarana.awex.transform.Filter;
import com.raycoarana.awex.transform.Mapper;
import com.raycoarana.awex.util.ObjectPool;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
     * @param result value used to resolve the promise
     * @throws IllegalStateException if the promise is not in pending state
     * @return this promise
     */
    @SuppressWarnings("unchecked")
    public Promise<Result, Progress> resolve(Result result) {
        List<DoneCallback<Result>> doneCallbacks;
        List<AlwaysCallback> alwaysCallbacks;
        synchronized (this) {
            validateInPendingState();

            mState = STATE_RESOLVED;
            printStateChanged("RESOLVED");
            mResult = result;

            doneCallbacks = mCallbacks.cloneDoneCallbacks();
            alwaysCallbacks = mCallbacks.cloneAlwaysCallbacks();
            clearCallbacks();
        }

        if (doneCallbacks.size() > 0 || alwaysCallbacks.size() > 0) {
            triggerAllDones(doneCallbacks);
            triggerAllAlways(alwaysCallbacks);
        }

        return this;
    }


    private void triggerAllDones(Collection<DoneCallback<Result>> doneCallbacks) {
        for (final DoneCallback<Result> callback : doneCallbacks) {
            triggerDone(callback);
        }
    }

    private void triggerDone(final DoneCallback<Result> callback) {
        if (callback instanceof UIDoneCallback && !mThreadHelper.isCurrentThread()) {
            mThreadHelper.post(new CancellableRunnable() {
                @Override
                public void execute() {
                    tryTrigger(callback, mResult);
                }
            });
        } else {
            tryTrigger(callback, mResult);
        }
    }

    private void tryTrigger(DoneCallback<Result> callback, Result result) {
        try {
            callback.onDone(result);
        } catch (Exception ex) {
            mLogger.e("Error when trigger done callback", ex);
        }
    }

    /**
     * Rejects the promise, triggers any fail/always callbacks
     *
     * @param ex exception that represents the rejection of the promise
     * @return this promise
     */
    @SuppressWarnings("unchecked")
    public Promise<Result, Progress> reject(Exception ex) {
        List<FailCallback> failCallbacks;
        List<AlwaysCallback> alwaysCallbacks;
        synchronized (this) {
            validateInPendingState();

            mState = STATE_REJECTED;
            printStateChanged("REJECTED");
            mException = ex;

            failCallbacks = mCallbacks.cloneFailCallbacks();
            alwaysCallbacks = mCallbacks.cloneAlwaysCallbacks();
            clearCallbacks();
        }

        if (failCallbacks.size() > 0 || alwaysCallbacks.size() > 0) {
            triggerAllFails(failCallbacks);
            triggerAllAlways(alwaysCallbacks);
        }

        return this;
    }

    private void triggerAllFails(Collection<FailCallback> failCallbacks) {
        for (final FailCallback callback : failCallbacks) {
            triggerFail(callback);
        }
    }

    private void triggerFail(final FailCallback callback) {
        if (callback instanceof UIFailCallback && !mThreadHelper.isCurrentThread()) {
            mThreadHelper.post(new CancellableRunnable() {
                @Override
                public void execute() {
                    tryTrigger(callback, mException);
                }
            });
        } else {
            tryTrigger(callback, mException);
        }
    }

    private void tryTrigger(FailCallback callback, Exception exception) {
        try {
            callback.onFail(exception);
        } catch (Exception ex) {
            mLogger.e("Error when trigger fail callback", ex);
        }
    }

    private void triggerAllAlways(List<AlwaysCallback> alwaysCallbacks) {
        for (final AlwaysCallback callback : alwaysCallbacks) {
            triggerAlways(callback);
        }
    }

    private void triggerAlways(final AlwaysCallback callback) {
        if (callback instanceof UIAlwaysCallback && !mThreadHelper.isCurrentThread()) {