summaryrefslogtreecommitdiffstats
path: root/common/specialpurposepreprocessor.cpp
blob: 25a6d1aafe89f4e15d610a782b30787b94d5fdb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "specialpurposepreprocessor.h"
#include "query.h"
#include "applicationdomaintype.h"
#include "datastorequery.h"

using namespace Sink;

SINK_DEBUG_AREA("SpecialPurposeProcessor")

static QHash<QByteArray, QString> specialPurposeFolders()
{
    QHash<QByteArray, QString> hash;
        //FIXME localize
    //TODO inbox
    //TODO use standardized values
    hash.insert(ApplicationDomain::SpecialPurpose::Mail::drafts, "Drafts");
    hash.insert(ApplicationDomain::SpecialPurpose::Mail::trash, "Trash");
    hash.insert(ApplicationDomain::SpecialPurpose::Mail::inbox, "Inbox");
    hash.insert(ApplicationDomain::SpecialPurpose::Mail::sent, "Sent");
    return hash;
}

static QHash<QString, QByteArray> specialPurposeNames()
{
    QHash<QString, QByteArray> hash;
    for (const auto &value : specialPurposeFolders().values()) {
        hash.insert(value.toLower(), specialPurposeFolders().key(value));
    }
    return hash;
}

//specialpurpose, name
static QHash<QByteArray, QString> sSpecialPurposeFolders = specialPurposeFolders();
//Lowercase-name, specialpurpose
static QHash<QString, QByteArray> sSpecialPurposeNames = specialPurposeNames();

namespace SpecialPurpose {
bool isSpecialPurposeFolderName(const QString &name)
{
    return sSpecialPurposeNames.contains(name.toLower());
}

QByteArray getSpecialPurposeType(const QString &name)
{
    return sSpecialPurposeNames.value(name.toLower());
}
}

SpecialPurposeProcessor::SpecialPurposeProcessor() : Sink::Preprocessor() {}

QByteArray SpecialPurposeProcessor::findFolder(const QByteArray &specialPurpose, bool createIfMissing)
{
    if (!mSpecialPurposeFolders.contains(specialPurpose)) {
        //Try to find an existing drafts folder
        DataStoreQuery dataStoreQuery{Sink::Query().filter<ApplicationDomain::Folder::SpecialPurpose>(Query::Comparator(specialPurpose, Query::Comparator::Contains)), ApplicationDomain::getTypeName<ApplicationDomain::Folder>(), entityStore()};
        auto resultSet = dataStoreQuery.execute();
        resultSet.replaySet(0, 1, [&, this](const ResultSet::Result &r) {
            mSpecialPurposeFolders.insert(specialPurpose, r.entity.identifier());
        });

        if (!mSpecialPurposeFolders.contains(specialPurpose) && createIfMissing) {
            SinkTrace() << "Failed to find a " << specialPurpose << " folder, creating a new one";
            auto folder = ApplicationDomain::Folder::create(resourceInstanceIdentifier());
            folder.setSpecialPurpose(QByteArrayList() << specialPurpose);
            folder.setName(sSpecialPurposeFolders.value(specialPurpose));
            folder.setIcon("folder");
            //This processes the pipeline synchronously
            createEntity(folder);
            mSpecialPurposeFolders.insert(specialPurpose, folder.identifier());
        }
    }
    return mSpecialPurposeFolders.value(specialPurpose);
}

bool SpecialPurposeProcessor::isSpecialPurposeFolder(const QByteArray &folder) const
{
    return mSpecialPurposeFolders.values().contains(folder);
}

void SpecialPurposeProcessor::moveToFolder(Sink::ApplicationDomain::ApplicationDomainType &newEntity)
{
    //If we remove the draft folder move back to inbox
    //If we remove the trash property, move back to other specialpurpose folder or inbox
    //If a folder is set explicitly, clear specialpurpose flags.
    using namespace Sink::ApplicationDomain;
    auto mail = newEntity.cast<Mail>();
    if (mail.getTrash()) {
        auto f = findFolder(ApplicationDomain::SpecialPurpose::Mail::trash, true);
        SinkTrace() << "Setting trash folder: " << f;
        mail.setFolder(f);
    } else if (mail.getDraft()) {
        SinkTrace() << "Setting drafts folder: ";
        mail.setFolder(findFolder(ApplicationDomain::SpecialPurpose::Mail::drafts, true));
    } else if (mail.getSent()) {
        SinkTrace() << "Setting sent folder: ";
        mail.setFolder(findFolder(ApplicationDomain::SpecialPurpose::Mail::sent, true));
    } else {
        //No longer a specialpurpose mail, so move to inbox
        if (isSpecialPurposeFolder(mail.getFolder()) || mail.getFolder().isEmpty()) {
            mail.setFolder(findFolder(ApplicationDomain::SpecialPurpose::Mail::inbox, true));
        }
    }
}

void SpecialPurposeProcessor::newEntity(Sink::ApplicationDomain::ApplicationDomainType &newEntity)
{
    auto mail = newEntity.cast<ApplicationDomain::Mail>();
    const auto folder = mail.getFolder();
    if (folder.isEmpty()) {
        moveToFolder(newEntity);
    } else {
        bool isDraft = findFolder(ApplicationDomain::SpecialPurpose::Mail::drafts) == folder;
        bool isSent = findFolder(ApplicationDomain::SpecialPurpose::Mail::sent) == folder;
        bool isTrash = findFolder(ApplicationDomain::SpecialPurpose::Mail::trash) == folder;
        mail.setDraft(isDraft);
        mail.setTrash(isTrash);
        mail.setSent(isSent);
    }

}

void SpecialPurposeProcessor::modifiedEntity(const Sink::ApplicationDomain::ApplicationDomainType &oldEntity, Sink::ApplicationDomain::ApplicationDomainType &newEntity)
{
    using namespace Sink::ApplicationDomain;
    auto mail = newEntity.cast<Mail>();
    //If we moved the mail to a non-specialpurpose folder explicitly, also clear the flags.
    if (mail.changedProperties().contains(Mail::Folder::name)) {
        auto folder = mail.getFolder();
        bool isDraft = findFolder(ApplicationDomain::SpecialPurpose::Mail::drafts) == folder;
        bool isSent = findFolder(ApplicationDomain::SpecialPurpose::Mail::sent) == folder;
        bool isTrash = findFolder(ApplicationDomain::SpecialPurpose::Mail::trash) == folder;
        mail.setDraft(isDraft);
        mail.setTrash(isTrash);
        mail.setSent(isSent);
    } else {
        moveToFolder(newEntity);
    }
}