MockUiProvider.java revision 33fe908589dca6a7f58aa9f56d73f74a48ac42f6
1/**
2 * Copyright (c) 2011, 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.protos.mock;
18
19import com.android.mail.providers.AccountCacheProvider;
20import com.android.mail.providers.UIProvider.AccountCapabilities;
21import com.android.mail.providers.UIProvider.AccountColumns;
22import com.android.mail.providers.UIProvider.AttachmentColumns;
23import com.android.mail.providers.UIProvider.ConversationColumns;
24import com.android.mail.providers.UIProvider.FolderCapabilities;
25import com.android.mail.providers.UIProvider.FolderColumns;
26import com.android.mail.providers.UIProvider.MessageColumns;
27
28import android.content.ContentProvider;
29import android.content.ContentValues;
30import android.database.Cursor;
31import android.database.MatrixCursor;
32import android.net.Uri;
33import android.provider.BaseColumns;
34import android.text.Html;
35
36import com.google.common.annotations.VisibleForTesting;
37import com.google.common.collect.Lists;
38import com.google.common.collect.Maps;
39import com.google.common.collect.ImmutableList;
40import com.google.common.collect.ImmutableMap;
41
42import java.lang.Long;
43import java.lang.Object;
44import java.lang.Override;
45import java.lang.String;
46import java.util.Date;
47import java.util.List;
48import java.util.Map;
49import java.util.Set;
50
51public final class MockUiProvider extends ContentProvider {
52
53    public static final String AUTHORITY = "com.android.mail.mockprovider";
54
55
56    static final String BASE_URI_STRING = "content://" + AUTHORITY;
57
58    public static final int NUM_MOCK_ACCOUNTS = 2;
59
60    // A map of query result for uris
61    // TODO(pwestbro) read this map from an external
62    private static final Map<String, List<Map<String, Object>>> MOCK_QUERY_RESULTS;
63
64    static {
65        ImmutableMap.Builder<String, List<Map<String, Object>>> builder = ImmutableMap.builder();
66
67        // Add results for account list
68        final List<Map<String, Object>> accountList = Lists.newArrayList();
69        Map<String, Object> accountDetailsMap1;
70
71        // Account 1
72        accountDetailsMap1 = createAccountDetailsMap(0);
73
74        accountList.add(accountDetailsMap1);
75        String accountUri1 = (String)accountDetailsMap1.get(AccountColumns.URI);
76        builder.put(accountUri1, ImmutableList.of(accountDetailsMap1));
77
78        // Account 2
79        Map<String, Object> accountDetailsMap2 = createAccountDetailsMap(1);
80        accountList.add(accountDetailsMap2);
81
82        String accountUri2 = (String) accountDetailsMap2.get(AccountColumns.URI);
83        builder.put(accountUri2, ImmutableList.of(accountDetailsMap2));
84
85        // Add the account list to the builder
86        builder.put(getAccountsUri().toString(), accountList);
87
88        Map<String, Object> folderDetailsMap0 = createFolderDetailsMap(0, "zero", true, 0, 2);
89        builder.put(folderDetailsMap0.get(FolderColumns.URI).toString(),
90                ImmutableList.of(folderDetailsMap0));
91        builder.put(
92                folderDetailsMap0.get(FolderColumns.CHILD_FOLDERS_LIST_URI).toString(),
93                ImmutableList.of(createFolderDetailsMap(10, "zeroChild0", 0, 0),
94                        createFolderDetailsMap(11, "zeroChild1", 0, 0)));
95
96        Map<String, Object> conv0 = createConversationDetailsMap("zeroConv0".hashCode(),
97                "zeroConv0", 1);
98        builder.put(conv0.get(ConversationColumns.URI).toString(),
99                ImmutableList.of(conv0));
100        Map<String, Object> conv1 = createConversationDetailsMap("zeroConv1".hashCode(),
101                "zeroConv1", 1);
102        builder.put(conv1.get(ConversationColumns.URI).toString(),
103                ImmutableList.of(conv1));
104        builder.put(folderDetailsMap0.get(FolderColumns.CONVERSATION_LIST_URI).toString(),
105                ImmutableList.of(conv0, conv1));
106
107        Map<String, Object> message0 = createMessageDetailsMap("zeroConv0".hashCode(), "zeroConv0",
108                1);
109        builder.put(message0.get(MessageColumns.URI).toString(), ImmutableList.of(message0));
110        builder.put(conv0.get(ConversationColumns.MESSAGE_LIST_URI).toString(),
111                ImmutableList.of(message0));
112        builder.put(message0.get(MessageColumns.ATTACHMENT_LIST_URI).toString(),
113                ImmutableList.of(createAttachmentDetailsMap(0, "zero")));
114        Map<String, Object> message1 = createMessageDetailsMap("zeroConv1".hashCode(), "zeroConv1",
115                1);
116        builder.put(message1.get(MessageColumns.URI).toString(), ImmutableList.of(message1));
117        Map<String, Object> message1a = createMessageDetailsMap("zeroConv1a".hashCode(), "zeroConv1a",
118                2);
119        builder.put(message1a.get(MessageColumns.URI).toString(), ImmutableList.of(message1a));
120        builder.put(conv1.get(ConversationColumns.MESSAGE_LIST_URI).toString(),
121                ImmutableList.of(message1, message1a));
122        builder.put(message1.get(MessageColumns.ATTACHMENT_LIST_URI).toString(),
123                ImmutableList.of(createAttachmentDetailsMap(1, "one")));
124
125        Map<String, Object> folderDetailsMap1 = createFolderDetailsMap(1, "one", 0, 0);
126        builder.put(folderDetailsMap1.get(FolderColumns.URI).toString(),
127                ImmutableList.of(folderDetailsMap1));
128        builder.put(accountDetailsMap1.get(AccountColumns.FOLDER_LIST_URI).toString(),
129                ImmutableList.of(folderDetailsMap0, folderDetailsMap1));
130
131        Map<String, Object> folderDetailsMap2 = createFolderDetailsMap(2, "two", 2, 2);
132        builder.put(folderDetailsMap2.get(FolderColumns.URI).toString(),
133                ImmutableList.of(folderDetailsMap2));
134        Map<String, Object> folderDetailsMap3 = createFolderDetailsMap(3, "three", 0, 0);
135        builder.put(folderDetailsMap3.get(FolderColumns.URI).toString(),
136                ImmutableList.of(folderDetailsMap3));
137        builder.put(accountDetailsMap2.get(AccountColumns.FOLDER_LIST_URI).toString(),
138                ImmutableList.of(folderDetailsMap2, folderDetailsMap3));
139
140        Map<String, Object> conv2 = createConversationDetailsMap("zeroConv2".hashCode(),
141                "zeroConv2", 0);
142        builder.put(conv2.get(ConversationColumns.URI).toString(),
143                ImmutableList.of(conv2));
144        Map<String, Object> conv3 = createConversationDetailsMap("zeroConv3".hashCode(),
145                "zeroConv3", 0);
146        builder.put(conv3.get(ConversationColumns.URI).toString(),
147                ImmutableList.of(conv3));
148        builder.put(folderDetailsMap2.get(FolderColumns.CONVERSATION_LIST_URI).toString(),
149                ImmutableList.of(conv2, conv3));
150
151        Map<String, Object> message2 = createMessageDetailsMap("zeroConv2".hashCode(), "zeroConv2",
152                0);
153        builder.put(message2.get(MessageColumns.URI).toString(), ImmutableList.of(message2));
154        builder.put(conv2.get(ConversationColumns.MESSAGE_LIST_URI).toString(),
155                ImmutableList.of(message2));
156        Map<String, Object> message3 = createMessageDetailsMap("zeroConv3".hashCode(), "zeroConv3",
157                0);
158        builder.put(message3.get(MessageColumns.URI).toString(), ImmutableList.of(message3));
159        builder.put(conv3.get(ConversationColumns.MESSAGE_LIST_URI).toString(),
160                ImmutableList.of(message3));
161
162        MOCK_QUERY_RESULTS = builder.build();
163    }
164
165    private static Map<String, Object> createConversationDetailsMap(int conversationId,
166            String subject, int hasAttachments) {
167        final String conversationUri = "content://" + AUTHORITY + "/conversation/" + conversationId;
168        Map<String, Object> conversationMap = Maps.newHashMap();
169        conversationMap.put(BaseColumns._ID, Long.valueOf(conversationId));
170        conversationMap.put(ConversationColumns.URI, conversationUri);
171        conversationMap.put(ConversationColumns.MESSAGE_LIST_URI, conversationUri + "/getMessages");
172        conversationMap.put(ConversationColumns.SUBJECT, "Conversation " + subject);
173        conversationMap.put(ConversationColumns.SNIPPET, "snippet");
174        conversationMap.put(ConversationColumns.SENDER_INFO, "Conversation " + subject);
175        conversationMap.put(ConversationColumns.DATE_RECEIVED_MS, new Date().getTime());
176        conversationMap.put(ConversationColumns.HAS_ATTACHMENTS, hasAttachments);
177        return conversationMap;
178    }
179
180    private static Map<String, Object> createMessageDetailsMap(int messageId, String subject,
181            int hasAttachments) {
182        final String messageUri = "content://" + AUTHORITY + "/message/" + messageId;
183        Map<String, Object> messageMap = Maps.newHashMap();
184        messageMap.put(BaseColumns._ID, Long.valueOf(messageId));
185        messageMap.put(MessageColumns.URI, messageUri);
186        messageMap.put(MessageColumns.SUBJECT, "Message " + subject);
187        messageMap.put(MessageColumns.SNIPPET, "SNIPPET");
188        String html = "<html><body><b><i>This is some html!!!</i></b></body></html>";
189        messageMap.put(MessageColumns.BODY_HTML, html);
190        messageMap.put(MessageColumns.BODY_TEXT, Html.fromHtml(html));
191        messageMap.put(MessageColumns.HAS_ATTACHMENTS, hasAttachments);
192        messageMap.put(MessageColumns.ATTACHMENT_LIST_URI, messageUri + "/getAttachments");
193        messageMap.put(MessageColumns.TO, "account1@mock.com, account2@mock.com");
194        messageMap.put(MessageColumns.FROM, "fromaccount1@mock.com");
195        return messageMap;
196    }
197
198    private static Map<String, Object> createAttachmentDetailsMap(int attachmentId, String name) {
199        Map<String, Object> attachmentMap = Maps.newHashMap();
200        attachmentMap.put(BaseColumns._ID, Long.valueOf(attachmentId));
201        attachmentMap.put(AttachmentColumns.NAME, "Attachment " + name);
202        return attachmentMap;
203    }
204
205    private static Map<String, Object> createFolderDetailsMap(int folderId, String name,
206            int unread, int total) {
207        return createFolderDetailsMap(folderId, name, false, unread, total);
208    }
209
210    private static Map<String, Object> createFolderDetailsMap(int folderId, String name,
211            boolean hasChildren, int unread, int total) {
212        final String folderUri = "content://" + AUTHORITY + "/folder/" + folderId;
213        Map<String, Object> folderMap = Maps.newHashMap();
214        folderMap.put(BaseColumns._ID, Long.valueOf(folderId));
215        folderMap.put(FolderColumns.URI, folderUri);
216        folderMap.put(FolderColumns.NAME, "Folder " + name);
217        folderMap.put(FolderColumns.HAS_CHILDREN, new Integer(hasChildren ? 1 : 0));
218        folderMap.put(FolderColumns.CONVERSATION_LIST_URI, folderUri + "/getConversations");
219        folderMap.put(FolderColumns.CHILD_FOLDERS_LIST_URI, folderUri + "/getChildFolders");
220        folderMap.put(FolderColumns.CAPABILITIES,
221                Long.valueOf(
222                        FolderCapabilities.SYNCABLE |
223                        FolderCapabilities.PARENT |
224                        FolderCapabilities.CAN_HOLD_MAIL |
225                        FolderCapabilities.CAN_ACCEPT_MOVED_MESSAGES));
226        folderMap.put(FolderColumns.UNREAD_COUNT, unread);
227        folderMap.put(FolderColumns.TOTAL_COUNT, total);
228        return folderMap;
229    }
230
231    // Temporarily made this public to allow the Gmail accounts to use the mock ui provider uris
232    public static Map<String, Object> createAccountDetailsMap(int accountId) {
233        final String accountUri = getMockAccountUri(accountId);
234        Map<String, Object> accountMap = Maps.newHashMap();
235        accountMap.put(BaseColumns._ID, Long.valueOf(accountId));
236        accountMap.put(AccountColumns.NAME, "account" + accountId + "@mockuiprovider.com");
237        accountMap.put(AccountColumns.PROVIDER_VERSION, Long.valueOf(1));
238        accountMap.put(AccountColumns.URI, accountUri);
239        accountMap.put(AccountColumns.CAPABILITIES,
240                Long.valueOf(
241                        AccountCapabilities.SYNCABLE_FOLDERS |
242                        AccountCapabilities.REPORT_SPAM |
243                        AccountCapabilities.ARCHIVE |
244                        AccountCapabilities.MUTE |
245                        AccountCapabilities.SERVER_SEARCH |
246                        AccountCapabilities.FOLDER_SERVER_SEARCH |
247                        AccountCapabilities.SANITIZED_HTML |
248                        AccountCapabilities.DRAFT_SYNCHRONIZATION |
249                        AccountCapabilities.MULTIPLE_FROM_ADDRESSES |
250                        AccountCapabilities.SMART_REPLY |
251                        AccountCapabilities.LOCAL_SEARCH |
252                        AccountCapabilities.THREADED_CONVERSATIONS));
253        accountMap.put(AccountColumns.FOLDER_LIST_URI, accountUri + "/folders");
254        accountMap.put(AccountColumns.SEARCH_URI, accountUri + "/search");
255        accountMap.put(AccountColumns.ACCOUNT_FROM_ADDRESSES_URI, accountUri + "/fromAddresses");
256        accountMap.put(AccountColumns.SAVE_DRAFT_URI, accountUri + "/saveDraft");
257        accountMap.put(AccountColumns.SEND_MESSAGE_URI, accountUri + "/sendMessage");
258
259        addAccountInfoToAccountCache(accountMap);
260        return accountMap;
261    }
262
263    public static String getMockAccountUri(int accountId) {
264        return "content://" + AUTHORITY + "/account/" + accountId;
265    }
266
267    @Override
268    public boolean onCreate() {
269        return true;
270    }
271
272    @Override
273    public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
274            String sortOrder) {
275
276        // TODO (pwestbro): respect the projection that is specified by the caller
277
278        final List<Map<String, Object>> queryResults =
279                MOCK_QUERY_RESULTS.get(url.toString());
280
281        if (queryResults != null && queryResults.size() > 0) {
282            // Get the projection.  If there are rows in the result set, pick the first item to
283            // generate the projection
284            // TODO (pwestbro): handle the case where we want to return an empty result.\
285            if (projection == null) {
286                Set<String> keys = queryResults.get(0).keySet();
287                projection = keys.toArray(new String[keys.size()]);
288            }
289            MatrixCursor matrixCursor = new MatrixCursor(projection, queryResults.size());
290
291            for (Map<String, Object> queryResult : queryResults) {
292                MatrixCursor.RowBuilder rowBuilder = matrixCursor.newRow();
293
294                for (String key : projection) {
295                    rowBuilder.add(queryResult.get(key));
296                }
297            }
298            return matrixCursor;
299        }
300
301        return null;
302    }
303
304    @Override
305    public Uri insert(Uri url, ContentValues values) {
306        return url;
307    }
308
309    @Override
310    public int update(Uri url, ContentValues values, String selection,
311            String[] selectionArgs) {
312        return 0;
313    }
314
315    @Override
316    public int delete(Uri url, String selection, String[] selectionArgs) {
317        return 0;
318    }
319
320    @Override
321    public String getType(Uri uri) {
322        return null;
323    }
324
325    @VisibleForTesting
326    static Uri getAccountsUri() {
327        // TODO: this should probably return a different specific to the mock account list
328        return Uri.parse(BASE_URI_STRING + "/");
329    }
330
331    private static void addAccountInfoToAccountCache(Map<String, Object> accountInfo) {
332        final AccountCacheProvider.CachedAccount account =
333                new AccountCacheProvider.CachedAccount((Long)accountInfo.get(BaseColumns._ID),
334                        (String)accountInfo.get(AccountColumns.NAME),
335                        (String)accountInfo.get(AccountColumns.URI),
336                        (Long)accountInfo.get(AccountColumns.CAPABILITIES),
337                        (String)accountInfo.get(AccountColumns.FOLDER_LIST_URI),
338                        (String)accountInfo.get(AccountColumns.SEARCH_URI),
339                        (String)accountInfo.get(AccountColumns.ACCOUNT_FROM_ADDRESSES_URI),
340                        (String)accountInfo.get(AccountColumns.SAVE_DRAFT_URI),
341                        (String)accountInfo.get(AccountColumns.SEND_MESSAGE_URI));
342
343
344        AccountCacheProvider.addAccount(account);
345    }
346}
347
348