File indexing completed on 2024-05-12 05:26:04

0001 #include "specialpurposepreprocessor.h"
0002 #include "query.h"
0003 #include "applicationdomaintype.h"
0004 #include "datastorequery.h"
0005 
0006 using namespace Sink;
0007 
0008 static QHash<QByteArray, QString> specialPurposeFolders()
0009 {
0010     QHash<QByteArray, QString> hash;
0011         //FIXME localize
0012     //TODO inbox
0013     //TODO use standardized values
0014     hash.insert(ApplicationDomain::SpecialPurpose::Mail::drafts, "Drafts");
0015     hash.insert(ApplicationDomain::SpecialPurpose::Mail::trash, "Trash");
0016     hash.insert(ApplicationDomain::SpecialPurpose::Mail::inbox, "Inbox");
0017     hash.insert(ApplicationDomain::SpecialPurpose::Mail::sent, "Sent");
0018     return hash;
0019 }
0020 
0021 static QHash<QString, QByteArray> specialPurposeNames()
0022 {
0023     QHash<QString, QByteArray> hash;
0024     for (const auto &value : specialPurposeFolders().values()) {
0025         hash.insert(value.toLower(), specialPurposeFolders().key(value));
0026     }
0027     return hash;
0028 }
0029 
0030 //specialpurpose, name
0031 static QHash<QByteArray, QString> sSpecialPurposeFolders = specialPurposeFolders();
0032 //Lowercase-name, specialpurpose
0033 static QHash<QString, QByteArray> sSpecialPurposeNames = specialPurposeNames();
0034 
0035 namespace SpecialPurpose {
0036 bool isSpecialPurposeFolderName(const QString &name)
0037 {
0038     return sSpecialPurposeNames.contains(name.toLower());
0039 }
0040 
0041 QByteArray getSpecialPurposeType(const QString &name)
0042 {
0043     return sSpecialPurposeNames.value(name.toLower());
0044 }
0045 }
0046 
0047 SpecialPurposeProcessor::SpecialPurposeProcessor() : Sink::Preprocessor() {}
0048 
0049 QByteArray SpecialPurposeProcessor::findFolder(const QByteArray &specialPurpose, bool createIfMissing)
0050 {
0051     if (!mSpecialPurposeFolders.contains(specialPurpose)) {
0052         //Try to find an existing and enabled folder we can use.
0053         auto query = Sink::Query();
0054         query.filter<ApplicationDomain::Folder::SpecialPurpose>(Query::Comparator(specialPurpose, Query::Comparator::Contains));
0055         query.filter<ApplicationDomain::Folder::Enabled>(true);
0056         query.request<ApplicationDomain::Folder::Enabled>();
0057 
0058         DataStoreQuery dataStoreQuery{query, ApplicationDomain::getTypeName<ApplicationDomain::Folder>(), entityStore()};
0059         auto resultSet = dataStoreQuery.execute();
0060         resultSet.replaySet(0, 1, [&, this](const ResultSet::Result &r) {
0061             mSpecialPurposeFolders.insert(specialPurpose, r.entity.identifier());
0062         });
0063 
0064         //Create a new folder if we couldn't find one. We will also create a new folder if the old one was disabled for some reason.
0065         if (!mSpecialPurposeFolders.contains(specialPurpose) && createIfMissing) {
0066             SinkTrace() << "Failed to find a " << specialPurpose << " folder, creating a new one";
0067             auto folder = ApplicationDomain::Folder::create(resourceInstanceIdentifier());
0068             folder.setSpecialPurpose(QByteArrayList() << specialPurpose);
0069             folder.setName(sSpecialPurposeFolders.value(specialPurpose));
0070             folder.setIcon("folder");
0071             folder.setEnabled(true);
0072             //This processes the pipeline synchronously
0073             createEntity(folder);
0074             mSpecialPurposeFolders.insert(specialPurpose, folder.identifier());
0075         }
0076     }
0077     return mSpecialPurposeFolders.value(specialPurpose);
0078 }
0079 
0080 bool SpecialPurposeProcessor::isSpecialPurposeFolder(const QByteArray &folder) const
0081 {
0082     return mSpecialPurposeFolders.values().contains(folder);
0083 }
0084 
0085 void SpecialPurposeProcessor::moveToFolder(Sink::ApplicationDomain::ApplicationDomainType &newEntity)
0086 {
0087     //If we remove the draft folder move back to inbox
0088     //If we remove the trash property, move back to other specialpurpose folder or inbox
0089     //If a folder is set explicitly, clear specialpurpose flags.
0090     using namespace Sink::ApplicationDomain;
0091     auto mail = newEntity.cast<Mail>();
0092     if (mail.getTrash()) {
0093         auto f = findFolder(ApplicationDomain::SpecialPurpose::Mail::trash, true);
0094         SinkTrace() << "Setting trash folder: " << f;
0095         mail.setFolder(f);
0096     } else if (mail.getDraft()) {
0097         SinkTrace() << "Setting drafts folder: ";
0098         mail.setFolder(findFolder(ApplicationDomain::SpecialPurpose::Mail::drafts, true));
0099     } else if (mail.getSent()) {
0100         SinkTrace() << "Setting sent folder: ";
0101         mail.setFolder(findFolder(ApplicationDomain::SpecialPurpose::Mail::sent, true));
0102     } else {
0103         //No longer a specialpurpose mail, so move to inbox
0104         if (isSpecialPurposeFolder(mail.getFolder()) || mail.getFolder().isEmpty()) {
0105             mail.setFolder(findFolder(ApplicationDomain::SpecialPurpose::Mail::inbox, true));
0106         }
0107     }
0108 }
0109 
0110 void SpecialPurposeProcessor::newEntity(Sink::ApplicationDomain::ApplicationDomainType &newEntity)
0111 {
0112     auto mail = newEntity.cast<ApplicationDomain::Mail>();
0113     const auto folder = mail.getFolder();
0114     if (folder.isEmpty()) {
0115         moveToFolder(newEntity);
0116     } else {
0117         bool isDraft = findFolder(ApplicationDomain::SpecialPurpose::Mail::drafts) == folder;
0118         bool isSent = findFolder(ApplicationDomain::SpecialPurpose::Mail::sent) == folder;
0119         bool isTrash = findFolder(ApplicationDomain::SpecialPurpose::Mail::trash) == folder;
0120         mail.setDraft(isDraft);
0121         mail.setTrash(isTrash);
0122         mail.setSent(isSent);
0123     }
0124 
0125 }
0126 
0127 void SpecialPurposeProcessor::modifiedEntity(const Sink::ApplicationDomain::ApplicationDomainType &oldEntity, Sink::ApplicationDomain::ApplicationDomainType &newEntity)
0128 {
0129     using namespace Sink::ApplicationDomain;
0130     auto mail = newEntity.cast<Mail>();
0131     //If we moved the mail to a non-specialpurpose folder explicitly, also clear the flags.
0132     if (mail.changedProperties().contains(Mail::Folder::name)) {
0133         auto folder = mail.getFolder();
0134         bool isDraft = findFolder(ApplicationDomain::SpecialPurpose::Mail::drafts) == folder;
0135         bool isSent = findFolder(ApplicationDomain::SpecialPurpose::Mail::sent) == folder;
0136         bool isTrash = findFolder(ApplicationDomain::SpecialPurpose::Mail::trash) == folder;
0137         mail.setDraft(isDraft);
0138         mail.setTrash(isTrash);
0139         mail.setSent(isSent);
0140     } else {
0141         moveToFolder(newEntity);
0142     }
0143 }