summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/synchronizer.cpp14
-rw-r--r--common/synchronizer.h2
-rw-r--r--examples/caldavresource/caldavresource.cpp71
-rw-r--r--examples/caldavresource/tests/caldavtest.cpp250
-rw-r--r--examples/webdavcommon/webdav.cpp83
-rw-r--r--examples/webdavcommon/webdav.h39
6 files changed, 424 insertions, 35 deletions
diff --git a/common/synchronizer.cpp b/common/synchronizer.cpp
index aa4f030..fa16002 100644
--- a/common/synchronizer.cpp
+++ b/common/synchronizer.cpp
@@ -632,6 +632,10 @@ KAsync::Job<void> Synchronizer::replay(const QByteArray &type, const QByteArray
632 job = replay(store().readEntity<ApplicationDomain::Contact>(key), operation, oldRemoteId, modifiedProperties); 632 job = replay(store().readEntity<ApplicationDomain::Contact>(key), operation, oldRemoteId, modifiedProperties);
633 } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Addressbook>()) { 633 } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Addressbook>()) {
634 job = replay(store().readEntity<ApplicationDomain::Addressbook>(key), operation, oldRemoteId, modifiedProperties); 634 job = replay(store().readEntity<ApplicationDomain::Addressbook>(key), operation, oldRemoteId, modifiedProperties);
635 } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Event>()) {
636 job = replay(store().readEntity<ApplicationDomain::Event>(key), operation, oldRemoteId, modifiedProperties);
637 } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Calendar>()) {
638 job = replay(store().readEntity<ApplicationDomain::Calendar>(key), operation, oldRemoteId, modifiedProperties);
635 } else { 639 } else {
636 SinkErrorCtx(mLogCtx) << "Replayed unknown type: " << type; 640 SinkErrorCtx(mLogCtx) << "Replayed unknown type: " << type;
637 } 641 }
@@ -688,6 +692,16 @@ KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Folder &,
688 return KAsync::null<QByteArray>(); 692 return KAsync::null<QByteArray>();
689} 693}
690 694
695KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Event &, Sink::Operation, const QByteArray &, const QList<QByteArray> &)
696{
697 return KAsync::null<QByteArray>();
698}
699
700KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Calendar &, Sink::Operation, const QByteArray &, const QList<QByteArray> &)
701{
702 return KAsync::null<QByteArray>();
703}
704
691bool Synchronizer::allChangesReplayed() 705bool Synchronizer::allChangesReplayed()
692{ 706{
693 if (!mSyncRequestQueue.isEmpty()) { 707 if (!mSyncRequestQueue.isEmpty()) {
diff --git a/common/synchronizer.h b/common/synchronizer.h
index 16905d7..2a3c3d8 100644
--- a/common/synchronizer.h
+++ b/common/synchronizer.h
@@ -79,6 +79,8 @@ protected:
79 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Addressbook &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); 79 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Addressbook &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
80 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Mail &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); 80 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Mail &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
81 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Folder &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); 81 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Folder &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
82 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Event &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
83 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Calendar &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
82protected: 84protected:
83 QString secret() const; 85 QString secret() const;
84 86
diff --git a/examples/caldavresource/caldavresource.cpp b/examples/caldavresource/caldavresource.cpp
index 6bf1a27..3fbd624 100644
--- a/examples/caldavresource/caldavresource.cpp
+++ b/examples/caldavresource/caldavresource.cpp
@@ -107,6 +107,77 @@ protected:
107 { 107 {
108 return syncStore().resolveRemoteId(ENTITY_TYPE_CALENDAR, resourceID(calendar)); 108 return syncStore().resolveRemoteId(ENTITY_TYPE_CALENDAR, resourceID(calendar));
109 } 109 }
110
111 KAsync::Job<QByteArray> replay(const Event &event, Sink::Operation operation,
112 const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE
113 {
114 SinkLog() << "Replaying event";
115
116 //auto incidence = KCalCore::ICalFormat().readIncidence(rawIcal);
117
118 KDAV2::DavItem item;
119
120 switch (operation) {
121 case Sink::Operation_Creation: {
122 SinkLog() << "Replaying creation";
123
124 auto rawIcal = event.getIcal();
125 if(rawIcal == "") {
126 return KAsync::error<QByteArray>("No ICal in event for creation replay");
127 }
128
129 auto collectionId = syncStore().resolveLocalId(ENTITY_TYPE_CALENDAR, event.getCalendar());
130
131 item.setData(rawIcal);
132 item.setContentType("text/calendar");
133 item.setUrl(urlOf(collectionId, event.getUid()));
134
135 return createItem(item).then([item] { return resourceID(item); });
136 }
137 case Sink::Operation_Removal: {
138 // We only need the URL in the DAV item for removal
139 item.setUrl(urlOf(oldRemoteId));
140
141 return removeItem(item).then([oldRemoteId] { return oldRemoteId; });
142 }
143 case Sink::Operation_Modification:
144 SinkLog() << "Replaying modification";
145
146 auto rawIcal = event.getIcal();
147 if(rawIcal == "") {
148 return KAsync::error<QByteArray>("No ICal in event for modification replay");
149 }
150
151 item.setData(rawIcal);
152 item.setContentType("text/calendar");
153 item.setUrl(urlOf(oldRemoteId));
154
155 // It would be nice to check that the URL of the item hasn't
156 // changed and move he item if it did, but since the URL is
157 // pretty much arbitrary, whoe does that anyway?
158 return modifyItem(item).then([oldRemoteId] { return oldRemoteId; });
159 }
160 }
161
162 KAsync::Job<QByteArray> replay(const Calendar &calendar, Sink::Operation operation,
163 const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE
164 {
165
166 // TODO: add the URL to list of attributes, can't do nothing otherwise
167 switch (operation) {
168 case Sink::Operation_Creation:
169 SinkLog() << "Replaying calendar creation";
170 break;
171 case Sink::Operation_Removal:
172 SinkLog() << "Replaying calendar removal";
173 break;
174 case Sink::Operation_Modification:
175 SinkLog() << "Replaying calendar modification";
176 break;
177 }
178
179 return KAsync::null<QByteArray>();
180 }
110}; 181};
111 182
112CalDavResource::CalDavResource(const Sink::ResourceContext &context) 183CalDavResource::CalDavResource(const Sink::ResourceContext &context)
diff --git a/examples/caldavresource/tests/caldavtest.cpp b/examples/caldavresource/tests/caldavtest.cpp
index 584e288..35ab033 100644
--- a/examples/caldavresource/tests/caldavtest.cpp
+++ b/examples/caldavresource/tests/caldavtest.cpp
@@ -1,5 +1,14 @@
1#include <QtTest> 1#include <QtTest>
2 2
3#include <KDAV2/DavCollectionsFetchJob>
4#include <KDAV2/DavItemFetchJob>
5#include <KDAV2/DavItemModifyJob>
6#include <KDAV2/DavItemsListJob>
7#include <KDAV2/EtagCache>
8
9#include <KCalCore/Event>
10#include <KCalCore/ICalFormat>
11
3#include "../caldavresource.h" 12#include "../caldavresource.h"
4 13
5#include "common/resourcecontrol.h" 14#include "common/resourcecontrol.h"
@@ -8,6 +17,8 @@
8#include "common/test.h" 17#include "common/test.h"
9#include "tests/testutils.h" 18#include "tests/testutils.h"
10 19
20#include <algorithm>
21
11using Sink::ApplicationDomain::Calendar; 22using Sink::ApplicationDomain::Calendar;
12using Sink::ApplicationDomain::DummyResource; 23using Sink::ApplicationDomain::DummyResource;
13using Sink::ApplicationDomain::Event; 24using Sink::ApplicationDomain::Event;
@@ -20,16 +31,17 @@ class CalDavTest : public QObject
20 SinkResource createResource() 31 SinkResource createResource()
21 { 32 {
22 auto resource = Sink::ApplicationDomain::CalDavResource::create("account1"); 33 auto resource = Sink::ApplicationDomain::CalDavResource::create("account1");
23 resource.setProperty("server", "http://localhost/dav/calendars/users/doe"); 34 resource.setProperty("server", "http://localhost:5232");
24 resource.setProperty("username", "doe"); 35 resource.setProperty("username", "test1");
25 Sink::SecretStore::instance().insert(resource.identifier(), "doe"); 36 Sink::SecretStore::instance().insert(resource.identifier(), "test1");
26 resource.setProperty("testmode", true); 37 resource.setProperty("testmode", true);
27 return resource; 38 return resource;
28 } 39 }
29 40
30
31 QByteArray mResourceInstanceIdentifier; 41 QByteArray mResourceInstanceIdentifier;
32 42
43 QString addedEventUid;
44
33private slots: 45private slots:
34 46
35 void initTestCase() 47 void initTestCase()
@@ -51,34 +63,208 @@ private slots:
51 VERIFYEXEC(Sink::ResourceControl::start(mResourceInstanceIdentifier)); 63 VERIFYEXEC(Sink::ResourceControl::start(mResourceInstanceIdentifier));
52 } 64 }
53 65
54 // void testSyncCal() 66 void testSyncCal()
55 // { 67 {
56 // VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); 68 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
57 // // Check in the logs that it doesn't synchronize events again because same CTag 69 // Check in the logs that it doesn't synchronize events again because same CTag
58 // VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); 70 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
59 // } 71 }
60 72
61 // void testSyncCalEmpty() 73 void testSyncCalEmpty()
62 // { 74 {
63 // VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); 75 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
64 76 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
65 // auto eventJob = 77
66 // Sink::Store::fetchAll<Event>(Sink::Query().request<Event::Uid>()).then([](const QList<Event::Ptr> &events) { 78 auto eventJob = Sink::Store::fetchAll<Event>(Sink::Query().request<Event::Uid>())
67 // QCOMPARE(events.size(), 14); 79 .then([](const QList<Event::Ptr> &events) { QCOMPARE(events.size(), 1); });
68 // }); 80 VERIFYEXEC(eventJob);
69 // VERIFYEXEC(eventJob); 81
70 82 auto calendarJob = Sink::Store::fetchAll<Calendar>(Sink::Query().request<Calendar::Name>())
71 // auto calendarJob = 83 .then([](const QList<Calendar::Ptr> &calendars) {
72 // Sink::Store::fetchAll<Calendar>(Sink::Query().request<Calendar::Name>()).then([](const QList<Calendar::Ptr> &calendars) { 84 QCOMPARE(calendars.size(), 1);
73 // QCOMPARE(calendars.size(), 2); 85 for (const auto &calendar : calendars) {
74 // for (const auto &calendar : calendars) { 86 QVERIFY(calendar->getName() == "MyCalendar");
75 // QVERIFY(calendar->getName() == "Calendar" || calendar->getName() == "Tasks"); 87 }
76 // } 88 });
77 // }); 89 VERIFYEXEC(calendarJob);
78 // VERIFYEXEC(calendarJob); 90
79 91 SinkLog() << "Finished";
80 // SinkLog() << "Finished"; 92 }
81 // } 93
94 void testAddEvent()
95 {
96 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
97 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
98
99 auto job = Sink::Store::fetchOne<Calendar>({}).exec();
100 job.waitForFinished();
101 QVERIFY2(!job.errorCode(), "Fetching Calendar failed");
102 auto calendar = job.value();
103
104 auto event = QSharedPointer<KCalCore::Event>::create();
105 event->setSummary("Hello");
106 event->setDtStart(QDateTime::currentDateTime());
107 event->setDtEnd(QDateTime::currentDateTime().addSecs(3600));
108 event->setCreated(QDateTime::currentDateTime());
109 addedEventUid = QUuid::createUuid().toString();
110 event->setUid(addedEventUid);
111
112 auto ical = KCalCore::ICalFormat().toICalString(event);
113 Event sinkEvent(mResourceInstanceIdentifier);
114 sinkEvent.setIcal(ical.toUtf8());
115 sinkEvent.setCalendar(calendar);
116
117 SinkLog() << "Adding event";
118 VERIFYEXEC(Sink::Store::create(sinkEvent));
119 VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
120
121 auto verifyEventCountJob =
122 Sink::Store::fetchAll<Event>(Sink::Query().request<Event::Uid>()).then([](const QList<Event::Ptr> &events) {
123 QCOMPARE(events.size(), 2);
124 });
125 VERIFYEXEC(verifyEventCountJob);
126
127 auto verifyEventJob =
128 Sink::Store::fetchOne<Event>(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)))
129 .then([](const Event &event) { QCOMPARE(event.getSummary(), "Hello"); });
130 VERIFYEXEC(verifyEventJob);
131 }
132
133 void testModifyEvent()
134 {
135 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
136 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
137
138 auto job = Sink::Store::fetchOne<Event>(
139 Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)))
140 .exec();
141 job.waitForFinished();
142 QVERIFY2(!job.errorCode(), "Fetching Event failed");
143 auto event = job.value();
144
145 auto incidence = KCalCore::ICalFormat().readIncidence(event.getIcal());
146 auto calevent = incidence.dynamicCast<KCalCore::Event>();
147 QVERIFY2(calevent, "Cannot convert to KCalCore event");
148
149 calevent->setSummary("Hello World!");
150 auto dummy = QSharedPointer<KCalCore::Event>(calevent);
151 auto newical = KCalCore::ICalFormat().toICalString(dummy);
152
153 event.setIcal(newical.toUtf8());
154
155 VERIFYEXEC(Sink::Store::modify(event));
156
157 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
158 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
159
160 auto verifyEventCountJob = Sink::Store::fetchAll<Event>({}).then(
161 [](const QList<Event::Ptr> &events) { QCOMPARE(events.size(), 2); });
162 VERIFYEXEC(verifyEventCountJob);
163
164 auto verifyEventJob =
165 Sink::Store::fetchOne<Event>(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)))
166 .then([](const Event &event) { QCOMPARE(event.getSummary(), "Hello World!"); });
167 VERIFYEXEC(verifyEventJob);
168 }
169
170 void testSneakyModifyEvent()
171 {
172 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
173 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
174
175 // Change the item without sink's knowledge
176 {
177 qWarning() << 1;
178 auto collection = ([]() -> KDAV2::DavCollection {
179 KDAV2::DavUrl davurl({ "http://test1:test1@localhost:5232" }, KDAV2::CalDav);
180 KDAV2::DavCollectionsFetchJob collectionsJob(davurl);
181 collectionsJob.exec();
182 Q_ASSERT(collectionsJob.error() == 0);
183 return collectionsJob.collections()[0];
184 })();
185
186 auto itemList = ([&collection]() -> KDAV2::DavItem::List {
187 auto cache = std::make_shared<KDAV2::EtagCache>();
188 KDAV2::DavItemsListJob itemsListJob(collection.url(), cache);
189 itemsListJob.exec();
190 Q_ASSERT(itemsListJob.error() == 0);
191 return itemsListJob.items();
192 })();
193 auto hollowDavItemIt =
194 std::find_if(itemList.begin(), itemList.end(), [this](const KDAV2::DavItem &item) {
195 return item.url().url().path().endsWith(addedEventUid);
196 });
197
198 auto davitem = ([this, &collection, &hollowDavItemIt]() -> KDAV2::DavItem {
199 QString itemUrl = collection.url().url().toEncoded() + addedEventUid;
200 KDAV2::DavItemFetchJob itemFetchJob(*hollowDavItemIt);
201 itemFetchJob.exec();
202 Q_ASSERT(itemFetchJob.error() == 0);
203 return itemFetchJob.item();
204 })();
205
206 qWarning() << 3;
207 auto incidence = KCalCore::ICalFormat().readIncidence(davitem.data());
208 auto calevent = incidence.dynamicCast<KCalCore::Event>();
209 QVERIFY2(calevent, "Cannot convert to KCalCore event");
210
211 qWarning() << 4;
212 calevent->setSummary("Manual Hello World!");
213 auto newical = KCalCore::ICalFormat().toICalString(calevent);
214
215 qWarning() << 5;
216 davitem.setData(newical.toUtf8());
217 KDAV2::DavItemModifyJob itemModifyJob(davitem);
218 itemModifyJob.exec();
219 QVERIFY2(itemModifyJob.error() == 0, "Cannot modify item");
220
221 qWarning() << 6;
222 }
223
224 // Try to change the item with sink
225 {
226 auto job = Sink::Store::fetchOne<Event>(
227 Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)))
228 .exec();
229 job.waitForFinished();
230 QVERIFY2(!job.errorCode(), "Fetching Event failed");
231 auto event = job.value();
232
233 auto incidence = KCalCore::ICalFormat().readIncidence(event.getIcal());
234 auto calevent = incidence.dynamicCast<KCalCore::Event>();
235 QVERIFY2(calevent, "Cannot convert to KCalCore event");
236
237 calevent->setSummary("Sink Hello World!");
238 auto dummy = QSharedPointer<KCalCore::Event>(calevent);
239 auto newical = KCalCore::ICalFormat().toICalString(dummy);
240
241 event.setIcal(newical.toUtf8());
242
243 // TODO: make that fail
244 VERIFYEXEC(Sink::Store::modify(event));
245 VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
246 }
247 }
248
249 void testRemoveEvent()
250 {
251 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
252 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
253
254 auto job = Sink::Store::fetchOne<Event>(
255 Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)))
256 .exec();
257 job.waitForFinished();
258 QVERIFY2(!job.errorCode(), "Fetching Event failed");
259 auto event = job.value();
260
261 VERIFYEXEC(Sink::Store::remove(event));
262 VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
263
264 auto verifyEventCountJob = Sink::Store::fetchAll<Event>({}).then(
265 [](const QList<Event::Ptr> &events) { QCOMPARE(events.size(), 1); });
266 VERIFYEXEC(verifyEventCountJob);
267 }
82}; 268};
83 269
84QTEST_MAIN(CalDavTest) 270QTEST_MAIN(CalDavTest)
diff --git a/examples/webdavcommon/webdav.cpp b/examples/webdavcommon/webdav.cpp
index ad1af35..f97a866 100644
--- a/examples/webdavcommon/webdav.cpp
+++ b/examples/webdavcommon/webdav.cpp
@@ -22,8 +22,13 @@
22#include "applicationdomaintype.h" 22#include "applicationdomaintype.h"
23#include "resourceconfig.h" 23#include "resourceconfig.h"
24 24
25#include <KDAV2/DavCollectionDeleteJob>
26#include <KDAV2/DavCollectionModifyJob>
25#include <KDAV2/DavCollectionsFetchJob> 27#include <KDAV2/DavCollectionsFetchJob>
28#include <KDAV2/DavItemCreateJob>
29#include <KDAV2/DavItemDeleteJob>
26#include <KDAV2/DavItemFetchJob> 30#include <KDAV2/DavItemFetchJob>
31#include <KDAV2/DavItemModifyJob>
27#include <KDAV2/DavItemsListJob> 32#include <KDAV2/DavItemsListJob>
28#include <KDAV2/EtagCache> 33#include <KDAV2/EtagCache>
29 34
@@ -180,7 +185,6 @@ KAsync::Job<void> WebDavSynchronizer::synchronizeCollection(const KDAV2::DavColl
180 185
181 auto localRid = collectionLocalResourceID(collection); 186 auto localRid = collectionLocalResourceID(collection);
182 187
183 // The ETag cache is useless here, since `sinkStore()` IS the cache.
184 auto cache = std::make_shared<KDAV2::EtagCache>(); 188 auto cache = std::make_shared<KDAV2::EtagCache>();
185 auto davItemsListJob = new KDAV2::DavItemsListJob(collection.url(), std::move(cache)); 189 auto davItemsListJob = new KDAV2::DavItemsListJob(collection.url(), std::move(cache));
186 190
@@ -234,14 +238,87 @@ KAsync::Job<void> WebDavSynchronizer::synchronizeItem(const KDAV2::DavItem &item
234 }); 238 });
235} 239}
236 240
241KAsync::Job<void> WebDavSynchronizer::createItem(const KDAV2::DavItem &item)
242{
243 auto job = new KDAV2::DavItemCreateJob(item);
244 return runJob(job).then([] {
245 SinkLog() << "Done creating item";
246 });
247}
248
249KAsync::Job<void> WebDavSynchronizer::removeItem(const KDAV2::DavItem &item)
250{
251 auto job = new KDAV2::DavItemDeleteJob(item);
252 return runJob(job).then([] {
253 SinkLog() << "Done removing item";
254 });
255}
256
257KAsync::Job<void> WebDavSynchronizer::modifyItem(const KDAV2::DavItem &item)
258{
259 auto job = new KDAV2::DavItemModifyJob(item);
260 return runJob(job).then([] {
261 SinkLog() << "Done modifying item";
262 });
263}
264
265/*
266KAsync::Job<void> WebDavSynchronizer::createCollection(const KDAV2::DavCollection &collection)
267{
268 auto job = new KDAV2::DavCollectionCreateJob(collection);
269 return runJob(job);
270}
271*/
272
273KAsync::Job<void> WebDavSynchronizer::removeCollection(const KDAV2::DavUrl &url)
274{
275 auto job = new KDAV2::DavCollectionDeleteJob(url);
276 return runJob(job);
277}
278
279KAsync::Job<void> WebDavSynchronizer::modifyCollection(const KDAV2::DavUrl &url)
280{
281 auto job = new KDAV2::DavCollectionModifyJob(url);
282 return runJob(job);
283}
284
285/*
286KAsync::Job<QByteArray> WebDavSynchronizer::replay(const Contact &, Sink::Operation operation,
287 const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties)
288{
289 return replayItem(Sink::ApplicationDomain::getTypeName<Contact>(), operation, oldRemoteId,
290changedProperties);
291}
292
293KAsync::Job<QByteArray> WebDavSynchronizer::replay(const Addressbook &, Sink::Operation operation,
294 const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties)
295{
296 return replayCollection(Sink::ApplicationDomain::getTypeName<Addressbook>(), operation,
297 oldRemoteId, changedProperties);
298}
299*/
300
237QByteArray WebDavSynchronizer::resourceID(const KDAV2::DavCollection &collection) 301QByteArray WebDavSynchronizer::resourceID(const KDAV2::DavCollection &collection)
238{ 302{
239 return collection.url().toDisplayString().toUtf8(); 303 return collection.url().url().toEncoded();
240} 304}
241 305
242QByteArray WebDavSynchronizer::resourceID(const KDAV2::DavItem &item) 306QByteArray WebDavSynchronizer::resourceID(const KDAV2::DavItem &item)
243{ 307{
244 return item.url().toDisplayString().toUtf8(); 308 return item.url().url().toEncoded();
309}
310
311KDAV2::DavUrl WebDavSynchronizer::urlOf(const QByteArray &remoteId)
312{
313 auto url = QUrl::fromEncoded(remoteId);
314 auto davurl = serverUrl();
315 davurl.setUrl(url);
316 return davurl;
317}
318
319KDAV2::DavUrl WebDavSynchronizer::urlOf(const QByteArray &collectionRemoteId, const QString &itemPath)
320{
321 return urlOf(collectionRemoteId + "/" + itemPath.toUtf8());
245} 322}
246 323
247bool WebDavSynchronizer::unchanged(const KDAV2::DavCollection &collection) 324bool WebDavSynchronizer::unchanged(const KDAV2::DavCollection &collection)
diff --git a/examples/webdavcommon/webdav.h b/examples/webdavcommon/webdav.h
index 3a4977c..ecb6a81 100644
--- a/examples/webdavcommon/webdav.h
+++ b/examples/webdavcommon/webdav.h
@@ -35,6 +35,32 @@ public:
35 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE; 35 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE;
36 36
37protected: 37protected:
38
39 /**
40 * Called in a child synchronizer, when replaying a creation of an item.
41 */
42 KAsync::Job<void> createItem(const KDAV2::DavItem &);
43
44 /**
45 * Called in a child synchronizer, when replaying a removal of an item.
46 */
47 KAsync::Job<void> removeItem(const KDAV2::DavItem &);
48
49 /**
50 * Called in a child synchronizer, when replaying a modification of an item.
51 *
52 * The item to modify is chosen according to the given item's URL.
53 * The job will fail if the ETag does not match.
54 */
55 KAsync::Job<void> modifyItem(const KDAV2::DavItem &);
56
57 /**
58 * See comments of the *Item version above
59 */
60 KAsync::Job<void> createCollection(const KDAV2::DavUrl &);
61 KAsync::Job<void> removeCollection(const KDAV2::DavUrl &);
62 KAsync::Job<void> modifyCollection(const KDAV2::DavUrl &);
63
38 /** 64 /**
39 * Called with the list of discovered collections. It's purpose should be 65 * Called with the list of discovered collections. It's purpose should be
40 * adding the said collections to the store. 66 * adding the said collections to the store.
@@ -63,6 +89,19 @@ protected:
63 static QByteArray resourceID(const KDAV2::DavCollection &); 89 static QByteArray resourceID(const KDAV2::DavCollection &);
64 static QByteArray resourceID(const KDAV2::DavItem &); 90 static QByteArray resourceID(const KDAV2::DavItem &);
65 91
92 /**
93 * Used to get the url of an item / collection with the given remote ID
94 */
95 KDAV2::DavUrl urlOf(const QByteArray &remoteId);
96
97 /**
98 * Used to get the url of an item / collection with the given remote ID,
99 * and append `itemPath` to the path of the URI.
100 *
101 * Useful when adding a new item to a collection
102 */
103 KDAV2::DavUrl urlOf(const QByteArray &collectionRemoteId, const QString &itemPath);
104
66 bool unchanged(const KDAV2::DavCollection &); 105 bool unchanged(const KDAV2::DavCollection &);
67 bool unchanged(const KDAV2::DavItem &); 106 bool unchanged(const KDAV2::DavItem &);
68 107