Replace copy_messages_to and move_messages_to with a single function that
[platform/upstream/evolution-data-server.git] / camel / camel-disco-folder.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-disco-folder.c: abstract class for a disconnectable folder */
3
4 /* 
5  * Authors: Dan Winship <danw@ximian.com>
6  *
7  * Copyright (C) 2001 Ximian, Inc.
8  *
9  * This program is free software; you can redistribute it and/or 
10  * modify it under the terms of version 2 of the GNU General Public 
11  * License as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21  * USA
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include "camel-disco-folder.h"
29 #include "camel-disco-store.h"
30 #include "camel-exception.h"
31
32 #define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
33 #define CDF_CLASS(o) (CAMEL_DISCO_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
34
35 static CamelFolderClass *parent_class = NULL;
36
37 static void disco_refresh_info (CamelFolder *folder, CamelException *ex);
38 static void disco_sync (CamelFolder *folder, gboolean expunge, CamelException *ex);
39 static void disco_expunge (CamelFolder *folder, CamelException *ex);
40
41 static void disco_append_message (CamelFolder *folder, CamelMimeMessage *message,
42                                   const CamelMessageInfo *info, CamelException *ex);
43 static void disco_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
44                                         CamelFolder *destination,
45                                         gboolean delete_originals,
46                                         CamelException *ex);
47
48 static void disco_cache_message       (CamelDiscoFolder *disco_folder,
49                                        const char *uid, CamelException *ex);
50 static void disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
51                                        const char *expression,
52                                        CamelException *ex);
53
54 static void
55 camel_disco_folder_class_init (CamelDiscoFolderClass *camel_disco_folder_class)
56 {
57         CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_disco_folder_class);
58
59         parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ()));
60
61         /* virtual method definition */
62         camel_disco_folder_class->cache_message = disco_cache_message;
63         camel_disco_folder_class->prepare_for_offline = disco_prepare_for_offline;
64
65         /* virtual method overload */
66         camel_folder_class->refresh_info = disco_refresh_info;
67         camel_folder_class->sync = disco_sync;
68         camel_folder_class->expunge = disco_expunge;
69
70         camel_folder_class->append_message = disco_append_message;
71         camel_folder_class->transfer_messages_to = disco_transfer_messages_to;
72 }
73
74 CamelType
75 camel_disco_folder_get_type (void)
76 {
77         static CamelType camel_disco_folder_type = CAMEL_INVALID_TYPE;
78
79         if (camel_disco_folder_type == CAMEL_INVALID_TYPE) {
80                 camel_disco_folder_type = camel_type_register (
81                         CAMEL_FOLDER_TYPE, "CamelDiscoFolder",
82                         sizeof (CamelDiscoFolder),
83                         sizeof (CamelDiscoFolderClass),
84                         (CamelObjectClassInitFunc) camel_disco_folder_class_init,
85                         NULL, NULL, NULL);
86         }
87
88         return camel_disco_folder_type;
89 }
90
91
92 static void
93 disco_refresh_info (CamelFolder *folder, CamelException *ex)
94 {
95         if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) != CAMEL_DISCO_STORE_ONLINE)
96                 return;
97         CDF_CLASS (folder)->refresh_info_online (folder, ex);
98 }
99
100 static void
101 disco_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
102 {
103         if (expunge) {
104                 disco_expunge (folder, ex);
105                 if (camel_exception_is_set (ex))
106                         return;
107         }
108
109         switch (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store))) {
110         case CAMEL_DISCO_STORE_ONLINE:
111                 CDF_CLASS (folder)->sync_online (folder, ex);
112                 break;
113
114         case CAMEL_DISCO_STORE_OFFLINE:
115                 CDF_CLASS (folder)->sync_offline (folder, ex);
116                 break;
117
118         case CAMEL_DISCO_STORE_RESYNCING:
119                 CDF_CLASS (folder)->sync_resyncing (folder, ex);
120                 break;
121         }
122 }
123
124 static void
125 disco_expunge_uids (CamelFolder *folder, GPtrArray *uids, CamelException *ex)
126 {
127         CamelDiscoStore *disco = CAMEL_DISCO_STORE (folder->parent_store);
128
129         if (uids->len == 0)
130                 return;
131
132         switch (camel_disco_store_status (disco)) {
133         case CAMEL_DISCO_STORE_ONLINE:
134                 CDF_CLASS (folder)->expunge_uids_online (folder, uids, ex);
135                 break;
136
137         case CAMEL_DISCO_STORE_OFFLINE:
138                 CDF_CLASS (folder)->expunge_uids_offline (folder, uids, ex);
139                 break;
140
141         case CAMEL_DISCO_STORE_RESYNCING:
142                 CDF_CLASS (folder)->expunge_uids_resyncing (folder, uids, ex);
143                 break;
144         }
145 }
146
147 static void
148 disco_expunge (CamelFolder *folder, CamelException *ex)
149 {
150         GPtrArray *uids;
151         int i, count;
152         CamelMessageInfo *info;
153
154         uids = g_ptr_array_new ();
155         count = camel_folder_summary_count (folder->summary);
156         for (i = 0; i < count; i++) {
157                 info = camel_folder_summary_index (folder->summary, i);
158                 if (info->flags & CAMEL_MESSAGE_DELETED)
159                         g_ptr_array_add (uids, g_strdup (camel_message_info_uid (info)));
160                 camel_folder_summary_info_free (folder->summary, info);
161         }
162
163         disco_expunge_uids (folder, uids, ex);
164
165         for (i = 0; i < uids->len; i++)
166                 g_free (uids->pdata[i]);
167         g_ptr_array_free (uids, TRUE);
168 }
169
170 static void
171 disco_append_message (CamelFolder *folder, CamelMimeMessage *message,
172                       const CamelMessageInfo *info, CamelException *ex)
173 {
174         CamelDiscoStore *disco = CAMEL_DISCO_STORE (folder->parent_store);
175
176         switch (camel_disco_store_status (disco)) {
177         case CAMEL_DISCO_STORE_ONLINE:
178                 CDF_CLASS (folder)->append_online (folder, message, info, ex);
179                 break;
180
181         case CAMEL_DISCO_STORE_OFFLINE:
182                 CDF_CLASS (folder)->append_offline (folder, message, info, ex);
183                 break;
184
185         case CAMEL_DISCO_STORE_RESYNCING:
186                 CDF_CLASS (folder)->append_resyncing (folder, message, info, ex);
187                 break;
188         }
189 }
190
191 static void
192 disco_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
193                             CamelFolder *destination,
194                             gboolean delete_originals, CamelException *ex)
195 {
196         CamelDiscoStore *disco = CAMEL_DISCO_STORE (source->parent_store);
197
198         switch (camel_disco_store_status (disco)) {
199         case CAMEL_DISCO_STORE_ONLINE:
200                 CDF_CLASS (source)->transfer_online (source, uids, destination,
201                                                      delete_originals, ex);
202                 break;
203
204         case CAMEL_DISCO_STORE_OFFLINE:
205                 CDF_CLASS (source)->transfer_offline (source, uids, destination,
206                                                       delete_originals, ex);
207                 break;
208
209         case CAMEL_DISCO_STORE_RESYNCING:
210                 CDF_CLASS (source)->transfer_resyncing (source, uids, destination,
211                                                         delete_originals, ex);
212                 break;
213         }
214 }
215
216
217 /**
218  * camel_disco_folder_expunge_uids:
219  * @folder: a (disconnectable) folder
220  * @uids: array of UIDs to expunge
221  * @ex: a CamelException
222  *
223  * This expunges the messages in @uids from @folder. It should take
224  * whatever steps are needed to avoid expunging any other messages,
225  * although in some cases it may not be possible to avoid expunging
226  * messages that are marked deleted by another client at the same time
227  * as the expunge_uids call is running.
228  **/
229 void
230 camel_disco_folder_expunge_uids (CamelFolder *folder, GPtrArray *uids,
231                                  CamelException *ex)
232 {
233         disco_expunge_uids (folder, uids, ex);
234 }
235
236
237 static void
238 disco_cache_message (CamelDiscoFolder *disco_folder, const char *uid,
239                      CamelException *ex)
240 {
241         g_warning ("CamelDiscoFolder::cache_message not implemented for `%s'",
242                    camel_type_to_name (CAMEL_OBJECT_GET_TYPE (disco_folder)));
243 }
244
245 /**
246  * camel_disco_folder_cache_message:
247  * @disco_folder: the folder
248  * @uid: the UID of the message to cache
249  * @ex: a CamelException
250  *
251  * Requests that @disco_folder cache message @uid to disk.
252  **/
253 void
254 camel_disco_folder_cache_message (CamelDiscoFolder *disco_folder,
255                                   const char *uid, CamelException *ex)
256 {
257         CDF_CLASS (disco_folder)->cache_message (disco_folder, uid, ex);
258 }
259
260
261 static void
262 disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
263                            const char *expression,
264                            CamelException *ex)
265 {
266         CamelFolder *folder = CAMEL_FOLDER (disco_folder);
267         GPtrArray *uids;
268         int i;
269
270         if (expression)
271                 uids = camel_folder_search_by_expression (folder, expression, ex);
272         else
273                 uids = camel_folder_get_uids (folder);
274         if (!uids)
275                 return;
276         for (i = 0; i < uids->len; i++) {
277                 camel_disco_folder_cache_message (disco_folder, uids->pdata[i], ex);
278                 if (camel_exception_is_set (ex))
279                         break;
280         }
281         if (expression)
282                 camel_folder_search_free (folder, uids);
283         else
284                 camel_folder_free_uids (folder, uids);
285 }
286
287 /**
288  * camel_disco_folder_prepare_for_offline:
289  * @disco_folder: the folder
290  * @expression: an expression describing messages to synchronize, or %NULL
291  * if all messages should be sync'ed.
292  * @ex: a CamelException
293  *
294  * This prepares @disco_folder for offline operation, by downloading
295  * the bodies of all messages described by @expression (using the
296  * same syntax as camel_folder_search_by_expression() ).
297  **/
298 void 
299 camel_disco_folder_prepare_for_offline (CamelDiscoFolder *disco_folder,
300                                         const char *expression,
301                                         CamelException *ex)
302 {
303         g_return_if_fail (CAMEL_IS_DISCO_FOLDER (disco_folder));
304
305         CDF_CLASS (disco_folder)->prepare_for_offline (disco_folder, expression, ex);
306 }