summaryrefslogtreecommitdiffstats
path: root/common/mail/threadindexer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/mail/threadindexer.cpp')
-rw-r--r--common/mail/threadindexer.cpp84
1 files changed, 11 insertions, 73 deletions
diff --git a/common/mail/threadindexer.cpp b/common/mail/threadindexer.cpp
index d91ab5f..4171d85 100644
--- a/common/mail/threadindexer.cpp
+++ b/common/mail/threadindexer.cpp
@@ -21,74 +21,15 @@
21#include "typeindex.h" 21#include "typeindex.h"
22#include "log.h" 22#include "log.h"
23 23
24SINK_DEBUG_AREA("threadindex")
25
26using namespace Sink; 24using namespace Sink;
27using namespace Sink::ApplicationDomain; 25using namespace Sink::ApplicationDomain;
28 26
29static QString stripOffPrefixes(const QString &subject)
30{
31 //TODO this hardcoded list is probably not good enough (especially regarding internationalization)
32 //TODO this whole routine, including internationalized re/fwd ... should go into some library.
33 //We'll require the same for generating reply/forward subjects in kube
34 static QStringList defaultReplyPrefixes = QStringList() << QLatin1String("Re\\s*:")
35 << QLatin1String("Re\\[\\d+\\]:")
36 << QLatin1String("Re\\d+:");
37
38 static QStringList defaultForwardPrefixes = QStringList() << QLatin1String("Fwd:")
39 << QLatin1String("FW:");
40
41 QStringList replyPrefixes; // = GlobalSettings::self()->replyPrefixes();
42 if (replyPrefixes.isEmpty()) {
43 replyPrefixes = defaultReplyPrefixes;
44 }
45
46 QStringList forwardPrefixes; // = GlobalSettings::self()->forwardPrefixes();
47 if (forwardPrefixes.isEmpty()) {
48 forwardPrefixes = defaultReplyPrefixes;
49 }
50
51 const QStringList prefixRegExps = replyPrefixes + forwardPrefixes;
52
53 // construct a big regexp that
54 // 1. is anchored to the beginning of str (sans whitespace)
55 // 2. matches at least one of the part regexps in prefixRegExps
56 const QString bigRegExp = QString::fromLatin1("^(?:\\s+|(?:%1))+\\s*").arg(prefixRegExps.join(QLatin1String(")|(?:")));
57
58 static QString regExpPattern;
59 static QRegExp regExp;
60
61 regExp.setCaseSensitivity(Qt::CaseInsensitive);
62 if (regExpPattern != bigRegExp) {
63 // the prefixes have changed, so update the regexp
64 regExpPattern = bigRegExp;
65 regExp.setPattern(regExpPattern);
66 }
67
68 if(regExp.isValid()) {
69 QString tmp = subject;
70 if (regExp.indexIn( tmp ) == 0) {
71 return tmp.remove(0, regExp.matchedLength());
72 }
73 } else {
74 SinkWarning() << "bigRegExp = \""
75 << bigRegExp << "\"\n"
76 << "prefix regexp is invalid!";
77 }
78
79 return subject;
80}
81
82
83void ThreadIndexer::updateThreadingIndex(const QByteArray &identifier, const ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction) 27void ThreadIndexer::updateThreadingIndex(const QByteArray &identifier, const ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction)
84{ 28{
85 auto messageId = entity.getProperty(Mail::MessageId::name); 29 auto messageId = entity.getProperty(Mail::MessageId::name);
86 auto parentMessageId = entity.getProperty(Mail::ParentMessageId::name); 30 auto parentMessageId = entity.getProperty(Mail::ParentMessageId::name);
87 const auto subject = entity.getProperty(Mail::Subject::name);
88 const auto normalizedSubject = stripOffPrefixes(subject.toString()).toUtf8();
89 if (messageId.toByteArray().isEmpty()) { 31 if (messageId.toByteArray().isEmpty()) {
90 SinkWarning() << "Found an email without messageId. This is illegal and threading will break. Entity id: " << identifier; 32 SinkWarning() << "Found an email without messageId. This is illegal and threading will break. Entity id: " << identifier;
91 SinkWarning() << "Subject: " << subject;
92 } 33 }
93 34
94 QVector<QByteArray> thread; 35 QVector<QByteArray> thread;
@@ -101,18 +42,9 @@ void ThreadIndexer::updateThreadingIndex(const QByteArray &identifier, const App
101 thread = index().secondaryLookup<Mail::MessageId, Mail::ThreadId>(parentMessageId); 42 thread = index().secondaryLookup<Mail::MessageId, Mail::ThreadId>(parentMessageId);
102 SinkTrace() << "Found parent: " << thread; 43 SinkTrace() << "Found parent: " << thread;
103 } 44 }
104
105 if (thread.isEmpty()) { 45 if (thread.isEmpty()) {
106 //Try to lookup the thread by subject if not empty 46 thread << QUuid::createUuid().toByteArray();
107 if ( !normalizedSubject.isEmpty()) { 47 SinkTrace() << "Created a new thread: " << thread;
108 thread = index().secondaryLookup<Mail::Subject, Mail::ThreadId>(normalizedSubject);
109 }
110 if (thread.isEmpty()) {
111 thread << QUuid::createUuid().toByteArray();
112 SinkTrace() << "Created a new thread: " << thread;
113 } else {
114 SinkTrace() << "Found thread by subject: " << thread;
115 }
116 } 48 }
117 49
118 Q_ASSERT(!thread.isEmpty()); 50 Q_ASSERT(!thread.isEmpty());
@@ -124,9 +56,6 @@ void ThreadIndexer::updateThreadingIndex(const QByteArray &identifier, const App
124 } 56 }
125 index().index<Mail::MessageId, Mail::ThreadId>(messageId, thread.first(), transaction); 57 index().index<Mail::MessageId, Mail::ThreadId>(messageId, thread.first(), transaction);
126 index().index<Mail::ThreadId, Mail::MessageId>(thread.first(), messageId, transaction); 58 index().index<Mail::ThreadId, Mail::MessageId>(thread.first(), messageId, transaction);
127 if (!normalizedSubject.isEmpty()) {
128 index().index<Mail::Subject, Mail::ThreadId>(normalizedSubject, thread.first(), transaction);
129 }
130} 59}
131 60
132 61
@@ -142,6 +71,15 @@ void ThreadIndexer::modify(const ApplicationDomain::ApplicationDomainType &old,
142 71
143void ThreadIndexer::remove(const ApplicationDomain::ApplicationDomainType &entity) 72void ThreadIndexer::remove(const ApplicationDomain::ApplicationDomainType &entity)
144{ 73{
74 auto messageId = entity.getProperty(Mail::MessageId::name);
75 auto thread = index().secondaryLookup<Mail::MessageId, Mail::ThreadId>(messageId);
76 index().unindex<Mail::MessageId, Mail::ThreadId>(messageId.toByteArray(), thread.first(), transaction());
77 index().unindex<Mail::ThreadId, Mail::MessageId>(thread.first(), messageId.toByteArray(), transaction());
78}
145 79
80QMap<QByteArray, int> ThreadIndexer::databases()
81{
82 return {{"mail.index.messageIdthreadId", 1},
83 {"mail.index.threadIdmessageId", 1}};
146} 84}
147 85