2 * Copyright (C) 2005-2009 Patrick Ohly <patrick.ohly@gmx.de>
3 * Copyright (C) 2009 Intel Corporation
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.
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.
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
21 #ifndef INCL_SYNCSOURCE
22 #define INCL_SYNCSOURCE
24 #include <syncevo/SyncConfig.h>
25 #include <syncevo/Logging.h>
26 #include <syncevo/SyncML.h>
28 #include <synthesis/sync_declarations.h>
29 #include <synthesis/syerror.h>
31 #include <boost/function.hpp>
33 #include <syncevo/declarations.h>
40 * This set of parameters always has to be passed when constructing
41 * SyncSource instances.
43 struct SyncSourceParams {
45 * @param name the name needed by SyncSource
46 * @param nodes a set of config nodes to be used by this source
48 SyncSourceParams(const string &name,
49 const SyncSourceNodes &nodes = SyncSourceNodes()) :
55 SyncSourceNodes m_nodes;
59 * The SyncEvolution core has no knowledge of existing SyncSource
60 * implementations. Implementations have to register themselves
61 * by instantiating this class exactly once with information
64 * It is also possible to add configuration options. For that define a
65 * derived class. In its constructor use
66 * SyncSourceConfig::getRegistry() resp. SyncConfig::getRegistry() to
67 * define new configuration properties. The advantage of registering
68 * them is that the user interface will automatically handle them like
69 * the predefined ones. The namespace of these configuration options
70 * is shared by all sources and the core.
72 * For properties with arbitrary names use the
73 * SyncSourceNodes::m_trackingNode.
75 class RegisterSyncSource
79 * Users select a SyncSource and its data format via the "type"
80 * config property. Backends have to add this kind of function to
81 * the SourceRegistry_t in order to be considered by the
82 * SyncSource creation mechanism.
84 * The function will be called to check whether the backend was
85 * meant by the user. It should return a new instance which will
86 * be freed by the caller or NULL if it does not support the
89 * Inactive sources should return the special InactiveSource
90 * pointer value if they recognize without a doubt that the user
91 * wanted to instantiate them: for example, an inactive
92 * EvolutionContactSource will return NULL for "addressbook" but
93 * InactiveSource for "evolution-contacts".
95 typedef SyncSource *(*Create_t)(const SyncSourceParams ¶ms);
97 /** special return value of Create_t, not a real sync source! */
98 static SyncSource *const InactiveSource;
101 * @param shortDescr a few words identifying the data to be synchronized,
102 * e.g. "Evolution Calendar"
103 * @param enabled true if the sync source can be instantiated,
104 * false if it was not enabled during compilation or is
105 * otherwise not functional
106 * @param create factory function for sync sources of this type
107 * @param typeDescr multiple lines separated by \n which get appended to
108 * the the description of the type property, e.g.
109 * "Evolution Memos = memo = evolution-memo\n"
110 * " plain text in UTF-8 (default) = text/plain\n"
111 * " iCalendar 2.0 = text/calendar\n"
112 * " The later format is not tested because none of the\n"
113 * " supported SyncML servers accepts it.\n"
114 * @param typeValues the config accepts multiple names for the same internal
115 * type string; this list here is added to that list of
116 * aliases. It should contain at least one unique string
117 * the can be used to pick this sync source among all
118 * SyncEvolution sync sources (testing, listing backends, ...).
119 * Example: Values() + (Aliases("Evolution Memos") + "evolution-memo")
121 RegisterSyncSource(const string &shortDescr,
124 const string &typeDescr,
125 const Values &typeValues);
127 const string m_shortDescr;
128 const bool m_enabled;
129 const Create_t m_create;
130 const string m_typeDescr;
131 const Values m_typeValues;
134 typedef list<const RegisterSyncSource *> SourceRegistry;
136 class TestingSyncSource;
139 * Information about a data source. For the sake of simplicity all
140 * items pointed to are owned by the ClientTest and must
141 * remain valid throughout a test session. Not setting a pointer
142 * is okay, but it will disable all tests that need the
145 struct ClientTestConfig{
147 * The name is used in test names and has to be set.
149 const char *sourceName;
152 * A default URI to be used when creating a client config.
157 * A corresponding source name in the default server template,
158 * this is used to copy corresponding uri set in the server template
159 * instead of the uri field above (which is the same for all servers).
161 const char *sourceNameServerTemplate;
164 * A member function of a subclass which is called to create a
165 * sync source referencing the data. This is used in tests of
166 * the SyncSource API itself as well as in tests which need to
167 * modify or check the data sources used during synchronization.
169 * The test framework will call beginSync() and then some of
170 * the functions it wants to test. After a successful test it
171 * will call endSync() which is then expected to store all
172 * changes persistently. Creating a sync source again
173 * with the same call should not report any
174 * new/updated/deleted items until such changes are made via
175 * another sync source.
177 * The instance will be deleted by the caller. Because this
178 * may be in the error case or in an exception handler,
179 * the sync source's desctructor should not thow exceptions.
181 * @param client the same instance to which this config belongs
182 * @param source index of the data source (from 0 to ClientTest::getNumSources() - 1)
183 * @param isSourceA true if the requested SyncSource is the first one accessing that
184 * data, otherwise the second
186 typedef TestingSyncSource *(*createsource_t)(ClientTest &client, int source, bool isSourceA);
189 * Creates a sync source which references the primary database;
190 * it may report the same changes as the sync source used during
193 createsource_t createSourceA;
196 * A second sync source also referencing the primary data
197 * source, but configured so that it tracks changes
198 * independently from the the primary sync source.
200 * In local tests the usage is like this:
201 * - add item via first SyncSource
202 * - iterate over new items in second SyncSource
203 * - check that it lists the added item
205 * In tests with a server the usage is:
206 * - do a synchronization with the server
207 * - iterate over items in second SyncSource
208 * - check that the total number and number of
209 * added/updated/deleted items is as expected
211 createsource_t createSourceB;
214 * The framework can generate vCard and vCalendar/iCalendar items
215 * automatically by copying a template item and modifying certain
218 * This is the template for these automatically generated items.
219 * It must contain the string <<REVISION>> which will be replaced
220 * with the revision parameter of the createItem() method.
222 const char *templateItem;
225 * This is a colon (:) separated list of properties which need
226 * to be modified in templateItem.
228 const char *uniqueProperties;
231 * the number of items to create during stress tests
236 * This is a single property in templateItem which can be extended
237 * to increase the size of generated items.
239 const char *sizeProperty;
242 * Type to be set when importing any of the items into the
243 * corresponding sync sources. Use "" if sync source doesn't
244 * need this information.
246 * Not currently used! All items are assumed to be in the raw,
247 * internal format (see SyncSourceRaw and SyncSourceSerialize).
249 const char *itemType;
252 * A very simple item that is inserted during basic tests. Ideally
253 * it only contains properties supported by all servers.
255 const char *insertItem;
258 * A slightly modified version of insertItem. If the source has UIDs
259 * embedded into the item data, then both must have the same UID.
260 * Again all servers should better support these modified properties.
262 const char *updateItem;
265 * A more heavily modified version of insertItem. Same UID if necessary,
266 * but can test changes to items only supported by more advanced
269 const char *complexUpdateItem;
272 * To test merge conflicts two different updates of insertItem are
273 * needed. This is the first such update.
275 const char *mergeItem1;
278 * The second merge update item. To avoid true conflicts it should
279 * update different properties than mergeItem1, but even then servers
280 * usually have problems perfectly merging items. Therefore the
281 * test is run without expecting a certain merge result.
283 const char *mergeItem2;
286 * These two items are related: one is main one, the other is
287 * a subordinate one. The semantic is that the main item is
288 * complete on it its own, while the other normally should only
289 * be used in combination with the main one.
291 * Because SyncML cannot express such dependencies between items,
292 * a SyncSource has to be able to insert, updated and remove
293 * both items independently. However, operations which violate
294 * the semantic of the related items (like deleting the parent, but
295 * not the child) may have unspecified results (like also deleting
296 * the child). See LINKED_ITEMS_RELAXED_SEMANTIC.
298 * One example for main and subordinate items are a recurring
299 * iCalendar 2.0 event and a detached recurrence.
301 const char *parentItem, *childItem;
304 * Backends atomic modification tests
306 bool atomicModification;
309 * define to 0 to disable tests which slightly violate the
310 * semantic of linked items by inserting children
311 * before/without their parent
313 #ifndef LINKED_ITEMS_RELAXED_SEMANTIC
314 # define LINKED_ITEMS_RELAXED_SEMANTIC 1
318 * setting this to false disables tests which depend
319 * on the source's support for linked item semantic
320 * (testLinkedItemsInsertParentTwice, testLinkedItemsInsertChildTwice)
322 bool sourceKnowsItemSemantic;
325 * called to dump all items into a file, required by tests which need
328 * ClientTest::dump can be used: it will simply dump all items of the source
329 * with a blank line as separator.
331 * @param source sync source A already created and with beginSync() called
332 * @param file a file name
333 * @return error code, 0 for success
335 int (*dump)(ClientTest &client, TestingSyncSource &source, const char *file);
338 * import test items: which these are is determined entirely by
339 * the implementor, but tests work best if several complex items are
342 * ClientTest::import can be used if the file contains items separated by
345 * @param source sync source A already created and with beginSync() called
346 * @param file the name of the file to import
347 * @retval realfile the name of the file that was really imported;
348 * this may depend on the current server that is being tested
349 * @return error code, 0 for success
351 int (*import)(ClientTest &client, TestingSyncSource &source, const char *file, std::string &realfile);
354 * a function which compares two files with items in the format used by "dump"
356 * @param fileA first file name
357 * @param fileB second file name
358 * @return true if the content of the files is considered equal
360 bool (*compare)(ClientTest &client, const char *fileA, const char *fileB);
363 * a file with test cases in the format expected by import and compare
365 const char *testcases;
368 * the item type normally used by the source (not used by the tests
369 * themselves; client-test.cpp uses it to initialize source configs)
374 * a list of sub configs separated via , if this is a super datastore
376 const char *subConfigs;
379 * TRUE if the source supports recovery from an interrupted
380 * synchronization. Enables the Client::Sync::*::Retry group
389 * In addition to registering the sync source itself by creating an
390 * instance of RegisterSyncSource, configurations for testing it can
391 * also be registered. A sync source which supports more than one data
392 * exchange format can register one configuration for each format, but
393 * not registering any configuration is also okay.
395 * *Using* the registered tests depends on the CPPUnit test framework.
396 * *Registering* does not. Therefore backends should always register *
397 * *themselves for testing and leave it to the test runner
398 * "client-test" whether tests are really executed.
400 * Unit tests are different. They create hard dependencies on CPPUnit
401 * inside the code that contains them, and thus should be encapsulated
402 * inside #ifdef ENABLE_UNIT_TESTS checks.
404 * Sync sources have to work stand-alone without a full SyncClient
405 * configuration for all local tests. The minimal configuration prepared
406 * for the source includes:
407 * - a tracking node (as used f.i. by TrackingSyncSource) which
408 * points towards "~/.config/syncevolution/client-test-changes"
409 * - a unique change ID (as used f.i. by EvolutionContactSource)
410 * - a valid "evolutionsource" property in the config node, starting
411 * with the CLIENT_TEST_EVOLUTION_PREFIX env variable or (if that
412 * wasn't set) the "SyncEvolution_Test_" prefix
413 * - "evolutionuser/password" if CLIENT_TEST_EVOLUTION_USER/PASSWORD
416 * No other properties are set, which implies that currently sync sources
417 * which require further parameters cannot be tested.
419 * @warning There is a potential problem with the registration
420 * mechanism. Both the sync source tests as well as the CPPUnit tests
421 * derived from them are registrered when global class instances are
422 * initialized. If the RegisterTestEvolution instance in
423 * client-test-app.cpp is initialized *before* the sync source tests,
424 * then those won't show up in the test list. Currently the right
425 * order seems to be used, so everything works as expected.
427 class RegisterSyncSourceTest
431 * This call is invoked after setting up the config with default
432 * values for the test cases selected via the constructor's
433 * testCaseName parameter (one of vcard21, vcard30, ical20, itodo20;
434 * see ClientTest in the Funambol client library for the current
437 * This call can then override any of the values or (if there
438 * are no predefined test cases) add them.
440 * The "type" property must select your sync source and the
441 * data format for the test.
443 * @retval config change any field whose default is not suitable
445 virtual void updateConfig(ClientTestConfig &config) const = 0;
448 * @param configName a unique string: the predefined names known by
449 * ClientTest::getTestData() are already used for the initial
450 * set of Evolution sync sources, for new sync sources
451 * build a string by combining them with the sync source name
452 * (e.g., "sqlite_vcard30")
453 * @param testCaseName a string recognized by ClientTest::getTestData() or an
454 * empty string if there are no predefined test cases
456 RegisterSyncSourceTest(const string &configName,
457 const string &testCaseName);
458 virtual ~RegisterSyncSourceTest() {}
460 const string m_configName;
461 const string m_testCaseName;
464 class TestRegistry : public vector<const RegisterSyncSourceTest *>
467 // TODO: using const RegisterSyncSourceTest * operator [] (int);
468 const RegisterSyncSourceTest * operator [] (const string &configName) const {
469 BOOST_FOREACH(const RegisterSyncSourceTest *test, *this) {
470 if (test->m_configName == configName) {
474 throw out_of_range(string("test config registry: ") + configName);
480 * a container for Synthesis XML config fragments
482 * Backends can define their own field lists, profiles, datatypes and
483 * remote rules. The name of each of these entities have to be unique:
484 * either prefix each name with the name of the backend or coordinate
485 * with other developers (e.g. regarding shared field lists).
487 * To add new items, add them to the respective hash in your backend's
488 * getDatastoreXML() or getSynthesisInfo() implementation. Both
489 * methods have default implementations: getSynthesisInfo() is called
490 * by the default getDatastoreXML() to provide some details and
491 * provides them based on the "type" configuration option.
493 * The default config XML contains several predefined items:
494 * - field lists: contacts, calendar, Note, bookmarks
495 * - profiles: vCard, vCalendar, Note, vBookmark
496 * - datatypes: vCard21, vCard30, vCalendar10, iCalendar20,
497 * note10/11 (no difference except the versioning!),
499 * - remote rule: EVOLUTION
501 * These items do not appear in the hashes, so avoid picking the same
502 * names. The entries of each hash has to be a well-formed XML
503 * element, their keys the name encoded in each XML element.
505 struct XMLConfigFragments {
506 class mapping : public std::map<std::string, std::string> {
511 BOOST_FOREACH(const value_type &entry, *this) {
512 len += entry.second.size() + 1;
515 BOOST_FOREACH(const value_type &entry, *this) {
528 * abstract base class for SyncSource with some common functionality
531 * Used to implement and call that functionality in multiple derived
532 * classes, including situations where a derived class is derived from
533 * this base via different intermediate classes, therefore the
534 * need to keep it abstract.
536 class SyncSourceBase : public Logger {
538 virtual ~SyncSourceBase() {}
540 /** the unique name of the sync source (for example, "addressbook") */
541 virtual const char *getName() const { return "uninitialized SyncSourceBase"; }
544 * Convenience function, to be called inside a catch() block of
545 * (or for) the sync source.
547 * Rethrows the exception to determine what it is, then logs it
548 * as an error and returns a suitable error code (usually a general
549 * STATUS_DATASTORE_FAILURE).
551 SyncMLStatus handleException();
554 * throw an exception after an operation failed
556 * output format: <source name>: <action>: <error string>
558 * @param action a string describing the operation or object involved
559 * @param error the errno error code for the failure
561 void throwError(const string &action, int error);
564 * throw an exception after an operation failed and
565 * remember that this instance has failed
567 * output format: <source name>: <failure>
569 * @param action a string describing what was attempted *and* how it failed
571 void throwError(const string &failure);
574 * The Synthesis engine only counts items which are deleted by the
575 * peer. Items deleted locally at the start of a
576 * refresh-from-server sync are not counted (and cannot be counted
579 * Sync sources which want to have those items included in the
580 * sync statistics should count *all* deleted items using these
581 * methods. SyncContext will use this number for
582 * refresh-from-server syncs.
585 virtual long getNumDeleted() const = 0;
586 virtual void setNumDeleted(long num) = 0;
587 virtual void incrementNumDeleted() = 0;
591 * Return Synthesis <datastore> XML fragment for this sync source.
592 * Must *not* include the <datastore> element; it is created by
595 * The default implementation returns a configuration for the
596 * SynthesisDBPlugin, which invokes SyncSource::Operations. Items
597 * are exchanged with the SyncsSource in the format defined by
598 * getSynthesisInfo(). The format used with the SyncML side is
599 * negotiated via the peer's capabilities, with the type defined
600 * in the configuration being the preferred one of the data store.
602 * See SyncContext::getConfigXML() for details about
603 * predefined <datatype> entries that can be referenced here.
605 * @retval xml put content of <datastore>...</datastore> here
606 * @retval fragments the necessary definitions for the datastore have to be added here
608 virtual void getDatastoreXML(string &xml, XMLConfigFragments &fragments);
611 * Synthesis <datatype> name which matches the format used
612 * for importing and exporting items (exportData()).
613 * This is not necessarily the same format that is given
614 * to the Synthesis engine. If this internal format doesn't
615 * have a <datatype> in the engine, then an empty string is
618 virtual string getNativeDatatypeName();
621 * Logging utility code.
623 * Every sync source adds "<name>" as prefix to its output.
624 * All calls are redirected into SyncContext logger.
626 virtual void messagev(Level level,
630 const char *function,
635 * return Synthesis API pointer, if one currently is available
636 * (between SyncEvolution_Module_CreateContext() and
637 * SyncEvolution_Module_DeleteContext())
639 virtual SDKInterface *getSynthesisAPI() const = 0;
642 * Prepare the sync source for usage inside a SyncML server. To
643 * be called directly after creating the source, if at all.
645 virtual void enableServerMode() = 0;
646 virtual bool serverModeEnabled() const = 0;
649 struct SynthesisInfo {
651 * name to use for MAKE/PARSETEXTWITHPROFILE,
652 * leave empty when acessing the field list directly
654 std::string m_profile;
657 * the second parameter for MAKE/PARSETEXTWITHPROFILE
658 * which specifies a remote rule to be applied when
659 * converting to and from the backend
661 std::string m_backendRule;
663 /** list of supported datatypes in "<use .../>" format */
664 std::string m_datatypes;
666 /** native datatype (see getNativeDatatypeName()) */
667 std::string m_native;
669 /** name of the field list used by the datatypes */
670 std::string m_fieldlist;
673 * One or more Synthesis script statements, separated
674 * and terminated with a semicolon. Can be left empty.
676 * If not empty, then these statements are executed directly
677 * before converting the current item fields into
678 * a single string with MAKETEXTWITHPROFILE() in the sync source's
679 * <beforewritescript> (see SyncSourceBase::getDatastoreXML()).
681 * This value is currently only used by sync sources which
684 std::string m_beforeWriteScript;
687 * Same as m_beforeWriteScript, but used directly after
688 * converting a string into fields with PARSETEXTWITHPROFILE()
689 * in <afterreadscript>.
691 std::string m_afterReadScript;
695 * helper function for getDatastoreXML(): fill in information
698 * @retval fragments the necessary definitions for the other
699 * return values have to be added here
701 virtual void getSynthesisInfo(SynthesisInfo &info,
702 XMLConfigFragments &fragments) = 0;
705 * utility code: creates Synthesis <use datatype=...>
706 * statements, using the predefined vCard21/vCard30/vcalendar10/icalendar20
707 * types. Throws an error if no suitable result can be returned (empty or invalid type)
709 * @param type the format specifier as used in SyncEvolution configs, with and without version
710 * (text/x-vcard:2.1, text/x-vcard, text/x-vcalendar, text/calendar, text/plain, ...);
711 * see SourceType::m_format
712 * @param forceFormat if true, then don't allow alternative formats (like vCard 3.0 in addition to 2.1);
713 * see SourceType::m_force
714 * @return generated XML fragment
716 std::string getDataTypeSupport(const std::string &type,
721 * SyncEvolution accesses all sources through this interface.
723 * Certain functionality is optional or can be implemented in
724 * different ways. These methods are accessed through functors
725 * (function objects) which may be unset. The expected usage is that
726 * derived classes fill in the pieces that they provide by binding the
727 * functors to normal methods. For example, TrackingSyncSource
728 * provides a normal base class with pure virtual functions which have
729 * to be provided by users of that class.
731 * Error reporting is done via the Log class.
733 class SyncSource : virtual public SyncSourceBase, public SyncSourceConfig, public SyncSourceReport
736 SyncSource(const SyncSourceParams ¶ms) :
737 SyncSourceConfig(params.m_name, params.m_nodes),
739 m_forceSlowSync(false)
742 virtual ~SyncSource() {}
745 * SyncSource implementations must register themselves here via
748 static SourceRegistry &getSourceRegistry();
751 * SyncSource tests are registered here by the constructor of
752 * RegisterSyncSourceTest
754 static TestRegistry &getTestRegistry();
757 Database(const string &name, const string &uri, bool isDefault = false) :
758 m_name( name ), m_uri( uri ), m_isDefault(isDefault) {}
763 typedef vector<Database> Databases;
766 * returns a list of all know data sources for the kind of items
767 * supported by this sync source
769 virtual Databases getDatabases() = 0;
772 * Actually opens the data source specified in the constructor,
773 * will throw the normal exceptions if that fails. Should
774 * not modify the state of the sync source.
776 * The expectation is that this call is fairly light-weight, but
777 * does enough checking to determine whether the source is
778 * usable. More expensive operations (like determining changes)
779 * should be done in the m_startDataRead callback (bound to
780 * beginSync() in some of the utility classes).
782 * In clients, it will be called for all sources before
783 * the sync starts. In servers, it is called for each source once
784 * the client asks for it, but not sooner.
786 virtual void open() = 0;
789 * The optional operations.
791 * All of them are guaranteed to happen between open() and
794 * They are all allowed to throw exceptions: the operations called
795 * by SyncEvolution then abort whatever SyncEvolution was doing
796 * and end in the normal exception handling. For the Synthesis
797 * operations, the bridge code in SynthesisDBPlugin code catches
798 * exceptions, logs them and translates them into Synthesis error
799 * codes, which are returned to the Synthesis engine.
803 * The caller determines where item data is stored (m_dirname)
804 * and where meta information about them (m_node). The callee
805 * then can use both arbitrarily. As an additional hint,
806 * m_mode specifies why and when the backup is made, which
807 * is useful to determine whether information can be reused.
811 BACKUP_BEFORE, /**< directly at start of sync */
812 BACKUP_AFTER, /**< directly after sync */
816 boost::shared_ptr<ConfigNode> m_node;
818 BackupInfo(Mode mode,
819 const string &dirname,
820 const boost::shared_ptr<ConfigNode> &node) :
826 struct ConstBackupInfo {
827 BackupInfo::Mode m_mode;
829 boost::shared_ptr<const ConfigNode> m_node;
831 ConstBackupInfo(BackupInfo::Mode mode,
832 const string &dirname,
833 const boost::shared_ptr<const ConfigNode> &node) :
841 * Dump all data from source unmodified into the given backup location.
842 * Information about the created backup is added to the
845 * Required for the backup/restore functionality in
846 * SyncEvolution, not for syncing itself. But typically it is
847 * called before syncing (can be turned off by users), so
848 * implementations can reuse the information gathered while
849 * making a backup in later operations.
851 * @param previous the most recent backup, empty m_dirname if none
852 * @param next the backup which is to be created, directory and node are empty
853 * @param report to be filled with information about backup (number of items, etc.)
855 typedef void (BackupData_t)(const ConstBackupInfo &oldBackup,
856 const BackupInfo &newBackup,
857 BackupReport &report);
858 boost::function<BackupData_t> m_backupData;
861 * Restore database from data stored in backupData().
862 * If possible don't touch items which are the same as in the
863 * backup, to mimimize impact on future incremental syncs.
865 * @param oldBackup the backup which is to be restored
866 * @param dryrun pretend to restore and fill in report, without
867 * actually touching backend data
868 * @param report to be filled with information about restore
869 * (number of total items and changes)
871 typedef void (RestoreData_t)(const ConstBackupInfo &oldBackup,
873 SyncSourceReport &report);
874 boost::function<RestoreData_t> m_restoreData;
877 * initialize information about local changes and items
878 * as in beginSync() with all parameters set to true,
879 * but without changing the state of the underlying database
881 * This method will be called to check for local changes without
882 * actually running a sync, so there is no matching end call.
884 * There might be sources which don't support non-destructive
885 * change tracking (in other words, checking changes permanently
886 * modifies the state of the source and cannot be repeated).
887 * Such sources should leave the functor empty.
889 typedef void (CheckStatus_t)(SyncSourceReport &local);
890 boost::function<CheckStatus_t> m_checkStatus;
893 * A quick check whether the source currently has data.
895 * If this cannot be determined easily, don't provide the
896 * operation. The information is currently only used to
897 * determine whether a slow sync should be allowed. If
898 * the operation is not provided, the assumption is that
899 * there is local data, which disables the "allow slow
900 * sync for empty databases" heuristic and forces the user
903 typedef bool (IsEmpty_t)();
904 boost::function<IsEmpty_t> m_isEmpty;
907 * Synthesis DB API callbacks. For documentation see the
908 * Synthesis API specification (PDF and/or sync_dbapi.h).
910 * Implementing this is necessary for SyncSources which want
911 * to be part of a sync session.
914 typedef void (Callback_t)();
915 typedef boost::function<Callback_t> CallbackFunctor_t;
916 typedef std::list<CallbackFunctor_t> Callbacks_t;
918 /** all of these functions will be called before accessing
919 the source's data for the first time, i.e., before m_startDataRead */
920 Callbacks_t m_startAccess;
922 typedef sysync::TSyError (StartDataRead_t)(const char *lastToken, const char *resumeToken);
923 boost::function<StartDataRead_t> m_startDataRead;
925 /** all of these functions will be called directly after
926 m_startDataRead() returned successfully */
927 Callbacks_t m_startSession;
929 typedef sysync::TSyError (EndDataRead_t)();
930 boost::function<EndDataRead_t> m_endDataRead;
932 typedef sysync::TSyError (StartDataWrite_t)();
933 boost::function<StartDataWrite_t> m_startDataWrite;
935 /** all of these functions will be called right
936 before m_endDataWrite() */
937 std::list<CallbackFunctor_t> m_endSession;
939 typedef sysync::TSyError (EndDataWrite_t)(bool success, char **newToken);
940 boost::function<EndDataWrite_t> m_endDataWrite;
942 /** the SynthesisDBPlugin is configured so that this operation
943 doesn't have to (and cannot) return the item data */
944 typedef sysync::TSyError (ReadNextItem_t)(sysync::ItemID aID,
945 sysync::sInt32 *aStatus, bool aFirst);
946 boost::function<ReadNextItem_t> m_readNextItem;
948 typedef sysync::TSyError (ReadItemAsKey_t)(sysync::cItemID aID, sysync::KeyH aItemKey);
949 boost::function<ReadItemAsKey_t> m_readItemAsKey;
951 typedef sysync::TSyError (InsertItemAsKey_t)(sysync::KeyH aItemKey, sysync::ItemID newID);
952 boost::function<InsertItemAsKey_t> m_insertItemAsKey;
954 typedef sysync::TSyError (UpdateItemAsKey_t)(sysync::KeyH aItemKey, sysync::cItemID aID, sysync::ItemID updID);
955 boost::function<UpdateItemAsKey_t> m_updateItemAsKey;
957 typedef sysync::TSyError (DeleteItem_t)(sysync::cItemID aID);
958 boost::function<DeleteItem_t> m_deleteItem;
963 * Synthesis administration callbacks. For documentation see the
964 * Synthesis API specification (PDF and/or sync_dbapi.h).
966 * Implementing this is *optional* in clients. In the Synthesis client
967 * engine, the "binfiles" module provides these calls without SyncEvolution
970 * In the Synthesis server engine, the
971 * SyncSource::enableServerMode() call must install an
972 * implementation, like the one from SyncSourceAdmin.
975 typedef sysync::TSyError (LoadAdminData_t)(const char *aLocDB,
978 boost::function<LoadAdminData_t> m_loadAdminData;
980 typedef sysync::TSyError (SaveAdminData_t)(const char *adminData);
981 boost::function<SaveAdminData_t> m_saveAdminData;
983 typedef bool (ReadNextMapItem_t)(sysync::MapID mID, bool aFirst);
984 boost::function<ReadNextMapItem_t> m_readNextMapItem;
986 typedef sysync::TSyError (InsertMapItem_t)(sysync::cMapID mID);
987 boost::function<InsertMapItem_t> m_insertMapItem;
989 typedef sysync::TSyError (UpdateMapItem_t)(sysync::cMapID mID);
990 boost::function<UpdateMapItem_t> m_updateMapItem;
992 typedef sysync::TSyError (DeleteMapItem_t)(sysync::cMapID mID);
993 boost::function<DeleteMapItem_t> m_deleteMapItem;
996 const Operations &getOperations() { return m_operations; }
999 * outside users of the source are only allowed to add callbacks,
1000 * not overwrite arbitrary operations
1002 void addCallback(Operations::CallbackFunctor_t callback, Operations::Callbacks_t Operations::* where) { (m_operations.*where).push_back(callback); }
1005 * closes the data source so that it can be reopened
1007 * Just as open() it should not affect the state of
1008 * the database unless some previous action requires
1011 virtual void close() = 0;
1014 * return Synthesis API pointer, if one currently is available
1015 * (between SyncEvolution_Module_CreateContext() and
1016 * SyncEvolution_Module_DeleteContext())
1018 virtual SDKInterface *getSynthesisAPI() const;
1021 * change the Synthesis API that is used by the source
1023 void pushSynthesisAPI(sysync::SDK_InterfaceType *synthesisAPI);
1026 * remove latest Synthesis API and return to previous one (if any)
1028 void popSynthesisAPI();
1031 * factory function for a SyncSource that provides the
1032 * source type specified in the params.m_nodes.m_configNode
1034 * @param error throw a runtime error describing what the problem is if no matching source is found
1035 * @param config optional, needed for intantiating virtual sources
1036 * @return valid instance, NULL if no source can handle the given type (only when error==false)
1038 static SyncSource *createSource(const SyncSourceParams ¶ms,
1040 SyncConfig *config = NULL);
1043 * Factory function for a SyncSource with the given name
1044 * and handling the kind of data specified by "type" (e.g.
1045 * "Evolution Contacts:text/x-vcard").
1047 * The source is instantiated with dummy configuration nodes under
1048 * the pseudo server name "testing". This function is used for
1049 * testing sync sources, not for real syncs. If the prefix is set,
1050 * then <prefix>_<name>_1 is used as database, just as in the
1051 * Client::Sync and Client::Source tests. Otherwise the default
1054 * @param error throw a runtime error describing what the problem is if no matching source is found
1055 * @return NULL if no source can handle the given type
1057 static SyncSource *createTestingSource(const string &name, const string &type, bool error,
1058 const char *prefix = getenv("CLIENT_TEST_EVOLUTION_PREFIX"));
1061 * Some information about available backends.
1062 * Multiple lines, formatted for users of the
1065 static string backendsInfo();
1067 * Debug information about backends.
1069 static string backendsDebug();
1072 * Mime type a backend provides by default, this is used to alert the
1073 * remote peer in SAN during server alerted sync.
1075 virtual const char *getPeerMimeType() const =0;
1077 /* implementation of SyncSourceBase */
1078 virtual const char * getName() const { return SyncSourceConfig::getName(); }
1079 virtual long getNumDeleted() const { return m_numDeleted; }
1080 virtual void setNumDeleted(long num) { m_numDeleted = num; }
1081 virtual void incrementNumDeleted() { m_numDeleted++; }
1084 * Set to true in SyncContext::initSAN() when a SyncML server has
1085 * to force a client into slow sync mode. This is necessary because
1086 * the server cannot request that mode (missing in the standard).
1087 * Forcing the slow sync mode is done via a FORCESLOWSYNC() macro
1088 * call in an <alertscript>.
1090 void setForceSlowSync(bool forceSlowSync) { m_forceSlowSync = forceSlowSync; }
1091 bool getForceSlowSync() const { return m_forceSlowSync; }
1094 Operations m_operations;
1098 * Counter for items deleted in the source. Has to be incremented
1099 * by RemoveAllItems() and DeleteItem(). This counter is used to
1100 * update the Synthesis engine counter in those cases where the
1101 * engine does not (refresh from server) or cannot
1102 * (RemoveAllItems()) count the removals itself.
1106 bool m_forceSlowSync;
1109 * Interface pointer for this sync source, allocated for us by the
1110 * Synthesis engine and registered here by
1111 * SyncEvolution_Module_CreateContext(). Only valid until
1112 * SyncEvolution_Module_DeleteContext(), in other words, while
1113 * the engine is running.
1115 std::vector<sysync::SDK_InterfaceType *> m_synthesisAPI;
1119 * A SyncSource with no pure virtual functions.
1121 class DummySyncSource : public SyncSource
1124 DummySyncSource(const SyncSourceParams ¶ms) :
1125 SyncSource(params) {}
1127 DummySyncSource(const std::string &name) :
1128 SyncSource(SyncSourceParams(name)) {}
1130 virtual Databases getDatabases() { return Databases(); }
1131 virtual void open() {}
1132 virtual void close() {}
1133 virtual void getSynthesisInfo(SynthesisInfo &info,
1134 XMLConfigFragments &fragments) {}
1135 virtual void enableServerMode() {}
1136 virtual bool serverModeEnabled() const { return false; }
1137 virtual const char *getPeerMimeType() const {return "";}
1141 * A special source which combines one or more real sources.
1142 * Most of the special handling for that is in SyncContext.cpp.
1144 * This class can be instantiated, opened and closed if and only if
1145 * the underlying sources also support that.
1147 class VirtualSyncSource : public DummySyncSource
1149 std::vector< boost::shared_ptr<SyncSource> > m_sources;
1153 * @param config optional: when given, the constructor will instantiate the
1154 * referenced underlying sources and check them in open()
1156 VirtualSyncSource(const SyncSourceParams ¶ms, SyncConfig *config = NULL);
1158 /** opens underlying sources and checks config by calling getDataTypeSupport() */
1159 virtual void open();
1160 virtual void close();
1163 * returns array with source names that are referenced by this
1166 std::vector<std::string> getMappedSources();
1169 * returns <use datatype=...> statements for XML config,
1170 * throws error if not configured correctly
1172 std::string getDataTypeSupport();
1173 using SyncSourceBase::getDataTypeSupport;
1177 * Hooks up the Synthesis DB Interface start sync (BeginDataRead) and
1178 * end sync (EndDataWrite) calls with virtual methods. Ensures that
1179 * sleepSinceModification() is called.
1181 * Inherit from this class in your sync source and call the init()
1184 class SyncSourceSession : virtual public SyncSourceBase {
1187 * called before Synthesis engine starts to ask for changes and item data
1189 * See BeingDataRead for details.
1191 * @param lastToken identifies the last completed sync
1192 * @param resumeToken identifies a more recent sync which needs to be resumed;
1193 * if not empty, then report changes made after that sync
1194 * instead of the last completed sync
1196 virtual void beginSync(const std::string &lastToken, const std::string &resumeToken) = 0;
1199 * called after completing or suspending the current sync
1201 * See EndDataWrite for details.
1203 * @return a token identifying this sync session for a future beginSync()
1205 virtual std::string endSync(bool success) = 0;
1207 /** set Synthesis DB Interface operations */
1208 void init(SyncSource::Operations &ops);
1210 sysync::TSyError startDataRead(const char *lastToken, const char *resumeToken);
1211 sysync::TSyError endDataWrite(bool success, char **newToken);
1216 * Implements the Synthesis DB Interface for reporting item changes
1217 * (ReadNextItemAsKey) *without* actually delivering the item data.
1219 class SyncSourceChanges : virtual public SyncSourceBase {
1221 SyncSourceChanges();
1232 * Add the LUID of a NEW/UPDATED/DELETED item.
1233 * If unspecified, the luid is added to the list of
1234 * all items. This must be done *in addition* to adding
1235 * the luid with a specific state.
1237 * For example, the luid of an updated item should be added with
1238 * addItem(luid [, ANY]) and again with addItem(luid, DELETED).
1240 * The Synthesis engine does not need the list of deleted items
1241 * and does not distinguish between added and updated items, so
1242 * for syncing, adding DELETED items is optional and all items
1243 * which are different from the last sync can be added as
1244 * UPDATED. The client-test program expects that the information
1245 * is provided precisely.
1247 * @return true if the luid was already listed
1249 bool addItem(const string &luid, State state = ANY);
1251 typedef std::set<std::string> Items_t;
1252 const Items_t &getItems(State state) { return m_items[state]; }
1253 const Items_t &getAllItems() const { return m_items[ANY]; }
1254 const Items_t &getNewItems() const { return m_items[NEW]; }
1255 const Items_t &getUpdatedItems() const { return m_items[UPDATED]; }
1256 const Items_t &getDeletedItems() const { return m_items[DELETED]; }
1258 /** set Synthesis DB Interface operations */
1259 void init(SyncSource::Operations &ops);
1262 Items_t m_items[MAX];
1264 Items_t::const_iterator m_it;
1266 sysync::TSyError iterate(sysync::ItemID aID,
1267 sysync::sInt32 *aStatus,
1272 * Implements the Synthesis DB Interface for deleting an item
1273 * (DeleteItem). Increments number of deleted items in
1276 class SyncSourceDelete : virtual public SyncSourceBase {
1278 virtual void deleteItem(const string &luid) = 0;
1280 /** set Synthesis DB Interface operations */
1281 void init(SyncSource::Operations &ops);
1284 sysync::TSyError deleteItemSynthesis(sysync::cItemID aID);
1288 * an interface for reading and writing items in the internal
1289 * format; see SyncSourceSerialize for an explanation
1291 class SyncSourceRaw : virtual public SyncSourceBase {
1293 class InsertItemResult {
1295 InsertItemResult() :
1300 * @param luid the LUID after the operation; during an update the LUID must
1301 * not be changed, so return the original one here
1302 * @param revision the revision string after the operation; leave empty if not used
1303 * @param merged set this to true if an existing item was updated instead of adding it
1305 InsertItemResult(const string &luid,
1306 const string &revision,
1309 m_revision(revision),
1318 /** same as SyncSourceSerialize::insertItem(), but with internal format */
1319 virtual InsertItemResult insertItemRaw(const std::string &luid, const std::string &item) = 0;
1321 /** same as SyncSourceSerialize::readItem(), but with internal format */
1322 virtual void readItemRaw(const std::string &luid, std::string &item) = 0;
1326 * Implements the Synthesis DB Interface for importing/exporting item
1327 * data (ReadItemAsKey, InsertItemAsKey, UpdateItemAsKey) in such a
1328 * way that the sync source only has to deal with a text
1329 * representation of an item.
1331 * There may be two such representations:
1332 * - "engine format" is the one exchanged with the Synthesis engine
1333 * - "internal or raw format" is a format that might better capture
1334 * the internal representation and can be used for backup/restore
1337 * To give an example, the EvolutionMemoSource uses plain text as
1338 * engine format and iCalendar 2.0 as raw format.
1340 * The BackupData_t and RestoreData_t operations are implemented by
1341 * this class using the internal format.
1343 * The engine format must be something that the Synthesis engine can
1344 * parse and generate, in other words, there must be a corresponding
1345 * profile in the XML configuration. This class uses information
1346 * provided by the sync source (mime type and version) and from the
1347 * configuration (format selected by user) to generate the required
1348 * XML configuration parts for common configurations (vCard,
1349 * vCalendar, iCalendar, text). Special representations can be added
1350 * to the global XML configuration by overriding default
1351 * implementations provided in this class.
1353 * InsertItemAsKey and UpdateItemAsKey are mapped to the same
1354 * insertItem() call because in practice it can happen that a request
1355 * to add an item must be turned into an update. For example, a
1356 * meeting was imported both into the server and the client. A request
1357 * to add the item again should be treated as an update, based on the
1358 * unique iCalendar 2.0 LUID.
1360 class SyncSourceSerialize : virtual public SyncSourceBase, virtual public SyncSourceRaw {
1363 * Returns the preferred mime type of the items handled by the sync source.
1364 * Example: "text/x-vcard"
1366 virtual const char *getMimeType() const = 0;
1369 * Returns the version of the mime type used by client.
1372 virtual const char *getMimeVersion() const = 0;
1375 * returns the backend selection and configuration
1377 virtual SourceType getSourceType() const = 0;
1380 * Create or modify an item.
1382 * The sync source should be flexible: if the LUID is non-empty, it
1383 * shall modify the item referenced by the LUID. If the LUID is
1384 * empty, the normal operation is to add it. But if the item
1385 * already exists (e.g., a calendar event which was imported
1386 * by the user manually), then the existing item should be
1387 * updated also in the second case.
1389 * Passing a LUID of an item which does not exist is an error.
1390 * This error should be reported instead of covering it up by
1391 * (re)creating the item.
1393 * Errors are signaled by throwing an exception. Returning empty
1394 * strings in the result is an error which triggers an "item could
1395 * not be stored" error.
1397 * @param luid identifies the item to be modified, empty for creating
1398 * @param item contains the new content of the item, using the engine format
1399 * @return the result of inserting the item
1401 virtual InsertItemResult insertItem(const std::string &luid, const std::string &item) = 0;
1404 * Return item data in engine format.
1406 * @param luid identifies the item
1407 * @retval item item data
1409 virtual void readItem(const std::string &luid, std::string &item) = 0;
1411 /* implement SyncSourceRaw under the assumption that the internal and engine format are identical */
1412 virtual InsertItemResult insertItemRaw(const std::string &luid, const std::string &item) { return insertItem(luid, item); }
1413 virtual void readItemRaw(const std::string &luid, std::string &item) { return readItem(luid, item); }
1415 /** set Synthesis DB Interface operations */
1416 void init(SyncSource::Operations &ops);
1420 * used getMimeType(), getMimeVersion() and getSourceType()
1421 * to provide the information necessary for automatic
1422 * conversion to the sync source's internal item representation
1424 virtual void getSynthesisInfo(SynthesisInfo &info,
1425 XMLConfigFragments &fragments);
1427 sysync::TSyError readItemAsKey(sysync::cItemID aID, sysync::KeyH aItemKey);
1428 sysync::TSyError insertItemAsKey(sysync::KeyH aItemKey, sysync::cItemID aID, sysync::ItemID newID);
1432 * Implements change tracking based on a "revision" string, a string
1433 * which is guaranteed to change automatically each time an item is
1434 * modified. Backup/restore is optionally implemented by this class if
1435 * pointers to SyncSourceRaw and SyncSourceDelete interfaces are
1436 * passed to init(). For backup only the former is needed, for restore
1439 * Potential implementations of the revision string are:
1440 * - a modification time stamp
1441 * - a hash value of a textual representation of the item
1442 * (beware, such a hash might change as the textual representation
1443 * changes even though the item is unchanged)
1445 * Sync sources which want to use this functionality have to provide
1446 * the following functionality by implementing the pure virtual
1448 * - enumerate all existing items
1449 * - provide LUID and the revision string
1450 * The LUID must remain *constant* when making changes to an item,
1451 * whereas the revision string must *change* each time the item is
1452 * changed by anyone.
1453 * Both can be arbitrary strings, but keeping them simple (printable
1454 * ASCII, no white spaces, no equal sign) makes debugging simpler
1455 * because they can be stored as they are as key/value pairs in the
1456 * sync source's change tracking config node (the .other.ini files when
1457 * using file-based configuration). More complex strings use escape
1458 * sequences introduced with an exclamation mark for unsafe characters.
1460 * Most of the functionality of this class must be activated
1461 * explicitly as part of the life cycle of the sync source instance by
1462 * calling detectChanges(), updateRevision() and deleteRevision().
1464 * If the required interfaces are provided to init(), then backup/restore
1465 * operations are set. init() also hooks into the session life cycle
1466 * with an end callback that ensures that enough time passes at the end
1467 * of the sync. This is important for sync sources which use time stamps
1468 * as revision string. "enough time" is defined by a parameter to the
1471 class SyncSourceRevisions : virtual public SyncSourceChanges, virtual public SyncSourceBase {
1473 typedef map<string, string> RevisionMap_t;
1476 * fills the complete mapping from UID to revision string of all
1477 * currently existing items
1479 * Usually both UID and revision string must be non-empty. The
1480 * only exception is a refresh-from-client: in that case the
1481 * revision string may be empty. The implementor of this call
1482 * cannot know whether empty strings are allowed, therefore it
1483 * should not throw errors when it cannot create a non-empty
1484 * string. The caller of this method will detect situations where
1485 * a non-empty string is necessary and none was provided.
1487 * This call is typically only invoked only once during the
1488 * lifetime of a source. The result returned in that invocation is
1489 * used throught the session.
1491 virtual void listAllItems(RevisionMap_t &revisions) = 0;
1494 * calculate changes, call when sync source is ready for
1495 * listAllItems() and before changes are needed
1497 * The trackingNode must be provided by the caller. It will
1498 * be updated by each of the calls and must be stored by
1501 * @param trackingNode a config node for exclusive use by this class
1503 void detectChanges(ConfigNode &trackingNode);
1506 * record that an item was added or updated
1508 * @param old_luid empty for add, old LUID otherwise
1509 * @param new_luid normally LUIDs must not change, but this call allows it
1510 * @param revision revision string after change
1512 void updateRevision(ConfigNode &trackingNode,
1513 const std::string &old_luid,
1514 const std::string &new_luid,
1515 const std::string &revision);
1518 * record that we deleted an item
1520 * @param luid the obsolete LUID
1522 void deleteRevision(ConfigNode &trackingNode,
1523 const std::string &luid);
1526 * set Synthesis DB Interface and backup/restore operations
1527 * @param raw needed for backups; if NULL, no backups are made
1528 * @param del needed for restores; if NULL, only backups are possible
1529 * @param granularity time that has to pass between making a modification
1530 * and checking for changes; this class ensures that
1531 * at least this amount of time has passed before letting
1532 * the session terminate. Delays in different source do
1535 void init(SyncSourceRaw *raw, SyncSourceDelete *del,
1537 SyncSource::Operations &ops);
1540 SyncSourceRaw *m_raw;
1541 SyncSourceDelete *m_del;
1542 int m_revisionAccuracySeconds;
1544 /** buffers the result of the initial listAllItems() call */
1545 RevisionMap_t m_revisions;
1546 bool m_revisionsSet;
1547 void initRevisions();
1550 * Dump all data from source unmodified into the given directory.
1551 * The ConfigNode can be used to store meta information needed for
1552 * restoring that state. Both directory and node are empty.
1554 void backupData(const SyncSource::Operations::ConstBackupInfo &oldBackup,
1555 const SyncSource::Operations::BackupInfo &newBackup,
1556 BackupReport &report);
1559 * Restore database from data stored in backupData(). Will be
1560 * called inside open()/close() pair. beginSync() is *not* called.
1562 void restoreData(const SyncSource::Operations::ConstBackupInfo &oldBackup,
1564 SyncSourceReport &report);
1567 * Increments the time stamp of the latest database modification,
1568 * called automatically whenever revisions change.
1570 void databaseModified();
1572 /** time stamp of latest database modification, for sleepSinceModification() */
1573 time_t m_modTimeStamp;
1574 void sleepSinceModification();
1579 * Common logging for sync sources.
1581 * This class wraps the Synthesis DB functors that were set before
1582 * calling its init() method. The wrappers then log a single line
1583 * describing what is happening (adding/updating/removing)
1584 * to which item (with a short item specific description extracted
1585 * from the incoming item data or the backend).
1587 class SyncSourceLogging : public virtual SyncSourceBase
1591 * wrap Synthesis DB Interface operations
1593 * @param fields list of fields to read in getDescription()
1594 * @param sep separator between non-empty fields
1596 void init(const std::list<std::string> &fields,
1597 const std::string &sep,
1598 SyncSource::Operations &ops);
1601 * Extract short description from Synthesis item data.
1602 * The default implementation reads a list of fields
1603 * as strings and concatenates the non-empty ones
1606 * @param aItemKey key for reading fields
1607 * @return description, empty string will cause the ID of the item to be printed
1609 virtual std::string getDescription(sysync::KeyH aItemKey);
1612 * Extract short description from backend.
1613 * Necessary for deleted items. The default implementation
1614 * returns an empty string, so that implementing this
1617 * @param luid LUID of the item to be deleted in the backend
1618 * @return description, empty string will cause the ID of the item to be printed
1620 virtual std::string getDescription(const string &luid);
1623 std::list<std::string> m_fields;
1626 sysync::TSyError insertItemAsKey(sysync::KeyH aItemKey, sysync::ItemID newID,
1627 const boost::function<SyncSource::Operations::InsertItemAsKey_t> &parent);
1628 sysync::TSyError updateItemAsKey(sysync::KeyH aItemKey, sysync::cItemID aID, sysync::ItemID newID,
1629 const boost::function<SyncSource::Operations::UpdateItemAsKey_t> &parent);
1630 sysync::TSyError deleteItem(sysync::cItemID aID,
1631 const boost::function<SyncSource::Operations::DeleteItem_t> &parent);
1635 * Implements Load/SaveAdminData and MapItem handling in a SyncML
1636 * server. Uses a single property for the admin data in the "internal"
1637 * node and a complete node for the map items.
1639 class SyncSourceAdmin : public virtual SyncSourceBase
1641 boost::shared_ptr<ConfigNode> m_configNode;
1642 std::string m_adminPropertyName;
1643 boost::shared_ptr<ConfigNode> m_mappingNode;
1644 bool m_mappingLoaded;
1646 ConfigProps m_mapping;
1647 ConfigProps::const_iterator m_mappingIterator;
1649 sysync::TSyError loadAdminData(const char *aLocDB,
1652 sysync::TSyError saveAdminData(const char *adminData);
1653 bool readNextMapItem(sysync::MapID mID, bool aFirst);
1654 sysync::TSyError insertMapItem(sysync::cMapID mID);
1655 sysync::TSyError updateMapItem(sysync::cMapID mID);
1656 sysync::TSyError deleteMapItem(sysync::cMapID mID);
1660 void mapid2entry(sysync::cMapID mID, string &key, string &value);
1661 void entry2mapid(const string &key, const string &value, sysync::MapID mID);
1664 /** flexible initialization */
1665 void init(SyncSource::Operations &ops,
1666 const boost::shared_ptr<ConfigNode> &config,
1667 const std::string adminPropertyName,
1668 const boost::shared_ptr<ConfigNode> &mapping);
1671 * simpler initialization, using the default placement of data
1672 * inside the SyncSourceConfig base class
1674 void init(SyncSource::Operations &ops, SyncSource *source);
1678 * This is an interface definition that is expected by the client-test
1679 * program. Part of the reason for this requirement is that the test
1680 * program was originally written for the Funambol SyncSource API.
1681 * The other reason is that the testing is based on importing/exporting
1682 * items in the internal format of the sync source, which has to be
1683 * text based or even MIMEDIR based (for tests involving synccompare).
1685 class TestingSyncSource : public SyncSource,
1686 virtual public SyncSourceSession,
1687 virtual public SyncSourceChanges,
1688 virtual public SyncSourceDelete,
1689 virtual public SyncSourceSerialize {
1691 TestingSyncSource(const SyncSourceParams ¶ms) :
1694 SyncSourceSession::init(m_operations);
1695 SyncSourceChanges::init(m_operations);
1696 SyncSourceDelete::init(m_operations);
1697 SyncSourceSerialize::init(m_operations);
1699 ~TestingSyncSource() {}
1701 virtual SourceType getSourceType() const { return SyncSourceConfig::getSourceType(); }
1703 void removeAllItems() {
1704 BOOST_FOREACH(const string &luid, getAllItems()) {
1712 #endif // INCL_SYNCSOURCE