Search in sources :

Example 31 with Task

use of bolts.Task in project Parse-SDK-Android by ParsePlatform.

the class NetworkObjectController method saveAllAsync.

@Override
public List<Task<ParseObject.State>> saveAllAsync(List<ParseObject.State> states, List<ParseOperationSet> operationsList, String sessionToken, List<ParseDecoder> decoders) {
    int batchSize = states.size();
    List<ParseRESTObjectCommand> commands = new ArrayList<>(batchSize);
    ParseEncoder encoder = PointerEncoder.get();
    for (int i = 0; i < batchSize; i++) {
        ParseObject.State state = states.get(i);
        ParseOperationSet operations = operationsList.get(i);
        JSONObject objectJSON = coder.encode(state, operations, encoder);
        ParseRESTObjectCommand command = ParseRESTObjectCommand.saveObjectCommand(state, objectJSON, sessionToken);
        commands.add(command);
    }
    final List<Task<JSONObject>> batchTasks = ParseRESTObjectBatchCommand.executeBatch(client, commands, sessionToken);
    final List<Task<ParseObject.State>> tasks = new ArrayList<>(batchSize);
    for (int i = 0; i < batchSize; i++) {
        final ParseObject.State state = states.get(i);
        final ParseDecoder decoder = decoders.get(i);
        tasks.add(batchTasks.get(i).onSuccess(new Continuation<JSONObject, ParseObject.State>() {

            @Override
            public ParseObject.State then(Task<JSONObject> task) throws Exception {
                JSONObject result = task.getResult();
                // Copy and clear to create an new empty instance of the same type as `state`
                ParseObject.State.Init<?> builder = state.newBuilder().clear();
                return coder.decode(builder, result, decoder).isComplete(false).build();
            }
        }));
    }
    return tasks;
}
Also used : Task(bolts.Task) Continuation(bolts.Continuation) ArrayList(java.util.ArrayList) JSONObject(org.json.JSONObject)

Example 32 with Task

use of bolts.Task in project Parse-SDK-Android by ParsePlatform.

the class OfflineQueryLogic method createMatcher.

/**
   * Returns a ConstraintMatcher that return true iff the object matches QueryConstraints. This
   * takes in a SQLiteDatabase connection because SQLite is finicky about nesting connections, so we
   * want to reuse them whenever possible.
   */
private <T extends ParseObject> ConstraintMatcher<T> createMatcher(ParseUser user, QueryConstraints queryConstraints) {
    // Make a list of all the matchers to AND together.
    final ArrayList<ConstraintMatcher<T>> matchers = new ArrayList<>();
    for (final String key : queryConstraints.keySet()) {
        final Object queryConstraintValue = queryConstraints.get(key);
        if (key.equals("$or")) {
            /*
         * A set of queries to be OR-ed together.
         */
            @SuppressWarnings("unchecked") ConstraintMatcher<T> matcher = createOrMatcher(user, (ArrayList<QueryConstraints>) queryConstraintValue);
            matchers.add(matcher);
        } else if (queryConstraintValue instanceof KeyConstraints) {
            /*
         * It's a set of constraints that should be AND-ed together.
         */
            KeyConstraints keyConstraints = (KeyConstraints) queryConstraintValue;
            for (String operator : keyConstraints.keySet()) {
                final Object keyConstraintValue = keyConstraints.get(operator);
                ConstraintMatcher<T> matcher = createMatcher(user, operator, keyConstraintValue, key, keyConstraints);
                matchers.add(matcher);
            }
        } else if (queryConstraintValue instanceof RelationConstraint) {
            /*
         * It's a $relatedTo constraint.
         */
            final RelationConstraint relation = (RelationConstraint) queryConstraintValue;
            matchers.add(new ConstraintMatcher<T>(user) {

                @Override
                public Task<Boolean> matchesAsync(T object, ParseSQLiteDatabase db) {
                    return Task.forResult(relation.getRelation().hasKnownObject(object));
                }
            });
        } else {
            /*
         * It's not a set of constraints, so it's just a value to compare against.
         */
            matchers.add(new ConstraintMatcher<T>(user) {

                @Override
                public Task<Boolean> matchesAsync(T object, ParseSQLiteDatabase db) {
                    Object objectValue;
                    try {
                        objectValue = getValue(object, key);
                    } catch (ParseException e) {
                        return Task.forError(e);
                    }
                    return Task.forResult(matchesEqualConstraint(queryConstraintValue, objectValue));
                }
            });
        }
    }
    /*
     * Now AND together the constraints for each key.
     */
    return new ConstraintMatcher<T>(user) {

        @Override
        public Task<Boolean> matchesAsync(final T object, final ParseSQLiteDatabase db) {
            Task<Boolean> task = Task.forResult(true);
            for (final ConstraintMatcher<T> matcher : matchers) {
                task = task.onSuccessTask(new Continuation<Boolean, Task<Boolean>>() {

                    @Override
                    public Task<Boolean> then(Task<Boolean> task) throws Exception {
                        if (!task.getResult()) {
                            return task;
                        }
                        return matcher.matchesAsync(object, db);
                    }
                });
            }
            return task;
        }
    };
}
Also used : Task(bolts.Task) Continuation(bolts.Continuation) ArrayList(java.util.ArrayList) QueryConstraints(com.parse.ParseQuery.QueryConstraints) RelationConstraint(com.parse.ParseQuery.RelationConstraint) JSONObject(org.json.JSONObject) KeyConstraints(com.parse.ParseQuery.KeyConstraints)

Example 33 with Task

