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.emailcommon.mail;
18
19import android.content.Context;
20
21import com.android.emailcommon.service.SearchParams;
22import com.google.common.annotations.VisibleForTesting;
23
24
25public abstract class Folder {
26    public enum OpenMode {
27        READ_WRITE, READ_ONLY,
28    }
29
30    public enum FolderType {
31        HOLDS_FOLDERS, HOLDS_MESSAGES,
32    }
33
34    /**
35     * Identifiers of "special" folders.
36     */
37    public enum FolderRole {
38        INBOX,      // NOTE:  The folder's name must be INBOX
39        TRASH,
40        SENT,
41        DRAFTS,
42
43        OUTBOX,     // Local folders only - not used in remote Stores
44        OTHER,      // this folder has no specific role
45        UNKNOWN     // the role of this folder is unknown
46    }
47
48    /**
49     * Callback for each message retrieval.
50     *
51     * Not all {@link Folder} implementations may invoke it.
52     */
53    public interface MessageRetrievalListener {
54        public void messageRetrieved(Message message);
55        public void loadAttachmentProgress(int progress);
56    }
57
58    /**
59     * Forces an open of the MailProvider. If the provider is already open this
60     * function returns without doing anything.
61     *
62     * @param mode READ_ONLY or READ_WRITE
63     * @param callbacks Pointer to callbacks class.  This may be used by the folder between this
64     * time and when close() is called.  This is only used for remote stores - should be null
65     * for LocalStore.LocalFolder.
66     */
67    public abstract void open(OpenMode mode)
68            throws MessagingException;
69
70    /**
71     * Forces a close of the MailProvider. Any further access will attempt to
72     * reopen the MailProvider.
73     *
74     * @param expunge If true all deleted messages will be expunged.
75     */
76    public abstract void close(boolean expunge);
77
78    /**
79     * @return True if further commands are not expected to have to open the
80     *         connection.
81     */
82    @VisibleForTesting
83    public abstract boolean isOpen();
84
85    /**
86     * Returns the mode the folder was opened with. This may be different than the mode the open
87     * was requested with.
88     */
89    public abstract OpenMode getMode() throws MessagingException;
90
91    /**
92     * Reports if the Store is able to create folders of the given type.
93     * Does not actually attempt to create a folder.
94     * @param type
95     * @return true if can create, false if cannot create
96     */
97    public abstract boolean canCreate(FolderType type);
98
99    /**
100     * Attempt to create the given folder remotely using the given type.
101     * @return true if created, false if cannot create (e.g. server side)
102     */
103    public abstract boolean create(FolderType type) throws MessagingException;
104
105    public abstract boolean exists() throws MessagingException;
106
107    /**
108     * Returns the number of messages in the selected folder.
109     */
110    public abstract int getMessageCount() throws MessagingException;
111
112    public abstract int getUnreadMessageCount() throws MessagingException;
113
114    public abstract Message getMessage(String uid) 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    public abstract Message[] getMessages(int start, int end, MessageRetrievalListener listener)
123            throws MessagingException;
124
125    public abstract Message[] getMessages(long startDate, long endDate, MessageRetrievalListener listener)
126            throws MessagingException;
127
128    public abstract Message[] getMessages(SearchParams params,MessageRetrievalListener listener)
129            throws MessagingException;
130
131    public abstract Message[] getMessages(String[] uids, MessageRetrievalListener listener)
132            throws MessagingException;
133
134    /**
135     * Return a set of messages based on the state of the flags.
136     * Note: Not typically implemented in remote stores, so not abstract.
137     *
138     * @param setFlags The flags that should be set for a message to be selected (can be null)
139     * @param clearFlags The flags that should be clear for a message to be selected (can be null)
140     * @param listener
141     * @return A list of messages matching the desired flag states.
142     * @throws MessagingException
143     */
144    public Message[] getMessages(Flag[] setFlags, Flag[] clearFlags,
145            MessageRetrievalListener listener) throws MessagingException {
146        throw new MessagingException("Not implemented");
147    }
148
149    public abstract void appendMessage(Context context, Message message, final boolean noTimeout)
150            throws MessagingException;
151
152    /**
153     * Copies the given messages to the destination folder.
154     */
155    public abstract void copyMessages(Message[] msgs, Folder folder,
156            MessageUpdateCallbacks callbacks) throws MessagingException;
157
158    public abstract void setFlags(Message[] messages, Flag[] flags, boolean value)
159            throws MessagingException;
160
161    public abstract Message[] expunge() throws MessagingException;
162
163    public abstract void fetch(Message[] messages, FetchProfile fp,
164            MessageRetrievalListener listener) throws MessagingException;
165
166    public abstract void delete(boolean recurse) throws MessagingException;
167
168    public abstract String getName();
169
170    public abstract Flag[] getPermanentFlags() throws MessagingException;
171
172    /**
173     * This method returns a string identifying the name of a "role" folder
174     * (such as inbox, draft, sent, or trash).  Stores that do not implement this
175     * feature can be used - the account UI will provide default strings.  To
176     * let the server identify specific folder roles, simply override this method.
177     *
178     * @return The server- or protocol- specific role for this folder.  If some roles are known
179     * but this is not one of them, return FolderRole.OTHER.  If roles are unsupported here,
180     * return FolderRole.UNKNOWN.
181     */
182    public FolderRole getRole() {
183        return FolderRole.UNKNOWN;
184    }
185
186    /**
187     * Create an empty message of the appropriate type for the Folder.
188     */
189    public abstract Message createMessage(String uid) throws MessagingException;
190
191    /**
192     * Callback interface by which a folder can report UID changes caused by certain operations.
193     */
194    public interface MessageUpdateCallbacks {
195        /**
196         * The operation caused the message's UID to change
197         * @param message The message for which the UID changed
198         * @param newUid The new UID for the message
199         */
200        public void onMessageUidChange(Message message, String newUid) throws MessagingException;
201
202        /**
203         * The operation could not be completed because the message doesn't exist
204         * (for example, it was already deleted from the server side.)
205         * @param message The message that does not exist
206         * @throws MessagingException
207         */
208        public void onMessageNotFound(Message message) throws MessagingException;
209    }
210
211    @Override
212    public String toString() {
213        return getName();
214    }
215}
216