class ResponseHandlers {

    public static <T> HttpClient.ResponseHandler<T> jsonResponseHandler(Class<T> klass) {
        return (statusCode, responseBody, responseHeaders) -> {
            if (statusCode == 204) {
                return null;
            }

            PushbackInputStream pushbackResponseBody = new PushbackInputStream(responseBody);
            String contentType = responseHeaders.getHeader(RequestHeaders.CONTENT_TYPE);

            if (statusCode >= 400) {
                // this statement is needed as error response handling is different from the successful response
                if ((contentType == null || !contentType.startsWith(APPLICATION_JSON)) && isNotJson(pushbackResponseBody)) {
                        throw responseException(statusCode, pushbackResponseBody, responseHeaders,
                            ResponseHandlers::buildEmptyErrorResponse);
                }
                throw responseException(statusCode, pushbackResponseBody, responseHeaders,
                    ResponseHandlers::buildErrorResponseFromString);
            }

            if (contentType != null && !contentType.startsWith(APPLICATION_JSON)) {
                throw new NotAcceptableException(String.format(
                    "Content type %s is not acceptable, has to start with %s", contentType, APPLICATION_JSON));
            }

            switch (statusCode) {
                case 200:
                case 201:
                case 202:
                    return jsonMapper.readValue(responseBody, klass);
                default:
                    throw responseException(statusCode, pushbackResponseBody, responseHeaders,
                                            ResponseHandlers::buildErrorResponseFromString);
            }
        };
    }

    private  ResponseHandlers();

}