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

com.parse.ParseRESTObjectBatchCommand Maven / Gradle / Ivy

Go to download

A library that gives you access to the powerful Parse cloud platform from your Android app.

There is a newer version: 1.17.3
Show newest version
/*
 * Copyright (c) 2015-present, Parse, LLC.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
package com.parse;

import com.parse.http.ParseHttpRequest;
import com.parse.http.ParseHttpResponse;

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

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import bolts.Continuation;
import bolts.Task;
import bolts.TaskCompletionSource;

/** package */ class ParseRESTObjectBatchCommand extends ParseRESTCommand {
  public final static int COMMAND_OBJECT_BATCH_MAX_SIZE = 50;

  private static final String KEY_RESULTS = "results";

  public static List> executeBatch(
      ParseHttpClient 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> tcss = new ArrayList<>(batchSize);
    for (int i = 0; i < batchSize; i++) {
      TaskCompletionSource tcs = new TaskCompletionSource<>();
      tcss.add(tcs);
      tasks.add(tcs.getTask());
    }

    JSONObject parameters = new JSONObject();
    JSONArray requests = new JSONArray();
    try {
      for (ParseRESTObjectCommand command : commands) {
        JSONObject requestParameters = new JSONObject();
        requestParameters.put("method", command.method.toString());
        requestParameters.put("path", new URL(server, command.httpPath).getPath());
        JSONObject body = command.jsonParameters;
        if (body != null) {
          requestParameters.put("body", body);
        }
        requests.put(requestParameters);
      }
      parameters.put("requests", requests);
    } catch (JSONException e) {
      throw new RuntimeException(e);
    } catch (MalformedURLException e) {
      throw new RuntimeException(e);
    }

    ParseRESTCommand command = new ParseRESTObjectBatchCommand(
        "batch", ParseHttpRequest.Method.POST, parameters, sessionToken);

    command.executeAsync(client).continueWith(new Continuation() {
      @Override
      public Void then(Task task) throws Exception {
        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 ParseException(error.getInt("code"), error.getString("error")));
          }
        }
        return null;
      }
    });

    return tasks;
  }

  private ParseRESTObjectBatchCommand(
      String httpPath,
      ParseHttpRequest.Method httpMethod,
      JSONObject 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(ParseHttpResponse response,
      ProgressCallback downloadProgressCallback) {
    InputStream responseStream = null;
    String content = null;
    try {
      responseStream = response.getContent();
      content = new String(ParseIOUtils.toByteArray(responseStream));
    } catch (IOException e) {
      return Task.forError(e);
    } finally {
      ParseIOUtils.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