00001 /* 00002 * Copyright (C) 2008 Patrick Ohly 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 */ 00018 00019 #ifndef INCL_TRACKINGSYNCSOURCE 00020 #define INCL_TRACKINGSYNCSOURCE 00021 00022 #include "EvolutionSyncSource.h" 00023 #include "ConfigNode.h" 00024 00025 #include <boost/shared_ptr.hpp> 00026 #include <string> 00027 #include <map> 00028 using namespace std; 00029 00030 /** 00031 * This class implements change tracking. Data sources which want to use 00032 * this functionality have to provide the following functionality 00033 * by implementing the pure virtual functions below: 00034 * - open() the data 00035 * - enumerate all existing items 00036 * - provide UID and "revision string": 00037 * The UID must remain *constant* when the user edits an item (it 00038 * may change when SyncEvolution changes an item), whereas the 00039 * revision string must *change* each time the item is changed 00040 * by anyone. 00041 * Both can be arbitrary strings, but keeping them simple (printable 00042 * ASCII, no white spaces, no equal sign) makes debugging simpler 00043 * because they can be stored as they are as key/value pairs in the 00044 * sync source's change tracking config node (the .other.ini files when 00045 * using file-based configuration). More complex strings use escape 00046 * sequences introduced with an exclamation mark for unsafe characters. 00047 * - import/export/update single items 00048 * - persistently store all changes in flush() 00049 * - clean up in close() 00050 * 00051 * A derived class may (but doesn't have to) override additional 00052 * functions to modify or replace the default implementations, e.g.: 00053 * - dumping the complete database (export()) 00054 * 00055 * Potential implementations of the revision string are: 00056 * - a modification time stamp 00057 * - a hash value of a textual representation of the item 00058 * (beware, such a hash might change as the textual representation 00059 * changes even though the item is unchanged) 00060 */ 00061 class TrackingSyncSource : public EvolutionSyncSource 00062 { 00063 public: 00064 /** 00065 * Creates a new tracking sync source. 00066 */ 00067 TrackingSyncSource(const EvolutionSyncSourceParams ¶ms); 00068 00069 /** 00070 * returns a list of all know sources for the kind of items 00071 * supported by this sync source 00072 */ 00073 virtual Databases getDatabases() = 0; 00074 00075 /** 00076 * Actually opens the data source specified in the constructor, 00077 * will throw the normal exceptions if that fails. Should 00078 * not modify the state of the sync source: that can be deferred 00079 * until the server is also ready and beginSync() is called. 00080 */ 00081 virtual void open() = 0; 00082 00083 /** 00084 * exports all items one after the other, separated by blank line; 00085 * if that format is not suitable, then the derived class must 00086 * override this call 00087 */ 00088 virtual void exportData(ostream &out); 00089 00090 typedef map<string, string> RevisionMap_t; 00091 00092 /** 00093 * fills the complete mapping from UID to revision string of all 00094 * currently existing items 00095 * 00096 * Usually both UID and revision string must be non-empty. The 00097 * only exception is a refresh-from-client: in that case the 00098 * revision string may be empty. The implementor of this call 00099 * cannot know whether empty strings are allowed, therefore it 00100 * should not throw errors when it cannot create a non-empty 00101 * string. The caller of this method will detect situations where 00102 * a non-empty string is necessary and none was provided. 00103 */ 00104 virtual void listAllItems(RevisionMap_t &revisions) = 0; 00105 00106 class InsertItemResult { 00107 public: 00108 /** 00109 * @param uid the uid after the operation; during an update the uid must 00110 * not be changed, so return the original one here 00111 * @param revision the revision string after the operation 00112 * @param merged set this to true if an existing item was updated instead of adding it 00113 */ 00114 InsertItemResult(const string &uid, 00115 const string &revision, 00116 bool merged) : 00117 m_uid(uid), 00118 m_revision(revision), 00119 m_merged(merged) 00120 {} 00121 00122 const string m_uid; 00123 const string m_revision; 00124 const bool m_merged; 00125 }; 00126 00127 /** 00128 * Create or modify an item. 00129 * 00130 * The sync source should be flexible: if the UID is non-empty, it 00131 * shall modify the item referenced by the UID. If the UID is 00132 * empty, the normal operation is to add it. But if the item 00133 * already exists (e.g., a calendar event which was imported 00134 * by the user manually), then the existing item should be 00135 * updated also in the second case. 00136 * 00137 * Passing a UID of an item which does not exist is an error. 00138 * This error should be reported instead of covering it up by 00139 * (re)creating the item. 00140 * 00141 * Errors are signalled by throwing an exception. Returning empty 00142 * strings in the result is an error which triggers an "item could 00143 * not be stored" error. 00144 * 00145 * @param uid identifies the item to be modified, empty for creating 00146 * @param item contains the new content of the item and its MIME type 00147 * @return the result of inserting the item 00148 */ 00149 virtual InsertItemResult insertItem(const string &uid, const SyncItem &item) = 0; 00150 00151 /** 00152 * Extract information for the item identified by UID 00153 * and store it in a new SyncItem. The caller must 00154 * free that item. May throw exceptions. 00155 * 00156 * @param uid identifies the item 00157 */ 00158 virtual SyncItem *createItem(const string &uid) = 0; 00159 00160 /** 00161 * removes and item 00162 */ 00163 virtual void deleteItem(const string &uid) = 0; 00164 00165 /** 00166 * optional: write all changes, throw error if that fails 00167 * 00168 * This is called while the sync is still active whereas 00169 * close() is called afterwards. Reporting problems 00170 * as early as possible may be useful at some point, 00171 * but currently doesn't make a relevant difference. 00172 */ 00173 virtual void flush() {} 00174 00175 /** 00176 * closes the data source so that it can be reopened 00177 * 00178 * Just as open() it should not affect the state of 00179 * the database unless some previous action requires 00180 * it. 00181 */ 00182 virtual void close() = 0; 00183 00184 /** 00185 * file suffix for database files 00186 */ 00187 virtual string fileSuffix() const = 0; 00188 00189 /** 00190 * Returns the preferred mime type of the items handled by the sync source. 00191 * Example: "text/x-vcard" 00192 */ 00193 virtual const char *getMimeType() const = 0; 00194 00195 /** 00196 * Returns the version of the mime type used by client. 00197 * Example: "2.1" 00198 */ 00199 virtual const char *getMimeVersion() const = 0; 00200 00201 /** 00202 * A string representing the source types (with versions) supported by the SyncSource. 00203 * The string must be formatted as a sequence of "type:version" separated by commas ','. 00204 * For example: "text/x-vcard:2.1,text/vcard:3.0". 00205 * The version can be left empty, for example: "text/x-s4j-sifc:". 00206 * Supported types will be sent as part of the DevInf. 00207 */ 00208 virtual const char* getSupportedTypes() const = 0; 00209 00210 protected: 00211 /** log a one-line info about an item */ 00212 virtual void logItem(const string &uid, const string &info, bool debug = false) = 0; 00213 virtual void logItem(const SyncItem &item, const string &info, bool debug = false) = 0; 00214 00215 virtual void setItemStatusThrow(const char *key, int status); 00216 00217 private: 00218 /* implementations of EvolutionSyncSource callbacks */ 00219 virtual void beginSyncThrow(bool needAll, 00220 bool needPartial, 00221 bool deleteLocal); 00222 virtual void endSyncThrow(); 00223 virtual int addItemThrow(SyncItem& item); 00224 virtual int updateItemThrow(SyncItem& item); 00225 virtual int deleteItemThrow(SyncItem& item); 00226 00227 boost::shared_ptr<ConfigNode> m_trackingNode; 00228 }; 00229 00230 #endif // INCL_TRACKINGSYNCSOURCE