Search in sources :

Example 16 with Task

use of com.parse.boltsinternal.Task in project Parse-SDK-Android by ParsePlatform.

the class ParseObject method deepSaveAsync.

/**
 * This saves all of the objects and files reachable from the given object. It does its work in
 * multiple waves, saving as many as possible in each wave. If there's ever an error, it just
 * gives up, sets error, and returns NO.
 */
private static Task<Void> deepSaveAsync(final Object object, final String sessionToken) {
    Set<ParseObject> objects = new HashSet<>();
    Set<ParseFile> files = new HashSet<>();
    collectDirtyChildren(object, objects, files);
    // This has to happen separately from everything else because ParseUser.save() is
    // special-cased to work for lazy users, but new users can't be created by
    // ParseMultiCommand's regular save.
    Set<ParseUser> users = new HashSet<>();
    for (ParseObject o : objects) {
        if (o instanceof ParseUser) {
            ParseUser user = (ParseUser) o;
            if (user.isLazy()) {
                users.add((ParseUser) o);
            }
        }
    }
    objects.removeAll(users);
    // objects will need to wait for files to be complete since they may be nested children.
    final AtomicBoolean filesComplete = new AtomicBoolean(false);
    List<Task<Void>> tasks = new ArrayList<>();
    for (ParseFile file : files) {
        tasks.add(file.saveAsync(sessionToken, null, null));
    }
    Task<Void> filesTask = Task.whenAll(tasks).continueWith(task -> {
        filesComplete.set(true);
        return null;
    });
    // objects will need to wait for users to be complete since they may be nested children.
    final AtomicBoolean usersComplete = new AtomicBoolean(false);
    tasks = new ArrayList<>();
    for (final ParseUser user : users) {
        tasks.add(user.saveAsync(sessionToken));
    }
    Task<Void> usersTask = Task.whenAll(tasks).continueWith(task -> {
        usersComplete.set(true);
        return null;
    });
    final Capture<Set<ParseObject>> remaining = new Capture<>(objects);
    Task<Void> objectsTask = Task.forResult(null).continueWhile(() -> remaining.get().size() > 0, task -> {
        // Partition the objects into two sets: those that can be save
        // immediately,
        // and those that rely on other objects to be created first.
        final List<ParseObject> current = new ArrayList<>();
        final Set<ParseObject> nextBatch = new HashSet<>();
        for (ParseObject obj : remaining.get()) {
            if (obj.canBeSerialized()) {
                current.add(obj);
            } else {
                nextBatch.add(obj);
            }
        }
        remaining.set(nextBatch);
        if (current.size() == 0 && filesComplete.get() && usersComplete.get()) {
            // exception instead of an infinite loop.
            throw new RuntimeException("Unable to save a ParseObject with a relation to a cycle.");
        }
        // Package all save commands together
        if (current.size() == 0) {
            return Task.forResult(null);
        }
        return enqueueForAll(current, toAwait -> saveAllAsync(current, sessionToken, toAwait));
    });
    return Task.whenAll(Arrays.asList(filesTask, usersTask, objectsTask));
}
Also used : Task(com.parse.boltsinternal.Task) HashSet(java.util.HashSet) Set(java.util.Set) ArrayList(java.util.ArrayList) Capture(com.parse.boltsinternal.Capture) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashSet(java.util.HashSet)

Example 17 with Task

use of com.parse.boltsinternal.Task in project Parse-SDK-Android by ParsePlatform.

the class ParseRESTObjectBatchCommand method executeBatch.

public static List<Task<JSONObject>> executeBatch(ParseHttpClient client, List<ParseRESTObjectCommand> commands, String sessionToken) {
    final int batchSize = commands.size();
    List<Task<JSONObject>> 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<List<ParseRESTObjectCommand>> batches = Lists.partition(commands, COMMAND_OBJECT_BATCH_MAX_SIZE);
        for (int i = 0, size = batches.size(); i < size; i++) {
            List<ParseRESTObjectCommand> batch = batches.get(i);
            tasks.addAll(executeBatch(client, batch, sessionToken));
        }
        return tasks;
    }
    final List<TaskCompletionSource<JSONObject>> tcss = new ArrayList<>(batchSize);
    for (int i = 0; i < batchSize; i++) {
        TaskCompletionSource<JSONObject> 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 | MalformedURLException e) {
        throw new RuntimeException(e);
    }
    ParseRESTCommand command = new ParseRESTObjectBatchCommand("batch", ParseHttpRequest.Method.POST, parameters, sessionToken);
    command.executeAsync(client).continueWith((Continuation<JSONObject, Void>) task -> {
        TaskCompletionSource<JSONObject> tcs;
        if (task.isFaulted() || task.isCancelled()) {
            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) {
            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;
}
Also used : ParseHttpRequest(com.parse.http.ParseHttpRequest) MalformedURLException(java.net.MalformedURLException) URL(java.net.URL) IOException(java.io.IOException) ArrayList(java.util.ArrayList) List(java.util.List) JSONException(org.json.JSONException) Continuation(com.parse.boltsinternal.Continuation) JSONObject(org.json.JSONObject) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) ParseHttpResponse(com.parse.http.ParseHttpResponse) JSONArray(org.json.JSONArray) InputStream(java.io.InputStream) Task(com.parse.boltsinternal.Task) MalformedURLException(java.net.MalformedURLException) ArrayList(java.util.ArrayList) JSONArray(org.json.JSONArray) JSONException(org.json.JSONException) URL(java.net.URL) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) JSONObject(org.json.JSONObject) ArrayList(java.util.ArrayList) List(java.util.List)

