diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-02-05 17:33:08 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-02-05 18:14:43 +0100 |
commit | 47bfba0d9152a1f7f689d7936b107b1a899a0b76 (patch) | |
tree | d3097b1da7bc87984bd7fdffbf803ed682e95fcc | |
parent | b9a79ed514e7ab6bab0d6dedfcb9a78387d2b7c1 (diff) | |
download | sink-47bfba0d9152a1f7f689d7936b107b1a899a0b76.tar.gz sink-47bfba0d9152a1f7f689d7936b107b1a899a0b76.zip |
Use property transformation for the mimeMessage
The filepath changes with every flag change. It is thus easier to only
store a limited path that remains stable, and figure out the rest as
the property is requested (we'll have to translate it anyways once we
the file handoff protocol is implemented).
The reason why we don't update the mimeMessage path on every
modification is because we move the message during change replay,
and not while storing the modification in the db. This would lead to
the message-path on disk not correspond to what is in the db for some
time.
-rw-r--r-- | examples/maildirresource/facade.cpp | 30 | ||||
-rw-r--r-- | examples/maildirresource/facade.h | 1 | ||||
-rw-r--r-- | examples/maildirresource/libmaildir/maildir.cpp | 20 | ||||
-rw-r--r-- | examples/maildirresource/libmaildir/maildir.h | 13 | ||||
-rw-r--r-- | examples/maildirresource/maildirresource.cpp | 6 | ||||
-rw-r--r-- | tests/maildirresourcetest.cpp | 17 |
6 files changed, 83 insertions, 4 deletions
diff --git a/examples/maildirresource/facade.cpp b/examples/maildirresource/facade.cpp index 7178ab9..a10a18b 100644 --- a/examples/maildirresource/facade.cpp +++ b/examples/maildirresource/facade.cpp | |||
@@ -19,17 +19,47 @@ | |||
19 | 19 | ||
20 | #include "facade.h" | 20 | #include "facade.h" |
21 | 21 | ||
22 | #include <QDir> | ||
23 | #include <QFileInfo> | ||
24 | |||
22 | #include "domainadaptor.h" | 25 | #include "domainadaptor.h" |
26 | #include "queryrunner.h" | ||
23 | 27 | ||
24 | MaildirResourceMailFacade::MaildirResourceMailFacade(const QByteArray &instanceIdentifier) | 28 | MaildirResourceMailFacade::MaildirResourceMailFacade(const QByteArray &instanceIdentifier) |
25 | : Sink::GenericFacade<Sink::ApplicationDomain::Mail>(instanceIdentifier, QSharedPointer<MaildirMailAdaptorFactory>::create()) | 29 | : Sink::GenericFacade<Sink::ApplicationDomain::Mail>(instanceIdentifier, QSharedPointer<MaildirMailAdaptorFactory>::create()) |
26 | { | 30 | { |
31 | mResultTransformation = [](Sink::ApplicationDomain::ApplicationDomainType &value) { | ||
32 | const auto property = value.getProperty("mimeMessage"); | ||
33 | if (property.isValid()) { | ||
34 | //Transform the mime message property into the actual path on disk. | ||
35 | const auto mimeMessage = property.toString(); | ||
36 | auto parts = mimeMessage.split('/'); | ||
37 | auto key = parts.takeLast(); | ||
38 | const auto folderPath = parts.join('/'); | ||
39 | const auto path = folderPath + "/cur/"; | ||
40 | |||
41 | Trace() << "Looking for mail in: " << path << key; | ||
42 | QDir dir(path); | ||
43 | const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files); | ||
44 | if (list.size() != 1) { | ||
45 | Warning() << "Failed to find message " << path << key << list.size(); | ||
46 | value.setProperty("mimeMessage", QVariant()); | ||
47 | } else { | ||
48 | value.setProperty("mimeMessage", list.at(0).filePath()); | ||
49 | } | ||
50 | } | ||
51 | }; | ||
27 | } | 52 | } |
28 | 53 | ||
29 | MaildirResourceMailFacade::~MaildirResourceMailFacade() | 54 | MaildirResourceMailFacade::~MaildirResourceMailFacade() |
30 | { | 55 | { |
31 | } | 56 | } |
32 | 57 | ||
58 | QPair<KAsync::Job<void>, Sink::ResultEmitter<Sink::ApplicationDomain::Mail::Ptr>::Ptr> MaildirResourceMailFacade::load(const Sink::Query &query) | ||
59 | { | ||
60 | return Sink::GenericFacade<Sink::ApplicationDomain::Mail>::load(query); | ||
61 | } | ||
62 | |||
33 | 63 | ||
34 | MaildirResourceFolderFacade::MaildirResourceFolderFacade(const QByteArray &instanceIdentifier) | 64 | MaildirResourceFolderFacade::MaildirResourceFolderFacade(const QByteArray &instanceIdentifier) |
35 | : Sink::GenericFacade<Sink::ApplicationDomain::Folder>(instanceIdentifier, QSharedPointer<MaildirFolderAdaptorFactory>::create()) | 65 | : Sink::GenericFacade<Sink::ApplicationDomain::Folder>(instanceIdentifier, QSharedPointer<MaildirFolderAdaptorFactory>::create()) |
diff --git a/examples/maildirresource/facade.h b/examples/maildirresource/facade.h index a243b0d..38981d0 100644 --- a/examples/maildirresource/facade.h +++ b/examples/maildirresource/facade.h | |||
@@ -26,6 +26,7 @@ class MaildirResourceMailFacade : public Sink::GenericFacade<Sink::ApplicationDo | |||
26 | public: | 26 | public: |
27 | MaildirResourceMailFacade(const QByteArray &instanceIdentifier); | 27 | MaildirResourceMailFacade(const QByteArray &instanceIdentifier); |
28 | virtual ~MaildirResourceMailFacade(); | 28 | virtual ~MaildirResourceMailFacade(); |
29 | QPair<KAsync::Job<void>, Sink::ResultEmitter<Sink::ApplicationDomain::Mail::Ptr>::Ptr> load(const Sink::Query &query) Q_DECL_OVERRIDE; | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | class MaildirResourceFolderFacade : public Sink::GenericFacade<Sink::ApplicationDomain::Folder> | 32 | class MaildirResourceFolderFacade : public Sink::GenericFacade<Sink::ApplicationDomain::Folder> |
diff --git a/examples/maildirresource/libmaildir/maildir.cpp b/examples/maildirresource/libmaildir/maildir.cpp index 0057b26..59e7e5c 100644 --- a/examples/maildirresource/libmaildir/maildir.cpp +++ b/examples/maildirresource/libmaildir/maildir.cpp | |||
@@ -177,6 +177,13 @@ public: | |||
177 | return realKey; | 177 | return realKey; |
178 | } | 178 | } |
179 | 179 | ||
180 | static QString stripFlags(const QString& key) | ||
181 | { | ||
182 | const QRegExp rx = *(statusSeparatorRx()); | ||
183 | const int index = key.indexOf(rx); | ||
184 | return key.mid(0, index); | ||
185 | } | ||
186 | |||
180 | static QString subDirNameForFolderName(const QString &folderName) | 187 | static QString subDirNameForFolderName(const QString &folderName) |
181 | { | 188 | { |
182 | return QString::fromLatin1(".%1.directory").arg(folderName); | 189 | return QString::fromLatin1(".%1.directory").arg(folderName); |
@@ -559,6 +566,19 @@ QDateTime Maildir::lastModified(const QString& key) const | |||
559 | return info.lastModified(); | 566 | return info.lastModified(); |
560 | } | 567 | } |
561 | 568 | ||
569 | QString Maildir::getKeyFromFile(const QString& file) | ||
570 | { | ||
571 | return Maildir::Private::stripFlags(file.split('/').last()); | ||
572 | } | ||
573 | |||
574 | QString Maildir::getDirectoryFromFile( const QString& file ) | ||
575 | { | ||
576 | auto parts = file.split('/'); | ||
577 | parts.removeLast(); //File | ||
578 | parts.removeLast(); //cur/new/tmp | ||
579 | return parts.join('/') + "/"; | ||
580 | } | ||
581 | |||
562 | QByteArray Maildir::readEntryHeadersFromFile(const QString& file) | 582 | QByteArray Maildir::readEntryHeadersFromFile(const QString& file) |
563 | { | 583 | { |
564 | QByteArray result; | 584 | QByteArray result; |
diff --git a/examples/maildirresource/libmaildir/maildir.h b/examples/maildirresource/libmaildir/maildir.h index 5936515..6c68656 100644 --- a/examples/maildirresource/libmaildir/maildir.h +++ b/examples/maildirresource/libmaildir/maildir.h | |||
@@ -262,6 +262,19 @@ public: | |||
262 | querying the last error string. */ | 262 | querying the last error string. */ |
263 | QString lastError() const; | 263 | QString lastError() const; |
264 | 264 | ||
265 | /** | ||
266 | * Returns the key from the file identified by the full path @param file. | ||
267 | */ | ||
268 | static QString getKeyFromFile( const QString& file ); | ||
269 | |||
270 | /** | ||
271 | * Returns the directory from a file. | ||
272 | * | ||
273 | * Strips key and new/cur/tmp. | ||
274 | * The returned path is ended with a trailing slash. | ||
275 | */ | ||
276 | static QString getDirectoryFromFile( const QString& file ); | ||
277 | |||
265 | private: | 278 | private: |
266 | void swap( const Maildir& ); | 279 | void swap( const Maildir& ); |
267 | class Private; | 280 | class Private; |
diff --git a/examples/maildirresource/maildirresource.cpp b/examples/maildirresource/maildirresource.cpp index 87623ca..d5cc24b 100644 --- a/examples/maildirresource/maildirresource.cpp +++ b/examples/maildirresource/maildirresource.cpp | |||
@@ -175,6 +175,7 @@ void MaildirResource::synchronizeMails(Sink::Storage::Transaction &transaction, | |||
175 | msg->parse(); | 175 | msg->parse(); |
176 | 176 | ||
177 | const auto flags = maildir.readEntryFlags(fileName); | 177 | const auto flags = maildir.readEntryFlags(fileName); |
178 | const auto maildirKey = maildir.getKeyFromFile(fileName); | ||
178 | 179 | ||
179 | Trace() << "Found a mail " << filePath << " : " << fileName << msg->subject(true)->asUnicodeString(); | 180 | Trace() << "Found a mail " << filePath << " : " << fileName << msg->subject(true)->asUnicodeString(); |
180 | 181 | ||
@@ -184,7 +185,8 @@ void MaildirResource::synchronizeMails(Sink::Storage::Transaction &transaction, | |||
184 | mail.setProperty("senderName", msg->from(true)->asUnicodeString()); | 185 | mail.setProperty("senderName", msg->from(true)->asUnicodeString()); |
185 | mail.setProperty("date", msg->date(true)->dateTime()); | 186 | mail.setProperty("date", msg->date(true)->dateTime()); |
186 | mail.setProperty("folder", folderLocalId); | 187 | mail.setProperty("folder", folderLocalId); |
187 | mail.setProperty("mimeMessage", filePath); | 188 | //We only store the directory path + key, so we facade can add the changing bits (flags) |
189 | mail.setProperty("mimeMessage", KPIM::Maildir::getDirectoryFromFile(filePath) + maildirKey); | ||
188 | mail.setProperty("unread", !flags.testFlag(KPIM::Maildir::Seen)); | 190 | mail.setProperty("unread", !flags.testFlag(KPIM::Maildir::Seen)); |
189 | mail.setProperty("important", flags.testFlag(KPIM::Maildir::Flagged)); | 191 | mail.setProperty("important", flags.testFlag(KPIM::Maildir::Flagged)); |
190 | 192 | ||
@@ -274,7 +276,7 @@ KAsync::Job<void> MaildirResource::replay(Sink::Storage &synchronizationStore, c | |||
274 | if (!maildir.isValid(true)) { | 276 | if (!maildir.isValid(true)) { |
275 | return KAsync::error<void>(1, "Invalid folder " + parentFolderPath); | 277 | return KAsync::error<void>(1, "Invalid folder " + parentFolderPath); |
276 | } | 278 | } |
277 | //FIXME assemble the MIME message | 279 | //FIXME move the mime message from the mimeMessage property to the proper place. |
278 | Trace() << "Creating a new mail."; | 280 | Trace() << "Creating a new mail."; |
279 | const auto remoteId = maildir.addEntry("foobar"); | 281 | const auto remoteId = maildir.addEntry("foobar"); |
280 | if (remoteId.isEmpty()) { | 282 | if (remoteId.isEmpty()) { |
diff --git a/tests/maildirresourcetest.cpp b/tests/maildirresourcetest.cpp index 7cdfc36..e502d10 100644 --- a/tests/maildirresourcetest.cpp +++ b/tests/maildirresourcetest.cpp | |||
@@ -158,6 +158,9 @@ private Q_SLOTS: | |||
158 | QVERIFY(!mail->getProperty("subject").toString().isEmpty()); | 158 | QVERIFY(!mail->getProperty("subject").toString().isEmpty()); |
159 | QVERIFY(!mail->getProperty("mimeMessage").toString().isEmpty()); | 159 | QVERIFY(!mail->getProperty("mimeMessage").toString().isEmpty()); |
160 | QVERIFY(mail->getProperty("date").toDateTime().isValid()); | 160 | QVERIFY(mail->getProperty("date").toDateTime().isValid()); |
161 | |||
162 | QFileInfo info(mail->getProperty("mimeMessage").toString()); | ||
163 | QVERIFY(info.exists()); | ||
161 | } | 164 | } |
162 | 165 | ||
163 | 166 | ||
@@ -368,10 +371,11 @@ private Q_SLOTS: | |||
368 | result.waitForFinished(); | 371 | result.waitForFinished(); |
369 | QVERIFY(!result.errorCode()); | 372 | QVERIFY(!result.errorCode()); |
370 | 373 | ||
374 | //Verify that we can still query for all relevant information | ||
371 | auto result2 = Store::fetchAll<Mail>( | 375 | auto result2 = Store::fetchAll<Mail>( |
372 | Query::ResourceFilter("org.kde.maildir.instance1") + Query::PropertyFilter("folder", f) + Query::RequestedProperties(QByteArrayList() << "folder" << "subject") | 376 | Query::ResourceFilter("org.kde.maildir.instance1") + Query::PropertyFilter("folder", f) + Query::RequestedProperties(QByteArrayList() << "folder" << "subject" << "mimeMessage" << "unread") |
373 | ) | 377 | ) |
374 | .then<void, KAsync::Job<void>, QList<Mail::Ptr> >([query](const QList<Mail::Ptr> &mails) { | 378 | .then<void, KAsync::Job<void>, QList<Mail::Ptr> >([](const QList<Mail::Ptr> &mails) { |
375 | //Can't use QCOMPARE because it tries to return FIXME Implement ASYNCCOMPARE | 379 | //Can't use QCOMPARE because it tries to return FIXME Implement ASYNCCOMPARE |
376 | if (mails.size() != 1) { | 380 | if (mails.size() != 1) { |
377 | qWarning() << "Wrong number of mails"; | 381 | qWarning() << "Wrong number of mails"; |
@@ -382,6 +386,15 @@ private Q_SLOTS: | |||
382 | qWarning() << "Wrong subject"; | 386 | qWarning() << "Wrong subject"; |
383 | return KAsync::error<void>(1, "Wrong subject."); | 387 | return KAsync::error<void>(1, "Wrong subject."); |
384 | } | 388 | } |
389 | if (mail->getProperty("unread").toBool() != true) { | ||
390 | qWarning() << "Not unread"; | ||
391 | return KAsync::error<void>(1, "Not unread."); | ||
392 | } | ||
393 | QFileInfo info(mail->getProperty("mimeMessage").toString()); | ||
394 | if (!info.exists()) { | ||
395 | qWarning() << "Wrong subject"; | ||
396 | return KAsync::error<void>(1, "Can't find mime message."); | ||
397 | } | ||
385 | return KAsync::null<void>(); | 398 | return KAsync::null<void>(); |
386 | }) | 399 | }) |
387 | .exec(); | 400 | .exec(); |