package com.kickstarter.libs.rx.operators; import android.support.annotation.NonNull; import com.google.gson.Gson; import com.kickstarter.services.ApiException; import com.kickstarter.services.ResponseException; import com.kickstarter.services.apiresponses.ErrorEnvelope; import java.io.IOException; import retrofit2.Response; import rx.Observable; import rx.Subscriber; /** * Takes a {@link retrofit2.Response}, if it's successful send it to {@link Subscriber#onNext}, otherwise * attempt to parse the error. * * Errors that conform to the API's error format are converted into an {@link ApiException} exception and sent to * {@link Subscriber#onError}, otherwise a more generic {@link ResponseException} is sent to {@link Subscriber#onError}. * * @param <T> The response type. */ public final class ApiErrorOperator<T> implements Observable.Operator<T, retrofit2.Response<T>> { private final Gson gson; public ApiErrorOperator(final @NonNull Gson gson) { this.gson = gson; } @Override public Subscriber<? super Response<T>> call(final @NonNull Subscriber<? super T> subscriber) { return new Subscriber<retrofit2.Response<T>>() { @Override public void onCompleted() { if (!subscriber.isUnsubscribed()) { subscriber.onCompleted(); } } @Override public void onError(final @NonNull Throwable e) { if (!subscriber.isUnsubscribed()) { subscriber.onError(e); } } @Override public void onNext(final @NonNull retrofit2.Response<T> response) { if (subscriber.isUnsubscribed()) { return; } if (!response.isSuccess()) { try { final ErrorEnvelope envelope = gson.fromJson(response.errorBody().string(), ErrorEnvelope.class); subscriber.onError(new ApiException(envelope, response)); } catch (final @NonNull IOException e) { subscriber.onError(new ResponseException(response)); } } else { subscriber.onNext(response.body()); subscriber.onCompleted(); } } }; } }