Example 18 with Task

use of com.parse.boltsinternal.Task in project Parse-SDK-Android by ParsePlatform.

the class ParseSQLiteDatabase method rawQueryAsync.

/**
 * Runs a raw query.
 *
 * @see SQLiteDatabase#rawQuery
 */
public Task<Cursor> rawQueryAsync(final String sql, final String[] args) {
    synchronized (currentLock) {
        Task<Cursor> task = current.onSuccess(task13 -> db.rawQuery(sql, args), dbExecutor).onSuccess(task12 -> {
            Cursor cursor = task12.getResult();
            // Ensure the cursor window is filled on the dbExecutor
            // thread. We need to do this because
            // the cursor cannot be filled from a different thread than
            // it was created on.
            cursor.getCount();
            return cursor;
        }, dbExecutor);
        current = task.makeVoid();
        return task.continueWithTask(task1 -> {
            // We want to jump off the dbExecutor
            return task1;
        }, Task.BACKGROUND_EXECUTOR);
    }
}
Also used : SQLiteDatabase(android.database.sqlite.SQLiteDatabase) SQLiteOpenHelper(android.database.sqlite.SQLiteOpenHelper) ContentValues(android.content.ContentValues) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) ExecutorService(java.util.concurrent.ExecutorService) Executors(java.util.concurrent.Executors) Cursor(android.database.Cursor) Cursor(android.database.Cursor)

Example 19 with Task

use of com.parse.boltsinternal.Task in project Parse-SDK-Android by ParsePlatform.

the class OfflineStore method getOrCreateUUIDAsync.

/**
 * Gets the UUID for the given object, if it has one. Otherwise, creates a new UUID for the
 * object and adds a new row to the database for the object with no data.
 */
private Task<String> getOrCreateUUIDAsync(final ParseObject object, ParseSQLiteDatabase db) {
    final String newUUID = UUID.randomUUID().toString();
    final TaskCompletionSource<String> tcs = new TaskCompletionSource<>();
    synchronized (lock) {
        Task<String> uuidTask = objectToUuidMap.get(object);
        if (uuidTask != null) {
            return uuidTask;
        }
        // The object doesn't have a UUID yet, so we're gonna have to make one.
        objectToUuidMap.put(object, tcs.getTask());
        uuidToObjectMap.put(newUUID, object);
        fetchedObjects.put(object, tcs.getTask().onSuccess(task -> object));
    }
    /*
         * We need to put a placeholder row in the database so that later on, the save can just be an
         * update. This could be a pointer to an object that itself never gets saved offline, in which
         * case the consumer will just have to deal with that.
         */
    ContentValues values = new ContentValues();
    values.put(OfflineSQLiteOpenHelper.KEY_UUID, newUUID);
    values.put(OfflineSQLiteOpenHelper.KEY_CLASS_NAME, object.getClassName());
    db.insertOrThrowAsync(OfflineSQLiteOpenHelper.TABLE_OBJECTS, values).continueWith((Continuation<Void, Void>) task -> {
        tcs.setResult(newUUID);
        return null;
    });
    return tcs.getTask();
}
Also used : Context(android.content.Context) Arrays(java.util.Arrays) ConstraintMatcher(com.parse.OfflineQueryLogic.ConstraintMatcher) Pair(android.util.Pair) TextUtils(android.text.TextUtils) HashMap(java.util.HashMap) UUID(java.util.UUID) ArrayList(java.util.ArrayList) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) List(java.util.List) JSONException(org.json.JSONException) Capture(com.parse.boltsinternal.Capture) Continuation(com.parse.boltsinternal.Continuation) JSONObject(org.json.JSONObject) Map(java.util.Map) ContentValues(android.content.ContentValues) LinkedList(java.util.LinkedList) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) WeakHashMap(java.util.WeakHashMap) Cursor(android.database.Cursor) ContentValues(android.content.ContentValues) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource)

Example 20 with Task

use of com.parse.boltsinternal.Task in project Parse-SDK-Android by ParsePlatform.

the class OfflineStore method deleteDataForObjectAsync.

