Attachment.java revision 14977bf661dd6dc4d2a2414d0839e628ebed4d50
17b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira/**
27b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * Copyright (c) 2011, Google Inc.
37b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira *
47b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License");
57b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * you may not use this file except in compliance with the License.
67b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * You may obtain a copy of the License at
77b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira *
87b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira *     http://www.apache.org/licenses/LICENSE-2.0
97b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira *
107b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * Unless required by applicable law or agreed to in writing, software
117b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
127b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * See the License for the specific language governing permissions and
147b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira * limitations under the License.
157b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira */
1630e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangpackage com.android.mail.providers;
177b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira
1888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport android.content.Intent;
1988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport android.database.Cursor;
2088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport android.net.Uri;
217aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereiraimport android.os.Parcel;
227aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereiraimport android.os.Parcelable;
23f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereiraimport android.text.TextUtils;
24f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira
2588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport com.android.mail.providers.UIProvider.AttachmentColumns;
2688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport com.android.mail.providers.UIProvider.AttachmentDestination;
2788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huangimport com.android.mail.providers.UIProvider.AttachmentState;
28b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag;
294c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sappersteinimport com.google.common.collect.Lists;
305a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
315a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport org.json.JSONArray;
325a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport org.json.JSONException;
335a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport org.json.JSONObject;
347b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira
355a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport java.util.Collection;
365a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport java.util.List;
374401c9049f0327019b0bfed554bf8ff5cdaa20e2Mindy Pereira
387aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereirapublic class Attachment implements Parcelable {
39f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira    public static final int SERVER_ATTACHMENT = 0;
40f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira    /** Extras are "<path>". */
41f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira    public static final int  LOCAL_FILE = 1;
42f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira
43b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook    public static final String LOG_TAG = LogTag.getLogTag();
445a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
457aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    /**
4688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang     * Attachment file name. See {@link AttachmentColumns#NAME}.
477aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira     */
487aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    public String name;
49f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira
5088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    /**
5188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang     * Attachment size in bytes. See {@link AttachmentColumns#SIZE}.
5288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang     */
5388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public int size;
54f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira
557aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    /**
565c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * The provider-generated URI for this Attachment. Must be globally unique. For local
575c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * attachments generated by the Compose UI prior to send/save, this field will be null.
585c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     *
595c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     *@see AttachmentColumns#URI
607aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira     */
6188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public Uri uri;
6288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
637aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    /**
645c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * MIME type of the file.
655c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     *
665c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * @see AttachmentColumns#CONTENT_TYPE
677aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira     */
681eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang    public String contentType;
6988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
7088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    /**
715c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * @see AttachmentColumns#STATE
7288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang     */
7388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public int state;
7488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
7588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    /**
765c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * @see AttachmentColumns#DESTINATION
7788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang     */
7888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public int destination;
7988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
807aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    /**
815c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * @see AttachmentColumns#DOWNLOADED_SIZE
827aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira     */
8388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public int downloadedSize;
8488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
8588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    /**
865c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * @see AttachmentColumns#CONTENT_URI
8788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang     */
881eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang    public Uri contentUri;
8988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
9088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    /**
915c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * Might be null.
925c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     *
935c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * @see AttachmentColumns#THUMBNAIL_URI
9488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang     */
9588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public Uri thumbnailUri;
9688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
9788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    /**
985c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * Might be null.
995c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     *
1005c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     * @see AttachmentColumns#PREVIEW_INTENT
10188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang     */
10288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public Intent previewIntent;
10388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
1047aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    /**
1057aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira     * Part id of the attachment.
1067aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira     */
1075c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    @Deprecated
1085c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    // partId is provider implementation specific. providers must uniquely identify Attachments
1095c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    // by uri.
1107aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    public String partId;
11188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
1125c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    @Deprecated
1135c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    // this is a local file iff the provider 'uri' field is null.
11488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public int origin;
11588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
1167aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    /**
11788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang     * Attachment origin info.
11888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang     * TODO: do we want this? Or location?
1197aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira     */
1205c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    @Deprecated
12188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public String originExtras;
1227b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira
1237aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    public Attachment(Parcel in) {
1247aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        name = in.readString();
12588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        size = in.readInt();
12688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        uri = in.readParcelable(null);
1271eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang        contentType = in.readString();
12888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        state = in.readInt();
12988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        destination = in.readInt();
13088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        downloadedSize = in.readInt();
1311eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang        contentUri = in.readParcelable(null);
13288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        thumbnailUri = in.readParcelable(null);
13388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        previewIntent = in.readParcelable(null);
1347aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        partId = in.readString();
135f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira        origin = in.readInt();
13688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        originExtras = in.readString();
1377aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    }
1387b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira
1397aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    public Attachment() {
1407aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    }
1417b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira
14288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public Attachment(Cursor cursor) {
14388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        if (cursor == null) {
14488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang            return;
14588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        }
14688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
1474c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein        name = cursor.getString(cursor.getColumnIndex(AttachmentColumns.NAME));
1484c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein        size = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.SIZE));
1494c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein        uri = Uri.parse(cursor.getString(cursor.getColumnIndex(AttachmentColumns.URI)));
1504c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein        contentType = cursor.getString(cursor.getColumnIndex(AttachmentColumns.CONTENT_TYPE));
1514c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein        state = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.STATE));
1524c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein        destination = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.DESTINATION));
1534c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein        downloadedSize = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.DOWNLOADED_SIZE));
1544c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein        contentUri = parseOptionalUri(
1554c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein                cursor.getString(cursor.getColumnIndex(AttachmentColumns.CONTENT_URI)));
15688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        thumbnailUri = parseOptionalUri(
1574c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein                cursor.getString(cursor.getColumnIndex(AttachmentColumns.THUMBNAIL_URI)));
15888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        previewIntent = getOptionalIntentFromBlob(
1594c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein                cursor.getBlob(cursor.getColumnIndex(AttachmentColumns.PREVIEW_INTENT)));
16088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
16188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        // TODO: ensure that local files attached to a draft have sane values, like SAVED/EXTERNAL
16288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        // and that contentUri is populated
16388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    }
16488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
1655c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    @Deprecated
166f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira    public Attachment(String attachmentString) {
1675e1a5b7a9d694ff812e65f4b1240366252cdcde7Paul Westbrook        String[] attachmentValues = TextUtils.split(attachmentString, "\\|");
168f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira        if (attachmentValues != null) {
169f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira            partId = attachmentValues[0];
170f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira            name = attachmentValues[1];
1711eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang            contentType = attachmentValues[2];
172f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira            try {
17388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang                size = Integer.parseInt(attachmentValues[3]);
174f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira            } catch (NumberFormatException e) {
175f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira                size = 0;
176f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira            }
1771eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang            contentType = attachmentValues[4];
178f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira            origin = Integer.parseInt(attachmentValues[5]);
1791eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang            contentUri = parseOptionalUri(attachmentValues[6]);
180f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira            originExtras = attachmentValues[7];
181f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira        }
182f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira    }
183f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira
1845c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    @Deprecated
18588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public String toJoinedString() {
1861eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang        // FIXME: contentType is read/written twice
18788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        return TextUtils.join("|", Lists.newArrayList(partId == null ? "" : partId,
1881eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang                name == null ? "" : name.replaceAll("[|\n]", ""), contentType, size, contentType,
1895c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang                contentUri != null ? LOCAL_FILE : SERVER_ATTACHMENT, contentUri,
1905c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang                originExtras == null ? "" : originExtras, ""));
19188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    }
19288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
19388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    private static Intent getOptionalIntentFromBlob(byte[] blob) {
19488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        if (blob == null) {
19588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang            return null;
19688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        }
19788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        final Parcel intentParcel = Parcel.obtain();
19888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        intentParcel.unmarshall(blob, 0, blob.length);
19988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        final Intent intent = new Intent();
20088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        intent.readFromParcel(intentParcel);
20188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        return intent;
20288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    }
20388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
20488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    private static Uri parseOptionalUri(String uriString) {
20588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        return uriString == null ? null : Uri.parse(uriString);
20688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    }
20788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
2087aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    @Override
2097aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    public int describeContents() {
2107aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        return 0;
2117aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    }
2127b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira
2137aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    @Override
2147aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    public void writeToParcel(Parcel dest, int flags) {
2157aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        dest.writeString(name);
21688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        dest.writeInt(size);
21788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        dest.writeParcelable(uri, flags);
2181eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang        dest.writeString(contentType);
21988fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        dest.writeInt(state);
22088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        dest.writeInt(destination);
22188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        dest.writeInt(downloadedSize);
2221eb5f96d4e9c459d463d664563c755ec36f958f7Andy Huang        dest.writeParcelable(contentUri, flags);
22388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        dest.writeParcelable(thumbnailUri, flags);
22488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        dest.writeParcelable(previewIntent, flags);
2257aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        dest.writeString(partId);
226f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira        dest.writeInt(origin);
22788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        dest.writeString(originExtras);
2287aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    }
2297b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira
2307aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    public static final Creator<Attachment> CREATOR = new Creator<Attachment>() {
2317aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        @Override
2327aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        public Attachment createFromParcel(Parcel source) {
2337aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira            return new Attachment(source);
2347aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        }
2357b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira
2367aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        @Override
2377aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        public Attachment[] newArray(int size) {
2387aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira            return new Attachment[size];
2397aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira        }
2407aee8f75f07eb39ecacdf0630d2199211aea5718Mindy Pereira    };
241f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira
24288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public boolean isImage() {
243ac57b84f62110b1897176807ef1a02bd11675e71Mindy Pereira        return !TextUtils.isEmpty(contentType) ? contentType.startsWith("image/") : false;
24488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    }
245f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira
24688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public boolean isDownloading() {
24788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        return state == AttachmentState.DOWNLOADING;
248f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira    }
249f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira
25088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public boolean isPresentLocally() {
25188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        return state == AttachmentState.SAVED || origin == LOCAL_FILE;
25288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    }
25388fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang
25488fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public boolean isSavedToExternal() {
25588fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang        return state == AttachmentState.SAVED && destination == AttachmentDestination.EXTERNAL;
256f944e9655562e321aff52fe5f437e1d2fa2950a9Mindy Pereira    }
2574401c9049f0327019b0bfed554bf8ff5cdaa20e2Mindy Pereira
25888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    public boolean canSave() {
259c6663c4f87b458aefef3213599ddea65e87ae223Andy Huang        return origin != LOCAL_FILE && state != AttachmentState.DOWNLOADING &&
260c6663c4f87b458aefef3213599ddea65e87ae223Andy Huang                !isSavedToExternal();
26188fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang    }
2624401c9049f0327019b0bfed554bf8ff5cdaa20e2Mindy Pereira
2634cb51dbce9635f4bf68a6de88f759e2f86d20325Andrew Sapperstein    public boolean shouldShowProgress() {
2644cb51dbce9635f4bf68a6de88f759e2f86d20325Andrew Sapperstein        return state == AttachmentState.DOWNLOADING
2654cb51dbce9635f4bf68a6de88f759e2f86d20325Andrew Sapperstein                && size > 0 && downloadedSize > 0 && downloadedSize < size;
266d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang    }
267d0991f7f0d0882ac58dfdb1f8eb8e2a0abd573fcAndy Huang
26814977bf661dd6dc4d2a2414d0839e628ebed4d50Andrew Sapperstein    public boolean downloadFailed() {
26914977bf661dd6dc4d2a2414d0839e628ebed4d50Andrew Sapperstein        return state == AttachmentState.FAILED;
27014977bf661dd6dc4d2a2414d0839e628ebed4d50Andrew Sapperstein    }
27114977bf661dd6dc4d2a2414d0839e628ebed4d50Andrew Sapperstein
2725a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    // Methods to support JSON [de-]serialization of Attachment data
2735a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    // TODO: add support for origin/originExtras (and possibly partId?) or fold those fields into
2745a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    // other fields so Compose View can use JSON objects
2755a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
2765a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    public JSONObject toJSON() throws JSONException {
2775c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang        return toJSON(name, size, uri, contentUri, contentType);
2785a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    }
2795a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
2805c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    public static JSONObject toJSON(String name, int size, Uri uri, Uri contentUri,
2815c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang            String contentType) throws JSONException {
2825a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        final JSONObject result = new JSONObject();
2835a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
2845a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        result.putOpt(AttachmentColumns.NAME, name);
2855a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        result.putOpt(AttachmentColumns.SIZE, size);
2865a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        if (uri != null) {
2875a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang            result.putOpt(AttachmentColumns.URI, uri.toString());
2885a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        }
2895c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang        if (contentUri != null) {
2905c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang            result.putOpt(AttachmentColumns.CONTENT_URI, contentUri.toString());
2915c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang        }
2925a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        result.putOpt(AttachmentColumns.CONTENT_TYPE, contentType);
2935a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
2945a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        return result;
2955a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    }
2965a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
2975a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    public Attachment(JSONObject srcJson) {
2985a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        name = srcJson.optString(AttachmentColumns.NAME, null);
2995a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        size = srcJson.optInt(AttachmentColumns.SIZE);
3005a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        uri = parseOptionalUri(srcJson, AttachmentColumns.URI);
3015c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang        contentUri = parseOptionalUri(srcJson, AttachmentColumns.CONTENT_URI);
3025a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        contentType = srcJson.optString(AttachmentColumns.CONTENT_TYPE, null);
3035a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    }
3045a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
3055a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    private static Uri parseOptionalUri(JSONObject srcJson, String key) {
3065a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        final String uriStr = srcJson.optString(key, null);
3075a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        return uriStr == null ? null : Uri.parse(uriStr);
3085a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    }
3095a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
3105a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    public static String toJSONArray(Collection<Attachment> attachments) {
3115a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        final JSONArray result = new JSONArray();
3125a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        try {
3135a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang            for (Attachment attachment : attachments) {
3145a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang                result.put(attachment.toJSON());
3155a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang            }
3165a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        } catch (JSONException e) {
3175a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang            throw new IllegalArgumentException(e);
3185a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        }
3195a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        return result.toString();
3205a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    }
3215a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
3225a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    public static List<Attachment> fromJSONArray(String jsonArrayStr) {
3235a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        final List<Attachment> results = Lists.newArrayList();
3245a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        try {
3255a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang            final JSONArray arr = new JSONArray(jsonArrayStr);
3265a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
3275a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang            for (int i = 0; i < arr.length(); i++) {
3285a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang                results.add(new Attachment(arr.getJSONObject(i)));
3295a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang            }
3305a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
3315a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        } catch (JSONException e) {
3325a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang            throw new IllegalArgumentException(e);
3335a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        }
3345a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        return results;
3355a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    }
3367b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira}
337