be6305dba37cd121661f9bb0c606761486fcad6f
[platform/upstream/syncevolution.git] / src / syncevo / SyncSource.h
1 /*
2  * Copyright (C) 2005-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_SYNCSOURCE
22 #define INCL_SYNCSOURCE
23
24 #include <syncevo/SyncConfig.h>
25 #include <syncevo/Logging.h>
26 #include <syncevo/SyncML.h>
27
28 #include <synthesis/sync_declarations.h>
29 #include <synthesis/syerror.h>
30
31 #include <boost/function.hpp>
32
33 #include <syncevo/declarations.h>
34 SE_BEGIN_CXX
35
36 class SyncSource;
37 class SDKInterface;
38
39 /**
40  * This set of parameters always has to be passed when constructing
41  * SyncSource instances.
42  */
43 struct SyncSourceParams {
44     /**
45      * @param    name        the name needed by SyncSource
46      * @param    nodes       a set of config nodes to be used by this source
47      */
48     SyncSourceParams(const string &name,
49                      const SyncSourceNodes &nodes = SyncSourceNodes()) :
50         m_name(name),
51         m_nodes(nodes)
52     {}
53
54     string m_name;
55     SyncSourceNodes m_nodes;
56 };
57
58 /**
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
62  * about themselves.
63  *
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.
71  *
72  * For properties with arbitrary names use the
73  * SyncSourceNodes::m_trackingNode.
74  */
75 class RegisterSyncSource
76 {
77  public:
78     /**
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.
83      *
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
87      * selected type.
88      * 
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".
94      */
95     typedef SyncSource *(*Create_t)(const SyncSourceParams &params);
96
97     /** special return value of Create_t, not a real sync source! */
98     static SyncSource *const InactiveSource;
99
100     /**
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")
120      */
121     RegisterSyncSource(const string &shortDescr,
122                        bool enabled,
123                        Create_t create,
124                        const string &typeDescr,
125                        const Values &typeValues);
126  public:
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;
132 };
133     
134 typedef list<const RegisterSyncSource *> SourceRegistry;
135 class ClientTest;
136 class TestingSyncSource;
137
138 /**
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
143  * information.
144  */
145 struct ClientTestConfig{
146     /**
147      * The name is used in test names and has to be set.
148      */
149     const char *sourceName;
150
151     /**
152      * A default URI to be used when creating a client config.
153      */
154     const char *uri;
155
156     /**
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).
160      */
161     const char *sourceNameServerTemplate;
162
163     /**
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.
168      *
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.
176      *
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.
180      *
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
185      */
186     typedef TestingSyncSource *(*createsource_t)(ClientTest &client, int source, bool isSourceA);
187
188     /**
189      * Creates a sync source which references the primary database;
190      * it may report the same changes as the sync source used during
191      * sync tests.
192      */
193     createsource_t createSourceA;
194
195     /**
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.
199      *
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
204      *
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
210      */
211     createsource_t createSourceB;
212
213     /**
214      * The framework can generate vCard and vCalendar/iCalendar items
215      * automatically by copying a template item and modifying certain
216      * properties.
217      *
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.
221      */
222     const char *templateItem;
223
224     /**
225      * This is a colon (:) separated list of properties which need
226      * to be modified in templateItem.
227      */
228     const char *uniqueProperties;
229
230     /**
231      * the number of items to create during stress tests
232      */
233     int numItems;
234
235     /**
236      * This is a single property in templateItem which can be extended
237      * to increase the size of generated items.
238      */
239     const char *sizeProperty;
240
241     /**
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.
245      *
246      * Not currently used! All items are assumed to be in the raw,
247      * internal format (see SyncSourceRaw and SyncSourceSerialize).
248      */
249     const char *itemType;
250
251     /**
252      * A very simple item that is inserted during basic tests. Ideally
253      * it only contains properties supported by all servers.
254      */
255     const char *insertItem;
256
257     /**
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.
261      */
262     const char *updateItem;
263
264     /**
265      * A more heavily modified version of insertItem. Same UID if necessary,
266      * but can test changes to items only supported by more advanced
267      * servers.
268      */
269     const char *complexUpdateItem;
270
271     /**
272      * To test merge conflicts two different updates of insertItem are
273      * needed. This is the first such update.
274      */
275     const char *mergeItem1;
276
277     /**
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.
282      */
283     const char *mergeItem2;
284
285     /**
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.
290      *
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.
297      *
298      * One example for main and subordinate items are a recurring
299      * iCalendar 2.0 event and a detached recurrence.
300      */
301     const char *parentItem, *childItem;
302
303     /**
304      * Backends atomic modification tests
305      */
306     bool atomicModification;
307
308     /**
309      * define to 0 to disable tests which slightly violate the
310      * semantic of linked items by inserting children
311      * before/without their parent
312      */
313 #ifndef LINKED_ITEMS_RELAXED_SEMANTIC
314 # define LINKED_ITEMS_RELAXED_SEMANTIC 1
315 #endif
316
317     /**
318      * setting this to false disables tests which depend
319      * on the source's support for linked item semantic
320      * (testLinkedItemsInsertParentTwice, testLinkedItemsInsertChildTwice)
321      */
322     bool sourceKnowsItemSemantic;
323
324     /**
325      * called to dump all items into a file, required by tests which need
326      * to compare items
327      *
328      * ClientTest::dump can be used: it will simply dump all items of the source
329      * with a blank line as separator.
330      *
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
334      */
335     int (*dump)(ClientTest &client, TestingSyncSource &source, const char *file);
336
337     /**
338      * import test items: which these are is determined entirely by
339      * the implementor, but tests work best if several complex items are
340      * imported
341      *
342      * ClientTest::import can be used if the file contains items separated by
343      * empty lines.
344      *
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
350      */
351     int (*import)(ClientTest &client, TestingSyncSource &source, const char *file, std::string &realfile);
352
353     /**
354      * a function which compares two files with items in the format used by "dump"
355      *
356      * @param fileA      first file name
357      * @param fileB      second file name
358      * @return true if the content of the files is considered equal
359      */
360     bool (*compare)(ClientTest &client, const char *fileA, const char *fileB);
361
362     /**
363      * a file with test cases in the format expected by import and compare
364      */
365     const char *testcases;
366
367     /**
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)
370      */
371     const char *type;
372
373     /**
374      * a list of sub configs separated via , if this is a super datastore
375      */
376     const char *subConfigs;
377
378     /**
379      * TRUE if the source supports recovery from an interrupted
380      * synchronization. Enables the Client::Sync::*::Retry group
381      * of tests.
382      */
383     bool retrySync;
384     bool suspendSync;
385     bool resendSync;
386 };
387
388 /**
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.
394  *
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.
399  *
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.
403  *
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
414  *   are set
415  *
416  * No other properties are set, which implies that currently sync sources
417  * which require further parameters cannot be tested.
418  *
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.
426  */
427 class RegisterSyncSourceTest
428 {
429  public:
430     /**
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
435      * list).
436      *
437      * This call can then override any of the values or (if there
438      * are no predefined test cases) add them.
439      *
440      * The "type" property must select your sync source and the
441      * data format for the test.
442      *
443      * @retval config        change any field whose default is not suitable
444      */
445     virtual void updateConfig(ClientTestConfig &config) const = 0;
446
447     /**
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
455      */
456     RegisterSyncSourceTest(const string &configName,
457                            const string &testCaseName);
458     virtual ~RegisterSyncSourceTest() {}
459
460     const string m_configName;
461     const string m_testCaseName;
462 };
463
464 class TestRegistry : public vector<const RegisterSyncSourceTest *>
465 {
466  public:
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) {
471                 return test;
472             }
473         }
474         throw out_of_range(string("test config registry: ") + configName);
475         return NULL;
476     }
477 };
478
479 /**
480  * a container for Synthesis XML config fragments
481  *
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).
486  *
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.
492  *
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!),
498  *              vBookmark10
499  * - remote rule: EVOLUTION
500  *
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.
504  */
505 struct XMLConfigFragments {
506     class mapping : public std::map<std::string, std::string> {
507     public:
508         string join() {
509             string res;
510             size_t len = 0;
511             BOOST_FOREACH(const value_type &entry, *this) {
512                 len += entry.second.size() + 1;
513             }
514             res.reserve(len);
515             BOOST_FOREACH(const value_type &entry, *this) {
516                 res += entry.second;
517                 res += "\n";
518             }
519             return res;
520         }
521     } m_fieldlists,
522         m_profiles,
523         m_datatypes,
524         m_remoterules;
525 };
526
527 /**
528  * abstract base class for SyncSource with some common functionality
529  * and no data
530  *
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.
535  */
536 class SyncSourceBase : public Logger {
537  public:
538     virtual ~SyncSourceBase() {}
539
540     /** the unique name of the sync source (for example, "addressbook") */
541     virtual const char *getName() const { return "uninitialized SyncSourceBase"; }
542
543     /**
544      * Convenience function, to be called inside a catch() block of
545      * (or for) the sync source.
546      *
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).
550      */
551     SyncMLStatus handleException();
552
553     /**
554      * throw an exception after an operation failed
555      *
556      * output format: <source name>: <action>: <error string>
557      *
558      * @param action   a string describing the operation or object involved
559      * @param error    the errno error code for the failure
560      */
561     void throwError(const string &action, int error);
562
563     /**
564      * throw an exception after an operation failed and
565      * remember that this instance has failed
566      *
567      * output format: <source name>: <failure>
568      *
569      * @param action     a string describing what was attempted *and* how it failed
570      */
571     void throwError(const string &failure);
572
573     /**
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
577      * in all cases).
578      *
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.
583      */
584     /**@{*/
585     virtual long getNumDeleted() const = 0;
586     virtual void setNumDeleted(long num) = 0;
587     virtual void incrementNumDeleted() = 0;
588     /**@}*/
589
590     /**
591      * Return Synthesis <datastore> XML fragment for this sync source.
592      * Must *not* include the <datastore> element; it is created by
593      * the caller.
594      *
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.
601      *
602      * See SyncContext::getConfigXML() for details about
603      * predefined <datatype> entries that can be referenced here.
604      *
605      * @retval xml         put content of <datastore>...</datastore> here
606      * @retval fragments   the necessary definitions for the datastore have to be added here
607      */
608     virtual void getDatastoreXML(string &xml, XMLConfigFragments &fragments);
609
610     /**
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
616      * returned.
617      */
618     virtual string getNativeDatatypeName();
619
620     /**
621      * Logging utility code.
622      *
623      * Every sync source adds "<name>" as prefix to its output.
624      * All calls are redirected into SyncContext logger.
625      */
626     virtual void messagev(Level level,
627                           const char *prefix,
628                           const char *file,
629                           int line,
630                           const char *function,
631                           const char *format,
632                           va_list args);
633
634     /**
635      * return Synthesis API pointer, if one currently is available
636      * (between SyncEvolution_Module_CreateContext() and
637      * SyncEvolution_Module_DeleteContext())
638      */
639     virtual SDKInterface *getSynthesisAPI() const = 0;
640
641     /**
642      * Prepare the sync source for usage inside a SyncML server.  To
643      * be called directly after creating the source, if at all.
644      */
645     virtual void enableServerMode() = 0;
646     virtual bool serverModeEnabled() const = 0;
647
648  protected:
649     struct SynthesisInfo {
650         /**
651          * name to use for MAKE/PARSETEXTWITHPROFILE,
652          * leave empty when acessing the field list directly
653          */
654         std::string m_profile;
655
656         /**
657          * the second parameter for MAKE/PARSETEXTWITHPROFILE
658          * which specifies a remote rule to be applied when
659          * converting to and from the backend
660          */
661         std::string m_backendRule;
662     
663         /** list of supported datatypes in "<use .../>" format */
664         std::string m_datatypes;
665
666         /** native datatype (see getNativeDatatypeName()) */
667         std::string m_native;
668
669         /** name of the field list used by the datatypes */
670         std::string m_fieldlist;
671
672         /**
673          * One or more Synthesis script statements, separated
674          * and terminated with a semicolon. Can be left empty.
675          *
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()).
680          *
681          * This value is currently only used by sync sources which
682          * set m_profile.
683          */
684         std::string m_beforeWriteScript;
685
686         /**
687          * Same as m_beforeWriteScript, but used directly after
688          * converting a string into fields with PARSETEXTWITHPROFILE()
689          * in <afterreadscript>.
690          */
691         std::string m_afterReadScript;
692     };
693
694     /**
695      * helper function for getDatastoreXML(): fill in information
696      * as necessary
697      *
698      * @retval fragments   the necessary definitions for the other
699      *                     return values have to be added here
700      */
701     virtual void getSynthesisInfo(SynthesisInfo &info,
702                                   XMLConfigFragments &fragments) = 0;
703
704     /**
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)
708      *
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
715      */
716     std::string getDataTypeSupport(const std::string &type,
717                                    bool forceFormat);
718 };
719
720 /**
721  * SyncEvolution accesses all sources through this interface.
722  *
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.
730  *
731  * Error reporting is done via the Log class.
732  */
733 class SyncSource : virtual public SyncSourceBase, public SyncSourceConfig, public SyncSourceReport
734 {
735  public:
736     SyncSource(const SyncSourceParams &params) :
737         SyncSourceConfig(params.m_name, params.m_nodes),
738         m_numDeleted(0),
739         m_forceSlowSync(false)
740         {
741         }
742     virtual ~SyncSource() {}
743
744     /**
745      * SyncSource implementations must register themselves here via
746      * RegisterSyncSource
747      */
748     static SourceRegistry &getSourceRegistry();
749
750     /**
751      * SyncSource tests are registered here by the constructor of
752      * RegisterSyncSourceTest
753      */
754     static TestRegistry &getTestRegistry();
755
756     struct Database {
757     Database(const string &name, const string &uri, bool isDefault = false) :
758         m_name( name ), m_uri( uri ), m_isDefault(isDefault) {}
759         string m_name;
760         string m_uri;
761         bool m_isDefault;
762     };
763     typedef vector<Database> Databases;
764     
765     /**
766      * returns a list of all know data sources for the kind of items
767      * supported by this sync source
768      */
769     virtual Databases getDatabases() = 0;
770
771     /**
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.
775      *
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).
781      *
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.
785      */
786     virtual void open() = 0;
787
788     /**
789      * The optional operations.
790      *
791      * All of them are guaranteed to happen between open() and
792      * close().
793      *
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.
800      */
801     struct Operations {
802         /**
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.
808          */
809         struct BackupInfo {
810             enum Mode {
811                 BACKUP_BEFORE,   /**< directly at start of sync */
812                 BACKUP_AFTER,    /**< directly after sync */
813                 BACKUP_OTHER
814             } m_mode;
815             string m_dirname;
816             boost::shared_ptr<ConfigNode> m_node;
817             BackupInfo() {}
818             BackupInfo(Mode mode,
819                        const string &dirname,
820                        const boost::shared_ptr<ConfigNode> &node) :
821                 m_mode(mode),
822                 m_dirname(dirname),
823                 m_node(node)
824             {}
825         };
826         struct ConstBackupInfo {
827             BackupInfo::Mode m_mode;
828             string m_dirname;
829             boost::shared_ptr<const ConfigNode> m_node;
830             ConstBackupInfo() {}
831             ConstBackupInfo(BackupInfo::Mode mode,
832                             const string &dirname,
833                             const boost::shared_ptr<const ConfigNode> &node) :
834                 m_mode(mode),
835                 m_dirname(dirname),
836                 m_node(node)
837             {}
838         };
839
840         /**
841          * Dump all data from source unmodified into the given backup location.
842          * Information about the created backup is added to the
843          * report.
844          *
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.
850          *
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.)
854          */
855         typedef void (BackupData_t)(const ConstBackupInfo &oldBackup,
856                                     const BackupInfo &newBackup,
857                                     BackupReport &report);
858         boost::function<BackupData_t> m_backupData;
859
860         /**
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.
864          *
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)
870          */
871         typedef void (RestoreData_t)(const ConstBackupInfo &oldBackup,
872                                      bool dryrun,
873                                      SyncSourceReport &report);
874         boost::function<RestoreData_t> m_restoreData;
875
876         /**
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
880          *
881          * This method will be called to check for local changes without
882          * actually running a sync, so there is no matching end call.
883          *
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.
888          */
889         typedef void (CheckStatus_t)(SyncSourceReport &local);
890         boost::function<CheckStatus_t> m_checkStatus;
891
892         /**
893          * A quick check whether the source currently has data.
894          *
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
901          * to choose.
902          */
903         typedef bool (IsEmpty_t)();
904         boost::function<IsEmpty_t> m_isEmpty;
905
906         /**
907          * Synthesis DB API callbacks. For documentation see the
908          * Synthesis API specification (PDF and/or sync_dbapi.h).
909          *
910          * Implementing this is necessary for SyncSources which want
911          * to be part of a sync session.
912          */
913         /**@{*/
914         typedef void (Callback_t)();
915         typedef boost::function<Callback_t> CallbackFunctor_t;
916         typedef std::list<CallbackFunctor_t> Callbacks_t;
917
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;
921
922         typedef sysync::TSyError (StartDataRead_t)(const char *lastToken, const char *resumeToken);
923         boost::function<StartDataRead_t> m_startDataRead;
924
925         /** all of these functions will be called directly after
926             m_startDataRead() returned successfully */
927         Callbacks_t m_startSession;
928
929         typedef sysync::TSyError (EndDataRead_t)();
930         boost::function<EndDataRead_t> m_endDataRead;
931
932         typedef sysync::TSyError (StartDataWrite_t)();
933         boost::function<StartDataWrite_t> m_startDataWrite;
934
935         /** all of these functions will be called right
936             before m_endDataWrite() */
937         std::list<CallbackFunctor_t> m_endSession;
938
939         typedef sysync::TSyError (EndDataWrite_t)(bool success, char **newToken);
940         boost::function<EndDataWrite_t> m_endDataWrite;
941
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;
947         
948         typedef sysync::TSyError (ReadItemAsKey_t)(sysync::cItemID aID, sysync::KeyH aItemKey);
949         boost::function<ReadItemAsKey_t> m_readItemAsKey;
950
951         typedef sysync::TSyError (InsertItemAsKey_t)(sysync::KeyH aItemKey, sysync::ItemID newID);
952         boost::function<InsertItemAsKey_t> m_insertItemAsKey;
953         
954         typedef sysync::TSyError (UpdateItemAsKey_t)(sysync::KeyH aItemKey, sysync::cItemID aID, sysync::ItemID updID);
955         boost::function<UpdateItemAsKey_t> m_updateItemAsKey;
956
957         typedef sysync::TSyError (DeleteItem_t)(sysync::cItemID aID);
958         boost::function<DeleteItem_t> m_deleteItem;
959         /**@}*/
960
961
962         /**
963          * Synthesis administration callbacks. For documentation see the
964          * Synthesis API specification (PDF and/or sync_dbapi.h).
965          *
966          * Implementing this is *optional* in clients. In the Synthesis client
967          * engine, the "binfiles" module provides these calls without SyncEvolution
968          * doing anything.
969          *
970          * In the Synthesis server engine, the
971          * SyncSource::enableServerMode() call must install an
972          * implementation, like the one from SyncSourceAdmin.
973          */
974         /**@{*/
975         typedef sysync::TSyError (LoadAdminData_t)(const char *aLocDB,
976                                                    const char *aRemDB,
977                                                    char **adminData);
978         boost::function<LoadAdminData_t> m_loadAdminData;
979
980         typedef sysync::TSyError (SaveAdminData_t)(const char *adminData);
981         boost::function<SaveAdminData_t> m_saveAdminData;
982
983         typedef bool (ReadNextMapItem_t)(sysync::MapID mID, bool aFirst);
984         boost::function<ReadNextMapItem_t> m_readNextMapItem;
985
986         typedef sysync::TSyError (InsertMapItem_t)(sysync::cMapID mID);
987         boost::function<InsertMapItem_t> m_insertMapItem;
988
989         typedef sysync::TSyError (UpdateMapItem_t)(sysync::cMapID mID);
990         boost::function<UpdateMapItem_t> m_updateMapItem;
991
992         typedef sysync::TSyError (DeleteMapItem_t)(sysync::cMapID mID);
993         boost::function<DeleteMapItem_t> m_deleteMapItem;
994         /**@}*/
995     };
996     const Operations &getOperations() { return m_operations; }
997
998     /**
999      * outside users of the source are only allowed to add callbacks,
1000      * not overwrite arbitrary operations
1001      */
1002     void addCallback(Operations::CallbackFunctor_t callback, Operations::Callbacks_t Operations::* where) { (m_operations.*where).push_back(callback); }
1003         
1004     /**
1005      * closes the data source so that it can be reopened
1006      *
1007      * Just as open() it should not affect the state of
1008      * the database unless some previous action requires
1009      * it.
1010      */
1011     virtual void close() = 0;
1012
1013     /**
1014      * return Synthesis API pointer, if one currently is available
1015      * (between SyncEvolution_Module_CreateContext() and
1016      * SyncEvolution_Module_DeleteContext())
1017      */
1018     virtual SDKInterface *getSynthesisAPI() const;
1019
1020     /**
1021      * change the Synthesis API that is used by the source
1022      */
1023     void pushSynthesisAPI(sysync::SDK_InterfaceType *synthesisAPI);
1024
1025     /**
1026      * remove latest Synthesis API and return to previous one (if any)
1027      */
1028     void popSynthesisAPI();
1029
1030     /**
1031      * factory function for a SyncSource that provides the
1032      * source type specified in the params.m_nodes.m_configNode
1033      *
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)
1037      */
1038     static SyncSource *createSource(const SyncSourceParams &params,
1039                                     bool error = true,
1040                                     SyncConfig *config = NULL);
1041
1042     /**
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").
1046      *
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
1052      * database is used.
1053      *
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
1056      */
1057     static SyncSource *createTestingSource(const string &name, const string &type, bool error,
1058                                            const char *prefix = getenv("CLIENT_TEST_EVOLUTION_PREFIX"));
1059
1060     /**
1061      * Some information about available backends.
1062      * Multiple lines, formatted for users of the
1063      * command line.
1064      */
1065     static string backendsInfo();
1066     /**
1067      * Debug information about backends.
1068      */
1069     static string backendsDebug();
1070
1071     /**
1072      * Mime type a backend provides by default, this is used to alert the
1073      * remote peer in SAN during server alerted sync.
1074      */
1075     virtual const char *getPeerMimeType() const =0;
1076
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++; }
1082
1083     /**
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>.
1089      */
1090     void setForceSlowSync(bool forceSlowSync) { m_forceSlowSync = forceSlowSync; }
1091     bool getForceSlowSync() const { return m_forceSlowSync; }
1092
1093  protected:
1094     Operations m_operations;
1095
1096   private:
1097     /**
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.
1103      */
1104     long m_numDeleted;
1105
1106     bool m_forceSlowSync;
1107
1108     /**
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.
1114      */
1115     std::vector<sysync::SDK_InterfaceType *> m_synthesisAPI;
1116 };
1117
1118 /**
1119  * A SyncSource with no pure virtual functions.
1120  */
1121 class DummySyncSource : public SyncSource
1122 {
1123  public:
1124     DummySyncSource(const SyncSourceParams &params) :
1125        SyncSource(params) {}
1126
1127     DummySyncSource(const std::string &name) :
1128        SyncSource(SyncSourceParams(name)) {}
1129
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 "";} 
1138 };
1139
1140 /**
1141  * A special source which combines one or more real sources.
1142  * Most of the special handling for that is in SyncContext.cpp.
1143  *
1144  * This class can be instantiated, opened and closed if and only if
1145  * the underlying sources also support that.
1146  */
1147 class VirtualSyncSource : public DummySyncSource 
1148 {
1149     std::vector< boost::shared_ptr<SyncSource> > m_sources;
1150
1151 public:
1152     /**
1153      * @param config   optional: when given, the constructor will instantiate the
1154      *                 referenced underlying sources and check them in open()
1155      */
1156     VirtualSyncSource(const SyncSourceParams &params, SyncConfig *config = NULL);
1157
1158     /** opens underlying sources and checks config by calling getDataTypeSupport() */
1159     virtual void open();
1160     virtual void close();
1161
1162     /**
1163      * returns array with source names that are referenced by this
1164      * virtual source
1165      */
1166     std::vector<std::string> getMappedSources();
1167
1168     /**
1169      * returns <use datatype=...> statements for XML config,
1170      * throws error if not configured correctly
1171      */
1172     std::string getDataTypeSupport();
1173     using SyncSourceBase::getDataTypeSupport;
1174 };
1175
1176 /**
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.
1180  *
1181  * Inherit from this class in your sync source and call the init()
1182  * method to use it.
1183  */
1184 class SyncSourceSession : virtual public SyncSourceBase {
1185  public:
1186     /**
1187      * called before Synthesis engine starts to ask for changes and item data
1188      *
1189      * See BeingDataRead for details.
1190      *
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
1195      */
1196     virtual void beginSync(const std::string &lastToken, const std::string &resumeToken) = 0;
1197
1198     /**
1199      * called after completing or suspending the current sync
1200      *
1201      * See EndDataWrite for details.
1202      *
1203      * @return a token identifying this sync session for a future beginSync()
1204      */
1205     virtual std::string endSync(bool success) = 0;
1206
1207     /** set Synthesis DB Interface operations */
1208     void init(SyncSource::Operations &ops);
1209  private:
1210     sysync::TSyError startDataRead(const char *lastToken, const char *resumeToken);
1211     sysync::TSyError endDataWrite(bool success, char **newToken);
1212 };
1213
1214
1215 /**
1216  * Implements the Synthesis DB Interface for reporting item changes
1217  * (ReadNextItemAsKey) *without* actually delivering the item data.
1218  */
1219 class SyncSourceChanges : virtual public SyncSourceBase {
1220  public:
1221     SyncSourceChanges();
1222
1223     enum State {
1224         ANY,
1225         NEW,
1226         UPDATED,
1227         DELETED,
1228         MAX
1229     };
1230
1231     /**
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.
1236      *
1237      * For example, the luid of an updated item should be added with
1238      * addItem(luid [, ANY]) and again with addItem(luid, DELETED).
1239      *
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.
1246      *
1247      * @return true if the luid was already listed
1248      */
1249     bool addItem(const string &luid, State state = ANY);
1250
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]; }
1257
1258     /** set Synthesis DB Interface operations */
1259     void init(SyncSource::Operations &ops);
1260
1261  private:
1262     Items_t m_items[MAX];
1263     bool m_first;
1264     Items_t::const_iterator m_it;
1265
1266     sysync::TSyError iterate(sysync::ItemID aID,
1267                              sysync::sInt32 *aStatus,
1268                              bool aFirst);
1269 };
1270
1271 /**
1272  * Implements the Synthesis DB Interface for deleting an item
1273  * (DeleteItem). Increments number of deleted items in
1274  * SyncSourceBase.
1275  */
1276 class SyncSourceDelete : virtual public SyncSourceBase {
1277  public:
1278     virtual void deleteItem(const string &luid) = 0;
1279
1280     /** set Synthesis DB Interface operations */
1281     void init(SyncSource::Operations &ops);
1282
1283  private:
1284     sysync::TSyError deleteItemSynthesis(sysync::cItemID aID);
1285 };
1286
1287 /**
1288  * an interface for reading and writing items in the internal
1289  * format; see SyncSourceSerialize for an explanation
1290  */
1291 class SyncSourceRaw : virtual public SyncSourceBase {
1292  public:
1293     class InsertItemResult {
1294     public:
1295         InsertItemResult() :
1296             m_merged(false)
1297             {}
1298         
1299         /**
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
1304          */
1305         InsertItemResult(const string &luid,
1306                          const string &revision,
1307                          bool merged) :
1308         m_luid(luid),
1309             m_revision(revision),
1310             m_merged(merged)
1311             {}
1312
1313         string m_luid;
1314         string m_revision;
1315         bool m_merged;
1316     };
1317
1318     /** same as SyncSourceSerialize::insertItem(), but with internal format */
1319     virtual InsertItemResult insertItemRaw(const std::string &luid, const std::string &item) = 0;
1320
1321     /** same as SyncSourceSerialize::readItem(), but with internal format */
1322     virtual void readItemRaw(const std::string &luid, std::string &item) = 0;
1323 };
1324
1325 /**
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.
1330  *
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
1335  *   and testing
1336  *
1337  * To give an example, the EvolutionMemoSource uses plain text as
1338  * engine format and iCalendar 2.0 as raw format.
1339  *
1340  * The BackupData_t and RestoreData_t operations are implemented by
1341  * this class using the internal format.
1342  *
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.
1352  *
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.
1359  */
1360 class SyncSourceSerialize : virtual public SyncSourceBase, virtual public SyncSourceRaw {
1361  public:
1362     /**
1363      * Returns the preferred mime type of the items handled by the sync source.
1364      * Example: "text/x-vcard"
1365      */
1366     virtual const char *getMimeType() const = 0;
1367
1368     /**
1369      * Returns the version of the mime type used by client.
1370      * Example: "2.1"
1371      */
1372     virtual const char *getMimeVersion() const = 0;
1373
1374     /**
1375      * returns the backend selection and configuration
1376      */
1377     virtual SourceType getSourceType() const = 0;
1378
1379     /**
1380      * Create or modify an item.
1381      *
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.
1388      *
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.
1392      *
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.
1396      *
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
1400      */
1401     virtual InsertItemResult insertItem(const std::string &luid, const std::string &item) = 0;
1402
1403     /**
1404      * Return item data in engine format.
1405      *
1406      * @param luid     identifies the item
1407      * @retval item    item data
1408      */
1409     virtual void readItem(const std::string &luid, std::string &item) = 0;
1410
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); }
1414
1415     /** set Synthesis DB Interface operations */
1416     void init(SyncSource::Operations &ops);
1417
1418  protected:
1419     /**
1420      * used getMimeType(), getMimeVersion() and getSourceType()
1421      * to provide the information necessary for automatic
1422      * conversion to the sync source's internal item representation
1423      */
1424     virtual void getSynthesisInfo(SynthesisInfo &info,
1425                                   XMLConfigFragments &fragments);
1426  private:
1427     sysync::TSyError readItemAsKey(sysync::cItemID aID, sysync::KeyH aItemKey);
1428     sysync::TSyError insertItemAsKey(sysync::KeyH aItemKey, sysync::cItemID aID, sysync::ItemID newID);
1429 };
1430
1431 /**
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
1437  * both.
1438  *
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)
1444  *
1445  * Sync sources which want to use this functionality have to provide
1446  * the following functionality by implementing the pure virtual
1447  * functions below:
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.
1459  *
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().
1463  *
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
1469  * init call.
1470  */
1471 class SyncSourceRevisions : virtual public SyncSourceChanges, virtual public SyncSourceBase {
1472  public:
1473     typedef map<string, string> RevisionMap_t;
1474
1475     /**
1476      * fills the complete mapping from UID to revision string of all
1477      * currently existing items
1478      *
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.
1486      *
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.
1490      */
1491     virtual void listAllItems(RevisionMap_t &revisions) = 0;
1492
1493     /**
1494      * calculate changes, call when sync source is ready for
1495      * listAllItems() and before changes are needed
1496      *
1497      * The trackingNode must be provided by the caller. It will
1498      * be updated by each of the calls and must be stored by
1499      * the caller.
1500      *
1501      * @param trackingNode     a config node for exclusive use by this class
1502      */
1503     void detectChanges(ConfigNode &trackingNode);
1504
1505     /**
1506      * record that an item was added or updated
1507      *
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
1511      */
1512     void updateRevision(ConfigNode &trackingNode,
1513                         const std::string &old_luid,
1514                         const std::string &new_luid,
1515                         const std::string &revision);
1516
1517     /**
1518      * record that we deleted an item
1519      *
1520      * @param luid        the obsolete LUID
1521      */
1522     void deleteRevision(ConfigNode &trackingNode,
1523                         const std::string &luid);
1524
1525     /**
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
1533      *                      not add up.
1534      */
1535     void init(SyncSourceRaw *raw, SyncSourceDelete *del,
1536               int granularity,
1537               SyncSource::Operations &ops);
1538
1539  private:
1540     SyncSourceRaw *m_raw;
1541     SyncSourceDelete *m_del;
1542     int m_revisionAccuracySeconds;
1543
1544     /** buffers the result of the initial listAllItems() call */
1545     RevisionMap_t m_revisions;
1546     bool m_revisionsSet;
1547     void initRevisions();
1548
1549     /**
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.
1553      */
1554     void backupData(const SyncSource::Operations::ConstBackupInfo &oldBackup,
1555                     const SyncSource::Operations::BackupInfo &newBackup,
1556                     BackupReport &report);
1557
1558     /**
1559      * Restore database from data stored in backupData(). Will be
1560      * called inside open()/close() pair. beginSync() is *not* called.
1561      */
1562     void restoreData(const SyncSource::Operations::ConstBackupInfo &oldBackup,
1563                      bool dryrun,
1564                      SyncSourceReport &report);
1565
1566     /**
1567      * Increments the time stamp of the latest database modification,
1568      * called automatically whenever revisions change.
1569      */
1570     void databaseModified();
1571
1572     /** time stamp of latest database modification, for sleepSinceModification() */
1573     time_t m_modTimeStamp;
1574     void sleepSinceModification();
1575 };
1576
1577
1578 /**
1579  * Common logging for sync sources.
1580  *
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).
1586  */
1587 class SyncSourceLogging : public virtual SyncSourceBase
1588 {
1589  public:
1590     /**
1591      * wrap Synthesis DB Interface operations
1592      *
1593      * @param fields     list of fields to read in getDescription()
1594      * @param sep        separator between non-empty fields
1595      */
1596     void init(const std::list<std::string> &fields,
1597               const std::string &sep,
1598               SyncSource::Operations &ops);
1599
1600     /**
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
1604      * with a separator.
1605      *
1606      * @param aItemKey     key for reading fields
1607      * @return description, empty string will cause the ID of the item to be printed
1608      */
1609     virtual std::string getDescription(sysync::KeyH aItemKey);
1610
1611     /**
1612      * Extract short description from backend.
1613      * Necessary for deleted items. The default implementation
1614      * returns an empty string, so that implementing this
1615      * is optional.
1616      *
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
1619      */
1620     virtual std::string getDescription(const string &luid);
1621
1622  private:
1623     std::list<std::string> m_fields;
1624     std::string m_sep;
1625
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);
1632 };
1633
1634 /**
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.
1638  */
1639 class SyncSourceAdmin : public virtual SyncSourceBase
1640 {
1641     boost::shared_ptr<ConfigNode> m_configNode;
1642     std::string m_adminPropertyName;
1643     boost::shared_ptr<ConfigNode> m_mappingNode;
1644     bool m_mappingLoaded;
1645
1646     ConfigProps m_mapping;
1647     ConfigProps::const_iterator m_mappingIterator;
1648
1649     sysync::TSyError loadAdminData(const char *aLocDB,
1650                                    const char *aRemDB,
1651                                    char **adminData);
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);
1657     void flush();
1658
1659     void resetMap();
1660     void mapid2entry(sysync::cMapID mID, string &key, string &value);
1661     void entry2mapid(const string &key, const string &value, sysync::MapID mID);
1662
1663  public:
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);
1669
1670     /**
1671      * simpler initialization, using the default placement of data
1672      * inside the SyncSourceConfig base class
1673      */
1674     void init(SyncSource::Operations &ops, SyncSource *source);
1675 };
1676
1677 /**
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).
1684  */
1685 class TestingSyncSource : public SyncSource,
1686     virtual public SyncSourceSession,
1687     virtual public SyncSourceChanges,
1688     virtual public SyncSourceDelete,
1689     virtual public SyncSourceSerialize {
1690  public:
1691     TestingSyncSource(const SyncSourceParams &params) :
1692        SyncSource(params)
1693     {
1694         SyncSourceSession::init(m_operations);
1695         SyncSourceChanges::init(m_operations);
1696         SyncSourceDelete::init(m_operations);
1697         SyncSourceSerialize::init(m_operations);
1698     }
1699     ~TestingSyncSource() {}
1700
1701     virtual SourceType getSourceType() const { return SyncSourceConfig::getSourceType(); }
1702
1703     void removeAllItems() {
1704         BOOST_FOREACH(const string &luid, getAllItems()) {
1705             deleteItem(luid);
1706         }
1707     }
1708 };
1709
1710
1711 SE_END_CXX
1712 #endif // INCL_SYNCSOURCE