boost::function<std::string (const std::string &data, bool update, const std::string &uniqueUIDSuffix)> m_mangleItem;
/**
+ * Items have a UID which really has to be unique among all items
+ * in the database. True for iCalendar 2.0, false for vCard 3.0
+ * (there is a UID, but its uniqueness is not enforced).
+ */
+ bool m_uniqueID;
+
+ /**
* A very simple item that is inserted during basic tests. Ideally
* it only contains properties supported by all servers.
*/
};
/**
- * Implements the "call all slots, error if any failed" semantic of
- * the pre- and post-signals described below.
- */
-class OperationSlotInvoker {
- public:
- typedef sysync::TSyError result_type;
- template<typename InputIterator>
- result_type operator() (InputIterator first, InputIterator last) const
- {
- result_type res = sysync::LOCERR_OK;
- while (first != last) {
- try {
- *first;
- } catch (...) {
- SyncMLStatus status = Exception::handle();
- if (res == sysync::LOCERR_OK) {
- res = static_cast<result_type>(status);
- }
- }
- ++first;
- }
- return res;
- }
-};
-
-/**
* Helper class for looking up a pending operation by a Synthesis parameter.
* KeyH (add, replace) and item ID (delete) are supported.
*/
};
/**
+ * Interface expected by SyncSourceBase helper class.
+ * Needed to break a cyclic dependency.
+ */
+class SyncSourceName
+{
+ public:
+ /**
+ * the name of the sync source (for example, "addressbook"),
+ * unique in the context of its own configuration
+ **/
+ virtual std::string getName() const { return "uninitialized SyncSourceBase"; }
+
+ /**
+ * the name of the sync source as it should be displayed to users
+ * in debug messages; typically the same as getName(), but may
+ * also include a context ("@foobar/addressbook") to disambiguate
+ * the name when "addressbook" is used multiple times in a sync (as
+ * with local sync)
+ */
+ virtual std::string getDisplayName() const { return "uninitialized SyncSourceBase"; }
+};
+
+/**
+ * Implements the "call all slots, error if any failed" semantic of
+ * the pre- and post-signals described below.
+ */
+class OperationSlotInvoker {
+ SyncSourceName &m_source;
+
+ public:
+ OperationSlotInvoker(SyncSourceName &source) :
+ m_source(source)
+ {}
+
+ typedef sysync::TSyError result_type;
+ template<typename InputIterator>
+ result_type operator() (InputIterator first, InputIterator last) const
+ {
+ result_type res = sysync::LOCERR_OK;
+ while (first != last) {
+ try {
+ *first;
+ } catch (...) {
+ SyncMLStatus status = Exception::handle(m_source.getDisplayName());
+ if (res == sysync::LOCERR_OK) {
+ res = static_cast<result_type>(status);
+ }
+ }
+ ++first;
+ }
+ return res;
+ }
+};
+
+
+/**
* Helper class, needs to be specialized based on number of parameters
* and return type.
*/
* invokes signals and implementation of operation,
* combines all return codes into one
*/
- sysync::TSyError operator () (SyncSource &source) const throw ()
+ sysync::TSyError operator () () const throw ()
{
sysync::TSyError res;
OperationExecution exec;
- res = m_pre(source);
+ res = m_pre(dynamic_cast<SyncSource &>(m_source));
if (res != sysync::LOCERR_OK) {
exec = OPERATION_SKIPPED;
} else {
res = m_operation();
exec = OPERATION_FINISHED;
} catch (...) {
- res = Exception::handle(/* source */);
+ res = Exception::handle(m_source.getDisplayName());
exec = OPERATION_EXCEPTION;
}
} else {
exec = OPERATION_EMPTY;
}
}
- sysync::TSyError newres = m_post(source, exec, res);
+ sysync::TSyError newres = m_post(dynamic_cast<SyncSource &>(m_source), exec, res);
if (newres != sysync::LOCERR_OK) {
res = newres;
}
PreSignal &getPreSignal() const { return const_cast<PreSignal &>(m_pre); }
PostSignal &getPostSignal() const { return const_cast<PostSignal &>(m_post); }
+
+ OperationWrapperSwitch(SyncSourceName &source) :
+ m_source(source),
+ m_pre(OperationSlotInvoker(source)),
+ m_post(OperationSlotInvoker(source))
+ {
+ }
+
protected:
OperationType m_operation;
private:
+ SyncSourceName &m_source;
PreSignal m_pre;
PostSignal m_post;
};
arg1_type a1),
OperationSlotInvoker> PostSignal;
- sysync::TSyError operator () (SyncSource &source,
- arg1_type a1) const throw ()
+ sysync::TSyError operator () (arg1_type a1) const throw ()
{
sysync::TSyError res;
OperationExecution exec;
- res = m_pre(source, a1);
+ res = m_pre(dynamic_cast<SyncSource &>(m_source), a1);
if (res != sysync::LOCERR_OK) {
exec = OPERATION_SKIPPED;
} else {
res = m_operation(a1);
exec = OPERATION_FINISHED;
} catch (...) {
- res = Exception::handle(/* source */);
+ res = Exception::handle(m_source.getDisplayName());
exec = OPERATION_EXCEPTION;
}
} else {
exec = OPERATION_EMPTY;
}
}
- sysync::TSyError newres = m_post(source, exec, res, a1);
+ sysync::TSyError newres = m_post(dynamic_cast<SyncSource &>(m_source), exec, res, a1);
if (newres != sysync::LOCERR_OK) {
res = newres;
}
PreSignal &getPreSignal() const { return const_cast<PreSignal &>(m_pre); }
PostSignal &getPostSignal() const { return const_cast<PostSignal &>(m_post); }
+ OperationWrapperSwitch(SyncSourceName &source) :
+ m_source(source),
+ m_pre(OperationSlotInvoker(source)),
+ m_post(OperationSlotInvoker(source))
+ {
+ }
+
protected:
OperationType m_operation;
private:
+ SyncSourceName &m_source;
PreSignal m_pre;
PostSignal m_post;
};
typedef ContinueOperation<sysync::TSyError (arg1_type)> Continue;
typedef std::map<typename Converter::key_type, Continue> Pending;
- sysync::TSyError operator () (SyncSource &source,
- arg1_type a1) const throw ()
+ sysync::TSyError operator () (arg1_type a1) const throw ()
{
sysync::TSyError res;
OperationExecution exec;
typename Pending::iterator it = const_cast<Pending &>(m_pending).find(Converter::toKey(a1));
bool continuing = it != m_pending.end();
- res = continuing ? sysync::LOCERR_OK : m_pre(source, a1);
+ res = continuing ? sysync::LOCERR_OK : m_pre(dynamic_cast<SyncSource &>(m_source), a1);
if (res != sysync::LOCERR_OK) {
exec = OPERATION_SKIPPED;
} else {
}
exec = OPERATION_FINISHED;
} catch (...) {
- res = Exception::handle(/* source */);
+ res = Exception::handle(m_source.getDisplayName());
exec = OPERATION_EXCEPTION;
}
} else {
}
}
if (res != sysync::LOCERR_AGAIN) {
- sysync::TSyError newres = m_post(source, exec, res, a1);
+ sysync::TSyError newres = m_post(dynamic_cast<SyncSource &>(m_source), exec, res, a1);
if (newres != sysync::LOCERR_OK) {
res = newres;
}
PreSignal &getPreSignal() const { return const_cast<PreSignal &>(m_pre); }
PostSignal &getPostSignal() const { return const_cast<PostSignal &>(m_post); }
+ OperationWrapperSwitch(SyncSourceName &source) :
+ m_source(source),
+ m_pre(OperationSlotInvoker(source)),
+ m_post(OperationSlotInvoker(source))
+ {
+ }
+
protected:
OperationType m_operation;
private:
+ SyncSourceName &m_source;
PreSignal m_pre;
PostSignal m_post;
Pending m_pending;
arg1_type a1, arg2_type a2),
OperationSlotInvoker> PostSignal;
- sysync::TSyError operator () (SyncSource &source,
- arg1_type a1, arg2_type a2) const throw ()
+ sysync::TSyError operator () (arg1_type a1, arg2_type a2) const throw ()
{
sysync::TSyError res;
OperationExecution exec;
- res = m_pre(source, a1, a2);
+ res = m_pre(dynamic_cast<SyncSource &>(m_source), a1, a2);
if (res != sysync::LOCERR_OK) {
exec = OPERATION_SKIPPED;
} else {
res = m_operation(a1, a2);
exec = OPERATION_FINISHED;
} catch (...) {
- res = Exception::handle(/* source */);
+ res = Exception::handle(m_source.getDisplayName());
exec = OPERATION_EXCEPTION;
}
} else {
exec = OPERATION_EMPTY;
}
}
- sysync::TSyError newres = m_post(source, exec, res, a1, a2);
+ sysync::TSyError newres = m_post(dynamic_cast<SyncSource &>(m_source), exec, res, a1, a2);
if (newres != sysync::LOCERR_OK) {
res = newres;
}
PreSignal &getPreSignal() const { return const_cast<PreSignal &>(m_pre); }
PostSignal &getPostSignal() const { return const_cast<PostSignal &>(m_post); }
+ OperationWrapperSwitch(SyncSourceName &source) :
+ m_source(source),
+ m_pre(OperationSlotInvoker(source)),
+ m_post(OperationSlotInvoker(source))
+ {
+ }
+
protected:
OperationType m_operation;
private:
+ SyncSourceName &m_source;
PreSignal m_pre;
PostSignal m_post;
};
typedef ContinueOperation<sysync::TSyError (arg1_type, arg2_type)> Continue;
typedef std::map<typename Converter::key_type, Continue> Pending;
- sysync::TSyError operator () (SyncSource &source,
- arg1_type a1, arg2_type a2) const throw ()
+ sysync::TSyError operator () (arg1_type a1, arg2_type a2) const throw ()
{
sysync::TSyError res;
OperationExecution exec;
typename Pending::iterator it = const_cast<Pending &>(m_pending).find(Converter::toKey(a1));
bool continuing = it != m_pending.end();
- res = continuing ? sysync::LOCERR_OK : m_pre(source, a1, a2);
+ res = continuing ? sysync::LOCERR_OK : m_pre(dynamic_cast<SyncSource &>(m_source), a1, a2);
if (res != sysync::LOCERR_OK) {
exec = OPERATION_SKIPPED;
} else {
}
exec = OPERATION_FINISHED;
} catch (...) {
- res = Exception::handle(/* source */);
+ res = Exception::handle(m_source.getDisplayName());
exec = OPERATION_EXCEPTION;
}
} else {
}
}
if (res != sysync::LOCERR_AGAIN) {
- sysync::TSyError newres = m_post(source, exec, res, a1, a2);
+ sysync::TSyError newres = m_post(dynamic_cast<SyncSource &>(m_source), exec, res, a1, a2);
if (newres != sysync::LOCERR_OK) {
res = newres;
}
PreSignal &getPreSignal() const { return const_cast<PreSignal &>(m_pre); }
PostSignal &getPostSignal() const { return const_cast<PostSignal &>(m_post); }
+ OperationWrapperSwitch(SyncSourceName &source) :
+ m_source(source),
+ m_pre(OperationSlotInvoker(source)),
+ m_post(OperationSlotInvoker(source))
+ {
+ }
+
protected:
OperationType m_operation;
private:
+ SyncSourceName &m_source;
PreSignal m_pre;
PostSignal m_post;
Pending m_pending;
arg1_type a1, arg2_type a2, arg3_type a3),
OperationSlotInvoker> PostSignal;
- sysync::TSyError operator () (SyncSource &source,
- arg1_type a1, arg2_type a2, arg3_type a3) const throw ()
+ sysync::TSyError operator () (arg1_type a1, arg2_type a2, arg3_type a3) const throw ()
{
sysync::TSyError res;
OperationExecution exec;
- res = m_pre(source, a1, a2, a3);
+ res = m_pre(dynamic_cast<SyncSource &>(m_source), a1, a2, a3);
if (res != sysync::LOCERR_OK) {
exec = OPERATION_SKIPPED;
} else {
res = m_operation(a1, a2, a3);
exec = OPERATION_FINISHED;
} catch (...) {
- res = Exception::handle(/* source */);
+ res = Exception::handle(m_source.getDisplayName());
exec = OPERATION_EXCEPTION;
}
} else {
exec = OPERATION_EMPTY;
}
}
- sysync::TSyError newres = m_post(source, exec, res, a1, a2, a3);
+ sysync::TSyError newres = m_post(dynamic_cast<SyncSource &>(m_source), exec, res, a1, a2, a3);
if (newres != sysync::LOCERR_OK) {
res = newres;
}
PreSignal &getPreSignal() const { return const_cast<PreSignal &>(m_pre); }
PostSignal &getPostSignal() const { return const_cast<PostSignal &>(m_post); }
+ OperationWrapperSwitch(SyncSourceName &source) :
+ m_source(source),
+ m_pre(OperationSlotInvoker(source)),
+ m_post(OperationSlotInvoker(source))
+ {
+ }
+
protected:
OperationType m_operation;
private:
+ SyncSourceName &m_source;
PreSignal m_pre;
PostSignal m_post;
typedef ContinueOperation<sysync::TSyError (arg1_type, arg2_type, arg3_type)> Continue;
typedef std::map<typename Converter::key_type, Continue> Pending;
- sysync::TSyError operator () (SyncSource &source,
- arg1_type a1, arg2_type a2, arg3_type a3) const throw ()
+ sysync::TSyError operator () (arg1_type a1, arg2_type a2, arg3_type a3) const throw ()
{
sysync::TSyError res;
OperationExecution exec;
typename Pending::iterator it = const_cast<Pending &>(m_pending).find(Converter::toKey(a1));
bool continuing = it != m_pending.end();
- res = continuing ? sysync::LOCERR_OK : m_pre(source, a1, a2, a3);
+ res = continuing ? sysync::LOCERR_OK : m_pre(dynamic_cast<SyncSource &>(m_source), a1, a2, a3);
if (res != sysync::LOCERR_OK) {
exec = OPERATION_SKIPPED;
} else {
}
exec = OPERATION_FINISHED;
} catch (...) {
- res = Exception::handle(/* source */);
+ res = Exception::handle(m_source.getDisplayName());
exec = OPERATION_EXCEPTION;
}
} else {
}
}
if (res != sysync::LOCERR_AGAIN) {
- sysync::TSyError newres = m_post(source, exec, res, a1, a2, a3);
+ sysync::TSyError newres = m_post(dynamic_cast<SyncSource &>(m_source), exec, res, a1, a2, a3);
if (newres != sysync::LOCERR_OK) {
res = newres;
}
PreSignal &getPreSignal() const { return const_cast<PreSignal &>(m_pre); }
PostSignal &getPostSignal() const { return const_cast<PostSignal &>(m_post); }
+ OperationWrapperSwitch(SyncSourceName &source) :
+ m_source(source),
+ m_pre(OperationSlotInvoker(source)),
+ m_post(OperationSlotInvoker(source))
+ {
+ }
+
protected:
OperationType m_operation;
private:
+ SyncSourceName &m_source;
PreSignal m_pre;
PostSignal m_post;
Pending m_pending;
{
typedef OperationWrapperSwitch<F, boost::function<F>::arity, typename boost::function<F>::result_type> inherited;
public:
+ OperationWrapper(SyncSourceName &source): inherited(source) {}
+
/** operation implemented? */
operator bool () const { return inherited::m_operation; }
* this base via different intermediate classes, therefore the
* need to keep it abstract.
*/
-class SyncSourceBase {
+class SyncSourceBase : public SyncSourceName {
public:
virtual ~SyncSourceBase() {}
/**
- * the name of the sync source (for example, "addressbook"),
- * unique in the context of its own configuration
- **/
- virtual std::string getName() const { return "uninitialized SyncSourceBase"; }
-
- /**
- * the name of the sync source as it should be displayed to users
- * in debug messages; typically the same as getName(), but may
- * also include a context ("@foobar/addressbook") to disambiguate
- * the name when "addressbook" is used multiple times in a sync (as
- * with local sync)
- */
- virtual std::string getDisplayName() const { return "uninitialized SyncSourceBase"; }
-
- /**
* Convenience function, to be called inside a catch() block of
* (or for) the sync source.
*
* @param action a string describing the operation or object involved
* @param error the errno error code for the failure
*/
- void throwError(const string &action, int error) SE_NORETURN;
+ void throwError(const SourceLocation &where, const string &action, int error) SE_NORETURN;
/**
* throw an exception after an operation failed and
*
* @param action a string describing what was attempted *and* how it failed
*/
- void throwError(const string &failure) SE_NORETURN;
+ void throwError(const SourceLocation &where, const string &failure) SE_NORETURN;
/**
* throw an exception with a specific status code after an operation failed and
* @param status a more specific status code; other throwError() variants use STATUS_FATAL
* @param action a string describing what was attempted *and* how it failed
*/
- void throwError(SyncMLStatus status, const string &failure) SE_NORETURN;
+ void throwError(const SourceLocation &where, SyncMLStatus status, const string &failure) SE_NORETURN;
/**
* The Synthesis engine only counts items which are deleted by the
* post-signals managed by OperationWrapper.
*/
struct Operations {
+ Operations(SyncSourceName &source);
+
/**
* The caller determines where item data is stored (m_dirname)
* and where meta information about them (m_node). The callee
static TestRegistry &getTestRegistry();
struct Database {
- Database(const string &name, const string &uri, bool isDefault = false) :
- m_name( name ), m_uri( uri ), m_isDefault(isDefault) {}
+ Database(const string &name, const string &uri, bool isDefault = false, bool isReadOnly = false) :
+ m_name( name ), m_uri( uri ), m_isDefault(isDefault), m_isReadOnly(isReadOnly) {}
string m_name;
string m_uri;
bool m_isDefault;
+ bool m_isReadOnly;
};
typedef vector<Database> Databases;
* a specific URI.
* @return description of the new database
*/
- virtual Database createDatabase(const Database &database) { throwError("creating databases is not supported by backend " + getBackend()); return Database("", ""); }
+ virtual Database createDatabase(const Database &database) { throwError(SE_HERE, "creating databases is not supported by backend " + getBackend()); return Database("", ""); }
/**
* Removing a database primarily removes the meta data about the
* @param uri unique identifier for the database
* @param removeData describes what to do about the database content
*/
- virtual void deleteDatabase(const std::string &uri, RemoveData removeData) { throwError("deleting databases is not supported by backend " + getBackend()); }
+ virtual void deleteDatabase(const std::string &uri, RemoveData removeData) { throwError(SE_HERE, "deleting databases is not supported by backend " + getBackend()); }
/**
* Actually opens the data source specified in the constructor,