summaryrefslogtreecommitdiffstats
path: root/common/domain
diff options
context:
space:
mode:
Diffstat (limited to 'common/domain')
-rw-r--r--common/domain/applicationdomaintype.h2
-rw-r--r--common/domain/event.cpp10
-rw-r--r--common/domain/event.h8
-rw-r--r--common/domain/folder.cpp9
-rw-r--r--common/domain/folder.h3
-rw-r--r--common/domain/mail.cpp117
-rw-r--r--common/domain/mail.fbs2
-rw-r--r--common/domain/mail.h8
8 files changed, 113 insertions, 46 deletions
diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h
index 67f33c8..c853397 100644
--- a/common/domain/applicationdomaintype.h
+++ b/common/domain/applicationdomaintype.h
@@ -238,6 +238,8 @@ struct SINK_EXPORT Mail : public Entity {
238 SINK_PROPERTY(bool, Draft, draft); 238 SINK_PROPERTY(bool, Draft, draft);
239 SINK_PROPERTY(bool, Trash, trash); 239 SINK_PROPERTY(bool, Trash, trash);
240 SINK_PROPERTY(bool, Sent, sent); 240 SINK_PROPERTY(bool, Sent, sent);
241 SINK_EXTRACTED_PROPERTY(QByteArray, MessageId, messageId);
242 SINK_EXTRACTED_PROPERTY(QByteArray, ParentMessageId, parentMessageId);
241}; 243};
242 244
243/** 245/**
diff --git a/common/domain/event.cpp b/common/domain/event.cpp
index dfbcb61..118ffa3 100644
--- a/common/domain/event.cpp
+++ b/common/domain/event.cpp
@@ -52,11 +52,6 @@ static TypeIndex &getIndex()
52 return *index; 52 return *index;
53} 53}
54 54
55ResultSet TypeImplementation<Event>::queryIndexes(const Sink::Query &query, const QByteArray &resourceInstanceIdentifier, QSet<QByteArray> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::Transaction &transaction)
56{
57 return getIndex().query(query, appliedFilters, appliedSorting, transaction);
58}
59
60void TypeImplementation<Event>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) 55void TypeImplementation<Event>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
61{ 56{
62 return getIndex().add(identifier, bufferAdaptor, transaction); 57 return getIndex().add(identifier, bufferAdaptor, transaction);
@@ -87,11 +82,10 @@ QSharedPointer<WritePropertyMapper<TypeImplementation<Event>::BufferBuilder> > T
87 return propertyMapper; 82 return propertyMapper;
88} 83}
89 84
90DataStoreQuery TypeImplementation<Event>::prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction) 85DataStoreQuery::Ptr TypeImplementation<Event>::prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction)
91{ 86{
92
93 auto mapper = initializeReadPropertyMapper(); 87 auto mapper = initializeReadPropertyMapper();
94 return DataStoreQuery(query, ApplicationDomain::getTypeName<Event>(), transaction, getIndex(), [mapper](const Sink::Entity &entity, const QByteArray &property) { 88 return DataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName<Event>(), transaction, getIndex(), [mapper](const Sink::Entity &entity, const QByteArray &property) {
95 89
96 const auto localBuffer = Sink::EntityBuffer::readBuffer<Buffer>(entity.local()); 90 const auto localBuffer = Sink::EntityBuffer::readBuffer<Buffer>(entity.local());
97 return mapper->getProperty(property, localBuffer); 91 return mapper->getProperty(property, localBuffer);
diff --git a/common/domain/event.h b/common/domain/event.h
index 4ac572c..e1ca061 100644
--- a/common/domain/event.h
+++ b/common/domain/event.h
@@ -51,13 +51,7 @@ public:
51 typedef Sink::ApplicationDomain::Buffer::Event Buffer; 51 typedef Sink::ApplicationDomain::Buffer::Event Buffer;
52 typedef Sink::ApplicationDomain::Buffer::EventBuilder BufferBuilder; 52 typedef Sink::ApplicationDomain::Buffer::EventBuilder BufferBuilder;
53 static QSet<QByteArray> indexedProperties(); 53 static QSet<QByteArray> indexedProperties();
54 static DataStoreQuery prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction); 54 static DataStoreQuery::Ptr prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction);
55 /**
56 * Returns the potential result set based on the indexes.
57 *
58 * An empty result set indicates that a full scan is required.
59 */
60 static ResultSet queryIndexes(const Sink::Query &query, const QByteArray &resourceInstanceIdentifier, QSet<QByteArray> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::Transaction &transaction);
61 static void index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction); 55 static void index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction);
62 static void removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction); 56 static void removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction);
63 static QSharedPointer<ReadPropertyMapper<Buffer> > initializeReadPropertyMapper(); 57 static QSharedPointer<ReadPropertyMapper<Buffer> > initializeReadPropertyMapper();
diff --git a/common/domain/folder.cpp b/common/domain/folder.cpp
index 6d487b1..17d9f13 100644
--- a/common/domain/folder.cpp
+++ b/common/domain/folder.cpp
@@ -55,11 +55,6 @@ static TypeIndex &getIndex()
55 return *index; 55 return *index;
56} 56}
57 57
58ResultSet TypeImplementation<Folder>::queryIndexes(const Sink::Query &query, const QByteArray &resourceInstanceIdentifier, QSet<QByteArray> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::Transaction &transaction)
59{
60 return getIndex().query(query, appliedFilters, appliedSorting, transaction);
61}
62
63void TypeImplementation<Folder>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) 58void TypeImplementation<Folder>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
64{ 59{
65 SinkTrace() << "Indexing " << identifier; 60 SinkTrace() << "Indexing " << identifier;
@@ -91,10 +86,10 @@ QSharedPointer<WritePropertyMapper<TypeImplementation<Folder>::BufferBuilder> >
91 return propertyMapper; 86 return propertyMapper;
92} 87}
93 88
94DataStoreQuery TypeImplementation<Folder>::prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction) 89DataStoreQuery::Ptr TypeImplementation<Folder>::prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction)
95{ 90{
96 auto mapper = initializeReadPropertyMapper(); 91 auto mapper = initializeReadPropertyMapper();
97 return DataStoreQuery(query, ApplicationDomain::getTypeName<Folder>(), transaction, getIndex(), [mapper](const Sink::Entity &entity, const QByteArray &property) { 92 return DataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName<Folder>(), transaction, getIndex(), [mapper](const Sink::Entity &entity, const QByteArray &property) {
98 const auto localBuffer = Sink::EntityBuffer::readBuffer<Buffer>(entity.local()); 93 const auto localBuffer = Sink::EntityBuffer::readBuffer<Buffer>(entity.local());
99 return mapper->getProperty(property, localBuffer); 94 return mapper->getProperty(property, localBuffer);
100 }); 95 });
diff --git a/common/domain/folder.h b/common/domain/folder.h
index 77edc8a..ff87006 100644
--- a/common/domain/folder.h
+++ b/common/domain/folder.h
@@ -45,9 +45,8 @@ class TypeImplementation<Sink::ApplicationDomain::Folder> {
45public: 45public:
46 typedef Sink::ApplicationDomain::Buffer::Folder Buffer; 46 typedef Sink::ApplicationDomain::Buffer::Folder Buffer;
47 typedef Sink::ApplicationDomain::Buffer::FolderBuilder BufferBuilder; 47 typedef Sink::ApplicationDomain::Buffer::FolderBuilder BufferBuilder;
48 static DataStoreQuery prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction); 48 static DataStoreQuery::Ptr prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction);
49 static QSet<QByteArray> indexedProperties(); 49 static QSet<QByteArray> indexedProperties();
50 static ResultSet queryIndexes(const Sink::Query &query, const QByteArray &resourceInstanceIdentifier, QSet<QByteArray> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::Transaction &transaction);
51 static void index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction); 50 static void index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction);
52 static void removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction); 51 static void removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction);
53 static QSharedPointer<ReadPropertyMapper<Buffer> > initializeReadPropertyMapper(); 52 static QSharedPointer<ReadPropertyMapper<Buffer> > initializeReadPropertyMapper();
diff --git a/common/domain/mail.cpp b/common/domain/mail.cpp
index bb5ad58..859ebef 100644
--- a/common/domain/mail.cpp
+++ b/common/domain/mail.cpp
@@ -41,6 +41,7 @@ SINK_DEBUG_AREA("mail");
41 41
42static QMutex sMutex; 42static QMutex sMutex;
43 43
44using namespace Sink;
44using namespace Sink::ApplicationDomain; 45using namespace Sink::ApplicationDomain;
45 46
46static TypeIndex &getIndex() 47static TypeIndex &getIndex()
@@ -49,26 +50,54 @@ static TypeIndex &getIndex()
49 static TypeIndex *index = 0; 50 static TypeIndex *index = 0;
50 if (!index) { 51 if (!index) {
51 index = new TypeIndex("mail"); 52 index = new TypeIndex("mail");
52 index->addProperty<QByteArray>("uid"); 53 index->addProperty<QByteArray>(Mail::Uid::name);
53 index->addProperty<QByteArray>("sender"); 54 index->addProperty<QByteArray>(Mail::Sender::name);
54 index->addProperty<QByteArray>("senderName"); 55 index->addProperty<QByteArray>(Mail::SenderName::name);
55 index->addProperty<QString>("subject"); 56 index->addProperty<QString>(Mail::Subject::name);
56 index->addProperty<QDateTime>("date"); 57 index->addProperty<QDateTime>(Mail::Date::name);
57 index->addProperty<QByteArray>("folder"); 58 index->addProperty<QByteArray>(Mail::Folder::name);
58 index->addPropertyWithSorting<QByteArray, QDateTime>("folder", "date"); 59 index->addPropertyWithSorting<QByteArray, QDateTime>(Mail::Folder::name, Mail::Date::name);
60 index->addProperty<QByteArray>(Mail::MessageId::name);
61 index->addProperty<QByteArray>(Mail::ParentMessageId::name);
59 } 62 }
60 return *index; 63 return *index;
61} 64}
62 65
63ResultSet TypeImplementation<Mail>::queryIndexes(const Sink::Query &query, const QByteArray &resourceInstanceIdentifier, QSet<QByteArray> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::Transaction &transaction) 66static void updateThreadingIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
64{ 67{
65 return getIndex().query(query, appliedFilters, appliedSorting, transaction); 68 auto messageId = bufferAdaptor.getProperty(Mail::MessageId::name).toByteArray();
69 auto parentMessageId = bufferAdaptor.getProperty(Mail::ParentMessageId::name).toByteArray();
70
71 Index msgIdIndex("msgId", transaction);
72 Index msgIdThreadIdIndex("msgIdThreadId", transaction);
73
74 //Add the message to the index
75 Q_ASSERT(msgIdIndex.lookup(messageId).isEmpty());
76 msgIdIndex.add(messageId, identifier);
77
78 //If parent is already available, add to thread of parent
79 QByteArray thread;
80 if (!parentMessageId.isEmpty() && !msgIdIndex.lookup(parentMessageId).isEmpty()) {
81 thread = msgIdThreadIdIndex.lookup(parentMessageId);
82 msgIdThreadIdIndex.add(messageId, thread);
83 } else {
84 thread = QUuid::createUuid().toByteArray();
85 if (!parentMessageId.isEmpty()) {
86 //Register parent with thread for when it becomes available
87 msgIdThreadIdIndex.add(parentMessageId, thread);
88 }
89 }
90 Q_ASSERT(!thread.isEmpty());
91 msgIdThreadIdIndex.add(messageId, thread);
92
93 //Look for parentMessageId and resolve to local id if available
66} 94}
67 95
68void TypeImplementation<Mail>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) 96void TypeImplementation<Mail>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
69{ 97{
70 SinkTrace() << "Indexing " << identifier; 98 SinkTrace() << "Indexing " << identifier;
71 getIndex().add(identifier, bufferAdaptor, transaction); 99 getIndex().add(identifier, bufferAdaptor, transaction);
100 updateThreadingIndex(identifier, bufferAdaptor, transaction);
72} 101}
73 102
74void TypeImplementation<Mail>::removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) 103void TypeImplementation<Mail>::removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
@@ -91,6 +120,8 @@ QSharedPointer<ReadPropertyMapper<TypeImplementation<Mail>::Buffer> > TypeImplem
91 propertyMapper->addMapping<Mail::Draft, Buffer>(&Buffer::draft); 120 propertyMapper->addMapping<Mail::Draft, Buffer>(&Buffer::draft);
92 propertyMapper->addMapping<Mail::Trash, Buffer>(&Buffer::trash); 121 propertyMapper->addMapping<Mail::Trash, Buffer>(&Buffer::trash);
93 propertyMapper->addMapping<Mail::Sent, Buffer>(&Buffer::sent); 122 propertyMapper->addMapping<Mail::Sent, Buffer>(&Buffer::sent);
123 propertyMapper->addMapping<Mail::MessageId, Buffer>(&Buffer::messageId);
124 propertyMapper->addMapping<Mail::ParentMessageId, Buffer>(&Buffer::parentMessageId);
94 return propertyMapper; 125 return propertyMapper;
95} 126}
96 127
@@ -110,16 +141,72 @@ QSharedPointer<WritePropertyMapper<TypeImplementation<Mail>::BufferBuilder> > Ty
110 propertyMapper->addMapping<Mail::Draft>(&BufferBuilder::add_draft); 141 propertyMapper->addMapping<Mail::Draft>(&BufferBuilder::add_draft);
111 propertyMapper->addMapping<Mail::Trash>(&BufferBuilder::add_trash); 142 propertyMapper->addMapping<Mail::Trash>(&BufferBuilder::add_trash);
112 propertyMapper->addMapping<Mail::Sent>(&BufferBuilder::add_sent); 143 propertyMapper->addMapping<Mail::Sent>(&BufferBuilder::add_sent);
144 propertyMapper->addMapping<Mail::MessageId>(&BufferBuilder::add_messageId);
145 propertyMapper->addMapping<Mail::ParentMessageId>(&BufferBuilder::add_parentMessageId);
113 return propertyMapper; 146 return propertyMapper;
114} 147}
115 148
116DataStoreQuery TypeImplementation<Mail>::prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction) 149class ThreadedDataStoreQuery : public DataStoreQuery
150{
151public:
152 typedef QSharedPointer<ThreadedDataStoreQuery> Ptr;
153 using DataStoreQuery::DataStoreQuery;
154
155protected:
156 ResultSet postSortFilter(ResultSet &resultSet) Q_DECL_OVERRIDE
157 {
158 auto query = mQuery;
159 if (query.threadLeaderOnly) {
160 auto rootCollection = QSharedPointer<QMap<QByteArray, QDateTime>>::create();
161 auto filter = [this, query, rootCollection](const QByteArray &uid, const Sink::EntityBuffer &entity) -> bool {
162 //TODO lookup thread
163 //if we got thread already in the result set compare dates and if newer replace
164 //else insert
165
166 const auto messageId = getProperty(entity.entity(), ApplicationDomain::Mail::MessageId::name).toByteArray();
167
168 Index msgIdIndex("msgId", mTransaction);
169 Index msgIdThreadIdIndex("msgIdThreadId", mTransaction);
170 auto thread = msgIdThreadIdIndex.lookup(messageId);
171 SinkTrace() << "MsgId: " << messageId << " Thread: " << thread << getProperty(entity.entity(), ApplicationDomain::Mail::Date::name).toDateTime();
172
173 if (rootCollection->contains(thread)) {
174 auto date = rootCollection->value(thread);
175 //The mail we have in our result already is newer, so we can ignore this one
176 if (date > getProperty(entity.entity(), ApplicationDomain::Mail::Date::name).toDateTime()) {
177 return false;
178 }
179 qWarning() << "############################################################################";
180 qWarning() << "Found a newer mail, remove the old one";
181 qWarning() << "############################################################################";
182 }
183 rootCollection->insert(thread, getProperty(entity.entity(), ApplicationDomain::Mail::Date::name).toDateTime());
184 return true;
185 };
186 return createFilteredSet(resultSet, filter);
187 } else {
188 return resultSet;
189 }
190 }
191};
192
193DataStoreQuery::Ptr TypeImplementation<Mail>::prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction)
117{ 194{
118 auto mapper = initializeReadPropertyMapper(); 195 if (query.threadLeaderOnly) {
119 return DataStoreQuery(query, ApplicationDomain::getTypeName<Mail>(), transaction, getIndex(), [mapper](const Sink::Entity &entity, const QByteArray &property) { 196 auto mapper = initializeReadPropertyMapper();
197 return ThreadedDataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName<Mail>(), transaction, getIndex(), [mapper](const Sink::Entity &entity, const QByteArray &property) {
198
199 const auto localBuffer = Sink::EntityBuffer::readBuffer<Buffer>(entity.local());
200 return mapper->getProperty(property, localBuffer);
201 });
120 202
121 const auto localBuffer = Sink::EntityBuffer::readBuffer<Buffer>(entity.local()); 203 } else {
122 return mapper->getProperty(property, localBuffer); 204 auto mapper = initializeReadPropertyMapper();
123 }); 205 return DataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName<Mail>(), transaction, getIndex(), [mapper](const Sink::Entity &entity, const QByteArray &property) {
206
207 const auto localBuffer = Sink::EntityBuffer::readBuffer<Buffer>(entity.local());
208 return mapper->getProperty(property, localBuffer);
209 });
210 }
124} 211}
125 212
diff --git a/common/domain/mail.fbs b/common/domain/mail.fbs
index a0c0d82..f14e9f1 100644
--- a/common/domain/mail.fbs
+++ b/common/domain/mail.fbs
@@ -13,6 +13,8 @@ table Mail {
13 draft:bool = false; 13 draft:bool = false;
14 trash:bool = false; 14 trash:bool = false;
15 sent:bool = false; 15 sent:bool = false;
16 messageId:string;
17 parentMessageId:string;
16} 18}
17 19
18root_type Mail; 20root_type Mail;
diff --git a/common/domain/mail.h b/common/domain/mail.h
index d6af9c5..3b0e9da 100644
--- a/common/domain/mail.h
+++ b/common/domain/mail.h
@@ -45,14 +45,8 @@ class TypeImplementation<Sink::ApplicationDomain::Mail> {
45public: 45public:
46 typedef Sink::ApplicationDomain::Buffer::Mail Buffer; 46 typedef Sink::ApplicationDomain::Buffer::Mail Buffer;
47 typedef Sink::ApplicationDomain::Buffer::MailBuilder BufferBuilder; 47 typedef Sink::ApplicationDomain::Buffer::MailBuilder BufferBuilder;
48 static DataStoreQuery prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction); 48 static DataStoreQuery::Ptr prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction);
49 static QSet<QByteArray> indexedProperties(); 49 static QSet<QByteArray> indexedProperties();
50 /**
51 * Returns the potential result set based on the indexes.
52 *
53 * An empty result set indicates that a full scan is required.
54 */
55 static ResultSet queryIndexes(const Sink::Query &query, const QByteArray &resourceInstanceIdentifier, QSet<QByteArray> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::Transaction &transaction);
56 static void index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction); 50 static void index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction);
57 static void removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction); 51 static void removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction);
58 static QSharedPointer<ReadPropertyMapper<Buffer> > initializeReadPropertyMapper(); 52 static QSharedPointer<ReadPropertyMapper<Buffer> > initializeReadPropertyMapper();