// Path: library/src/main/java/org/mariotaku/restfu/callback/Callback.java
// public interface Callback<T, E extends Exception> {
//     void result(@NotNull T result) throws E, IOException;
// 
//     void error(@NotNull E exception);
// }
// 
// Path: library/src/main/java/org/mariotaku/restfu/callback/RawCallback.java
// public interface RawCallback<E extends Exception> extends Callback<HttpResponse, E> {
// 
// }


import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mariotaku.restfu.callback.Callback;
import org.mariotaku.restfu.callback.RawCallback;
import org.mariotaku.restfu.http.*;
import java.io.IOException;
import java.lang.reflect.*;
                // Get converter before network requests, https://github.com/TwidereProject/Twidere-Android/issues/378
                // We can throw exceptions before network requests sent
                final Type returnType = method.getGenericReturnType();
                restRequest = requestInfoFactory.create(restMethod, converterFactory, constantPoll);
                httpRequest = requestFactory.create(endpoint, restRequest, authorization, converterFactory);
                httpCall = restClient.newCall(httpRequest);
                httpResponse = httpCall.execute();
                if (!httpResponse.isSuccessful()) {
                    return onError(null, httpRequest, httpResponse, callback);
                }
                return onResult(returnType, httpResponse, callback);
            } catch (IOException e) {
                return onError(e, httpRequest, httpResponse, callback);
            } catch (RestConverter.ConvertException e) {
                return onError(e, httpRequest, httpResponse, callback);
            } finally {
                RestFuUtils.closeSilently(httpResponse);
                RestFuUtils.closeSilently(httpCall);
            }
        }

        private <T> Object onResult(@NotNull Type returnType, @NotNull HttpResponse httpResponse,
                @Nullable final Callback<?, E> callback)
                throws RestConverter.ConvertException, E, IOException {
            if (callback == null) {
                //noinspection unchecked
                final RestConverter<HttpResponse, T, E> converter = (RestConverter<HttpResponse, T, E>)
                        converterFactory.forResponse(returnType);
                return converter.convert(httpResponse);
            }
// Path: library/src/main/java/org/mariotaku/restfu/callback/Callback.java
// public interface Callback<T, E extends Exception> {
//     void result(@NotNull T result) throws E, IOException;
// 
//     void error(@NotNull E exception);
// }
// 
// Path: library/src/main/java/org/mariotaku/restfu/callback/RawCallback.java
// public interface RawCallback<E extends Exception> extends Callback<HttpResponse, E> {
// 
// }


// Path: library/src/main/java/org/mariotaku/restfu/RestAPIFactory.java
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mariotaku.restfu.callback.Callback;
import org.mariotaku.restfu.callback.RawCallback;
import org.mariotaku.restfu.http.*;
import java.io.IOException;
import java.lang.reflect.*;

                // Get converter before network requests, https://github.com/TwidereProject/Twidere-Android/issues/378
                // We can throw exceptions before network requests sent
                final Type returnType = method.getGenericReturnType();
                restRequest = requestInfoFactory.create(restMethod, converterFactory, constantPoll);
                httpRequest = requestFactory.create(endpoint, restRequest, authorization, converterFactory);
                httpCall = restClient.newCall(httpRequest);
                httpResponse = httpCall.execute();
                if (!httpResponse.isSuccessful()) {
                    return onError(null, httpRequest, httpResponse, callback);
                }
                return onResult(returnType, httpResponse, callback);
            } catch (IOException e) {
                return onError(e, httpRequest, httpResponse, callback);
            } catch (RestConverter.ConvertException e) {
                return onError(e, httpRequest, httpResponse, callback);
            } finally {
                RestFuUtils.closeSilently(httpResponse);
                RestFuUtils.closeSilently(httpCall);
            }
        }

        private <T> Object onResult(@NotNull Type returnType, @NotNull HttpResponse httpResponse,
                @Nullable final Callback<?, E> callback)
                throws RestConverter.ConvertException, E, IOException {
            if (callback == null) {
                //noinspection unchecked
                final RestConverter<HttpResponse, T, E> converter = (RestConverter<HttpResponse, T, E>)
                        converterFactory.forResponse(returnType);
                return converter.convert(httpResponse);
            }
            if (callback instanceof RawCallback) {