Skip to content

Commit 46a0233

Browse files
authored
Merge pull request #624 from natario1/parcelable-file
Implementing Parcelable in ParseFile
2 parents aaf740a + 5152369 commit 46a0233

File tree

5 files changed

+111
-3
lines changed

5 files changed

+111
-3
lines changed

Parse/src/main/java/com/parse/ParseFile.java

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
*/
99
package com.parse;
1010

11+
import android.os.Parcel;
12+
import android.os.Parcelable;
13+
1114
import org.json.JSONException;
1215
import org.json.JSONObject;
1316

@@ -40,7 +43,7 @@
4043
* object.save();
4144
* </pre>
4245
*/
43-
public class ParseFile {
46+
public class ParseFile implements Parcelable {
4447

4548
/* package for tests */ static ParseFileController getFileController() {
4649
return ParseCorePlugins.getInstance().getFileController();
@@ -221,6 +224,33 @@ public ParseFile(byte[] data, String contentType) {
221224
this(null, data, contentType);
222225
}
223226

227+
/**
228+
* Creates a new file instance from a {@link Parcel} source. This is used when unparceling
229+
* a non-dirty ParseFile. Subclasses that need Parcelable behavior should provide their own
230+
* {@link android.os.Parcelable.Creator} and override this constructor.
231+
*
232+
* @param source
233+
* the source Parcel
234+
*/
235+
protected ParseFile(Parcel source) {
236+
this(source, ParseParcelDecoder.get());
237+
}
238+
239+
/**
240+
* Creates a new file instance from a {@link Parcel} using the given {@link ParseParcelDecoder}.
241+
* The decoder is currently unused, but it might be in the future, plus this is the pattern we
242+
* are using in parcelable classes.
243+
* @param source the parcel
244+
* @param decoder the decoder
245+
*/
246+
ParseFile(Parcel source, ParseParcelDecoder decoder) {
247+
this(new State.Builder()
248+
.url(source.readString())
249+
.name(source.readString())
250+
.mimeType(source.readByte() == 1 ? source.readString() : null)
251+
.build());
252+
}
253+
224254
/* package for tests */ ParseFile(State state) {
225255
this.state = state;
226256
}
@@ -705,4 +735,39 @@ public void cancel() {
705735

706736
return json;
707737
}
738+
739+
@Override
740+
public int describeContents() {
741+
return 0;
742+
}
743+
744+
@Override
745+
public void writeToParcel(Parcel dest, int flags) {
746+
writeToParcel(dest, ParseParcelEncoder.get());
747+
}
748+
749+
void writeToParcel(Parcel dest, ParseParcelEncoder encoder) {
750+
if (isDirty()) {
751+
throw new RuntimeException("Unable to parcel an unsaved ParseFile.");
752+
}
753+
dest.writeString(getUrl()); // Not null
754+
dest.writeString(getName()); // Not null
755+
String type = state.mimeType(); // Nullable
756+
dest.writeByte(type != null ? (byte) 1 : 0);
757+
if (type != null) {
758+
dest.writeString(type);
759+
}
760+
}
761+
762+
public final static Creator<ParseFile> CREATOR = new Creator<ParseFile>() {
763+
@Override
764+
public ParseFile createFromParcel(Parcel source) {
765+
return new ParseFile(source);
766+
}
767+
768+
@Override
769+
public ParseFile[] newArray(int size) {
770+
return new ParseFile[size];
771+
}
772+
};
708773
}

Parse/src/main/java/com/parse/ParseParcelDecoder.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public Object decode(Parcel source) {
5959
case ParseParcelEncoder.TYPE_OP:
6060
return ParseFieldOperations.decode(source, this);
6161

62+
case ParseParcelEncoder.TYPE_FILE:
63+
return new ParseFile(source, this);
64+
6265
case ParseParcelEncoder.TYPE_ACL:
6366
return new ParseACL(source, this);
6467

Parse/src/main/java/com/parse/ParseParcelEncoder.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ private static boolean isValidType(Object value) {
5353
/* package */ final static String TYPE_NULL = "Null";
5454
/* package */ final static String TYPE_NATIVE = "Native";
5555
/* package */ final static String TYPE_OP = "Operation";
56+
/* package */ final static String TYPE_FILE = "ParseFile";
5657

5758
public void encode(Object object, Parcel dest) {
5859
try {
@@ -75,7 +76,8 @@ public void encode(Object object, Parcel dest) {
7576
((ParseFieldOperation) object).encode(dest, this);
7677

7778
} else if (object instanceof ParseFile) {
78-
throw new IllegalArgumentException("Not supported yet");
79+
dest.writeString(TYPE_FILE);
80+
((ParseFile) object).writeToParcel(dest, this);
7981

8082
} else if (object instanceof ParseGeoPoint) {
8183
throw new IllegalArgumentException("Not supported yet");

Parse/src/test/java/com/parse/ParseFileTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@
88
*/
99
package com.parse;
1010

11+
import android.os.Parcel;
12+
1113
import org.junit.After;
1214
import org.junit.Before;
1315
import org.junit.Rule;
1416
import org.junit.Test;
1517
import org.junit.rules.TemporaryFolder;
18+
import org.junit.runner.RunWith;
1619
import org.mockito.ArgumentCaptor;
1720
import org.mockito.Matchers;
21+
import org.robolectric.RobolectricTestRunner;
22+
import org.robolectric.annotation.Config;
1823

1924
import java.io.File;
2025
import java.io.InputStream;
@@ -36,6 +41,8 @@
3641
import static org.mockito.Mockito.verify;
3742
import static org.mockito.Mockito.when;
3843

44+
@RunWith(RobolectricTestRunner.class)
45+
@Config(constants = BuildConfig.class, sdk = TestHelper.ROBOLECTRIC_SDK_VERSION)
3946
public class ParseFileTest {
4047

4148
@Rule
@@ -492,6 +499,33 @@ public void testCancel() {
492499
}
493500
}
494501

502+
@Test
503+
public void testParcelable() {
504+
String mime = "mime";
505+
String name = "name";
506+
String url = "url";
507+
ParseFile file = new ParseFile(new ParseFile.State.Builder()
508+
.name(name)
509+
.mimeType(mime)
510+
.url(url)
511+
.build());
512+
Parcel parcel = Parcel.obtain();
513+
file.writeToParcel(parcel, 0);
514+
parcel.setDataPosition(0);
515+
file = ParseFile.CREATOR.createFromParcel(parcel);
516+
assertEquals(file.getName(), name);
517+
assertEquals(file.getUrl(), url);
518+
assertEquals(file.getState().mimeType(), mime);
519+
assertFalse(file.isDirty());
520+
}
521+
522+
@Test( expected = RuntimeException.class )
523+
public void testDontParcelIfDirty() {
524+
ParseFile file = new ParseFile(new ParseFile.State.Builder().build());
525+
Parcel parcel = Parcel.obtain();
526+
file.writeToParcel(parcel, 0);
527+
}
528+
495529
// TODO(grantland): testEncode
496530
// TODO(grantland): testDecode
497531
}

Parse/src/test/java/com/parse/ParseObjectTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ public void testGetLongWithWrongValue() throws Exception {
497497

498498
@Test
499499
public void testParcelable() throws Exception {
500-
// TODO test ParseGeoPoint and ParseFile after merge
500+
// TODO test ParseGeoPoint after merge
501501
ParseObject object = ParseObject.createWithoutData("Test", "objectId");
502502
object.isDeleted = true;
503503
object.put("long", 200L);
@@ -528,6 +528,9 @@ public void testParcelable() throws Exception {
528528
ParseRelation<ParseObject> rel = new ParseRelation<>(object, "relation");
529529
rel.add(related);
530530
object.put("relation", rel);
531+
// File
532+
ParseFile file = new ParseFile(new ParseFile.State.Builder().url("fileUrl").build());
533+
object.put("file", file);
531534

532535
Parcel parcel = Parcel.obtain();
533536
object.writeToParcel(parcel, 0);
@@ -553,6 +556,7 @@ public void testParcelable() throws Exception {
553556
assertEquals(newRel.getKey(), rel.getKey());
554557
assertEquals(newRel.getKnownObjects().size(), rel.getKnownObjects().size());
555558
newRel.hasKnownObject(related);
559+
assertEquals(newObject.getParseFile("file").getUrl(), object.getParseFile("file").getUrl());
556560
}
557561

558562
@Test

0 commit comments

Comments
 (0)