Search in sources :

Example 16 with Continuation

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

the class ParseFile method getDataStreamInBackground.

/**
   * Asynchronously gets the data stream from cached file if available or fetches its content from
   * the network, saves the content as cached file and returns the data stream of the cached file.
   * The {@code ProgressCallback} will be called periodically with progress updates.
   *
   * @param progressCallback
   *          A {@code ProgressCallback} that is called periodically with progress updates.
   * @return A Task that is resolved when the data stream of this object has been fetched.
   */
public Task<InputStream> getDataStreamInBackground(final ProgressCallback progressCallback) {
    final TaskCompletionSource<Void> cts = new TaskCompletionSource<>();
    currentTasks.add(cts);
    return taskQueue.enqueue(new Continuation<Void, Task<InputStream>>() {

        @Override
        public Task<InputStream> then(Task<Void> toAwait) throws Exception {
            return fetchInBackground(progressCallback, toAwait, cts.getTask()).onSuccess(new Continuation<File, InputStream>() {

                @Override
                public InputStream then(Task<File> task) throws Exception {
                    return new FileInputStream(task.getResult());
                }
            });
        }
    }).continueWithTask(new Continuation<InputStream, Task<InputStream>>() {

        @Override
        public Task<InputStream> then(Task<InputStream> task) throws Exception {
            // release
            cts.trySetResult(null);
            currentTasks.remove(cts);
            return task;
        }
    });
}
Also used : Continuation(bolts.Continuation) Task(bolts.Task) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) JSONException(org.json.JSONException) FileInputStream(java.io.FileInputStream) TaskCompletionSource(bolts.TaskCompletionSource) File(java.io.File)

Example 17 with Continuation

use of bolts.Continuation 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 18 with Continuation

use of bolts.Continuation 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 19 with Continuation

use of bolts.Continuation 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 20 with Continuation

use of bolts.Continuation 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

Continuation (bolts.Continuation)22 Task (bolts.Task)22 JSONException (org.json.JSONException)9 ArrayList (java.util.ArrayList)8 JSONObject (org.json.JSONObject)8 CancellationException (java.util.concurrent.CancellationException)6 AggregateException (bolts.AggregateException)4 Capture (bolts.Capture)4 IOException (java.io.IOException)4 TaskCompletionSource (bolts.TaskCompletionSource)3 File (java.io.File)3 Callable (java.util.concurrent.Callable)3 ContentValues (android.content.ContentValues)2 Cursor (android.database.Cursor)2 QueryConstraints (com.parse.ParseQuery.QueryConstraints)2 FileNotFoundException (java.io.FileNotFoundException)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 HashMap (java.util.HashMap)2 LinkedList (java.util.LinkedList)2 List (java.util.List)2