Start of UI provider

This is the start of the contract for a UI provider, and also includes a
mock content provider implementing it.

Included is a unit test that just traverses the content provider

Change-Id: I4424e140830244f02eac204d71152dfc196c9741
diff --git a/src/com/android/email/providers/MockUiProvider.java b/src/com/android/email/providers/MockUiProvider.java
new file mode 100644
index 0000000..ae5a3fa
--- /dev/null
+++ b/src/com/android/email/providers/MockUiProvider.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright (c) 2011, Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.email.providers;
+
+import com.android.email.providers.UIProvider.AccountCapabilities;
+import com.android.email.providers.UIProvider.AccountColumns;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import java.lang.Long;
+import java.lang.Object;
+import java.lang.Override;
+import java.lang.String;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public final class MockUiProvider extends ContentProvider {
+
+    public static final String AUTHORITY = "com.android.mail.mockprovider";
+
+
+    static final String BASE_URI_STRING = "content://" + AUTHORITY;
+
+    // A map of query result for uris
+    // TODO(pwestbro) read this map from an external
+    private static final Map<String, List<Map<String, Object>>> MOCK_QUERY_RESULTS;
+
+    static {
+        ImmutableMap.Builder<String, List<Map<String, Object>>> builder = ImmutableMap.builder();
+
+        // Add results for account list
+        final List<Map<String, Object>> accountList = Lists.newArrayList();
+        Map<String, Object> accountDetailsMap;
+
+        // Account 1
+        accountDetailsMap = createAccountDetailsMap(0);
+
+        accountList.add(accountDetailsMap);
+        String accountUri = (String)accountDetailsMap.get(AccountColumns.URI);
+        builder.put(accountUri, ImmutableList.of(accountDetailsMap));
+
+        // Account 2
+        accountDetailsMap = createAccountDetailsMap(1);
+        accountList.add(accountDetailsMap);
+
+        accountUri = (String)accountDetailsMap.get(AccountColumns.URI);
+        builder.put(accountUri, ImmutableList.of(accountDetailsMap));
+
+        // Add the account list to the builder
+        builder.put(getAccountsUri().toString(), accountList);
+
+        MOCK_QUERY_RESULTS = builder.build();
+    }
+
+    private static Map<String, Object> createAccountDetailsMap(int accountId) {
+        final String accountUri =  "content://" + AUTHORITY + "/account/" + accountId;
+        Map<String, Object> accountMap = Maps.newHashMap();
+        accountMap.put(BaseColumns._ID, Long.valueOf(accountId));
+        accountMap.put(AccountColumns.NAME, "Account " + accountId);
+        accountMap.put(AccountColumns.PROVIDER_VERSION, Long.valueOf(1));
+        accountMap.put(AccountColumns.URI, accountUri);
+        accountMap.put(AccountColumns.CAPABILITIES,
+                Long.valueOf(
+                        AccountCapabilities.SYNCABLE_FOLDERS |
+                        AccountCapabilities.REPORT_SPAM |
+                        AccountCapabilities.ARCHIVE |
+                        AccountCapabilities.MUTE |
+                        AccountCapabilities.SERVER_SEARCH |
+                        AccountCapabilities.FOLDER_SERVER_SEARCH |
+                        AccountCapabilities.SANITIZED_HTML |
+                        AccountCapabilities.DRAFT_SYNCHRONIZATION |
+                        AccountCapabilities.MULTIPLE_FROM_ADDRESSES |
+                        AccountCapabilities.SMART_REPLY |
+                        AccountCapabilities.LOCAL_SEARCH |
+                        AccountCapabilities.THREADED_CONVERSATIONS));
+        accountMap.put(AccountColumns.FOLDER_LIST_URI, accountUri + "/folders");
+        accountMap.put(AccountColumns.SEARCH_URI, accountUri + "/search");
+        accountMap.put(AccountColumns.ACCOUNT_FROM_ADDRESSES_URI, accountUri + "/fromAddresses");
+        accountMap.put(AccountColumns.SAVE_NEW_DRAFT_URI, accountUri + "/saveDraft");
+        accountMap.put(AccountColumns.SEND_MESSAGE_URI, accountUri + "/sendMessage");
+        return accountMap;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+
+        // TODO (pwestbro): respect the projection that is specified by the caller
+
+        final List<Map<String, Object>> queryResults =
+                MOCK_QUERY_RESULTS.get(url.toString());
+
+        if (queryResults != null && queryResults.size() > 0) {
+            // Get the projection.  If there are rows in the result set, pick the first item to
+            // generate the projection
+            // TODO (pwestbro): handle the case where we want to return an empty result.\
+
+            final Set<String> keys = queryResults.get(0).keySet();
+
+            final String[] resultSetProjection = keys.toArray(new String[keys.size()]);
+            MatrixCursor matrixCursor = new MatrixCursor(resultSetProjection, queryResults.size());
+
+            for (Map<String, Object> queryResult : queryResults) {
+                MatrixCursor.RowBuilder rowBuilder = matrixCursor.newRow();
+
+                for (String key : keys) {
+                    rowBuilder.add(queryResult.get(key));
+                }
+            }
+            return matrixCursor;
+        }
+
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri url, ContentValues values) {
+        return url;
+    }
+
+    @Override
+    public int update(Uri url, ContentValues values, String selection,
+            String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int delete(Uri url, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    public static Uri getAccountsUri() {
+        // TODO: this should probably return a different specific to the mock account list
+        return Uri.parse(BASE_URI_STRING + "/");
+    }
+}
+
diff --git a/src/com/android/email/providers/UIProvider.java b/src/com/android/email/providers/UIProvider.java
index c68f9d2..40b90cd 100644
--- a/src/com/android/email/providers/UIProvider.java
+++ b/src/com/android/email/providers/UIProvider.java
@@ -19,18 +19,17 @@
 import android.net.Uri;
 import android.provider.BaseColumns;
 
+import java.lang.String;
+
 
 public class UIProvider {
-    // This authority is only needed to get to the account list
-    // NOTE: Overlay applications may want to override this authority
-    public static final String AUTHORITY = "com.android.email.providers";
-
-    static final String BASE_URI_STRING = "content://" + AUTHORITY;
+    // The actual content provider should define its own authority
+    //public static final String AUTHORITY = "com.android.email.providers";
 
     public static final String ACCOUNT_LIST_TYPE =
-            "vnd.android.cursor.dir/vnd.com.android.email.account";
+            "vnd.android.cursor.dir/vnd.com.android.mail.account";
     public static final String ACCOUNT_TYPE =
-            "vnd.android.cursor.item/vnd.com.android.email.account";
+            "vnd.android.cursor.item/vnd.com.android.mail.account";
 
     public static final String[] ACCOUNTS_PROJECTION = {
             BaseColumns._ID,
@@ -41,32 +40,79 @@
             AccountColumns.FOLDER_LIST_URI,
             AccountColumns.SEARCH_URI,
             AccountColumns.ACCOUNT_FROM_ADDRESSES_URI,
+            AccountColumns.SAVE_NEW_DRAFT_URI,
+            AccountColumns.SEND_MESSAGE_URI,
     };
 
     public static final class AccountCapabilities {
-        public static final int SUPPORTS_SYNCABLE_FOLDERS = 0x0001;
-        public static final int SUPPORTS_REPORT_SPAM = 0x0002;
-        public static final int SUPPORTS_ARCHIVE = 0x0004;
-        public static final int SUPPORTS_SERVER_SEARCH = 0x0008;
-        public static final int SUPPORTS_FOLDER_SERVER_SEARCH = 0x00018;
-        public static final int RETURNS_SANITIZED_HTML = 0x0020;
-        public static final int SUPPORTS_DRAFT_SYNCHRONIZATION = 0x0040;
-        public static final int SUPPORTS_MULTIPLE_FROM_ADDRESSES = 0x0080;
-        public static final int SUPPORTS_SMART_REPLY = 0x0100;
-        public static final int SUPPORTS_LOCAL_SEARCH = 0x0200;
-        public static final int SUPPORTS_THREADED_CONVERSATIONS = 0x0400;
+        public static final int SYNCABLE_FOLDERS = 0x0001;
+        public static final int REPORT_SPAM = 0x0002;
+        public static final int ARCHIVE = 0x0004;
+        public static final int MUTE = 0x0008;
+        public static final int SERVER_SEARCH = 0x0010;
+        public static final int FOLDER_SERVER_SEARCH = 0x0020;
+        public static final int SANITIZED_HTML = 0x0040;
+        public static final int DRAFT_SYNCHRONIZATION = 0x0080;
+        public static final int MULTIPLE_FROM_ADDRESSES = 0x0100;
+        public static final int SMART_REPLY = 0x0200;
+        public static final int LOCAL_SEARCH = 0x0400;
+        public static final int THREADED_CONVERSATIONS = 0x0800;
     }
 
     public static final class AccountColumns {
+        /**
+         * This string column contains the human visible name for the account.
+         */
         public static final String NAME = "name";
+
+        /**
+         * This integer column returns the version of the UI provider schema from which this
+         * account provider will return results.
+         */
         public static final String PROVIDER_VERSION = "providerVersion";
+
+        /**
+         * This string column contains the uri to directly access the information for this account.
+         */
         public static final String URI = "uri";
+
+        /**
+         * This integer column contains a bit field of the possible cabibilities that this account
+         * supports.
+         */
         public static final String CAPABILITIES = "capabilities";
+
+        /**
+         * This string column contains the content provider uri to return the list of folders for
+         * this account.
+         */
         public static final String FOLDER_LIST_URI = "folderListUri";
+
+        /**
+         * This string column contains the content provider uri that can be queried for search
+         * results.
+         */
         public static final String SEARCH_URI = "searchUri";
+
+        /**
+         * This string column contains the content provider uri that can be queried to access the
+         * from addresses for this account.
+         */
         public static final String ACCOUNT_FROM_ADDRESSES_URI = "accountFromAddressesUri";
+
+        /**
+         * This string column contains the content provider uri that can be used to save (insert)
+         * new draft messages for this account.
+         */
         public static final String SAVE_NEW_DRAFT_URI = "saveNewDraftUri";
 
+        /**
+         * This string column contains the content provider uri that can be used to send
+         * a message for this account.
+         * NOTE: This might be better to be an update operation on the messageUri.
+         */
+        public static final String SEND_MESSAGE_URI = "sendMessageUri";
+
         private AccountColumns() {};
     }
 
@@ -75,8 +121,18 @@
      * list of configured accounts.
      * @return
      */
-    public static Uri getAccountsUri() {
-        return Uri.parse(BASE_URI_STRING + "/");
+    // TODO: create a static registry for the starting point for the UI provider.
+//    public static Uri getAccountsUri() {
+//        return Uri.parse(BASE_URI_STRING + "/");
+//    }
+
+    public static final class DraftType {
+        public static final String COMPOSE = "compose";
+        public static final String REPLY = "reply";
+        public static final String REPLY_ALL = "replyAll";
+        public static final String FORWARD = "forward";
+
+        private DraftType() {}
     }
 
 
@@ -84,21 +140,20 @@
         public static final String ID = "_id";
         public static final String URI = "uri";
         public static final String MESSAGE_ID = "messageId";
-        public static final String CONVERSATION_ID = "conversation";
+        public static final String CONVERSATION_ID = "conversationId";
         public static final String SUBJECT = "subject";
         public static final String SNIPPET = "snippet";
         public static final String FROM = "fromAddress";
         public static final String TO = "toAddresses";
         public static final String CC = "ccAddresses";
         public static final String BCC = "bccAddresses";
-        public static final String REPLY_TO = "replyToAddresses";
-        public static final String DATE_SENT_MS = "dateSentMs";
+        public static final String REPLY_TO = "replyToAddress";
         public static final String DATE_RECEIVED_MS = "dateReceivedMs";
-        public static final String LIST_INFO = "listInfo";
-        public static final String BODY = "body";
+        public static final String BODY_HTML = "bodyHtml";
+        public static final String BODY_TEXT = "bodyText";
         public static final String EMBEDS_EXTERNAL_RESOURCES = "bodyEmbedsExternalResources";
         public static final String REF_MESSAGE_ID = "refMessageId";
-        public static final String FORWARD = "forward";
+        public static final String DRAFT_TYPE = "draftType";
         public static final String INCLUDE_QUOTED_TEXT = "includeQuotedText";
         public static final String QUOTE_START_POS = "quoteStartPos";
         public static final String CLIENT_CREATED = "clientCreated";
@@ -108,4 +163,4 @@
 
         private MessageColumns() {}
     }
-}
\ No newline at end of file
+}