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

co.easimart.EasimartRESTObjectBatchCommand Maven / Gradle / Ivy

package co.easimart;

import co.easimart.http.EasimartHttpRequest;
import co.easimart.http.EasimartHttpResponse;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import bolts.Continuation;
import bolts.Task;

/** package */ class EasimartRESTObjectBatchCommand extends EasimartRESTCommand {
  public final static int COMMAND_OBJECT_BATCH_MAX_SIZE = 50;

  private static final String KEY_RESULTS = "results";

  public static List> executeBatch(
      EasimartHttpClient client, List commands, String sessionToken) {
    final int batchSize = commands.size();
    List> tasks = new ArrayList<>(batchSize);

    if (batchSize == 1) {
      // There's only one, just execute it
      tasks.add(commands.get(0).executeAsync(client));
      return tasks;
    }

    if (batchSize > COMMAND_OBJECT_BATCH_MAX_SIZE) {
      // There's more than the max, split it up into batches
      List> batches = Lists.partition(commands,
          COMMAND_OBJECT_BATCH_MAX_SIZE);
      for (int i = 0, size = batches.size(); i < size; i++) {
        List batch = batches.get(i);
        tasks.addAll(executeBatch(client, batch, sessionToken));
      }
      return tasks;
    }

    final List.TaskCompletionSource> tcss = new ArrayList<>(batchSize);
    for (int i = 0; i < batchSize; i++) {
      Task.TaskCompletionSource tcs = Task.create();
      tcss.add(tcs);
      tasks.add(tcs.getTask());
    }

    List requests = new ArrayList<>(batchSize);
    try {
      for (EasimartRESTObjectCommand command : commands) {
        JSONObject requestParameters = new JSONObject();
        requestParameters.put("method", command.method.toString());
        requestParameters.put("path", String.format("/1/%s", command.httpPath));
        JSONObject body = command.jsonParameters;
        if (body != null) {
          requestParameters.put("body", body);
        }
        requests.add(requestParameters);
      }
    } catch (JSONException e) {
      throw new RuntimeException(e);
    }

    Map> parameters = new HashMap<>();
    parameters.put("requests", requests);
    EasimartRESTCommand command = new EasimartRESTObjectBatchCommand(
        "batch", EasimartHttpRequest.Method.POST, parameters, sessionToken);

    command.executeAsync(client).continueWith(new Continuation() {
      @Override
      public Void then(Task task) throws Exception {
        Task.TaskCompletionSource tcs;

        if (task.isFaulted() || task.isCancelled()) {
          // REST command failed or canceled, fail or cancel all tasks
          for (int i = 0; i < batchSize; i++) {
            tcs = tcss.get(i);
            if (task.isFaulted()) {
              tcs.setError(task.getError());
            } else {
              tcs.setCancelled();
            }
          }
        }

        JSONObject json = task.getResult();
        JSONArray results = json.getJSONArray(KEY_RESULTS);

        int resultLength = results.length();
        if (resultLength != batchSize) {
          // Invalid response, fail all tasks
          for (int i = 0; i < batchSize; i++) {
            tcs = tcss.get(i);
            tcs.setError(new IllegalStateException(
                "Batch command result count expected: " + batchSize + " but was: " + resultLength));
          }
        }

        for (int i = 0; i < batchSize; i++) {
          JSONObject result = results.getJSONObject(i);
          tcs = tcss.get(i);

          if (result.has("success")) {
            JSONObject success = result.getJSONObject("success");
            tcs.setResult(success);
          } else if (result.has("error")) {
            JSONObject error = result.getJSONObject("error");
            tcs.setError(new EasimartException(error.getInt("code"), error.getString("error")));
          }
        }
        return null;
      }
    });

    return tasks;
  }

  private EasimartRESTObjectBatchCommand(
          String httpPath,
          EasimartHttpRequest.Method httpMethod,
          Map parameters,
          String sessionToken) {
    super(httpPath, httpMethod, parameters, sessionToken);
  }

  /**
   * /batch is the only endpoint that doesn't return a JSONObject... It returns a JSONArray, but
   * let's wrap that with a JSONObject {@code { "results": <original response%gt; }}.
   */
  @Override
  protected Task onResponseAsync(EasimartHttpResponse response,
      ProgressCallback downloadProgressCallback) {
    InputStream responseStream = null;
    String content = null;
    try {
      responseStream = response.getContent();
      content = new String(EasimartIOUtils.toByteArray(responseStream));
    } catch (IOException e) {
      return Task.forError(e);
    } finally {
      EasimartIOUtils.closeQuietly(responseStream);
    }

    JSONObject json;
    try {
      JSONArray results = new JSONArray(content);
      json = new JSONObject();
      json.put(KEY_RESULTS, results);
    } catch (JSONException e) {
      return Task.forError(newTemporaryException("bad json response", e));
    }

    return Task.forResult(json);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy