Settings.java revision 6006991395131d7d1db4f883ff8c7a87498b6eec
1/**
2 * Copyright (c) 2012, Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.mail.providers;
18
19import com.google.common.base.Objects;
20
21import com.android.mail.providers.UIProvider.AccountColumns;
22import com.android.mail.providers.UIProvider.AutoAdvance;
23import com.android.mail.providers.UIProvider.DefaultReplyBehavior;
24import com.android.mail.providers.UIProvider.MessageTextSize;
25import com.android.mail.providers.UIProvider.SnapHeaderValue;
26import com.android.mail.providers.UIProvider.Swipe;
27import com.android.mail.utils.LogTag;
28import com.android.mail.utils.LogUtils;
29import com.android.mail.utils.Utils;
30
31import android.database.Cursor;
32import android.net.Uri;
33import android.os.Parcel;
34import android.os.Parcelable;
35import android.text.TextUtils;
36
37import org.json.JSONException;
38import org.json.JSONObject;
39
40/**
41 * Model to hold Settings for an account.
42 */
43public class Settings implements Parcelable {
44    /**
45     * Interface to listen to settings changes. You need to register with the
46     * {@link com.android.mail.ui.ActivityController} for observing changes to settings.
47     */
48    public interface ChangeListener {
49        /**
50         * Method that is called when settings are changed.
51         * @param updatedSettings the updated settings.
52         */
53        public void onSettingsChanged(Settings updatedSettings);
54    }
55
56    private static final String LOG_TAG = LogTag.getLogTag();
57
58    static final Settings EMPTY_SETTINGS = new Settings();
59
60    // Max size for attachments (5 megs). Will be overridden by an account
61    // setting, if found.
62    private static final int DEFAULT_MAX_ATTACHMENT_SIZE = 5 * 1024 * 1024;
63
64    public static final int SWIPE_SETTING_ARCHIVE = 0;
65    public static final int SWIPE_SETTING_DELETE = 1;
66    public static final int SWIPE_SETTING_DISABLED = 2;
67
68    private static final int DEFAULT = SWIPE_SETTING_ARCHIVE;
69
70    public final String signature;
71    /**
72     * Auto advance setting for this account.
73     * Integer, one of {@link AutoAdvance#LIST}, {@link AutoAdvance#NEWER},
74     * {@link AutoAdvance#OLDER} or  {@link AutoAdvance#UNSET}
75     */
76    public final int autoAdvance;
77    public final int messageTextSize;
78    public final int snapHeaders;
79    public final int replyBehavior;
80    public final boolean hideCheckboxes;
81    public final boolean confirmDelete;
82    public final boolean confirmArchive;
83    public final boolean confirmSend;
84    public final Uri defaultInbox;
85    /**
86     * The name of the default inbox: "Inbox" or "Priority Inbox", internationalized...
87     */
88    public final String defaultInboxName;
89    // If you find the need for more default Inbox information: ID or capabilities, then
90    // ask viki to replace the above two members with a single JSON object representing the default
91    // folder.  That should make all the information about the folder available without an
92    // explosion in the number of members.
93
94    public final boolean forceReplyFromDefault;
95    public final int maxAttachmentSize;
96    public final int swipe;
97
98    /** Cached value of hashCode */
99    private int mHashCode;
100
101    private Settings() {
102        signature = null;
103        autoAdvance = AutoAdvance.LIST;
104        messageTextSize = MessageTextSize.NORMAL;
105        snapHeaders = SnapHeaderValue.ALWAYS;
106        replyBehavior = DefaultReplyBehavior.REPLY;
107        hideCheckboxes = false;
108        confirmDelete = false;
109        confirmArchive = false;
110        confirmSend = false;
111        defaultInbox = Uri.EMPTY;
112        defaultInboxName = "";
113        forceReplyFromDefault = false;
114        maxAttachmentSize = 0;
115        swipe = DEFAULT;
116    }
117
118    public Settings(Parcel inParcel) {
119        signature = inParcel.readString();
120        autoAdvance = inParcel.readInt();
121        messageTextSize = inParcel.readInt();
122        snapHeaders = inParcel.readInt();
123        replyBehavior = inParcel.readInt();
124        hideCheckboxes = inParcel.readInt() != 0;
125        confirmDelete = inParcel.readInt() != 0;
126        confirmArchive = inParcel.readInt() != 0;
127        confirmSend = inParcel.readInt() != 0;
128        defaultInbox = Utils.getValidUri(inParcel.readString());
129        defaultInboxName = inParcel.readString();
130        forceReplyFromDefault = inParcel.readInt() != 0;
131        maxAttachmentSize = inParcel.readInt();
132        swipe = inParcel.readInt();
133    }
134
135    public Settings(Cursor cursor) {
136        signature = cursor.getString(UIProvider.ACCOUNT_SETTINGS_SIGNATURE_COLUMN);
137        autoAdvance = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_AUTO_ADVANCE_COLUMN);
138        messageTextSize = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_MESSAGE_TEXT_SIZE_COLUMN);
139        snapHeaders = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_SNAP_HEADERS_COLUMN);
140        replyBehavior = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_REPLY_BEHAVIOR_COLUMN);
141        hideCheckboxes = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_HIDE_CHECKBOXES_COLUMN) != 0;
142        confirmDelete = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_CONFIRM_DELETE_COLUMN) != 0;
143        confirmArchive = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_CONFIRM_ARCHIVE_COLUMN) != 0;
144        confirmSend = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_CONFIRM_SEND_COLUMN) != 0;
145        defaultInbox = Utils.getValidUri(
146                cursor.getString(UIProvider.ACCOUNT_SETTINGS_DEFAULT_INBOX_COLUMN));
147        defaultInboxName = cursor.getString(UIProvider.ACCOUNT_SETTINGS_DEFAULT_INBOX_NAME_COLUMN);
148        forceReplyFromDefault = cursor.getInt(
149                UIProvider.ACCOUNT_SETTINGS_FORCE_REPLY_FROM_DEFAULT_COLUMN) != 0;
150        maxAttachmentSize = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_MAX_ATTACHMENT_SIZE_COLUMN);
151        swipe = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_SWIPE_COLUMN);
152    }
153
154    private Settings(JSONObject json) throws JSONException {
155        signature = json.optString(AccountColumns.SettingsColumns.SIGNATURE);
156
157        autoAdvance = json.optInt(AccountColumns.SettingsColumns.AUTO_ADVANCE);
158        messageTextSize = json.optInt(AccountColumns.SettingsColumns.MESSAGE_TEXT_SIZE);
159        snapHeaders = json.optInt(AccountColumns.SettingsColumns.SNAP_HEADERS);
160        replyBehavior = json.optInt(AccountColumns.SettingsColumns.REPLY_BEHAVIOR);
161        hideCheckboxes = json.optBoolean(AccountColumns.SettingsColumns.HIDE_CHECKBOXES);
162        confirmDelete = json.optBoolean(AccountColumns.SettingsColumns.CONFIRM_DELETE);
163        confirmArchive = json.optBoolean(AccountColumns.SettingsColumns.CONFIRM_ARCHIVE);
164        confirmSend = json.optBoolean(AccountColumns.SettingsColumns.CONFIRM_SEND);
165        defaultInbox = Utils.getValidUri(
166                json.optString(AccountColumns.SettingsColumns.DEFAULT_INBOX));
167        defaultInboxName = json.optString(AccountColumns.SettingsColumns.DEFAULT_INBOX_NAME);
168        forceReplyFromDefault =
169                json.optBoolean(AccountColumns.SettingsColumns.FORCE_REPLY_FROM_DEFAULT);
170        maxAttachmentSize = json.getInt(AccountColumns.SettingsColumns.MAX_ATTACHMENT_SIZE);
171        swipe = json.optInt(AccountColumns.SettingsColumns.SWIPE);
172    }
173
174    /**
175     * Return a serialized String for these settings.
176     */
177    public synchronized String serialize() {
178        final JSONObject json = toJSON();
179        return json.toString();
180    }
181
182    /**
183     * Return a JSONObject for these settings.
184     */
185    public synchronized JSONObject toJSON() {
186        final JSONObject json = new JSONObject();
187        try {
188            json.put(AccountColumns.SettingsColumns.SIGNATURE, signature);
189            json.put(AccountColumns.SettingsColumns.AUTO_ADVANCE, autoAdvance);
190            json.put(AccountColumns.SettingsColumns.MESSAGE_TEXT_SIZE, messageTextSize);
191            json.put(AccountColumns.SettingsColumns.SNAP_HEADERS, snapHeaders);
192            json.put(AccountColumns.SettingsColumns.REPLY_BEHAVIOR, replyBehavior);
193            json.put(AccountColumns.SettingsColumns.HIDE_CHECKBOXES, hideCheckboxes);
194            json.put(AccountColumns.SettingsColumns.CONFIRM_DELETE, confirmDelete);
195            json.put(AccountColumns.SettingsColumns.CONFIRM_ARCHIVE, confirmArchive);
196            json.put(AccountColumns.SettingsColumns.CONFIRM_SEND, confirmSend);
197            json.put(AccountColumns.SettingsColumns.DEFAULT_INBOX, defaultInbox);
198            json.put(AccountColumns.SettingsColumns.DEFAULT_INBOX_NAME, defaultInboxName);
199            json.put(AccountColumns.SettingsColumns.FORCE_REPLY_FROM_DEFAULT,
200                    forceReplyFromDefault);
201            json.put(AccountColumns.SettingsColumns.MAX_ATTACHMENT_SIZE,
202                    maxAttachmentSize);
203            json.put(AccountColumns.SettingsColumns.SWIPE, swipe);
204        } catch (JSONException e) {
205            LogUtils.wtf(LOG_TAG, e, "Could not serialize settings");
206        }
207        return json;
208    }
209
210    /**
211     * Create a new instance of an Settings object using a serialized instance created previously
212     * using {@link #serialize()}. This returns null if the serialized instance was invalid or does
213     * not represent a valid account object.
214     *
215     * @param serializedAccount
216     * @return
217     */
218    public static Settings newInstance(String serializedSettings) {
219        JSONObject json = null;
220        try {
221            json = new JSONObject(serializedSettings);
222            return new Settings(json);
223        } catch (JSONException e) {
224            LogUtils.e(LOG_TAG, e, "Could not create an settings from this input: \"%s\"",
225                    serializedSettings);
226            return null;
227        }
228    }
229
230
231    /**
232     * Create a new instance of an Settings object using a JSONObject  instance created previously
233     * using {@link #toJSON(). This returns null if the serialized instance was invalid or does
234     * not represent a valid account object.
235     *
236     * @param serializedAccount
237     * @return
238     */
239    public static Settings newInstance(JSONObject json) {
240        if (json == null) {
241            return null;
242        }
243        try {
244            return new Settings(json);
245        } catch (JSONException e) {
246            LogUtils.e(LOG_TAG, e, "Could not create an settings from this input: \"%s\"",
247                    json.toString());
248            return null;
249        }
250    }
251
252    @Override
253    public int describeContents() {
254        return 0;
255    }
256
257    @Override
258    public void writeToParcel(Parcel dest, int flags) {
259        dest.writeString(signature);
260        dest.writeInt(autoAdvance);
261        dest.writeInt(messageTextSize);
262        dest.writeInt(snapHeaders);
263        dest.writeInt(replyBehavior);
264        dest.writeInt(hideCheckboxes ? 1 : 0);
265        dest.writeInt(confirmDelete ? 1 : 0);
266        dest.writeInt(confirmArchive? 1 : 0);
267        dest.writeInt(confirmSend? 1 : 0);
268        dest.writeString(defaultInbox.toString());
269        dest.writeString(defaultInboxName);
270        dest.writeInt(forceReplyFromDefault ? 1 : 0);
271        dest.writeInt(maxAttachmentSize);
272        dest.writeInt(swipe);
273    }
274
275    /**
276     * Returns the URI of the current account's default inbox if available, otherwise
277     * returns the empty URI {@link Uri#EMPTY}
278     * @param settings a settings object, possibly null.
279     * @return a valid default Inbox URI, or {@link Uri#EMPTY} if settings are null or no default
280     * is specified.
281     */
282    public static Uri getDefaultInboxUri(Settings settings) {
283        if (settings != null && settings.defaultInbox != null) {
284            return settings.defaultInbox;
285        }
286        return Uri.EMPTY;
287    }
288
289    /**
290     * Return the auto advance setting for the settings provided. It is safe to pass this method
291     * a null object. It always returns a valid {@link AutoAdvance} setting.
292     * @return the auto advance setting, a constant from {@link AutoAdvance}
293     */
294    public static int getAutoAdvanceSetting(Settings settings) {
295        // TODO(mindyp): if this isn't set, then show the dialog telling the user to set it.
296        // Remove defaulting to AutoAdvance.LIST.
297        final int autoAdvance = (settings != null) ?
298                (settings.autoAdvance == AutoAdvance.UNSET ?
299                        AutoAdvance.LIST : settings.autoAdvance)
300                : AutoAdvance.LIST;
301        return autoAdvance;
302    }
303
304    /**
305     * Return the swipe setting for the settings provided. It is safe to pass this method
306     * a null object. It always returns a valid {@link Swipe} setting.
307     * @return the auto advance setting, a constant from {@link Swipe}
308     */
309    public static int getSwipeSetting(Settings settings) {
310        return settings != null ? settings.swipe : Swipe.DEFAULT;
311    }
312
313    @SuppressWarnings("hiding")
314    public static final Creator<Settings> CREATOR = new Creator<Settings>() {
315        @Override
316        public Settings createFromParcel(Parcel source) {
317            return new Settings(source);
318        }
319
320        @Override
321        public Settings[] newArray(int size) {
322            return new Settings[size];
323        }
324    };
325
326    /**
327     *  Get the maximum size in KB for attachments.
328     */
329    public int getMaxAttachmentSize() {
330        return maxAttachmentSize <= 0 ? DEFAULT_MAX_ATTACHMENT_SIZE : maxAttachmentSize;
331    }
332
333    @Override
334    public boolean equals(final Object aThat) {
335        LogUtils.d(LOG_TAG, "Settings.equals(%s)", aThat);
336        if (this == aThat) {
337            return true;
338        }
339        if ((aThat == null) || (aThat.getClass() != this.getClass())) {
340            return false;
341        }
342        final Settings that = (Settings) aThat;
343        return (TextUtils.equals(signature, that.signature)
344                && autoAdvance == that.autoAdvance
345                && messageTextSize == that.messageTextSize
346                && replyBehavior == that.replyBehavior
347                && hideCheckboxes == that.hideCheckboxes
348                && confirmDelete == that.confirmDelete
349                && confirmArchive == that.confirmArchive
350                && confirmSend == that.confirmSend
351                && Objects.equal(defaultInbox, that.defaultInbox)
352                // Not checking default Inbox name, since is is identical to the URI check above.
353                && forceReplyFromDefault == that.forceReplyFromDefault
354                && maxAttachmentSize == that.maxAttachmentSize);
355    }
356
357    @Override
358    public int hashCode() {
359        if (mHashCode == 0) {
360            mHashCode = calculateHashCode();
361        }
362        return mHashCode;
363    }
364
365    /**
366     * Returns the hash code for this object.
367     * @return
368     */
369    private final int calculateHashCode() {
370        return super.hashCode()
371                ^ Objects.hashCode(signature, autoAdvance, messageTextSize, replyBehavior,
372                        hideCheckboxes, confirmDelete, confirmArchive, confirmSend,
373                        defaultInbox, forceReplyFromDefault, maxAttachmentSize);
374    }
375}
376