syncevolution/src/core/TrackingSyncSource.h

217 lines
7.6 KiB
C++

/*
* Copyright (C) 2008 Patrick Ohly
*/
#ifndef INCL_TRACKINGSYNCSOURCE
#define INCL_TRACKINGSYNCSOURCE
#include "EvolutionSyncSource.h"
#include "ConfigNode.h"
#include <boost/shared_ptr.hpp>
#include <string>
#include <map>
using namespace std;
/**
* This class implements change tracking. Data sources which want to use
* this functionality have to provide the following functionality
* by implementing the pure virtual functions below:
* - open() the data
* - enumerate all existing items
* - provide UID and "revision string":
* The UID must remain *constant* when the user edits an item (it
* may change when SyncEvolution changes an item), whereas the
* revision string must *change* each time the item is changed
* by anyone.
* Both can be arbitrary strings, but keeping them simple (printable
* ASCII, no white spaces, no equal sign) makes debugging simpler
* because they can be stored as they are as key/value pairs in the
* sync source's change tracking config node (the .other.ini files when
* using file-based configuration). More complex strings use escape
* sequences introduced with an exclamation mark for unsafe characters.
* - import/export/update single items
* - persistently store all changes in flush()
* - clean up in close()
*
* A derived class may (but doesn't have to) override additional
* functions to modify or replace the default implementations, e.g.:
* - dumping the complete database (export())
*
* Potential implementations of the revision string are:
* - a modification time stamp
* - a hash value of a textual representation of the item
* (beware, such a hash might change as the textual representation
* changes even though the item is unchanged)
*/
class TrackingSyncSource : public EvolutionSyncSource
{
public:
/**
* Creates a new tracking sync source.
*/
TrackingSyncSource(const EvolutionSyncSourceParams &params);
/**
* returns a list of all know sources for the kind of items
* supported by this sync source
*/
virtual Databases getDatabases() = 0;
/**
* Actually opens the data source specified in the constructor,
* will throw the normal exceptions if that fails. Should
* not modify the state of the sync source: that can be deferred
* until the server is also ready and beginSync() is called.
*/
virtual void open() = 0;
/**
* exports all items one after the other, separated by blank line;
* if that format is not suitable, then the derived class must
* override this call
*/
virtual void exportData(ostream &out);
typedef map<string, string> RevisionMap_t;
/**
* fills the complete mapping from UID to revision string of all
* currently existing items
*
* Usually both UID and revision string must be non-empty. The
* only exception is a refresh-from-client: in that case the
* revision string may be empty. The implementor of this call
* cannot know whether empty strings are allowed, therefore it
* should not throw errors when it cannot create a non-empty
* string. The caller of this method will detect situations where
* a non-empty string is necessary and none was provided.
*/
virtual void listAllItems(RevisionMap_t &revisions) = 0;
class InsertItemResult {
public:
/**
* @param uid the uid after the operation; during an update the uid must
* not be changed, so return the original one here
* @param revision the revision string after the operation
* @param merged set this to true if an existing item was updated instead of adding it
*/
InsertItemResult(const string &uid,
const string &revision,
bool merged) :
m_uid(uid),
m_revision(revision),
m_merged(merged)
{}
const string m_uid;
const string m_revision;
const bool m_merged;
};
/**
* Create or modify an item.
*
* The sync source should be flexible: if the UID is non-empty, it
* shall modify the item referenced by the UID. If the UID is
* empty, the normal operation is to add it. But if the item
* already exists (e.g., a calendar event which was imported
* by the user manually), then the existing item should be
* updated also in the second case.
*
* Passing a UID of an item which does not exist is an error.
* This error should be reported instead of covering it up by
* (re)creating the item.
*
* Errors are signalled by throwing an exception. Returning empty
* strings in the result is an error which triggers an "item could
* not be stored" error.
*
* @param uid identifies the item to be modified, empty for creating
* @param item contains the new content of the item and its MIME type
* @return the result of inserting the item
*/
virtual InsertItemResult insertItem(const string &uid, const SyncItem &item) = 0;
/**
* Extract information for the item identified by UID
* and store it in a new SyncItem. The caller must
* free that item. May throw exceptions.
*
* @param uid identifies the item
*/
virtual SyncItem *createItem(const string &uid) = 0;
/**
* removes and item
*/
virtual void deleteItem(const string &uid) = 0;
/**
* optional: write all changes, throw error if that fails
*
* This is called while the sync is still active whereas
* close() is called afterwards. Reporting problems
* as early as possible may be useful at some point,
* but currently doesn't make a relevant difference.
*/
virtual void flush() {}
/**
* closes the data source so that it can be reopened
*
* Just as open() it should not affect the state of
* the database unless some previous action requires
* it.
*/
virtual void close() = 0;
/**
* file suffix for database files
*/
virtual string fileSuffix() const = 0;
/**
* Returns the preferred mime type of the items handled by the sync source.
* Example: "text/x-vcard"
*/
virtual const char *getMimeType() const = 0;
/**
* Returns the version of the mime type used by client.
* Example: "2.1"
*/
virtual const char *getMimeVersion() const = 0;
/**
* A string representing the source types (with versions) supported by the SyncSource.
* The string must be formatted as a sequence of "type:version" separated by commas ','.
* For example: "text/x-vcard:2.1,text/vcard:3.0".
* The version can be left empty, for example: "text/x-s4j-sifc:".
* Supported types will be sent as part of the DevInf.
*/
virtual const char* getSupportedTypes() const = 0;
protected:
/** log a one-line info about an item */
virtual void logItem(const string &uid, const string &info, bool debug = false) = 0;
virtual void logItem(const SyncItem &item, const string &info, bool debug = false) = 0;
virtual void setItemStatusThrow(const char *key, int status);
private:
/* implementations of EvolutionSyncSource callbacks */
virtual void beginSyncThrow(bool needAll,
bool needPartial,
bool deleteLocal);
virtual void endSyncThrow();
virtual int addItemThrow(SyncItem& item);
virtual int updateItemThrow(SyncItem& item);
virtual int deleteItemThrow(SyncItem& item);
boost::shared_ptr<ConfigNode> m_trackingNode;
};
#endif // INCL_TRACKINGSYNCSOURCE