001package com.jaredsburrows.retrofit2.adapter.synchronous;
002
003import java.lang.annotation.Annotation;
004import java.lang.reflect.ParameterizedType;
005import java.lang.reflect.Type;
006import javax.annotation.Nullable;
007import retrofit2.Call;
008import retrofit2.CallAdapter;
009import retrofit2.Response;
010import retrofit2.Retrofit;
011
012/**
013 * A synchronous {@link CallAdapter.Factory} that uses the same thread for both I/O and
014 * application-level callbacks.
015 * <p>
016 * Adding this class to {@link Retrofit} allows you to return direct deserialized type from service
017 * methods:
018 * <pre><code>
019 * interface MyService {
020 *   &#64;GET("user/me")
021 *   User getUser()
022 * }
023 * </code></pre>
024 * or allows you to return deserialized type wrapped in {@link Response}:
025 * <pre><code>
026 * interface MyService {
027 *   &#64;GET("user/me")
028 *   Response&lt;User&gt; getUser()
029 * }
030 * </code></pre>
031 * {@link CallAdapter.Factory} returns the deserialized body for 2XX responses, sets {@link
032 * retrofit2.HttpException} errors for non-2XX responses, and for network errors.
033 */
034public final class SynchronousCallAdapterFactory extends CallAdapter.Factory {
035  private SynchronousCallAdapterFactory() {
036  }
037
038  public static CallAdapter.Factory create() {
039    return new SynchronousCallAdapterFactory();
040  }
041
042  @Override @Nullable public CallAdapter<?, ?> get(
043    Type returnType, Annotation[] annotations, Retrofit retrofit) {
044    // Prevent the Async calls via Call class
045    if (getRawType(returnType) == Call.class) {
046      return null;
047    }
048
049    // Return type is not Response<T>. Use it for body-only adapter.
050    if (getRawType(returnType) != Response.class) {
051      return new SynchronousBodyCallAdapter<>(returnType);
052    }
053
054    // Make sure Response<T> is parameterized
055    if (!(returnType instanceof ParameterizedType)) {
056      throw new IllegalStateException(
057        "Response must be parameterized as Response<Foo> or Response<? extends Foo>");
058    }
059
060    // Handle Response<T> return types
061    Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);
062    return new SynchronousResponseCallAdapter<>(responseType);
063  }
064}