package co.smartreceipts.android.apis;
import android.support.annotation.NonNull;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.HttpException;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
public class SmartReceiptsApisRxJavaCallAdapterFactory extends CallAdapter.Factory {
private final CallAdapter.Factory original;
private SmartReceiptsApisRxJavaCallAdapterFactory(@NonNull CallAdapter.Factory original) {
this.original = original;
}
public static SmartReceiptsApisRxJavaCallAdapterFactory createWithScheduler(@NonNull Scheduler scheduler) {
return new SmartReceiptsApisRxJavaCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(scheduler));
}
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new RxCallAdapterWrapper(retrofit, original.get(returnType, annotations, retrofit));
}
private static class RxCallAdapterWrapper<R> implements CallAdapter<R, Observable<?>> {
private final Retrofit retrofit;
private final CallAdapter<R, Observable<?>> wrapped;
public RxCallAdapterWrapper(Retrofit retrofit, CallAdapter<R, Observable<?>> wrapped) {
this.retrofit = retrofit;
this.wrapped = wrapped;
}
@Override
public Type responseType() {
return wrapped.responseType();
}
@Override
public Observable<?> adapt(Call<R> call) {
return ((Observable) wrapped.adapt(call)).onErrorResumeNext((Object throwable) -> {
return Observable.error(asPossiblyMappedException((Throwable) throwable));
}
);
}
private Throwable asPossiblyMappedException(Throwable throwable) {
// We had non-200 http error
if (throwable instanceof HttpException) {
final HttpException httpException = (HttpException) throwable;
final Response response = httpException.response();
if (response != null && response.errorBody() != null && response.errorBody().contentLength() > 0) {
// Only bother mapping if we saw an error response with actual content
return new SmartReceiptsApiException(response, httpException, retrofit);
} else {
return throwable;
}
} else {
// Network errors get returned as IO Exceptions, so pass those along
return throwable;
}
}
}
}