package com.apollographql.apollo.rx2;
import com.apollographql.apollo.ApolloCall;
import com.apollographql.apollo.ApolloPrefetch;
import com.apollographql.apollo.ApolloQueryWatcher;
import com.apollographql.apollo.api.Response;
import com.apollographql.apollo.exception.ApolloException;
import com.apollographql.apollo.internal.util.Cancelable;
import javax.annotation.Nonnull;
import io.reactivex.Completable;
import io.reactivex.CompletableEmitter;
import io.reactivex.CompletableOnSubscribe;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Single;
import io.reactivex.SingleEmitter;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.disposables.Disposable;
import io.reactivex.exceptions.Exceptions;
import static com.apollographql.apollo.api.internal.Utils.checkNotNull;
/**
* The Rx2Apollo class provides methods for converting ApolloCall, ApolloPrefetch
* and ApolloWatcher types to RxJava 2 sources.
*/
public class Rx2Apollo {
private Rx2Apollo() {
throw new AssertionError("This class cannot be instantiated");
}
/**
* Converts an {@link ApolloQueryWatcher} to an asynchronous Observable.
*
* @param watcher the ApolloQueryWatcher to convert.
* @param <T> the value type
* @return the converted Observable
* @throws NullPointerException if watcher == null
*/
public static <T> Observable<Response<T>> from(@Nonnull final ApolloQueryWatcher<T> watcher) {
checkNotNull(watcher, "watcher == null");
return Observable.create(new ObservableOnSubscribe<Response<T>>() {
@Override public void subscribe(final ObservableEmitter<Response<T>> emitter) throws Exception {
cancelOnObservableDisposed(emitter, watcher);
watcher.enqueueAndWatch(new ApolloCall.Callback<T>() {
@Override public void onResponse(@Nonnull Response<T> response) {
if (!emitter.isDisposed()) {
emitter.onNext(response);
}
}
@Override public void onFailure(@Nonnull ApolloException e) {
Exceptions.throwIfFatal(e);
if (!emitter.isDisposed()) {
emitter.onError(e);
}
}
});
}
});
}
/**
* Converts an {@link ApolloCall} to a synchronous Single.
*
* @param originalCall the ApolloCall to convert
* @param <T> the value type.
* @return the converted Single
* @throws NullPointerException if originalCall == null
*/
@Nonnull public static <T> Single<Response<T>> from(@Nonnull final ApolloCall<T> originalCall) {
checkNotNull(originalCall, "call == null");
return Single.create(new SingleOnSubscribe<Response<T>>() {
@Override public void subscribe(SingleEmitter<Response<T>> emitter) {
cancelOnSingleDisposed(emitter, originalCall);
try {
Response<T> response = originalCall.execute();
if (!emitter.isDisposed()) {
emitter.onSuccess(response);
}
} catch (ApolloException e) {
Exceptions.throwIfFatal(e);
if (!emitter.isDisposed()) {
emitter.onError(e);
}
}
}
});
}
/**
* Converts an {@link ApolloPrefetch} to a synchronous Completable
*
* @param prefetch the ApolloPrefetch to convert
* @return the converted Completable
* @throws NullPointerException if prefetch == null
*/
@Nonnull public static Completable from(@Nonnull final ApolloPrefetch prefetch) {
checkNotNull(prefetch, "prefetch == null");
return Completable.create(new CompletableOnSubscribe() {
@Override public void subscribe(CompletableEmitter emitter) {
cancelOnCompletableDisposed(emitter, prefetch);
try {
prefetch.execute();
if (!emitter.isDisposed()) {
emitter.onComplete();
}
} catch (ApolloException e) {
Exceptions.throwIfFatal(e);
if (!emitter.isDisposed()) {
emitter.onError(e);
}
}
}
});
}
private static void cancelOnCompletableDisposed(CompletableEmitter emitter, final Cancelable cancelable) {
emitter.setDisposable(getRx2Disposable(cancelable));
}
private static <T> void cancelOnSingleDisposed(SingleEmitter<T> emitter, final Cancelable cancelable) {
emitter.setDisposable(getRx2Disposable(cancelable));
}
private static <T> void cancelOnObservableDisposed(ObservableEmitter<T> emitter, final Cancelable cancelable) {
emitter.setDisposable(getRx2Disposable(cancelable));
}
private static Disposable getRx2Disposable(final Cancelable cancelable) {
return new Disposable() {
@Override public void dispose() {
cancelable.cancel();
}
@Override public boolean isDisposed() {
return cancelable.isCanceled();
}
};
}
}