private Task<Void> deleteDataForObjectAsync(final ParseObject object, final ParseSQLiteDatabase db) {
    final Capture<String> uuid = new Capture<>();
    // Make sure the object has a UUID.
    Task<String> uuidTask;
    synchronized (lock) {
        uuidTask = objectToUuidMap.get(object);
        if (uuidTask == null) {
            // database.
            return Task.forResult(null);
        }
    }
    uuidTask = uuidTask.onSuccessTask(task -> {
        uuid.set(task.getResult());
        return task;
    });
    // If the object was the root of a pin, unpin it.
    Task<Void> unpinTask = uuidTask.onSuccessTask(task -> {
        // Find all the roots for this object.
        String[] select = { OfflineSQLiteOpenHelper.KEY_KEY };
        String where = OfflineSQLiteOpenHelper.KEY_UUID + "=?";
        String[] args = { uuid.get() };
        return db.queryAsync(OfflineSQLiteOpenHelper.TABLE_DEPENDENCIES, select, where, args);
    }).onSuccessTask(task -> {
        // Try to unpin this object from the pin label if it's a root of
        // the ParsePin.
        Cursor cursor = task.getResult();
        List<String> uuids = new ArrayList<>();
        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
            uuids.add(cursor.getString(0));
        }
        cursor.close();
        List<Task<Void>> tasks = new ArrayList<>();
        for (final String uuid1 : uuids) {
            Task<Void> unpinTask1 = getPointerAsync(uuid1, db).onSuccessTask(task12 -> {
                ParsePin pin = (ParsePin) task12.getResult();
                return fetchLocallyAsync(pin, db);
            }).continueWithTask(task1 -> {
                ParsePin pin = task1.getResult();
                List<ParseObject> modified = pin.getObjects();
                if (modified == null || !modified.contains(object)) {
                    return task1.makeVoid();
                }
                modified.remove(object);
                if (modified.size() == 0) {
                    return unpinAsync(uuid1, db);
                }
                pin.setObjects(modified);
                return saveLocallyAsync(pin, true, db);
            });
            tasks.add(unpinTask1);
        }
        return Task.whenAll(tasks);
    });
    // Delete the object from the Local Datastore in case it wasn't the root of a pin.
    return unpinTask.onSuccessTask(task -> {
        String where = OfflineSQLiteOpenHelper.KEY_UUID + "=?";
        String[] args = { uuid.get() };
        return db.deleteAsync(OfflineSQLiteOpenHelper.TABLE_DEPENDENCIES, where, args);
    }).onSuccessTask(task -> {
        String where = OfflineSQLiteOpenHelper.KEY_UUID + "=?";
        String[] args = { uuid.get() };
        return db.deleteAsync(OfflineSQLiteOpenHelper.TABLE_OBJECTS, where, args);
    }).onSuccessTask(task -> {
        synchronized (lock) {
            // Clean up
            // TODO (grantland): we should probably clean up uuidToObjectMap and
            // objectToUuidMap, but
            // getting the uuid requires a task and things might get a little
            // funky...
            fetchedObjects.remove(object);
        }
        return task;
    });
}
Also used : Context(android.content.Context) Arrays(java.util.Arrays) ConstraintMatcher(com.parse.OfflineQueryLogic.ConstraintMatcher) Pair(android.util.Pair) TextUtils(android.text.TextUtils) HashMap(java.util.HashMap) UUID(java.util.UUID) ArrayList(java.util.ArrayList) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) List(java.util.List) JSONException(org.json.JSONException) Capture(com.parse.boltsinternal.Capture) Continuation(com.parse.boltsinternal.Continuation) JSONObject(org.json.JSONObject) Map(java.util.Map) ContentValues(android.content.ContentValues) LinkedList(java.util.LinkedList) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) WeakHashMap(java.util.WeakHashMap) Cursor(android.database.Cursor) Task(com.parse.boltsinternal.Task) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) Capture(com.parse.boltsinternal.Capture)

Aggregations

Task (com.parse.boltsinternal.Task)24 ArrayList (java.util.ArrayList)15 JSONObject (org.json.JSONObject)15 Continuation (com.parse.boltsinternal.Continuation)11 TaskCompletionSource (com.parse.boltsinternal.TaskCompletionSource)11 HashMap (java.util.HashMap)11 List (java.util.List)11 JSONException (org.json.JSONException)11 Map (java.util.Map)9 Capture (com.parse.boltsinternal.Capture)8 ContentValues (android.content.ContentValues)7 Context (android.content.Context)7 Cursor (android.database.Cursor)7 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)7 Test (org.junit.Test)7 Arrays (java.util.Arrays)6 Set (java.util.Set)6 JSONArray (org.json.JSONArray)6 TextUtils (android.text.TextUtils)5 Pair (android.util.Pair)5