
io.apimatic.core.ResponseHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core Show documentation
Show all versions of core Show documentation
A library that contains core logic and utilities for consuming REST APIs using Java SDKs generated by APIMatic.
The newest version!
package io.apimatic.core;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.apimatic.core.types.CoreApiException;
import io.apimatic.core.utilities.CoreHelper;
import io.apimatic.coreinterfaces.compatibility.CompatibilityFactory;
import io.apimatic.coreinterfaces.http.Context;
import io.apimatic.coreinterfaces.http.request.Request;
import io.apimatic.coreinterfaces.http.request.ResponseClassType;
import io.apimatic.coreinterfaces.http.request.configuration.CoreEndpointConfiguration;
import io.apimatic.coreinterfaces.http.response.Response;
import io.apimatic.coreinterfaces.type.functional.ContextInitializer;
import io.apimatic.coreinterfaces.type.functional.Deserializer;
/**
* Handler that encapsulates the process of generating a response object from a Response.
* @param The response to process.
* @param in case of a problem.
*/
public final class ResponseHandler {
/**
* Not found status code.
*/
private static final int NOT_FOUND_STATUS_CODE = 404;
/**
* Minimum Success code.
*/
private static final int MIN_SUCCESS_CODE = 200;
/**
* Maximum Success code.
*/
private static final int MAX_SUCCESS_CODE = 208;
/**
* A map for end point level errors.
*/
private final Map> localErrorCases;
/**
* A map for global level errors.
*/
private final Map> globalErrorCases;
/**
* An instance of {@link Deserializer}.
*/
private final Deserializer deserializer;
/**
* An instance of Intermediate {@link Deserializer}.
*/
private final Deserializer> intermediateDeserializer;
/**
* An instance of {@link ResponseClassType}.
*/
private final ResponseClassType responseClassType;
/**
* An instance of {@link ContextInitializer}.
*/
private final ContextInitializer contextInitializer;
/**
* Flag to determine to return null on 404 status code?.
*/
private final boolean isNullify404Enabled;
/**
* Flag to determine if the provided response type a nullable type.
*/
private final boolean isNullableResponseType;
/**
* @param localErrorCases the map of local errors.
* @param globalErrorCases the map of global errors.
* @param deserializer the deserializer of json response.
* @param intermediateDeserializer the api response deserializer.
* @param responseClassType the type of response class.
* @param contextInitializer the context initializer in response models.
* @param isNullify404Enabled on 404 error return null or not?.
* @param isNullableResponseType in case of nullable response type.
*/
private ResponseHandler(final Map> localErrorCases,
final Map> globalErrorCases,
final Deserializer deserializer,
final Deserializer> intermediateDeserializer,
final ResponseClassType responseClassType,
final ContextInitializer contextInitializer,
final boolean isNullify404Enabled,
final boolean isNullableResponseType) {
this.localErrorCases = localErrorCases;
this.globalErrorCases = globalErrorCases;
this.deserializer = deserializer;
this.intermediateDeserializer = intermediateDeserializer;
this.responseClassType = responseClassType;
this.contextInitializer = contextInitializer;
this.isNullify404Enabled = isNullify404Enabled;
this.isNullableResponseType = isNullableResponseType;
}
/**
* Processes an HttpResponse and returns some value corresponding to that response.
* @param httpRequest Request which is made for endpoint.
* @param httpResponse Response which is received after execution.
* @param globalConfiguration the global configuration to store the request global information.
* @param endpointConfiguration the endpoint level configuration.
* @return An object of type ResponseType.
* @throws IOException Signals that an I/O exception of some sort has occurred.
* @throws ExceptionType Represents error response from the server.
*/
@SuppressWarnings("unchecked")
public ResponseType handle(Request httpRequest, Response httpResponse,
GlobalConfiguration globalConfiguration,
CoreEndpointConfiguration endpointConfiguration) throws IOException, ExceptionType {
Context httpContext = globalConfiguration.getCompatibilityFactory()
.createHttpContext(httpRequest, httpResponse);
// invoke the callback after response if its not null
if (globalConfiguration.getHttpCallback() != null) {
globalConfiguration.getHttpCallback().onAfterResponse(httpContext);
}
if (isNullify404Enabled) {
int responseCode = httpContext.getResponse().getStatusCode();
// return null on 404
if (responseCode == NOT_FOUND_STATUS_CODE) {
return null;
}
}
// handle errors defined at the API level
validateResponse(httpContext);
ResponseType result = applyDeserializer(deserializer, httpResponse);
result = applyContextInitializer(contextInitializer, httpContext, result);
if (endpointConfiguration.hasBinaryResponse()) {
result = (ResponseType) httpResponse.getRawBody();
}
if (responseClassType != null) {
return createResponseClassType(httpResponse, globalConfiguration,
endpointConfiguration.hasBinaryResponse());
}
return result;
}
private ResponseType applyContextInitializer(
ContextInitializer contextInitializer, Context httpContext,
ResponseType result) throws IOException {
if (contextInitializer != null && deserializer != null) {
result = contextInitializer.apply(httpContext, result);
}
return result;
}
private T applyDeserializer(Deserializer deserializer, Response httpResponse)
throws IOException {
if (this.isNullableResponseType && CoreHelper.isNullOrWhiteSpace(httpResponse.getBody())) {
return null;
}
T result = null;
if (deserializer != null) {
// extract result from the http response
result = deserializer.apply(httpResponse.getBody());
}
return result;
}
@SuppressWarnings("unchecked")
private ResponseType createResponseClassType(Response httpResponse,
GlobalConfiguration coreConfig, boolean hasBinaryResponse) throws IOException {
CompatibilityFactory compatibilityFactory = coreConfig.getCompatibilityFactory();
switch (responseClassType) {
case API_RESPONSE:
return (ResponseType) compatibilityFactory.createApiResponse(
httpResponse.getStatusCode(), httpResponse.getHeaders(),
hasBinaryResponse ? httpResponse.getRawBody()
: applyDeserializer(intermediateDeserializer, httpResponse));
case DYNAMIC_RESPONSE:
return createDynamicResponse(httpResponse, compatibilityFactory);
case DYNAMIC_API_RESPONSE:
return (ResponseType) compatibilityFactory.createApiResponse(
httpResponse.getStatusCode(), httpResponse.getHeaders(),
createDynamicResponse(httpResponse, compatibilityFactory));
default:
return null;
}
}
@SuppressWarnings("unchecked")
private ResponseType createDynamicResponse(Response httpResponse,
CompatibilityFactory compatibilityFactory) {
return (ResponseType) compatibilityFactory.createDynamicResponse(httpResponse);
}
/**
* Validate the response and check that response contains the error code and throw the
* corresponding exception
* @param httpContext
* @throws ExceptionType
*/
private void validateResponse(Context httpContext) throws ExceptionType {
Response response = httpContext.getResponse();
int statusCode = response.getStatusCode();
String errorCode = String.valueOf(statusCode);
throwConfiguredException(localErrorCases, errorCode, httpContext);
throwConfiguredException(globalErrorCases, errorCode, httpContext);
if ((statusCode < MIN_SUCCESS_CODE) || (statusCode > MAX_SUCCESS_CODE)) {
globalErrorCases.get(ErrorCase.DEFAULT).throwException(httpContext);
}
}
private void throwConfiguredException(Map> errorCases,
String errorCode, Context httpContext) throws ExceptionType {
String defaultErrorCode = "";
Matcher match = Pattern.compile("^[(4|5)[0-9]]{3}").matcher(errorCode);
if (match.find()) {
defaultErrorCode = errorCode.charAt(0) + "XX";
}
if (errorCases != null) {
if (errorCases.containsKey(errorCode)) {
errorCases.get(errorCode).throwException(httpContext);
}
if (errorCases.containsKey(defaultErrorCode)) {
errorCases.get(defaultErrorCode).throwException(httpContext);
}
}
}
public static class Builder {
/**
* A map of end point level errors.
*/
private Map> localErrorCases = null;
/**
* A map of global level errors.
*/
private Map> globalErrorCases = null;
/**
* An instance of {@link Deserializer}.
*/
private Deserializer deserializer;
/**
* An instance of intermediate {@link Deserializer}.
*/
private Deserializer> intermediateDeserializer;
/**
* An instance of {@link ResponseClassType}.
*/
private ResponseClassType responseClassType;
/**
* An instance of {@link ContextInitializer}.
*/
private ContextInitializer contextInitializer;
/**
* A boolean variable to determine return null response on 404.
*/
private boolean isNullify404Enabled = true;
/**
* A boolean variable to determine if the provided response type is a nullable type.
*/
private boolean isNullableResponseType = false;
/**
* Setter for the localErrorCase.
* @param statusCode the response status code from the server.
* @param errorCase to generate the SDK Exception.
* @return {@link ResponseHandler.Builder}.
*/
public Builder localErrorCase(String statusCode,
ErrorCase errorCase) {
if (this.localErrorCases == null) {
this.localErrorCases = new HashMap>();
}
this.localErrorCases.put(statusCode, errorCase);
return this;
}
/**
* Setter for the globalErrorCases.
* @param globalErrorCases the global error cases for endpoints.
* @return {@link ResponseHandler.Builder}.
*/
public Builder globalErrorCase(
Map> globalErrorCases) {
this.globalErrorCases = globalErrorCases;
return this;
}
/**
* Setter for the deserializer.
* @param deserializer to deserialize the server response.
* @return {@link ResponseHandler.Builder}.
*/
public Builder deserializer(
Deserializer deserializer) {
this.deserializer = deserializer;
return this;
}
/**
* Setter for the deserializer.
* @param intermediateDeserializer to deserialize the api response.
* @param the intermediate type of api response.
* @return {@link ResponseHandler.Builder}.
*/
public Builder
apiResponseDeserializer(
Deserializer intermediateDeserializer) {
this.intermediateDeserializer = intermediateDeserializer;
return this;
}
/**
* Setter for the responseClassType.
* @param responseClassType specify the response class type for result.
* @return {@link ResponseHandler.Builder}.
*/
public Builder responseClassType(
ResponseClassType responseClassType) {
this.responseClassType = responseClassType;
return this;
}
/**
* Setter for the {@link ContextInitializer}.
* @param contextInitializer the context initializer in response models.
* @return {@link ResponseHandler.Builder}.
*/
public Builder contextInitializer(
ContextInitializer contextInitializer) {
this.contextInitializer = contextInitializer;
return this;
}
/**
* Setter for the nullify404.
* @param isNullify404Enabled in case of 404 error return null or not.
* @return {@link ResponseHandler.Builder}.
*/
public Builder nullify404(boolean isNullify404Enabled) {
this.isNullify404Enabled = isNullify404Enabled;
return this;
}
/**
* Setter for the isNullableResponseType.
* @param isNullableResponseType in case of nullable response type.
* @return {@link ResponseHandler.Builder}.
*/
public Builder nullableResponseType(
boolean isNullableResponseType) {
this.isNullableResponseType = isNullableResponseType;
return this;
}
/**
* build the ResponseHandler.
* @return the instance of {@link ResponseHandler}.
*/
public ResponseHandler build() {
return new ResponseHandler(localErrorCases,
globalErrorCases, deserializer, intermediateDeserializer, responseClassType,
contextInitializer, isNullify404Enabled, isNullableResponseType);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy