summaryrefslogtreecommitdiffstats
path: root/common/mail/threadindexer.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-10-20 13:34:38 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-10-21 09:18:50 +0200
commitda0c37dbad121252effa85941de4d49222176179 (patch)
tree6ea9831e80fc18dcae00cdf2788680bb8f4d1935 /common/mail/threadindexer.cpp
parent0dcc8e2985acbff52c497648e4fbb54e47bf3b51 (diff)
downloadsink-da0c37dbad121252effa85941de4d49222176179.tar.gz
sink-da0c37dbad121252effa85941de4d49222176179.zip
A new indexer subsystem that can be used for indexes that are more
complex than a simple key-value pair.
Diffstat (limited to 'common/mail/threadindexer.cpp')
-rw-r--r--common/mail/threadindexer.cpp140
1 files changed, 140 insertions, 0 deletions
diff --git a/common/mail/threadindexer.cpp b/common/mail/threadindexer.cpp
new file mode 100644
index 0000000..4a18625
--- /dev/null
+++ b/common/mail/threadindexer.cpp
@@ -0,0 +1,140 @@
1/*
2 * Copyright (C) 2015 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#include "threadindexer.h"
20
21#include "typeindex.h"
22#include "log.h"
23
24SINK_DEBUG_AREA("threadindex")
25
26using namespace Sink;
27using namespace Sink::ApplicationDomain;
28
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)
84{
85 auto messageId = entity.getProperty(Mail::MessageId::name);
86 auto parentMessageId = entity.getProperty(Mail::ParentMessageId::name);
87 auto subject = entity.getProperty(Mail::Subject::name);
88
89 auto normalizedSubject = stripOffPrefixes(subject.toString()).toUtf8();
90
91 QVector<QByteArray> thread;
92
93 //a child already registered our thread.
94 thread = index().secondaryLookup<Mail::MessageId, Mail::ThreadId>(messageId, transaction);
95
96 //If parent is already available, add to thread of parent
97 if (thread.isEmpty() && parentMessageId.isValid()) {
98 thread = index().secondaryLookup<Mail::MessageId, Mail::ThreadId>(parentMessageId, transaction);
99 SinkTrace() << "Found parent";
100 }
101 if (thread.isEmpty()) {
102 //Try to lookup the thread by subject:
103 thread = index().secondaryLookup<Mail::Subject, Mail::ThreadId>(normalizedSubject, transaction);
104 if (thread.isEmpty()) {
105 SinkTrace() << "Created a new thread ";
106 thread << QUuid::createUuid().toByteArray();
107 } else {
108 }
109 }
110
111 //We should have found the thread by now
112 if (!thread.isEmpty()) {
113 if (parentMessageId.isValid()) {
114 //Register parent with thread for when it becomes available
115 index().index<Mail::MessageId, Mail::ThreadId>(parentMessageId, thread.first(), transaction);
116 }
117 index().index<Mail::MessageId, Mail::ThreadId>(messageId, thread.first(), transaction);
118 index().index<Mail::ThreadId, Mail::MessageId>(thread.first(), messageId, transaction);
119 index().index<Mail::Subject, Mail::ThreadId>(normalizedSubject, thread.first(), transaction);
120 } else {
121 SinkWarning() << "Couldn't find a thread for: " << messageId;
122 }
123}
124
125
126void ThreadIndexer::add(const ApplicationDomain::ApplicationDomainType &entity)
127{
128 updateThreadingIndex(entity.identifier(), entity, transaction());
129}
130
131void ThreadIndexer::modify(const ApplicationDomain::ApplicationDomainType &old, const ApplicationDomain::ApplicationDomainType &entity)
132{
133
134}
135
136void ThreadIndexer::remove(const ApplicationDomain::ApplicationDomainType &entity)
137{
138
139}
140