1212import org .json .JSONObject ;
1313
1414import java .io .File ;
15+ import java .io .FileInputStream ;
1516import java .io .IOException ;
17+ import java .io .InputStream ;
1618import java .util .Collections ;
1719import java .util .HashSet ;
1820import java .util .Set ;
@@ -362,60 +364,14 @@ public void saveInBackground(SaveCallback callback) {
362364
363365 /**
364366 * Synchronously gets the data for this object. You probably want to use
365- * {@link #getDataInBackground} instead unless you're already in a background thread.
367+ * {@link #getDataInBackground() } instead unless you're already in a background thread.
366368 */
367369 public byte [] getData () throws ParseException {
368370 return ParseTaskUtils .wait (getDataInBackground ());
369371 }
370372
371- private Task <byte []> getDataAsync (final ProgressCallback progressCallback , Task <Void > toAwait ,
372- final Task <Void > cancellationToken ) {
373- // If data is already available, just return immediately.
374- if (data != null ) {
375- // in-memory
376- return Task .forResult (data );
377- }
378- if (cancellationToken != null && cancellationToken .isCancelled ()) {
379- return Task .cancelled ();
380- }
381-
382- // Wait for our turn in the queue, and return immediately if data is now available.
383- return toAwait .continueWithTask (new Continuation <Void , Task <byte []>>() {
384- @ Override
385- public Task <byte []> then (Task <Void > task ) throws Exception {
386- // If data is already available, just return immediately.
387- if (data != null ) {
388- // in-memory
389- return Task .forResult (data );
390- }
391- if (cancellationToken != null && cancellationToken .isCancelled ()) {
392- return Task .cancelled ();
393- }
394-
395- return getFileController ().fetchAsync (
396- state ,
397- null ,
398- progressCallbackOnMainThread (progressCallback ),
399- cancellationToken ).onSuccess (new Continuation <File , byte []>() {
400- @ Override
401- public byte [] then (Task <File > task ) throws Exception {
402- File file = task .getResult ();
403- try {
404- data = ParseFileUtils .readFileToByteArray (file );
405- return data ;
406- } catch (IOException e ) {
407- // do nothing
408- }
409- return null ;
410- }
411- });
412- }
413- });
414- }
415-
416373 /**
417- * Gets the data for this object in a background thread. `progressCallback` is guaranteed to be
418- * called with 100 before dataCallback is called.
374+ * Gets the data for this object in a background thread.
419375 *
420376 * @param progressCallback
421377 * A ProgressCallback that is called periodically with progress updates.
@@ -428,7 +384,19 @@ public Task<byte[]> getDataInBackground(final ProgressCallback progressCallback)
428384 return taskQueue .enqueue (new Continuation <Void , Task <byte []>>() {
429385 @ Override
430386 public Task <byte []> then (Task <Void > toAwait ) throws Exception {
431- return getDataAsync (progressCallback , toAwait , cts .getTask ());
387+ return fetchInBackground (progressCallback , toAwait , cts .getTask ()).onSuccess (new Continuation <File , byte []>() {
388+ @ Override
389+ public byte [] then (Task <File > task ) throws Exception {
390+ File file = task .getResult ();
391+ try {
392+ data = ParseFileUtils .readFileToByteArray (file );
393+ return data ;
394+ } catch (IOException e ) {
395+ // do nothing
396+ }
397+ return null ;
398+ }
399+ });
432400 }
433401 }).continueWithTask (new Continuation <byte [], Task <byte []>>() {
434402 @ Override
@@ -441,8 +409,7 @@ public Task<byte[]> then(Task<byte[]> task) throws Exception {
441409 }
442410
443411 /**
444- * Gets the data for this object in a background thread. `progressCallback` is guaranteed to be
445- * called with 100 before dataCallback is called.
412+ * Gets the data for this object in a background thread.
446413 *
447414 * @return A Task that is resolved when the data has been fetched.
448415 */
@@ -451,8 +418,7 @@ public Task<byte[]> getDataInBackground() {
451418 }
452419
453420 /**
454- * Gets the data for this object in a background thread. `progressCallback` is guaranteed to be
455- * called with 100 before dataCallback is called.
421+ * Gets the data for this object in a background thread.
456422 *
457423 * @param dataCallback
458424 * A GetDataCallback that is called when the get completes.
@@ -474,6 +440,169 @@ public void getDataInBackground(GetDataCallback dataCallback) {
474440 ParseTaskUtils .callbackOnMainThreadAsync (getDataInBackground (), dataCallback );
475441 }
476442
443+ /**
444+ * Synchronously gets the file pointer for this object. You probably want to use
445+ * {@link #getFileInBackground()} instead unless you're already in a background thread.
446+ */
447+ public File getFile () throws ParseException {
448+ return ParseTaskUtils .wait (getFileInBackground ());
449+ }
450+
451+ /**
452+ * Gets the file pointer for this object in a background thread.
453+ *
454+ * @param progressCallback
455+ * A ProgressCallback that is called periodically with progress updates.
456+ * @return A Task that is resolved when the file pointer of this object has been fetched.
457+ */
458+ public Task <File > getFileInBackground (final ProgressCallback progressCallback ) {
459+ final Task <Void >.TaskCompletionSource cts = Task .create ();
460+ currentTasks .add (cts );
461+
462+ return taskQueue .enqueue (new Continuation <Void , Task <File >>() {
463+ @ Override
464+ public Task <File > then (Task <Void > toAwait ) throws Exception {
465+ return fetchInBackground (progressCallback , toAwait , cts .getTask ());
466+ }
467+ }).continueWithTask (new Continuation <File , Task <File >>() {
468+ @ Override
469+ public Task <File > then (Task <File > task ) throws Exception {
470+ cts .trySetResult (null ); // release
471+ currentTasks .remove (cts );
472+ return task ;
473+ }
474+ });
475+ }
476+
477+ /**
478+ * Gets the file pointer for this object in a background thread.
479+ *
480+ * @return A Task that is resolved when the data has been fetched.
481+ */
482+ public Task <File > getFileInBackground () {
483+ return getFileInBackground ((ProgressCallback )null );
484+ }
485+
486+ /**
487+ * Gets the file pointer for this object in a background thread. `progressCallback` is guaranteed
488+ * to be called with 100 before `fileCallback` is called.
489+ *
490+ * @param fileCallback
491+ * A GetFileCallback that is called when the get completes.
492+ * @param progressCallback
493+ * A ProgressCallback that is called periodically with progress updates.
494+ */
495+ public void getFileInBackground (GetFileCallback fileCallback ,
496+ final ProgressCallback progressCallback ) {
497+ ParseTaskUtils .callbackOnMainThreadAsync (getFileInBackground (progressCallback ), fileCallback );
498+ }
499+
500+ /**
501+ * Gets the file pointer for this object in a background thread.
502+ *
503+ * @param fileCallback
504+ * A GetFileCallback that is called when the get completes.
505+ */
506+ public void getFileInBackground (GetFileCallback fileCallback ) {
507+ ParseTaskUtils .callbackOnMainThreadAsync (getFileInBackground (), fileCallback );
508+ }
509+
510+ /**
511+ * Synchronously gets the data stream for this object. You probably want to use
512+ * {@link #getDataStreamInBackground} instead unless you're already in a background thread.
513+ */
514+ public InputStream getDataStream () throws ParseException {
515+ return ParseTaskUtils .wait (getDataStreamInBackground ());
516+ }
517+
518+ /**
519+ * Gets the data stream for this object in a background thread.
520+ *
521+ * @param progressCallback
522+ * A ProgressCallback that is called periodically with progress updates.
523+ * @return A Task that is resolved when the data stream of this object has been fetched.
524+ */
525+ public Task <InputStream > getDataStreamInBackground (final ProgressCallback progressCallback ) {
526+ final Task <Void >.TaskCompletionSource cts = Task .create ();
527+ currentTasks .add (cts );
528+
529+ return taskQueue .enqueue (new Continuation <Void , Task <InputStream >>() {
530+ @ Override
531+ public Task <InputStream > then (Task <Void > toAwait ) throws Exception {
532+ return fetchInBackground (progressCallback , toAwait , cts .getTask ()).onSuccess (new Continuation <File , InputStream >() {
533+ @ Override
534+ public InputStream then (Task <File > task ) throws Exception {
535+ return new FileInputStream (task .getResult ());
536+ }
537+ });
538+ }
539+ }).continueWithTask (new Continuation <InputStream , Task <InputStream >>() {
540+ @ Override
541+ public Task <InputStream > then (Task <InputStream > task ) throws Exception {
542+ cts .trySetResult (null ); // release
543+ currentTasks .remove (cts );
544+ return task ;
545+ }
546+ });
547+ }
548+
549+ /**
550+ * Gets the data stream for this object in a background thread.
551+ *
552+ * @return A Task that is resolved when the data stream has been fetched.
553+ */
554+ public Task <InputStream > getDataStreamInBackground () {
555+ return getDataStreamInBackground ((ProgressCallback ) null );
556+ }
557+
558+ /**
559+ * Gets the data stream for this object in a background thread. `progressCallback` is guaranteed
560+ * to be called with 100 before `dataStreamCallback` is called.
561+ *
562+ * @param dataStreamCallback
563+ * A GetDataCallback that is called when the get completes.
564+ * @param progressCallback
565+ * A ProgressCallback that is called periodically with progress updates.
566+ */
567+ public void getDataStreamInBackground (GetDataStreamCallback dataStreamCallback ,
568+ final ProgressCallback progressCallback ) {
569+ ParseTaskUtils .callbackOnMainThreadAsync (
570+ getDataStreamInBackground (progressCallback ), dataStreamCallback );
571+ }
572+
573+ /**
574+ * Gets the data stream for this object in a background thread.
575+ *
576+ * @param dataStreamCallback
577+ * A GetDataCallback that is called when the get completes.
578+ */
579+ public void getDataStreamInBackground (GetDataStreamCallback dataStreamCallback ) {
580+ ParseTaskUtils .callbackOnMainThreadAsync (getDataStreamInBackground (), dataStreamCallback );
581+ }
582+
583+ private Task <File > fetchInBackground (
584+ final ProgressCallback progressCallback ,
585+ Task <Void > toAwait ,
586+ final Task <Void > cancellationToken ) {
587+ if (cancellationToken != null && cancellationToken .isCancelled ()) {
588+ return Task .cancelled ();
589+ }
590+
591+ return toAwait .continueWithTask (new Continuation <Void , Task <File >>() {
592+ @ Override
593+ public Task <File > then (Task <Void > task ) throws Exception {
594+ if (cancellationToken != null && cancellationToken .isCancelled ()) {
595+ return Task .cancelled ();
596+ }
597+ return getFileController ().fetchAsync (
598+ state ,
599+ null ,
600+ progressCallbackOnMainThread (progressCallback ),
601+ cancellationToken );
602+ }
603+ });
604+ }
605+
477606 /**
478607 * Cancels the current network request and callbacks whether it's uploading or fetching data from
479608 * the server.
@@ -490,7 +619,6 @@ public void cancel() {
490619 /*
491620 * Encode/Decode
492621 */
493-
494622 @ SuppressWarnings ("unused" )
495623 /* package */ ParseFile (JSONObject json , ParseDecoder decoder ) {
496624 this (new State .Builder ().name (json .optString ("name" )).url (json .optString ("url" )).build ());
0 commit comments