summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/CMakeLists.txt2
-rw-r--r--common/domain/addressbook.cpp54
-rw-r--r--common/domain/addressbook.fbs9
-rw-r--r--common/domain/addressbook.h51
-rw-r--r--common/domain/applicationdomaintype.cpp15
-rw-r--r--common/domain/applicationdomaintype.h12
-rw-r--r--common/domain/applicationdomaintype_p.h8
-rw-r--r--common/domain/contact.cpp5
-rw-r--r--common/domain/contact.fbs1
-rw-r--r--common/domain/contact.h3
-rw-r--r--common/domain/domaintypes.h1
-rw-r--r--common/domainadaptor.h5
-rw-r--r--common/synchronizer.cpp11
-rw-r--r--common/synchronizer.h2
-rw-r--r--examples/davresource/CMakeLists.txt6
-rw-r--r--examples/davresource/davresource.cpp374
-rw-r--r--examples/davresource/facade.cpp6
-rw-r--r--examples/davresource/facade.h6
-rw-r--r--sinksh/sinksh_utils.cpp4
19 files changed, 222 insertions, 353 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index b5275e0..a10f84f 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -62,6 +62,7 @@ set(command_SRCS
62 domain/propertyregistry.cpp 62 domain/propertyregistry.cpp
63 domain/applicationdomaintype.cpp 63 domain/applicationdomaintype.cpp
64 domain/contact.cpp 64 domain/contact.cpp
65 domain/addressbook.cpp
65 domain/event.cpp 66 domain/event.cpp
66 domain/mail.cpp 67 domain/mail.cpp
67 domain/folder.cpp 68 domain/folder.cpp
@@ -101,6 +102,7 @@ generate_flatbuffers(
101 commands/inspection 102 commands/inspection
102 commands/flush 103 commands/flush
103 domain/contact 104 domain/contact
105 domain/addressbook
104 domain/event 106 domain/event
105 domain/mail 107 domain/mail
106 domain/folder 108 domain/folder
diff --git a/common/domain/addressbook.cpp b/common/domain/addressbook.cpp
new file mode 100644
index 0000000..d1a3eaf
--- /dev/null
+++ b/common/domain/addressbook.cpp
@@ -0,0 +1,54 @@
1/*
2 * Copyright (C) 2017 Christian Mollekopf <chrigi_1@fastaddressbook.fm>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19#include "addressbook.h"
20
21#include <QByteArray>
22#include <QString>
23
24#include "../propertymapper.h"
25#include "../typeindex.h"
26#include "entitybuffer.h"
27#include "entity_generated.h"
28
29#include "addressbook_generated.h"
30
31using namespace Sink::ApplicationDomain;
32
33void TypeImplementation<Addressbook>::configure(TypeIndex &index)
34{
35 index.addProperty<QByteArray>(Addressbook::Parent::name);
36 index.addProperty<QString>(Addressbook::Name::name);
37}
38
39void TypeImplementation<Addressbook>::configure(ReadPropertyMapper<Buffer> &propertyMapper)
40{
41 propertyMapper.addMapping<Addressbook::Parent, Buffer>(&Buffer::parent);
42 propertyMapper.addMapping<Addressbook::Name, Buffer>(&Buffer::name);
43}
44
45void TypeImplementation<Addressbook>::configure(WritePropertyMapper<BufferBuilder> &propertyMapper)
46{
47 propertyMapper.addMapping<Addressbook::Parent>(&BufferBuilder::add_parent);
48 propertyMapper.addMapping<Addressbook::Name>(&BufferBuilder::add_name);
49}
50
51void TypeImplementation<Addressbook>::configure(IndexPropertyMapper &)
52{
53
54}
diff --git a/common/domain/addressbook.fbs b/common/domain/addressbook.fbs
new file mode 100644
index 0000000..c2bda2b
--- /dev/null
+++ b/common/domain/addressbook.fbs
@@ -0,0 +1,9 @@
1namespace Sink.ApplicationDomain.Buffer;
2
3table Addressbook {
4 name:string;
5 parent:string;
6}
7
8root_type Addressbook;
9file_identifier "AKFB";
diff --git a/common/domain/addressbook.h b/common/domain/addressbook.h
new file mode 100644
index 0000000..6475073
--- /dev/null
+++ b/common/domain/addressbook.h
@@ -0,0 +1,51 @@
1/*
2 * Copyright (C) 2017 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19#pragma once
20
21#include "applicationdomaintype.h"
22
23template<typename T>
24class ReadPropertyMapper;
25template<typename T>
26class WritePropertyMapper;
27class IndexPropertyMapper;
28
29class TypeIndex;
30
31namespace Sink {
32
33namespace ApplicationDomain {
34 namespace Buffer {
35 struct Addressbook;
36 struct AddressbookBuilder;
37 }
38
39template<>
40class TypeImplementation<Sink::ApplicationDomain::Addressbook> {
41public:
42 typedef Sink::ApplicationDomain::Buffer::Addressbook Buffer;
43 typedef Sink::ApplicationDomain::Buffer::AddressbookBuilder BufferBuilder;
44 static void configure(TypeIndex &);
45 static void configure(ReadPropertyMapper<Buffer> &);
46 static void configure(WritePropertyMapper<BufferBuilder> &);
47 static void configure(IndexPropertyMapper &indexPropertyMapper);
48};
49
50}
51}
diff --git a/common/domain/applicationdomaintype.cpp b/common/domain/applicationdomaintype.cpp
index 99f14a1..1efe052 100644
--- a/common/domain/applicationdomaintype.cpp
+++ b/common/domain/applicationdomaintype.cpp
@@ -96,6 +96,15 @@ SINK_REGISTER_PROPERTY(Folder, SpecialPurpose);
96SINK_REGISTER_PROPERTY(Folder, Enabled); 96SINK_REGISTER_PROPERTY(Folder, Enabled);
97SINK_REGISTER_PROPERTY(Folder, Parent); 97SINK_REGISTER_PROPERTY(Folder, Parent);
98 98
99SINK_REGISTER_PROPERTY(Contact, Uid);
100SINK_REGISTER_PROPERTY(Contact, Fn);
101SINK_REGISTER_PROPERTY(Contact, Emails);
102SINK_REGISTER_PROPERTY(Contact, Vcard);
103SINK_REGISTER_PROPERTY(Contact, Addressbook);
104
105SINK_REGISTER_PROPERTY(Addressbook, Name);
106SINK_REGISTER_PROPERTY(Addressbook, Parent);
107
99static const int foo = [] { 108static const int foo = [] {
100 QMetaType::registerEqualsComparator<Reference>(); 109 QMetaType::registerEqualsComparator<Reference>();
101 QMetaType::registerDebugStreamOperator<Reference>(); 110 QMetaType::registerDebugStreamOperator<Reference>();
@@ -369,6 +378,12 @@ QByteArray getTypeName<Contact>()
369} 378}
370 379
371template<> 380template<>
381QByteArray getTypeName<Addressbook>()
382{
383 return "addressbook";
384}
385
386template<>
372QByteArray getTypeName<Event>() 387QByteArray getTypeName<Event>()
373{ 388{
374 return "event"; 389 return "event";
diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h
index 3afef75..209f241 100644
--- a/common/domain/applicationdomaintype.h
+++ b/common/domain/applicationdomaintype.h
@@ -312,12 +312,19 @@ struct SINK_EXPORT Entity : public ApplicationDomainType {
312 virtual ~Entity() = default; 312 virtual ~Entity() = default;
313}; 313};
314 314
315struct SINK_EXPORT Addressbook : public Entity {
316 SINK_ENTITY(Addressbook);
317 SINK_REFERENCE_PROPERTY(Addressbook, Parent, parent);
318 SINK_PROPERTY(QString, Name, name);
319};
320
315struct SINK_EXPORT Contact : public Entity { 321struct SINK_EXPORT Contact : public Entity {
316 SINK_ENTITY(Contact); 322 SINK_ENTITY(Contact);
317 SINK_PROPERTY(QString, Uid, uid); 323 SINK_PROPERTY(QString, Uid, uid);
318 SINK_PROPERTY(QString, Fn, fn); 324 SINK_PROPERTY(QString, Fn, fn);
319 SINK_PROPERTY(QByteArrayList, Emails, emails); 325 SINK_PROPERTY(QByteArrayList, Emails, emails);
320 SINK_PROPERTY(QByteArray, Vcard, vcard); 326 SINK_PROPERTY(QByteArray, Vcard, vcard);
327 SINK_REFERENCE_PROPERTY(Addressbook, Addressbook, addressbook);
321}; 328};
322 329
323struct SINK_EXPORT Event : public Entity { 330struct SINK_EXPORT Event : public Entity {
@@ -429,6 +436,7 @@ namespace Mail {
429}; 436};
430namespace Contact { 437namespace Contact {
431 static constexpr const char *contact = "contact"; 438 static constexpr const char *contact = "contact";
439 static constexpr const char *addressbook = "addressbook";
432 static constexpr const char *storage = "contact.storage"; 440 static constexpr const char *storage = "contact.storage";
433}; 441};
434}; 442};
@@ -454,6 +462,9 @@ template<>
454QByteArray SINK_EXPORT getTypeName<Contact>(); 462QByteArray SINK_EXPORT getTypeName<Contact>();
455 463
456template<> 464template<>
465QByteArray SINK_EXPORT getTypeName<Addressbook>();
466
467template<>
457QByteArray SINK_EXPORT getTypeName<Event>(); 468QByteArray SINK_EXPORT getTypeName<Event>();
458 469
459template<> 470template<>
@@ -503,6 +514,7 @@ class SINK_EXPORT TypeImplementation;
503 */ 514 */
504#define SINK_REGISTER_TYPES() \ 515#define SINK_REGISTER_TYPES() \
505 REGISTER_TYPE(Sink::ApplicationDomain::Contact) \ 516 REGISTER_TYPE(Sink::ApplicationDomain::Contact) \
517 REGISTER_TYPE(Sink::ApplicationDomain::Addressbook) \
506 REGISTER_TYPE(Sink::ApplicationDomain::Event) \ 518 REGISTER_TYPE(Sink::ApplicationDomain::Event) \
507 REGISTER_TYPE(Sink::ApplicationDomain::Mail) \ 519 REGISTER_TYPE(Sink::ApplicationDomain::Mail) \
508 REGISTER_TYPE(Sink::ApplicationDomain::Folder) \ 520 REGISTER_TYPE(Sink::ApplicationDomain::Folder) \
diff --git a/common/domain/applicationdomaintype_p.h b/common/domain/applicationdomaintype_p.h
index 4b06864..a5a6b1d 100644
--- a/common/domain/applicationdomaintype_p.h
+++ b/common/domain/applicationdomaintype_p.h
@@ -33,13 +33,15 @@ struct TypeHelper {
33 template <typename R, typename ...Args> 33 template <typename R, typename ...Args>
34 R operator()(Args && ... args) const { 34 R operator()(Args && ... args) const {
35 if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Folder>()) { 35 if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Folder>()) {
36 return Func<Sink::ApplicationDomain::Folder>{}(std::forward<Args...>(args...)); 36 return Func<Sink::ApplicationDomain::Folder>{}(std::forward<Args...>(args...));
37 } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Mail>()) { 37 } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Mail>()) {
38 return Func<Sink::ApplicationDomain::Mail>{}(std::forward<Args...>(args...)); 38 return Func<Sink::ApplicationDomain::Mail>{}(std::forward<Args...>(args...));
39 } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Event>()) { 39 } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Event>()) {
40 return Func<Sink::ApplicationDomain::Event>{}(std::forward<Args...>(args...)); 40 return Func<Sink::ApplicationDomain::Event>{}(std::forward<Args...>(args...));
41 } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Contact>()) { 41 } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Contact>()) {
42 return Func<Sink::ApplicationDomain::Contact>{}(std::forward<Args...>(args...)); 42 return Func<Sink::ApplicationDomain::Contact>{}(std::forward<Args...>(args...));
43 } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Addressbook>()) {
44 return Func<Sink::ApplicationDomain::Addressbook>{}(std::forward<Args...>(args...));
43 } else { 45 } else {
44 Q_ASSERT(false); 46 Q_ASSERT(false);
45 } 47 }
diff --git a/common/domain/contact.cpp b/common/domain/contact.cpp
index ea7cac2..01f9144 100644
--- a/common/domain/contact.cpp
+++ b/common/domain/contact.cpp
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) 2017 Sandro Knauß <knauss@kolabsys.com> 2 * Copyright (C) 2017 Sandro Knauß <knauss@kolabsys.com>
3 * Copyright (C) 2017 Christian Mollekopf <mollekopf@kolabsys.com>
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -41,6 +42,7 @@ void TypeImplementation<Contact>::configure(ReadPropertyMapper<Buffer> &property
41 propertyMapper.addMapping<Contact::Fn, Buffer>(&Buffer::fn); 42 propertyMapper.addMapping<Contact::Fn, Buffer>(&Buffer::fn);
42 propertyMapper.addMapping<Contact::Emails, Buffer>(&Buffer::emails); 43 propertyMapper.addMapping<Contact::Emails, Buffer>(&Buffer::emails);
43 propertyMapper.addMapping<Contact::Vcard, Buffer>(&Buffer::vcard); 44 propertyMapper.addMapping<Contact::Vcard, Buffer>(&Buffer::vcard);
45 propertyMapper.addMapping<Contact::Addressbook, Buffer>(&Buffer::addressbook);
44} 46}
45 47
46void TypeImplementation<Contact>::configure(WritePropertyMapper<BufferBuilder> &propertyMapper) 48void TypeImplementation<Contact>::configure(WritePropertyMapper<BufferBuilder> &propertyMapper)
@@ -49,6 +51,7 @@ void TypeImplementation<Contact>::configure(WritePropertyMapper<BufferBuilder> &
49 propertyMapper.addMapping<Contact::Fn>(&BufferBuilder::add_fn); 51 propertyMapper.addMapping<Contact::Fn>(&BufferBuilder::add_fn);
50 propertyMapper.addMapping<Contact::Emails>(&BufferBuilder::add_emails); 52 propertyMapper.addMapping<Contact::Emails>(&BufferBuilder::add_emails);
51 propertyMapper.addMapping<Contact::Vcard>(&BufferBuilder::add_vcard); 53 propertyMapper.addMapping<Contact::Vcard>(&BufferBuilder::add_vcard);
54 propertyMapper.addMapping<Contact::Addressbook>(&BufferBuilder::add_addressbook);
52} 55}
53 56
54void TypeImplementation<Contact>::configure(IndexPropertyMapper &) 57void TypeImplementation<Contact>::configure(IndexPropertyMapper &)
diff --git a/common/domain/contact.fbs b/common/domain/contact.fbs
index 34fb1d6..7d7f797 100644
--- a/common/domain/contact.fbs
+++ b/common/domain/contact.fbs
@@ -3,6 +3,7 @@ namespace Sink.ApplicationDomain.Buffer;
3table Contact { 3table Contact {
4 uid:string; 4 uid:string;
5 fn:string; 5 fn:string;
6 addressbook:string;
6 emails: [string]; 7 emails: [string];
7 vcard: string; 8 vcard: string;
8} 9}
diff --git a/common/domain/contact.h b/common/domain/contact.h
index c803a9f..976f16e 100644
--- a/common/domain/contact.h
+++ b/common/domain/contact.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) 2017 Sandro Knauß <knauss@kolabsys.com> 2 * Copyright (C) 2017 Sandro Knauß <knauss@kolabsys.com>
3 * Copyright (C) 2017 Christian Mollekopf <mollekopf@kolabsys.com>
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
diff --git a/common/domain/domaintypes.h b/common/domain/domaintypes.h
index 0abdee7..8e31d48 100644
--- a/common/domain/domaintypes.h
+++ b/common/domain/domaintypes.h
@@ -1,5 +1,6 @@
1 1
2#include "contact.h" 2#include "contact.h"
3#include "addressbook.h"
3#include "mail.h" 4#include "mail.h"
4#include "folder.h" 5#include "folder.h"
5#include "event.h" 6#include "event.h"
diff --git a/common/domainadaptor.h b/common/domainadaptor.h
index 0377ef4..66ffb88 100644
--- a/common/domainadaptor.h
+++ b/common/domainadaptor.h
@@ -26,10 +26,7 @@
26 26
27#include "domaintypeadaptorfactoryinterface.h" 27#include "domaintypeadaptorfactoryinterface.h"
28#include "domain/applicationdomaintype.h" 28#include "domain/applicationdomaintype.h"
29#include "domain/contact.h" 29#include "domain/domaintypes.h"
30#include "domain/event.h"
31#include "domain/mail.h"
32#include "domain/folder.h"
33#include "bufferadaptor.h" 30#include "bufferadaptor.h"
34#include "entity_generated.h" 31#include "entity_generated.h"
35#include "metadata_generated.h" 32#include "metadata_generated.h"
diff --git a/common/synchronizer.cpp b/common/synchronizer.cpp
index fcdb5b8..8c0d31d 100644
--- a/common/synchronizer.cpp
+++ b/common/synchronizer.cpp
@@ -505,6 +505,12 @@ KAsync::Job<void> Synchronizer::replay(const QByteArray &type, const QByteArray
505 } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Mail>()) { 505 } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Mail>()) {
506 auto mail = store().readEntity<ApplicationDomain::Mail>(key); 506 auto mail = store().readEntity<ApplicationDomain::Mail>(key);
507 job = replay(mail, operation, oldRemoteId, modifiedProperties); 507 job = replay(mail, operation, oldRemoteId, modifiedProperties);
508 } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Contact>()) {
509 auto mail = store().readEntity<ApplicationDomain::Contact>(key);
510 job = replay(mail, operation, oldRemoteId, modifiedProperties);
511 } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Addressbook>()) {
512 auto mail = store().readEntity<ApplicationDomain::Addressbook>(key);
513 job = replay(mail, operation, oldRemoteId, modifiedProperties);
508 } else { 514 } else {
509 SinkErrorCtx(mLogCtx) << "Replayed unknown type: " << type; 515 SinkErrorCtx(mLogCtx) << "Replayed unknown type: " << type;
510 } 516 }
@@ -545,6 +551,11 @@ KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Contact &,
545 return KAsync::null<QByteArray>(); 551 return KAsync::null<QByteArray>();
546} 552}
547 553
554KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Addressbook &, Sink::Operation, const QByteArray &, const QList<QByteArray> &)
555{
556 return KAsync::null<QByteArray>();
557}
558
548KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Mail &, Sink::Operation, const QByteArray &, const QList<QByteArray> &) 559KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Mail &, Sink::Operation, const QByteArray &, const QList<QByteArray> &)
549{ 560{
550 return KAsync::null<QByteArray>(); 561 return KAsync::null<QByteArray>();
diff --git a/common/synchronizer.h b/common/synchronizer.h
index af042cb..45ec9e7 100644
--- a/common/synchronizer.h
+++ b/common/synchronizer.h
@@ -73,9 +73,9 @@ protected:
73protected: 73protected:
74 ///Implement to write back changes to the server 74 ///Implement to write back changes to the server
75 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Contact &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); 75 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Contact &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
76 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Addressbook &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
76 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Mail &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); 77 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Mail &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
77 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Folder &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); 78 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Folder &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
78
79protected: 79protected:
80 ///Calls the callback to enqueue the command 80 ///Calls the callback to enqueue the command
81 void enqueueCommand(int commandId, const QByteArray &data); 81 void enqueueCommand(int commandId, const QByteArray &data);
diff --git a/examples/davresource/CMakeLists.txt b/examples/davresource/CMakeLists.txt
index c7899eb..f8cbdb4 100644
--- a/examples/davresource/CMakeLists.txt
+++ b/examples/davresource/CMakeLists.txt
@@ -3,7 +3,6 @@ project(sink_resource_dav)
3add_definitions(-DQT_PLUGIN) 3add_definitions(-DQT_PLUGIN)
4include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) 4include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
5 5
6find_package(KF5 COMPONENTS REQUIRED Mime)
7find_package(KPimKDAV REQUIRED) 6find_package(KPimKDAV REQUIRED)
8 7
9add_library(${PROJECT_NAME} SHARED facade.cpp davresource.cpp domainadaptor.cpp) 8add_library(${PROJECT_NAME} SHARED facade.cpp davresource.cpp domainadaptor.cpp)
@@ -11,8 +10,3 @@ qt5_use_modules(${PROJECT_NAME} Core Network)
11target_link_libraries(${PROJECT_NAME} sink KPim::KDAV) 10target_link_libraries(${PROJECT_NAME} sink KPim::KDAV)
12 11
13install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${SINK_RESOURCE_PLUGINS_PATH}) 12install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${SINK_RESOURCE_PLUGINS_PATH})
14
15#add_definitions(-DTESTDATAPATH="${CMAKE_CURRENT_SOURCE_DIR}/tests/data")
16
17#add_subdirectory(libmaildir)
18#add_subdirectory(tests)
diff --git a/examples/davresource/davresource.cpp b/examples/davresource/davresource.cpp
index df2c4b4..3d23a04 100644
--- a/examples/davresource/davresource.cpp
+++ b/examples/davresource/davresource.cpp
@@ -21,10 +21,8 @@
21 21
22#include "facade.h" 22#include "facade.h"
23#include "resourceconfig.h" 23#include "resourceconfig.h"
24#include "index.h"
25#include "log.h" 24#include "log.h"
26#include "definitions.h" 25#include "definitions.h"
27#include "inspection.h"
28#include "synchronizer.h" 26#include "synchronizer.h"
29#include "inspector.h" 27#include "inspector.h"
30 28
@@ -40,181 +38,14 @@
40#include <KDAV/DavItemFetchJob> 38#include <KDAV/DavItemFetchJob>
41#include <KDAV/EtagCache> 39#include <KDAV/EtagCache>
42 40
43#include <QDir>
44#include <QDirIterator>
45
46//This is the resources entity type, and not the domain type 41//This is the resources entity type, and not the domain type
47#define ENTITY_TYPE_CONTACT "contact" 42#define ENTITY_TYPE_CONTACT "contact"
48#define ENTITY_TYPE_ADDRESSBOOK "folder" 43#define ENTITY_TYPE_ADDRESSBOOK "addressbook"
49 44
50SINK_DEBUG_AREA("davresource") 45SINK_DEBUG_AREA("davresource")
51 46
52using namespace Sink; 47using namespace Sink;
53 48
54/*static QString getFilePathFromMimeMessagePath(const QString &mimeMessagePath)
55{
56 auto parts = mimeMessagePath.split('/');
57 const auto key = parts.takeLast();
58 const auto path = parts.join("/") + "/cur/";
59
60 QDir dir(path);
61 const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files);
62 if (list.size() != 1) {
63 SinkWarning() << "Failed to find message " << mimeMessagePath;
64 SinkWarning() << "Failed to find message " << path;
65 return QString();
66 }
67 return list.first().filePath();
68}
69
70class MaildirMailPropertyExtractor : public MailPropertyExtractor
71{
72protected:
73 virtual QString getFilePathFromMimeMessagePath(const QString &mimeMessagePath) const Q_DECL_OVERRIDE
74 {
75 return ::getFilePathFromMimeMessagePath(mimeMessagePath);
76 }
77};
78
79class MaildirMimeMessageMover : public Sink::Preprocessor
80{
81public:
82 MaildirMimeMessageMover(const QByteArray &resourceInstanceIdentifier, const QString &maildirPath) : mResourceInstanceIdentifier(resourceInstanceIdentifier), mMaildirPath(maildirPath) {}
83
84 QString getPath(const QByteArray &folderIdentifier)
85 {
86 if (folderIdentifier.isEmpty()) {
87 return mMaildirPath;
88 }
89 QString folderPath;
90 const auto folder = entityStore().readLatest<ApplicationDomain::Folder>(folderIdentifier);
91 if (mMaildirPath.endsWith(folder.getName())) {
92 folderPath = mMaildirPath;
93 } else {
94 auto folderName = folder.getName();
95 //FIXME handle non toplevel folders
96 folderPath = mMaildirPath + "/" + folderName;
97 }
98 return folderPath;
99 }
100
101 QString moveMessage(const QString &oldPath, const QByteArray &folder)
102 {
103 if (oldPath.startsWith(Sink::temporaryFileLocation())) {
104 const auto path = getPath(folder);
105 KPIM::Contactdir maildir(path, false);
106 if (!maildir.isValid(true)) {
107 SinkWarning() << "Maildir is not existing: " << path;
108 }
109 auto identifier = maildir.addEntryFromPath(oldPath);
110 return path + "/" + identifier;
111 } else {
112 //Handle moves
113 const auto path = getPath(folder);
114 KPIM::Contactdir maildir(path, false);
115 if (!maildir.isValid(true)) {
116 SinkWarning() << "Maildir is not existing: " << path;
117 }
118 auto oldIdentifier = KPIM::Contactdir::getKeyFromFile(oldPath);
119 auto pathParts = oldPath.split('/');
120 pathParts.takeLast();
121 auto oldDirectory = pathParts.join('/');
122 if (oldDirectory == path) {
123 return oldPath;
124 }
125 KPIM::Contactdir oldMaildir(oldDirectory, false);
126 if (!oldMaildir.isValid(false)) {
127 SinkWarning() << "Maildir is not existing: " << path;
128 }
129 auto identifier = oldMaildir.moveEntryTo(oldIdentifier, maildir);
130 return path + "/" + identifier;
131 }
132 }
133
134 void newEntity(Sink::ApplicationDomain::ApplicationDomainType &newEntity) Q_DECL_OVERRIDE
135 {
136 auto mail = newEntity.cast<ApplicationDomain::Contact>();
137 const auto mimeMessage = mail.getMimeMessagePath();
138 if (!mimeMessage.isNull()) {
139 const auto path = moveMessage(mimeMessage, mail.getFolder());
140 auto blob = ApplicationDomain::BLOB{path};
141 blob.isExternal = false;
142 mail.setProperty(ApplicationDomain::Contact::MimeMessage::name, QVariant::fromValue(blob));
143 }
144 }
145
146 void modifiedEntity(const Sink::ApplicationDomain::ApplicationDomainType &oldEntity, Sink::ApplicationDomain::ApplicationDomainType &newEntity) Q_DECL_OVERRIDE
147 {
148 auto newMail = newEntity.cast<ApplicationDomain::Contact>();
149 const ApplicationDomain::Contact oldMail{oldEntity};
150 const auto mimeMessage = newMail.getMimeMessagePath();
151 const auto newFolder = newMail.getFolder();
152 const bool mimeMessageChanged = !mimeMessage.isNull() && mimeMessage != oldMail.getMimeMessagePath();
153 const bool folderChanged = !newFolder.isNull() && newFolder != oldMail.getFolder();
154 if (mimeMessageChanged || folderChanged) {
155 SinkTrace() << "Moving mime message: " << mimeMessageChanged << folderChanged;
156 auto newPath = moveMessage(mimeMessage, newMail.getFolder());
157 if (newPath != oldMail.getMimeMessagePath()) {
158 const auto oldPath = getFilePathFromMimeMessagePath(oldMail.getMimeMessagePath());
159 auto blob = ApplicationDomain::BLOB{newPath};
160 blob.isExternal = false;
161 newMail.setProperty(ApplicationDomain::Contact::MimeMessage::name, QVariant::fromValue(blob));
162 //Remove the olde mime message if there is a new one
163 QFile::remove(oldPath);
164 }
165 }
166
167 auto mimeMessagePath = newMail.getMimeMessagePath();
168 const auto maildirPath = getPath(newMail.getFolder());
169 KPIM::Contactdir maildir(maildirPath, false);
170 const auto file = getFilePathFromMimeMessagePath(mimeMessagePath);
171 QString identifier = KPIM::Contactdir::getKeyFromFile(file);
172
173 //get flags from
174 KPIM::Contactdir::Flags flags;
175 if (!newMail.getUnread()) {
176 flags |= KPIM::Contactdir::Seen;
177 }
178 if (newMail.getImportant()) {
179 flags |= KPIM::Contactdir::Flagged;
180 }
181
182 maildir.changeEntryFlags(identifier, flags);
183 }
184
185 void deletedEntity(const Sink::ApplicationDomain::ApplicationDomainType &oldEntity) Q_DECL_OVERRIDE
186 {
187 const ApplicationDomain::Contact oldMail{oldEntity};
188 const auto filePath = getFilePathFromMimeMessagePath(oldMail.getMimeMessagePath());
189 QFile::remove(filePath);
190 }
191 QByteArray mResourceInstanceIdentifier;
192 QString mMaildirPath;
193};
194
195class FolderPreprocessor : public Sink::Preprocessor
196{
197public:
198 FolderPreprocessor(const QString maildirPath) : mMaildirPath(maildirPath) {}
199
200 void newEntity(Sink::ApplicationDomain::ApplicationDomainType &newEntity) Q_DECL_OVERRIDE
201 {
202 auto folderName = Sink::ApplicationDomain::Folder{newEntity}.getName();
203 const auto path = mMaildirPath + "/" + folderName;
204 KPIM::Contactdir maildir(path, false);
205 maildir.create();
206 }
207
208 void modifiedEntity(const Sink::ApplicationDomain::ApplicationDomainType &oldEntity, Sink::ApplicationDomain::ApplicationDomainType &newEntity) Q_DECL_OVERRIDE
209 {
210 }
211
212 void deletedEntity(const Sink::ApplicationDomain::ApplicationDomainType &oldEntity) Q_DECL_OVERRIDE
213 {
214 }
215 QString mMaildirPath;
216};*/
217
218static KAsync::Job<void> runJob(KJob *job) 49static KAsync::Job<void> runJob(KJob *job)
219{ 50{
220 return KAsync::start<void>([job](KAsync::Future<void> &future) { 51 return KAsync::start<void>([job](KAsync::Future<void> &future) {
@@ -240,33 +71,33 @@ public:
240 71
241 } 72 }
242 73
243 QByteArray createAddressbook(const QString &folderName, const QString &folderPath, const QString &parentFolderRid, const QByteArray &icon) 74 QByteArray createAddressbook(const QString &addressbookName, const QString &addressbookPath, const QString &parentAddressbookRid)
244 { 75 {
245 SinkTrace() << "Creating addressbook: " << folderName << parentFolderRid; 76 SinkTrace() << "Creating addressbook: " << addressbookName << parentAddressbookRid;
246 const auto remoteId = folderPath.toUtf8(); 77 const auto remoteId = addressbookPath.toUtf8();
247 const auto bufferType = ENTITY_TYPE_ADDRESSBOOK; 78 const auto bufferType = ENTITY_TYPE_ADDRESSBOOK;
248 Sink::ApplicationDomain::Folder folder; 79 Sink::ApplicationDomain::Addressbook addressbook;
249 folder.setName(folderName); 80 addressbook.setName(addressbookName);
250 folder.setIcon(icon);
251 QHash<QByteArray, Query::Comparator> mergeCriteria; 81 QHash<QByteArray, Query::Comparator> mergeCriteria;
252 82
253 if (!parentFolderRid.isEmpty()) { 83 if (!parentAddressbookRid.isEmpty()) {
254 folder.setParent(syncStore().resolveRemoteId(ENTITY_TYPE_ADDRESSBOOK, parentFolderRid.toUtf8())); 84 addressbook.setParent(syncStore().resolveRemoteId(ENTITY_TYPE_ADDRESSBOOK, parentAddressbookRid.toUtf8()));
255 } 85 }
256 createOrModify(bufferType, remoteId, folder, mergeCriteria); 86 createOrModify(bufferType, remoteId, addressbook, mergeCriteria);
257 return remoteId; 87 return remoteId;
258 } 88 }
259 89
260 void synchronizeAddressbooks(const KDAV::DavCollection::List &folderList) 90 void synchronizeAddressbooks(const KDAV::DavCollection::List &addressbookList)
261 { 91 {
262 const QByteArray bufferType = ENTITY_TYPE_ADDRESSBOOK; 92 const QByteArray bufferType = ENTITY_TYPE_ADDRESSBOOK;
263 SinkTrace() << "Found addressbooks " << folderList.size(); 93 SinkTrace() << "Found addressbooks " << addressbookList.size();
264 94
265 QVector<QByteArray> ridList; 95 QVector<QByteArray> ridList;
266 for(const auto &f : folderList) { 96 for(const auto &f : addressbookList) {
267 const auto &rid = f.url().toDisplayString(); 97 const auto &rid = getRid(f);
268 ridList.append(rid.toUtf8()); 98 SinkTrace() << "Found addressbook:" << rid;
269 createAddressbook(f.displayName(), rid, "", "addressbook"); 99 ridList.append(rid);
100 createAddressbook(f.displayName(), rid, "");
270 } 101 }
271 102
272 scanForRemovals(bufferType, 103 scanForRemovals(bufferType,
@@ -284,21 +115,32 @@ public:
284 list << Synchronizer::SyncRequest{query}; 115 list << Synchronizer::SyncRequest{query};
285 } else { 116 } else {
286 //We want to synchronize everything 117 //We want to synchronize everything
287 list << Synchronizer::SyncRequest{Sink::QueryBase(ApplicationDomain::getTypeName<ApplicationDomain::Folder>())}; 118 list << Synchronizer::SyncRequest{Sink::QueryBase(ApplicationDomain::getTypeName<ApplicationDomain::Addressbook>())};
288 list << Synchronizer::SyncRequest{Sink::QueryBase(ApplicationDomain::getTypeName<ApplicationDomain::Contact>())}; 119 list << Synchronizer::SyncRequest{Sink::QueryBase(ApplicationDomain::getTypeName<ApplicationDomain::Contact>())};
289 } 120 }
290 return list; 121 return list;
291 } 122 }
292 123
124 static QByteArray getRid(const KDAV::DavItem &item)
125 {
126 return item.url().toDisplayString().toUtf8();
127 }
128
129 static QByteArray getRid(const KDAV::DavCollection &item)
130 {
131 return item.url().toDisplayString().toUtf8();
132 }
133
293 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE 134 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE
294 { 135 {
295 if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Folder>()) { 136 if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Addressbook>()) {
296 SinkLogCtx(mLogCtx) << "Synchronizing folders:" << mResourceUrl.url(); 137 SinkLogCtx(mLogCtx) << "Synchronizing addressbooks:" << mResourceUrl.url();
297 auto collectionsFetchJob = new KDAV::DavCollectionsFetchJob(mResourceUrl); 138 auto collectionsFetchJob = new KDAV::DavCollectionsFetchJob(mResourceUrl);
298 auto job = runJob(collectionsFetchJob).then([this, collectionsFetchJob] (const KAsync::Error &error) { 139 auto job = runJob(collectionsFetchJob).then([this, collectionsFetchJob] (const KAsync::Error &error) {
299 if (error) { 140 if (error) {
300 SinkWarningCtx(mLogCtx) << "Failed to synchronize folders." << collectionsFetchJob->errorString(); 141 SinkWarningCtx(mLogCtx) << "Failed to synchronize addressbooks." << collectionsFetchJob->errorString();
301 } else { 142 } else {
143 SinkWarningCtx(mLogCtx) << "Fetched addressbooks." << collectionsFetchJob->errorString();
302 synchronizeAddressbooks(collectionsFetchJob ->collections()); 144 synchronizeAddressbooks(collectionsFetchJob ->collections());
303 } 145 }
304 }); 146 });
@@ -312,7 +154,8 @@ public:
312 return collectionsFetchJob->collections(); 154 return collectionsFetchJob->collections();
313 }) 155 })
314 .serialEach([this, ridList](const KDAV::DavCollection &collection) { 156 .serialEach([this, ridList](const KDAV::DavCollection &collection) {
315 auto collId = collection.url().toDisplayString().toLatin1(); 157 auto collId = getRid(collection);
158 const auto addressbookLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_ADDRESSBOOK, collId);
316 auto ctag = collection.CTag().toLatin1(); 159 auto ctag = collection.CTag().toLatin1();
317 if (ctag != syncStore().readValue(collId + "_ctagXX")) { 160 if (ctag != syncStore().readValue(collId + "_ctagXX")) {
318 SinkTraceCtx(mLogCtx) << "Syncing " << collId; 161 SinkTraceCtx(mLogCtx) << "Syncing " << collId;
@@ -323,22 +166,23 @@ public:
323 auto colljob = runJob(davItemsListJob).then([davItemsListJob] { 166 auto colljob = runJob(davItemsListJob).then([davItemsListJob] {
324 return KAsync::value(davItemsListJob->items()); 167 return KAsync::value(davItemsListJob->items());
325 }) 168 })
326 .serialEach([this, ridList, bufferType, mergeCriteria] (const KDAV::DavItem &item) { 169 .serialEach([=] (const KDAV::DavItem &item) {
327 QByteArray rid = item.url().toDisplayString().toUtf8(); 170 QByteArray rid = getRid(item);
328 if (item.etag().toLatin1() != syncStore().readValue(rid + "_etag")){ 171 if (item.etag().toLatin1() != syncStore().readValue(rid + "_etag")){
329 SinkTrace() << "Updating " << rid; 172 SinkTrace() << "Updating " << rid;
330 auto davItemFetchJob = new KDAV::DavItemFetchJob(item); 173 auto davItemFetchJob = new KDAV::DavItemFetchJob(item);
331 auto itemjob = runJob(davItemFetchJob) 174 auto itemjob = runJob(davItemFetchJob)
332 .then([this, davItemFetchJob, bufferType, mergeCriteria] { 175 .then([=] {
333 const auto item = davItemFetchJob->item(); 176 const auto item = davItemFetchJob->item();
334 const auto rid = item.url().toDisplayString().toUtf8(); 177 const auto rid = getRid(item);
335 Sink::ApplicationDomain::Contact contact; 178 Sink::ApplicationDomain::Contact contact;
336 contact.setVcard(item.data()); 179 contact.setVcard(item.data());
180 contact.setAddressbook(addressbookLocalId);
337 createOrModify(bufferType, rid, contact, mergeCriteria); 181 createOrModify(bufferType, rid, contact, mergeCriteria);
338 return item; 182 return item;
339 }) 183 })
340 .then([this, ridList] (const KDAV::DavItem &item) { 184 .then([this, ridList] (const KDAV::DavItem &item) {
341 const auto rid = item.url().toDisplayString().toUtf8(); 185 const auto rid = getRid(item);
342 syncStore().writeValue(rid + "_etag", item.etag().toLatin1()); 186 syncStore().writeValue(rid + "_etag", item.etag().toLatin1());
343 ridList->append(rid); 187 ridList->append(rid);
344 return rid; 188 return rid;
@@ -375,43 +219,11 @@ public:
375 219
376KAsync::Job<QByteArray> replay(const ApplicationDomain::Contact &contact, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE 220KAsync::Job<QByteArray> replay(const ApplicationDomain::Contact &contact, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE
377 { 221 {
378 /*
379 if (operation == Sink::Operation_Creation) {
380 const auto remoteId = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
381 SinkTrace() << "Contact created: " << remoteId;
382 return KAsync::value(remoteId.toUtf8());
383 } else if (operation == Sink::Operation_Removal) {
384 SinkTrace() << "Removing a contact " << oldRemoteId;
385 return KAsync::null<QByteArray>();
386 } else if (operation == Sink::Operation_Modification) {
387 SinkTrace() << "Modifying a contact: " << oldRemoteId;
388 const auto remoteId = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
389 return KAsync::value(remoteId.toUtf8());
390 }*/
391 return KAsync::null<QByteArray>(); 222 return KAsync::null<QByteArray>();
392 } 223 }
393 224
394 KAsync::Job<QByteArray> replay(const ApplicationDomain::Folder &folder, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE 225 KAsync::Job<QByteArray> replay(const ApplicationDomain::Addressbook &addressbook, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE
395 { 226 {
396 /*
397 if (operation == Sink::Operation_Creation) {
398 auto folderName = folder.getName();
399 //FIXME handle non toplevel folders
400 auto path = mMaildirPath + "/" + folderName;
401 SinkTrace() << "Creating a new folder: " << path;
402 KPIM::Contactdir maildir(path, false);
403 maildir.create();
404 return KAsync::value(path.toUtf8());
405 } else if (operation == Sink::Operation_Removal) {
406 const auto path = oldRemoteId;
407 SinkTrace() << "Removing a folder: " << path;
408 KPIM::Contactdir maildir(path, false);
409 maildir.remove();
410 return KAsync::null<QByteArray>();
411 } else if (operation == Sink::Operation_Modification) {
412 SinkWarning() << "Folder modifications are not implemented";
413 return KAsync::value(oldRemoteId);
414 }*/
415 return KAsync::null<QByteArray>(); 227 return KAsync::null<QByteArray>();
416 } 228 }
417 229
@@ -419,103 +231,6 @@ public:
419 KDAV::DavUrl mResourceUrl; 231 KDAV::DavUrl mResourceUrl;
420}; 232};
421 233
422/*
423class MaildirInspector : public Sink::Inspector {
424public:
425 MaildirInspector(const Sink::ResourceContext &resourceContext)
426 : Sink::Inspector(resourceContext)
427 {
428
429 }
430protected:
431
432 KAsync::Job<void> inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) Q_DECL_OVERRIDE {
433 auto synchronizationStore = QSharedPointer<Sink::Storage::DataStore>::create(Sink::storageLocation(), mResourceContext.instanceId() + ".synchronization", Sink::Storage::DataStore::ReadOnly);
434 auto synchronizationTransaction = synchronizationStore->createTransaction(Sink::Storage::DataStore::ReadOnly);
435
436 auto mainStore = QSharedPointer<Sink::Storage::DataStore>::create(Sink::storageLocation(), mResourceContext.instanceId(), Sink::Storage::DataStore::ReadOnly);
437 auto transaction = mainStore->createTransaction(Sink::Storage::DataStore::ReadOnly);
438
439 Sink::Storage::EntityStore entityStore(mResourceContext, {"maildirresource"});
440 auto syncStore = QSharedPointer<SynchronizerStore>::create(synchronizationTransaction);
441
442 SinkTrace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue;
443
444 if (domainType == ENTITY_TYPE_MAIL) {
445 auto mail = entityStore.readLatest<Sink::ApplicationDomain::Contact>(entityId);
446 const auto filePath = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
447
448 if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) {
449 if (property == "unread") {
450 const auto flags = KPIM::Contactdir::readEntryFlags(filePath.split('/').last());
451 if (expectedValue.toBool() && (flags & KPIM::Contactdir::Seen)) {
452 return KAsync::error<void>(1, "Expected unread but couldn't find it.");
453 }
454 if (!expectedValue.toBool() && !(flags & KPIM::Contactdir::Seen)) {
455 return KAsync::error<void>(1, "Expected read but couldn't find it.");
456 }
457 return KAsync::null<void>();
458 }
459 if (property == "subject") {
460 KMime::Message *msg = new KMime::Message;
461 msg->setHead(KMime::CRLFtoLF(KPIM::Contactdir::readEntryHeadersFromFile(filePath)));
462 msg->parse();
463
464 if (msg->subject(true)->asUnicodeString() != expectedValue.toString()) {
465 return KAsync::error<void>(1, "Subject not as expected: " + msg->subject(true)->asUnicodeString());
466 }
467 return KAsync::null<void>();
468 }
469 }
470 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) {
471 if (QFileInfo(filePath).exists() != expectedValue.toBool()) {
472 return KAsync::error<void>(1, "Wrong file existence: " + filePath);
473 }
474 }
475 }
476 if (domainType == ENTITY_TYPE_FOLDER) {
477 const auto remoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, entityId);
478 auto folder = entityStore.readLatest<Sink::ApplicationDomain::Folder>(entityId);
479
480 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) {
481 SinkTrace() << "Inspecting cache integrity" << remoteId;
482 if (!QDir(remoteId).exists()) {
483 return KAsync::error<void>(1, "The directory is not existing: " + remoteId);
484 }
485
486 int expectedCount = 0;
487 Index index("mail.index.folder", transaction);
488 index.lookup(entityId, [&](const QByteArray &sinkId) {
489 expectedCount++;
490 },
491 [&](const Index::Error &error) {
492 SinkWarning() << "Error in index: " << error.message << property;
493 });
494
495 QDir dir(remoteId + "/cur");
496 const QFileInfoList list = dir.entryInfoList(QDir::Files);
497 if (list.size() != expectedCount) {
498 for (const auto &fileInfo : list) {
499 SinkWarning() << "Found in cache: " << fileInfo.fileName();
500 }
501 return KAsync::error<void>(1, QString("Wrong number of files; found %1 instead of %2.").arg(list.size()).arg(expectedCount));
502 }
503 }
504 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) {
505 if (!remoteId.endsWith(folder.getName().toUtf8())) {
506 return KAsync::error<void>(1, "Wrong folder name: " + remoteId);
507 }
508 //TODO we shouldn't use the remoteId here to figure out the path, it could be gone/changed already
509 if (QDir(remoteId).exists() != expectedValue.toBool()) {
510 return KAsync::error<void>(1, "Wrong folder existence: " + remoteId);
511 }
512 }
513
514 }
515 return KAsync::null<void>();
516 }
517};*/
518
519 234
520DavResource::DavResource(const Sink::ResourceContext &resourceContext) 235DavResource::DavResource(const Sink::ResourceContext &resourceContext)
521 : Sink::GenericResource(resourceContext) 236 : Sink::GenericResource(resourceContext)
@@ -530,7 +245,6 @@ DavResource::DavResource(const Sink::ResourceContext &resourceContext)
530 auto synchronizer = QSharedPointer<ContactSynchronizer>::create(resourceContext); 245 auto synchronizer = QSharedPointer<ContactSynchronizer>::create(resourceContext);
531 synchronizer->mResourceUrl = mResourceUrl; 246 synchronizer->mResourceUrl = mResourceUrl;
532 setupSynchronizer(synchronizer); 247 setupSynchronizer(synchronizer);
533 //setupInspector(QSharedPointer<MaildirInspector>::create(resourceContext));
534 248
535 setupPreprocessors(ENTITY_TYPE_CONTACT, QVector<Sink::Preprocessor*>() << new ContactPropertyExtractor); 249 setupPreprocessors(ENTITY_TYPE_CONTACT, QVector<Sink::Preprocessor*>() << new ContactPropertyExtractor);
536} 250}
@@ -539,8 +253,8 @@ DavResource::DavResource(const Sink::ResourceContext &resourceContext)
539DavResourceFactory::DavResourceFactory(QObject *parent) 253DavResourceFactory::DavResourceFactory(QObject *parent)
540 : Sink::ResourceFactory(parent, 254 : Sink::ResourceFactory(parent,
541 {Sink::ApplicationDomain::ResourceCapabilities::Contact::contact, 255 {Sink::ApplicationDomain::ResourceCapabilities::Contact::contact,
542 Sink::ApplicationDomain::ResourceCapabilities::Mail::folder, 256 Sink::ApplicationDomain::ResourceCapabilities::Contact::addressbook,
543 "-folder.rename"} 257 }
544 ) 258 )
545{ 259{
546} 260}
@@ -553,13 +267,13 @@ Sink::Resource *DavResourceFactory::createResource(const ResourceContext &contex
553void DavResourceFactory::registerFacades(const QByteArray &name, Sink::FacadeFactory &factory) 267void DavResourceFactory::registerFacades(const QByteArray &name, Sink::FacadeFactory &factory)
554{ 268{
555 factory.registerFacade<Sink::ApplicationDomain::Contact, DavResourceContactFacade>(name); 269 factory.registerFacade<Sink::ApplicationDomain::Contact, DavResourceContactFacade>(name);
556 factory.registerFacade<Sink::ApplicationDomain::Folder, DavResourceFolderFacade>(name); 270 factory.registerFacade<Sink::ApplicationDomain::Addressbook, DavResourceAddressbookFacade>(name);
557} 271}
558 272
559void DavResourceFactory::registerAdaptorFactories(const QByteArray &name, Sink::AdaptorFactoryRegistry &registry) 273void DavResourceFactory::registerAdaptorFactories(const QByteArray &name, Sink::AdaptorFactoryRegistry &registry)
560{ 274{
561 registry.registerFactory<Sink::ApplicationDomain::Contact, ContactAdaptorFactory>(name); 275 registry.registerFactory<Sink::ApplicationDomain::Contact, ContactAdaptorFactory>(name);
562 registry.registerFactory<Sink::ApplicationDomain::Folder, AddressbookAdaptorFactory>(name); 276 registry.registerFactory<Sink::ApplicationDomain::Addressbook, AddressbookAdaptorFactory>(name);
563} 277}
564 278
565void DavResourceFactory::removeDataFromDisk(const QByteArray &instanceIdentifier) 279void DavResourceFactory::removeDataFromDisk(const QByteArray &instanceIdentifier)
diff --git a/examples/davresource/facade.cpp b/examples/davresource/facade.cpp
index b56815a..8ee1b01 100644
--- a/examples/davresource/facade.cpp
+++ b/examples/davresource/facade.cpp
@@ -34,11 +34,11 @@ DavResourceContactFacade::~DavResourceContactFacade()
34} 34}
35 35
36 36
37DavResourceFolderFacade::DavResourceFolderFacade(const Sink::ResourceContext &context) 37DavResourceAddressbookFacade::DavResourceAddressbookFacade(const Sink::ResourceContext &context)
38 : Sink::GenericFacade<Sink::ApplicationDomain::Folder>(context) 38 : Sink::GenericFacade<Sink::ApplicationDomain::Addressbook>(context)
39{ 39{
40} 40}
41 41
42DavResourceFolderFacade::~DavResourceFolderFacade() 42DavResourceAddressbookFacade::~DavResourceAddressbookFacade()
43{ 43{
44} 44}
diff --git a/examples/davresource/facade.h b/examples/davresource/facade.h
index 02bd5dc..d520891 100644
--- a/examples/davresource/facade.h
+++ b/examples/davresource/facade.h
@@ -28,9 +28,9 @@ public:
28 virtual ~DavResourceContactFacade(); 28 virtual ~DavResourceContactFacade();
29}; 29};
30 30
31class DavResourceFolderFacade : public Sink::GenericFacade<Sink::ApplicationDomain::Folder> 31class DavResourceAddressbookFacade : public Sink::GenericFacade<Sink::ApplicationDomain::Addressbook>
32{ 32{
33public: 33public:
34 DavResourceFolderFacade(const Sink::ResourceContext &context); 34 DavResourceAddressbookFacade(const Sink::ResourceContext &context);
35 virtual ~DavResourceFolderFacade(); 35 virtual ~DavResourceAddressbookFacade();
36}; 36};
diff --git a/sinksh/sinksh_utils.cpp b/sinksh/sinksh_utils.cpp
index 171bb18..3a3484a 100644
--- a/sinksh/sinksh_utils.cpp
+++ b/sinksh/sinksh_utils.cpp
@@ -63,7 +63,9 @@ QList<QByteArray> requestedProperties(const QString &type)
63 } else if (type == getTypeName<Event>()) { 63 } else if (type == getTypeName<Event>()) {
64 return QList<QByteArray>() << Event::Summary::name; 64 return QList<QByteArray>() << Event::Summary::name;
65 } else if (type == getTypeName<Contact>()) { 65 } else if (type == getTypeName<Contact>()) {
66 return QList<QByteArray>() << Contact::Fn::name << Contact::Emails::name; 66 return QList<QByteArray>() << Contact::Fn::name << Contact::Emails::name << Contact::Addressbook::name;
67 } else if (type == getTypeName<Addressbook>()) {
68 return QList<QByteArray>() << Addressbook::Name::name << Addressbook::Parent::name;
67 } else if (type == getTypeName<SinkResource>()) { 69 } else if (type == getTypeName<SinkResource>()) {
68 return QList<QByteArray>() << SinkResource::ResourceType::name << SinkResource::Account::name << SinkResource::Capabilities::name; 70 return QList<QByteArray>() << SinkResource::ResourceType::name << SinkResource::Account::name << SinkResource::Capabilities::name;
69 } else if (type == getTypeName<SinkAccount>()) { 71 } else if (type == getTypeName<SinkAccount>()) {