use of bolts.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(new Continuation<Void, Void>() {

        @Override
        public Void then(Task<Void> task) throws Exception {
            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(new Continuation<Void, Void>() {

        @Override
        public Void then(Task<Void> task) throws Exception {
            usersComplete.set(true);
            return null;
        }
    });
    final Capture<Set<ParseObject>> remaining = new Capture<>(objects);
    Task<Void> objectsTask = Task.forResult(null).continueWhile(new Callable<Boolean>() {

        @Override
        public Boolean call() throws Exception {
            return remaining.get().size() > 0;
        }
    }, new Continuation<Void, Task<Void>>() {

        @Override
        public Task<Void> then(Task<Void> task) throws Exception {
            // 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, new Continuation<Void, Task<Void>>() {

                @Override
                public Task<Void> then(Task<Void> toAwait) throws Exception {
                    return saveAllAsync(current, sessionToken, toAwait);
                }
            });
        }
    });
    return Task.whenAll(Arrays.asList(filesTask, usersTask, objectsTask));
}
Also used : Task(bolts.Task) Set(java.util.Set) HashSet(java.util.HashSet) ArrayList(java.util.ArrayList) Capture(bolts.Capture) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashSet(java.util.HashSet) Continuation(bolts.Continuation) JSONException(org.json.JSONException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean)

Example 34 with Task

use of bolts.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 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<JSONObject, Void>() {

        @Override
        public Void then(Task<JSONObject> task) throws Exception {
            TaskCompletionSource<JSONObject> 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;
}
Also used : Task(bolts.Task) MalformedURLException(java.net.MalformedURLException) ArrayList(java.util.ArrayList) URL(java.net.URL) TaskCompletionSource(bolts.TaskCompletionSource) ArrayList(java.util.ArrayList) List(java.util.List) JSONArray(org.json.JSONArray) JSONException(org.json.JSONException) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) JSONException(org.json.JSONException) JSONObject(org.json.JSONObject)

Example 35 with Task

use of bolts.Task in project Parse-SDK-Android by ParsePlatform.

the class ParseFileController method fetchAsync.

public Task<File> fetchAsync(final ParseFile.State state, @SuppressWarnings("UnusedParameters") String sessionToken, final ProgressCallback downloadProgressCallback, final Task<Void> cancellationToken) {
    if (cancellationToken != null && cancellationToken.isCancelled()) {
        return Task.cancelled();
    }
    final File cacheFile = getCacheFile(state);
    return Task.call(new Callable<Boolean>() {

        @Override
        public Boolean call() throws Exception {
            return cacheFile.exists();
        }
    }, ParseExecutors.io()).continueWithTask(new Continuation<Boolean, Task<File>>() {

        @Override
        public Task<File> then(Task<Boolean> task) throws Exception {
            boolean result = task.getResult();
            if (result) {
                return Task.forResult(cacheFile);
            }
            if (cancellationToken != null && cancellationToken.isCancelled()) {
                return Task.cancelled();
            }
            // Generate the temp file path for caching ParseFile content based on ParseFile's url
            // The reason we do not write to the cacheFile directly is because there is no way we can
            // verify if a cacheFile is complete or not. If download is interrupted in the middle, next
            // time when we download the ParseFile, since cacheFile has already existed, we will return
            // this incomplete cacheFile
            final File tempFile = getTempFile(state);
            // network
            final ParseAWSRequest request = new ParseAWSRequest(ParseHttpRequest.Method.GET, state.url(), tempFile);
            // We do not need to delete the temp file since we always try to overwrite it
            return request.executeAsync(awsClient(), null, downloadProgressCallback, cancellationToken).continueWithTask(new Continuation<Void, Task<File>>() {

                @Override
                public Task<File> then(Task<Void> task) throws Exception {
                    // If the top-level task was cancelled, don't actually set the data -- just move on.
                    if (cancellationToken != null && cancellationToken.isCancelled()) {
                        throw new CancellationException();
                    }
                    if (task.isFaulted()) {
                        ParseFileUtils.deleteQuietly(tempFile);
                        return task.cast();
                    }
                    // Since we give the cacheFile pointer to developers, it is not safe to guarantee
                    // cacheFile always does not exist here, so it is better to delete it manually,
                    // otherwise moveFile may throw an exception.
                    ParseFileUtils.deleteQuietly(cacheFile);
                    ParseFileUtils.moveFile(tempFile, cacheFile);
                    return Task.forResult(cacheFile);
                }
            }, ParseExecutors.io());
        }
    });
}
Also used : Task(bolts.Task) Continuation(bolts.Continuation) CancellationException(java.util.concurrent.CancellationException) File(java.io.File) Callable(java.util.concurrent.Callable) CancellationException(java.util.concurrent.CancellationException) IOException(java.io.IOException)

Aggregations

Task (bolts.Task)46 JSONObject (org.json.JSONObject)27 Continuation (bolts.Continuation)23 JSONException (org.json.JSONException)20 ArrayList (java.util.ArrayList)15 JSONArray (org.json.JSONArray)14 RCLog (chat.rocket.android.log.RCLog)11 TaskCompletionSource (bolts.TaskCompletionSource)10 List (java.util.List)8 Context (android.content.Context)7 Uri (android.net.Uri)7 RealmHelper (chat.rocket.persistence.realm.RealmHelper)7 CancellationException (java.util.concurrent.CancellationException)7 TextUtils (android.text.TextUtils)6 SyncState (chat.rocket.core.SyncState)6 IOException (java.io.IOException)6 NonNull (android.support.annotation.NonNull)5 Nullable (android.support.annotation.Nullable)5 AggregateException (bolts.AggregateException)5 AppLink (bolts.AppLink)5