/*
This file is part of Reactive Cascade which is released under The MIT License.
See license.md , https://github.com/futurice/cascade and http://reactivecascade.com for details.
This is open source for the common good. Please contribute improvements by pull request or contact paulirotta@gmail.com
*/
package com.reactivecascade.functional;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.reactivecascade.Async;
import com.reactivecascade.i.IActionOne;
import com.reactivecascade.i.IThreadType;
import com.reactivecascade.i.NotCallOrigin;
import com.reactivecascade.util.RCLog;
/**
* The on-error action in a chain will be launched asynchronously
* <p>
* The error is consumed by this chain link. All downchain items will be notified synchronously
* as {@link #onCancelled(StateCancelled)}
*/
public class OnErrorAltFuture<T> extends SettableAltFuture<T> {
@NonNull
private final IActionOne<Exception> mOnErrorAction;
/**
* Constructor
*
* @param threadType the thread pool to run this command on
* @param onErrorAction a function that receives one input and no return from
*/
@SuppressWarnings("unchecked")
public OnErrorAltFuture(@NonNull IThreadType threadType,
@NonNull IActionOne<Exception> onErrorAction) {
super(threadType);
this.mOnErrorAction = onErrorAction;
}
@NotCallOrigin
@Override // IAltFuture
public void onError(@NonNull StateError stateError) throws Exception {
RCLog.d(this, "Handling onError(): " + stateError);
if (!this.stateAR.compareAndSet(VALUE_NOT_AVAILABLE, stateError) || (Async.USE_FORKED_STATE && !this.stateAR.compareAndSet(FORKED, stateError))) {
RCLog.i(this, "Will not onError() because IAltFuture state is already determined: " + stateAR.get());
return;
}
threadType
.from(stateError.getException())
.then(mOnErrorAction)
.fork();
StateCancelled stateCancelled = new StateCancelled() {
private final ImmutableValue<String> mOrigin = RCLog.originAsync();
@NonNull
@Override
public String getReason() {
return "Cancelled after onError() notified: " + getStateError();
}
@Nullable
@Override
public StateError getStateError() {
return stateError;
}
@NonNull
@Override
public ImmutableValue<String> getOrigin() {
return mOrigin;
}
};
Exception e = forEachThen(af -> {
af.onCancelled(stateCancelled);
});
if (e != null) {
throw e;
}
}
}