fe58d700cdba14933235b89ae94251f582978b73
[platform/upstream/syncevolution.git] / src / syncevo / TrackingSyncSource.h
1 /*
2  * Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
3  * Copyright (C) 2009 Intel Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) version 3.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301  USA
19  */
20
21 #ifndef INCL_TRACKINGSYNCSOURCE
22 #define INCL_TRACKINGSYNCSOURCE
23
24 #include <syncevo/SyncSource.h>
25 #include <syncevo/ConfigNode.h>
26
27 #include <boost/shared_ptr.hpp>
28 #include <string>
29 #include <map>
30
31 #include <syncevo/declarations.h>
32 SE_BEGIN_CXX
33 using namespace std;
34
35 /**
36  * This class implements change tracking. Data sources which want to use
37  * this functionality have to provide the following functionality
38  * by implementing the pure virtual functions below:
39  * - open() the data
40  * - enumerate all existing items
41  * - provide LUID and "revision string": 
42  *   The LUID must remain *constant* when the user edits an item (it
43  *   may change when SyncEvolution changes an item), whereas the
44  *   revision string must *change* each time the item is changed
45  *   by anyone.
46  *   Both can be arbitrary strings, but keeping them simple (printable
47  *   ASCII, no white spaces, no equal sign) makes debugging simpler
48  *   because they can be stored as they are as key/value pairs in the
49  *   sync source's change tracking config node (the .other.ini files when
50  *   using file-based configuration). More complex strings use escape
51  *   sequences introduced with an exclamation mark for unsafe characters.
52  * - import/export/update single items
53  * - persistently store all changes in flush()
54  * - clean up in close()
55  *
56  * A derived class may (but doesn't have to) override additional
57  * functions to modify or replace the default implementations, e.g.:
58  * - dumping the complete database (export())
59  *
60  * Potential implementations of the revision string are:
61  * - a modification time stamp
62  * - a hash value of a textual representation of the item
63  *   (beware, such a hash might change as the textual representation
64  *    changes even though the item is unchanged)
65  */
66 class TrackingSyncSource : public TestingSyncSource,
67     virtual public SyncSourceRevisions,
68     virtual public SyncSourceAdmin
69 {
70   public:
71     /**
72      * Creates a new tracking sync source.
73      *
74      * @param granularity    sync sources whose revision string
75      *                       is based on time should specify the number
76      *                       of seconds which has to pass before changes
77      *                       are detected reliably (see SyncSourceRevisions
78      *                       for details), otherwise pass 0
79      */
80     TrackingSyncSource(const SyncSourceParams &params,
81                        int granularitySeconds = 1);
82     ~TrackingSyncSource() {}
83
84     /**
85      * ConfigNode used for change tracking in SyncSourceRevisions.
86      * Derived classes might need that when implementing operations
87      * which have side effects on other items (for example,
88      * EvolutionCalendarSource::removeItem()).
89      */
90     ConfigNode &getTrackingNode() { return *m_trackingNode; }
91
92     /**
93      * returns a list of all know sources for the kind of items
94      * supported by this sync source
95      */
96     virtual Databases getDatabases() = 0;
97
98     /**
99      * Actually opens the data source specified in the constructor,
100      * will throw the normal exceptions if that fails. Should
101      * not modify the state of the sync source.
102      *
103      * The expectation is that this call is fairly light-weight, but
104      * does enough checking to determine whether the source is
105      * usable. More expensive operations (like determining changes)
106      * should be done in the beginSync() callback.
107      *
108      * In clients, it will be called for all sources before
109      * the sync starts. In servers, it is called for each source once
110      * the client asks for it, but not sooner.
111      */
112     virtual void open() = 0;
113
114     /**
115      * A quick check whether the source currently has data. Currently
116      * used as part of the "allow slow sync" checking after open() and
117      * before beginSync(). Returning false is acceptable when it is
118      * uncertain and too expensive to check.
119      */
120     virtual bool isEmpty() = 0;
121
122     /**
123      * fills the complete mapping from LUID to revision string of all
124      * currently existing items
125      *
126      * Usually both LUID and revision string must be non-empty. The
127      * only exception is a refresh-from-client: in that case the
128      * revision string may be empty. The implementor of this call
129      * cannot know whether empty strings are allowed, therefore it
130      * should not throw errors when it cannot create a non-empty
131      * string. The caller of this method will detect situations where
132      * a non-empty string is necessary and none was provided.
133      */
134     virtual void listAllItems(SyncSourceRevisions::RevisionMap_t &revisions) = 0;
135
136     /**
137      * Create or modify an item.
138      *
139      * The sync source should be flexible: if the LUID is non-empty, it
140      * shall modify the item referenced by the LUID. If the LUID is
141      * empty, the normal operation is to add it. But if the item
142      * already exists (e.g., a calendar event which was imported
143      * by the user manually), then the existing item should be
144      * updated also in the second case.
145      *
146      * Passing a LUID of an item which does not exist is an error.
147      * This error should be reported instead of covering it up by
148      * (re)creating the item.
149      *
150      * Errors are signaled by throwing an exception. Returning empty
151      * strings in the result is an error which triggers an "item could
152      * not be stored" error.
153      *
154      * @param luid     identifies the item to be modified, empty for creating
155      * @param item     contains the new content of the item
156      * @param raw      item has internal format instead of engine format;
157      *                 testing and backup/restore might use such an internal format
158      *                 which may be different (more complete!) than the
159      *                 format when talking to the sync engine
160      * @return the result of inserting the item
161      */
162     virtual InsertItemResult insertItem(const std::string &luid, const std::string &item, bool raw) = 0;
163
164     /**
165      * Return item data in engine format.
166      *
167      * @param luid     identifies the item
168      * @param raw      return item in internal format instead of engine format
169      * @retval item    item data
170      */
171     virtual void readItem(const std::string &luid, std::string &item, bool raw) = 0;
172
173     /**
174      * delete the item (renamed so that it can be wrapped by deleteItem())
175      */
176     virtual void removeItem(const string &luid) = 0;
177
178     /**
179      * optional: write all changes, throw error if that fails
180      *
181      * This is called while the sync is still active whereas
182      * close() is called afterwards. Reporting problems
183      * as early as possible may be useful at some point,
184      * but currently doesn't make a relevant difference.
185      */
186     virtual void flush() {}
187     
188     /**
189      * closes the data source so that it can be reopened
190      *
191      * Just as open() it should not affect the state of
192      * the database unless some previous action requires
193      * it.
194      */
195     virtual void close() = 0;
196
197     /**
198      * Returns the preferred mime type of the items handled by the sync source.
199      * Example: "text/x-vcard"
200      */
201     virtual const char *getMimeType() const = 0;
202
203     /**
204      * Returns the version of the mime type used by client.
205      * Example: "2.1"
206      */
207     virtual const char *getMimeVersion() const = 0;
208
209     using SyncSource::getName;
210
211   private:
212     void checkStatus(SyncSourceReport &changes);
213
214     /* implementations of SyncSource callbacks */
215     virtual void beginSync(const std::string &lastToken, const std::string &resumeToken);
216     virtual std::string endSync(bool success);
217     virtual void deleteItem(const string &luid);
218     virtual InsertItemResult insertItem(const std::string &luid, const std::string &item);
219     virtual void readItem(const std::string &luid, std::string &item);
220     virtual InsertItemResult insertItemRaw(const std::string &luid, const std::string &item);
221     virtual void readItemRaw(const std::string &luid, std::string &item);
222     virtual void enableServerMode();
223     virtual bool serverModeEnabled() const;
224     virtual const char *getPeerMimeType() const;
225
226     boost::shared_ptr<ConfigNode> m_trackingNode;
227 };
228
229
230 SE_END_CXX
231 #endif // INCL_TRACKINGSYNCSOURCE