All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.withabound.resources.base.AbstractAboundResource Maven / Gradle / Ivy

Go to download

The Abound Java SDK provides convenient access to the Abound API from applications written in Java.

The newest version!
package com.withabound.resources.base;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.withabound.AboundConfig;
import com.withabound.exceptions.AboundApiException;
import com.withabound.http.HttpUtils;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Base resource from which all other Abound Resources shall extend that maps an SDK action (e.g.
 * update, retrieve, list) to an HTTP verb (e.g. GET, POST, PUT).
 *
 * @param  the data type of the request body
 * @param  the data type of the payloads returned by SDK methods
 */
abstract class AbstractAboundResource {
  private static final MediaType JSON = MediaType.parse("application/json");
  private static final Gson GSON = new Gson();

  private final Type singleType;
  private final Type bulkType;

  protected final AboundConfig aboundConfig;
  private final OkHttpClient httpClient;

  /** @return the endpoint path of the resource. e.g., "/users", "/documents", etc. */
  protected abstract String getPath();

  /**
   * @param aboundConfig a valid config object
   * @param httpClient the OkHttpClient responsible for issuing network calls
   * @param clazz the explicit class used to unmarshal raw JSON to a POJO. This should be the class
   *     of the  type parameter, and is required due to type erasure in Java.
   */
  protected AbstractAboundResource(
      final AboundConfig aboundConfig, final OkHttpClient httpClient, final Class clazz) {
    this.aboundConfig = aboundConfig;
    this.httpClient = httpClient;

    this.singleType = TypeToken.getParameterized(AboundResponse.class, clazz).getType();
    this.bulkType = TypeToken.getParameterized(AboundBulkResponse.class, clazz).getType();
  }

  protected AboundResponse create(final String url, final Map requestPayload)
      throws IOException {
    final Request request = httpPost(url, requestPayload);

    return performRequestAndHandleSingleElementResponse(request);
  }

  protected AboundBulkResponse bulkCreate(
      final String url, final Map> requestPayload) throws IOException {
    final Request request = httpPost(url, requestPayload);

    return performRequestAndHandleBulkElementsResponse(request);
  }

  protected AboundBulkResponse list(final String url) throws IOException {
    return list(url, EmptyQueryParameters.getInstance());
  }

  protected AboundBulkResponse list(final String url, final AboundQueryParameters params)
      throws IOException {
    final Request request = httpGet(url, params);

    return performRequestAndHandleBulkElementsResponse(request);
  }

  protected AboundResponse retrieve(final String url) throws IOException {
    final Request request = httpGet(url, null);

    return performRequestAndHandleSingleElementResponse(request);
  }

  protected AboundResponse update(final String url, final Map requestPayload)
      throws IOException {
    final Request request = httpPut(url, requestPayload);

    return performRequestAndHandleSingleElementResponse(request);
  }

  protected AboundResponse delete(final String url) throws IOException {
    final Request request = httpDelete(url);

    return sendRequest(
        request, TypeToken.getParameterized(AboundResponse.class, EmptyJsonObject.class).getType());
  }

  /**
   * Performs the {@link Request} and deserializes the response body to {@link AboundResponse}. Use
   * this method when the API returns one element in its `data` field.
   */
  private AboundResponse performRequestAndHandleSingleElementResponse(final Request request)
      throws IOException {
    return sendRequest(request, singleType);
  }

  /**
   * Performs the {@link Request} and deserializes the response body to {@link AboundBulkResponse}.
   * Use this method when the API returns a list of elements in its `data` field.
   */
  private AboundBulkResponse performRequestAndHandleBulkElementsResponse(final Request request)
      throws IOException {
    return sendRequest(request, bulkType);
  }

  /**
   * Makes the HTTP call, deserializing the response body to the appropriate single or bulk type.
   */
  private  RESP sendRequest(final Request request, final Type serializationType)
      throws IOException {
    try (Response response = httpClient.newCall(request).execute()) {
      if (response.isSuccessful()) {
        return GSON.fromJson(response.body().string(), serializationType);
      }

      final AboundErrorResponse error =
          GSON.fromJson(response.body().string(), AboundErrorResponse.class);

      throw new AboundApiException(error, response.code());
    }
  }

  private static Request httpGet(final String url, final AboundQueryParameters params) {
    final String urlWithParams = HttpUtils.appendQueryParams(url, params);

    return new Request.Builder().get().url(urlWithParams).build();
  }

  private Request httpPost(final String url, final Map rawRequestBody) {
    final RequestBody requestBody = RequestBody.Companion.create(GSON.toJson(rawRequestBody), JSON);

    return new Request.Builder().post(requestBody).url(url).build();
  }

  private Request httpPut(final String url, final Map rawRequestBody) {
    final RequestBody requestBody = RequestBody.Companion.create(GSON.toJson(rawRequestBody), JSON);

    return new Request.Builder().put(requestBody).url(url).build();
  }

  private static Request httpDelete(final String url) {
    return new Request.Builder().delete().url(url).build();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy