package com.github.davidmoten.rx.internal.operators;
import rx.*;
import rx.Observable.*;
import rx.exceptions.*;
import rx.functions.Func1;
import rx.internal.producers.ProducerArbiter;
/**
* Switches to different Observables if the main source completes or signals an error.
*
* @param <T> the value type
*/
public final class TransformerOnTerminateResume<T> implements Transformer<T, T> {
final Func1<Throwable, Observable<T>> onError;
final Observable<T> onCompleted;
public TransformerOnTerminateResume(Func1<Throwable, Observable<T>> onError, Observable<T> onCompleted) {
this.onError = onError;
this.onCompleted = onCompleted;
}
@Override
public Observable<T> call(final Observable<T> o) {
return Observable.create(new OnSubscribe<T>() {
@Override
public void call(Subscriber<? super T> t) {
OnTerminateResumeSubscriber<T> parent = new OnTerminateResumeSubscriber<T>(t, onError, onCompleted);
t.add(parent);
t.setProducer(parent.arbiter);
o.unsafeSubscribe(parent);
}
});
}
static final class OnTerminateResumeSubscriber<T> extends Subscriber<T> {
final Subscriber<? super T> actual;
final Func1<Throwable, Observable<T>> onError;
final Observable<T> onCompleted;
final ProducerArbiter arbiter;
long produced;
public OnTerminateResumeSubscriber(Subscriber<? super T> actual, Func1<Throwable,
Observable<T>> onError,
Observable<T> onCompleted) {
this.arbiter = new ProducerArbiter();
this.actual = actual;
this.onError = onError;
this.onCompleted = onCompleted;
}
@Override
public void onNext(T t) {
produced++;
actual.onNext(t);
}
@Override
public void onError(Throwable e) {
long p = produced;
if (p != 0L) {
arbiter.produced(p);
}
Observable<T> o;
try {
o = onError.call(e);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
actual.onError(new CompositeException(e, ex));
return;
}
if (o == null) {
actual.onError(new NullPointerException("The onError function returned a null Observable."));
} else {
o.unsafeSubscribe(new ResumeSubscriber<T>(actual, arbiter));
}
}
@Override
public void onCompleted() {
long p = produced;
if (p != 0L) {
arbiter.produced(p);
}
onCompleted.unsafeSubscribe(new ResumeSubscriber<T>(actual, arbiter));
}
@Override
public void setProducer(Producer p) {
arbiter.setProducer(p);
}
static final class ResumeSubscriber<T> extends Subscriber<T> {
final Subscriber<? super T> actual;
final ProducerArbiter arbiter;
public ResumeSubscriber(Subscriber<? super T> actual, ProducerArbiter arbiter) {
this.actual = actual;
this.arbiter = arbiter;
}
@Override
public void onCompleted() {
actual.onCompleted();
}
@Override
public void onError(Throwable e) {
actual.onError(e);
}
@Override
public void onNext(T t) {
actual.onNext(t);
}
@Override
public void setProducer(Producer p) {
arbiter.setProducer(p);
}
}
}
}