1/*
2 * Copyright (C) 2008 The Android Open Source Project
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.email.mail;
18
19
20public abstract class Folder {
21    public enum OpenMode {
22        READ_WRITE, READ_ONLY,
23    }
24
25    public enum FolderType {
26        HOLDS_FOLDERS, HOLDS_MESSAGES,
27    }
28
29    /**
30     * Identifiers of "special" folders.
31     */
32    public enum FolderRole {
33        INBOX,      // NOTE:  The folder's name must be INBOX
34        TRASH,
35        SENT,
36        DRAFTS,
37
38        OUTBOX,     // Local folders only - not used in remote Stores
39        OTHER,      // this folder has no specific role
40        UNKNOWN     // the role of this folder is unknown
41    }
42
43    /**
44     * Callback for each message retrieval.
45     *
46     * Not all {@link Folder} implementation won't call it.
47     * (Currently {@link com.android.email.mail.store.LocalStore.LocalFolder} won't.)
48     */
49    public interface MessageRetrievalListener {
50        public void messageRetrieved(Message message);
51    }
52
53    /**
54     * Forces an open of the MailProvider. If the provider is already open this
55     * function returns without doing anything.
56     *
57     * @param mode READ_ONLY or READ_WRITE
58     * @param callbacks Pointer to callbacks class.  This may be used by the folder between this
59     * time and when close() is called.  This is only used for remote stores - should be null
60     * for LocalStore.LocalFolder.
61     */
62    public abstract void open(OpenMode mode, PersistentDataCallbacks callbacks)
63            throws MessagingException;
64
65    /**
66     * Forces a close of the MailProvider. Any further access will attempt to
67     * reopen the MailProvider.
68     *
69     * @param expunge If true all deleted messages will be expunged.
70     */
71    public abstract void close(boolean expunge) throws MessagingException;
72
73    /**
74     * @return True if further commands are not expected to have to open the
75     *         connection.
76     */
77    // TODO not used, get rid of this - it's a transport function
78    public abstract boolean isOpen();
79
80    /**
81     * Get the mode the folder was opened with. This may be different than the mode the open
82     * was requested with.
83     * @return
84     */
85    public abstract OpenMode getMode() throws MessagingException;
86
87    /**
88     * Reports if the Store is able to create folders of the given type.
89     * Does not actually attempt to create a folder.
90     * @param type
91     * @return true if can create, false if cannot create
92     */
93    public abstract boolean canCreate(FolderType type);
94
95    /**
96     * Attempt to create the given folder remotely using the given type.
97     * @param type
98     * @return true if created, false if cannot create (e.g. server side)
99     */
100    public abstract boolean create(FolderType type) throws MessagingException;
101
102    public abstract boolean exists() throws MessagingException;
103
104    /**
105     * @return A count of the messages in the selected folder.
106     */
107    public abstract int getMessageCount() throws MessagingException;
108
109    public abstract int getUnreadMessageCount() throws MessagingException;
110
111    public abstract Message getMessage(String uid) throws MessagingException;
112
113    public abstract Message[] getMessages(int start, int end, MessageRetrievalListener listener)
114            throws MessagingException;
115
116    /**
117     * Fetches the given list of messages. The specified listener is notified as
118     * each fetch completes. Messages are downloaded as (as) lightweight (as
119     * possible) objects to be filled in with later requests. In most cases this
120     * means that only the UID is downloaded.
121     *
122     * @param uids
123     * @param listener
124     */
125    public abstract Message[] getMessages(MessageRetrievalListener listener)
126            throws MessagingException;
127
128    public abstract Message[] getMessages(String[] uids, MessageRetrievalListener listener)
129            throws MessagingException;
130
131    /**
132     * Return a set of messages based on the state of the flags.
133     * Note: Not typically implemented in remote stores, so not abstract.
134     *
135     * @param setFlags The flags that should be set for a message to be selected (can be null)
136     * @param clearFlags The flags that should be clear for a message to be selected (can be null)
137     * @param listener
138     * @return A list of messages matching the desired flag states.
139     * @throws MessagingException
140     */
141    public Message[] getMessages(Flag[] setFlags, Flag[] clearFlags,
142            MessageRetrievalListener listener) throws MessagingException {
143        throw new MessagingException("Not implemented");
144    }
145
146    public abstract void appendMessages(Message[] messages) throws MessagingException;
147
148    public abstract void copyMessages(Message[] msgs, Folder folder,
149            MessageUpdateCallbacks callbacks) throws MessagingException;
150
151    public abstract void setFlags(Message[] messages, Flag[] flags, boolean value)
152            throws MessagingException;
153
154    public abstract Message[] expunge() throws MessagingException;
155
156    public abstract void fetch(Message[] messages, FetchProfile fp,
157            MessageRetrievalListener listener) throws MessagingException;
158
159    public abstract void delete(boolean recurse) throws MessagingException;
160
161    public abstract String getName();
162
163    public abstract Flag[] getPermanentFlags() throws MessagingException;
164
165    /**
166     * This method returns a string identifying the name of a "role" folder
167     * (such as inbox, draft, sent, or trash).  Stores that do not implement this
168     * feature can be used - the account UI will provide default strings.  To
169     * let the server identify specific folder roles, simply override this method.
170     *
171     * @return The server- or protocol- specific role for this folder.  If some roles are known
172     * but this is not one of them, return FolderRole.OTHER.  If roles are unsupported here,
173     * return FolderRole.UNKNOWN.
174     */
175    public FolderRole getRole() {
176        return FolderRole.UNKNOWN;
177    }
178
179    /**
180     * This function will be called after the messaging controller has called
181     * getPersonalNamespaces() and has created a matching LocalFolder object.  This can
182     * be used as a trigger for the folder to write back any folder-specific persistent data using
183     * callbacks.
184     *
185     * This is not abstract because most folders do not require this functionality and do not
186     * need to implement it.
187     */
188    @SuppressWarnings("unused")
189    public void localFolderSetupComplete(Folder localFolder) throws MessagingException {
190        // Do nothing - return immediately
191    }
192
193    /**
194     * Create an empty message of the appropriate type for the Folder.
195     */
196    public abstract Message createMessage(String uid) throws MessagingException;
197
198    /**
199     * Callback interface by which a Folder can read and write persistent data.
200     * TODO This needs to be made more generic & flexible
201     */
202    public interface PersistentDataCallbacks {
203
204        /**
205         * Provides keyed storage of strings.  Should be used for per-folder data.  Do not use for
206         * per-message data.
207         * @param key identifier for the data (e.g. "sync.key" or "folder.id")
208         * @param value Data to persist.  All data must be encoded into a string,
209         * so use base64 or some other encoding if necessary.
210         */
211        public void setPersistentString(String key, String value);
212
213        /**
214         * @param key identifier for the data of interest
215         * @return the data saved by the Folder, or defaultValue if never set.
216         */
217        public String getPersistentString(String key, String defaultValue);
218
219        /**
220         * In a single transaction:  Set a key/value pair for the folder, and bulk set or clear
221         * message flags.  Typically used at the beginning or conclusion of a bulk sync operation.
222         *
223         * @param key if non-null, the transaction will set this folder persistent value
224         * @param value the value that will be stored for the key
225         * @param setFlags if non-null, flag(s) will be set for all messages in the folder
226         * @param clearFlags if non-null, flag(s) will be cleared for all messages in the folder
227         */
228        public void setPersistentStringAndMessageFlags(String key, String value,
229                Flag[] setFlags, Flag[] clearFlags) throws MessagingException;
230    }
231
232    /**
233     * Callback interface by which a folder can report UID changes caused by certain operations.
234     */
235    public interface MessageUpdateCallbacks {
236        /**
237         * The operation caused the message's UID to change
238         * @param message The message for which the UID changed
239         * @param newUid The new UID for the message
240         */
241        public void onMessageUidChange(Message message, String newUid) throws MessagingException;
242
243        /**
244         * The operation could not be completed because the message doesn't exist
245         * (for example, it was already deleted from the server side.)
246         * @param message The message that does not exist
247         * @throws MessagingException
248         */
249        public void onMessageNotFound(Message message) throws MessagingException;
250    }
251
252    @Override
253    public String toString() {
254        return getName();
255    }
256}
257