use of com.parse.boltsinternal.Capture in project Parse-SDK-Android by ParsePlatform.
the class ParsePushTest method testSendDataInBackgroundWithCallback.
@Test
public void testSendDataInBackgroundWithCallback() throws Exception {
// Mock controller
ParsePushController controller = mock(ParsePushController.class);
when(controller.sendInBackground(any(ParsePush.State.class), nullable(String.class))).thenReturn(Task.<Void>forResult(null));
ParseCorePlugins.getInstance().registerPushController(controller);
// Make sample ParsePush data and call method
JSONObject data = new JSONObject();
data.put("key", "value");
data.put("keyAgain", "valueAgain");
ParseQuery<ParseInstallation> query = ParseInstallation.getQuery();
query.getBuilder().whereEqualTo("foo", "bar");
final Semaphore done = new Semaphore(0);
final Capture<Exception> exceptionCapture = new Capture<>();
ParsePush.sendDataInBackground(data, query, e -> {
exceptionCapture.set(e);
done.release();
});
shadowMainLooper().idle();
// Make sure controller is executed and state parameter is correct
assertNull(exceptionCapture.get());
assertTrue(done.tryAcquire(1, 10, TimeUnit.SECONDS));
ArgumentCaptor<ParsePush.State> stateCaptor = ArgumentCaptor.forClass(ParsePush.State.class);
verify(controller, times(1)).sendInBackground(stateCaptor.capture(), nullable(String.class));
ParsePush.State state = stateCaptor.getValue();
// Verify query state
ParseQuery.State<ParseInstallation> queryState = state.queryState();
JSONObject queryStateJson = queryState.toJSON(PointerEncoder.get());
assertEquals("bar", queryStateJson.getJSONObject("where").getString("foo"));
// Verify data
assertEquals(data, state.data(), JSONCompareMode.NON_EXTENSIBLE);
}
use of com.parse.boltsinternal.Capture 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));
}
use of com.parse.boltsinternal.Capture 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;
});
}
use of com.parse.boltsinternal.Capture in project Parse-SDK-Android by ParsePlatform.
the class OfflineStore method saveLocallyAsync.
/**
* Stores a single object in the local database. If the object is a pointer, isn't dirty, and
* has an objectId already, it may not be saved, since it would provide no useful data.
*
* @param object The object to save.
* @param db A database connection to use.
*/
private Task<Void> saveLocallyAsync(final String key, final ParseObject object, final ParseSQLiteDatabase db) {
// If this is just a clean, unfetched pointer known to Parse, then there is nothing to save.
if (object.getObjectId() != null && !object.isDataAvailable() && !object.hasChanges() && !object.hasOutstandingOperations()) {
return Task.forResult(null);
}
final Capture<String> uuidCapture = new Capture<>();
// Make sure we have a UUID for the object to be saved.
return getOrCreateUUIDAsync(object, db).onSuccessTask(task -> {
String uuid = task.getResult();
uuidCapture.set(uuid);
return updateDataForObjectAsync(uuid, object, db);
}).onSuccessTask(task -> {
final ContentValues values = new ContentValues();
values.put(OfflineSQLiteOpenHelper.KEY_KEY, key);
values.put(OfflineSQLiteOpenHelper.KEY_UUID, uuidCapture.get());
return db.insertWithOnConflict(OfflineSQLiteOpenHelper.TABLE_DEPENDENCIES, values, SQLiteDatabase.CONFLICT_IGNORE);
});
}
Aggregations