File indexing completed on 2024-05-26 05:27:46

0001 /*
0002  *   Copyright (C) 2014 Aaron Seigo <aseigo@kde.org>
0003  *   Copyright (C) 2015 Christian Mollekopf <chrigi_1@fastmail.fm>
0004  *
0005  *   This program is free software; you can redistribute it and/or modify
0006  *   it under the terms of the GNU General Public License as published by
0007  *   the Free Software Foundation; either version 2 of the License, or
0008  *   (at your option) any later version.
0009  *
0010  *   This program is distributed in the hope that it will be useful,
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013  *   GNU General Public License for more details.
0014  *
0015  *   You should have received a copy of the GNU General Public License
0016  *   along with this program; if not, write to the
0017  *   Free Software Foundation, Inc.,
0018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
0019  */
0020 
0021 #include "resourcefactory.h"
0022 #include "facade.h"
0023 #include "entitybuffer.h"
0024 #include "pipeline.h"
0025 #include "dummycalendar_generated.h"
0026 #include "mail_generated.h"
0027 #include "domainadaptor.h"
0028 #include "log.h"
0029 #include "dummystore.h"
0030 #include "definitions.h"
0031 #include "facadefactory.h"
0032 #include "adaptorfactoryregistry.h"
0033 #include "synchronizer.h"
0034 #include "inspector.h"
0035 #include "mailpreprocessor.h"
0036 #include "eventpreprocessor.h"
0037 #include "todopreprocessor.h"
0038 #include "contactpreprocessor.h"
0039 #include "specialpurposepreprocessor.h"
0040 #include "resourceconfig.h"
0041 #include <QDate>
0042 
0043 //This is the resources entity type, and not the domain type
0044 #define ENTITY_TYPE_EVENT "event"
0045 #define ENTITY_TYPE_TODO "todo"
0046 #define ENTITY_TYPE_CALENDAR "calendar"
0047 #define ENTITY_TYPE_ADDRESSBOOK "addressbook"
0048 #define ENTITY_TYPE_CONTACT "contact"
0049 #define ENTITY_TYPE_MAIL "mail"
0050 #define ENTITY_TYPE_FOLDER "folder"
0051 
0052 using namespace Sink;
0053 
0054 class DummySynchronizer : public Sink::Synchronizer {
0055     public:
0056 
0057     DummySynchronizer(const Sink::ResourceContext &context)
0058         : Sink::Synchronizer(context)
0059     {
0060         setSecret("dummy");
0061         auto config = ResourceConfig::getConfiguration(context.instanceId());
0062         if (config.value("populate", false).toBool()) {
0063             DummyStore::instance().populate();
0064         }
0065     }
0066 
0067     Sink::ApplicationDomain::Event::Ptr createEvent(const QByteArray &ridBuffer, const QMap<QString, QVariant> &data)
0068     {
0069         auto event = Sink::ApplicationDomain::Event::Ptr::create();
0070         event->setExtractedUid(data.value("uid").toString());
0071         event->setExtractedSummary(data.value("summary").toString());
0072         event->setExtractedDescription(data.value("description").toString());
0073         event->setExtractedStartTime(data.value("starttime").toDateTime());
0074         event->setExtractedEndTime(data.value("endtime").toDateTime());
0075         event->setProperty("remoteId", ridBuffer);
0076         return event;
0077     }
0078 
0079     Sink::ApplicationDomain::Mail::Ptr createMail(const QByteArray &ridBuffer, const QMap<QString, QVariant> &data)
0080     {
0081         auto mail = Sink::ApplicationDomain::Mail::Ptr::create();
0082         mail->setExtractedMessageId(ridBuffer);
0083         mail->setExtractedSubject(data.value("subject").toString());
0084         mail->setExtractedSender(Sink::ApplicationDomain::Mail::Contact{data.value("senderName").toString(), data.value("senderEmail").toString()});
0085         mail->setExtractedDate(data.value("date").toDateTime());
0086         mail->setFolder(syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, data.value("parentFolder").toByteArray()));
0087         mail->setUnread(data.value("unread").toBool());
0088         mail->setImportant(data.value("important").toBool());
0089         return mail;
0090     }
0091 
0092     Sink::ApplicationDomain::Folder::Ptr createFolder(const QByteArray &ridBuffer, const QMap<QString, QVariant> &data)
0093     {
0094         auto folder = Sink::ApplicationDomain::Folder::Ptr::create();
0095         folder->setName(data.value("name").toString());
0096         folder->setIcon(data.value("icon").toByteArray());
0097         if (!data.value("parent").toString().isEmpty()) {
0098             auto sinkId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, data.value("parent").toByteArray());
0099             folder->setParent(sinkId);
0100         }
0101         return folder;
0102     }
0103 
0104     void synchronize(const QByteArray &bufferType, const QMap<QString, QMap<QString, QVariant> > &data, std::function<Sink::ApplicationDomain::ApplicationDomainType::Ptr(const QByteArray &ridBuffer, const QMap<QString, QVariant> &data)> createEntity)
0105     {
0106         auto time = QSharedPointer<QTime>::create();
0107         time->start();
0108         //TODO find items to remove
0109         int count = 0;
0110         for (auto it = data.constBegin(); it != data.constEnd(); it++) {
0111             count++;
0112             const auto remoteId = it.key().toUtf8();
0113             auto entity = createEntity(remoteId, it.value());
0114             createOrModify(bufferType, remoteId, *entity);
0115         }
0116         SinkTrace() << "Sync of " << count << " entities of type " << bufferType << " done." << Sink::Log::TraceTime(time->elapsed());
0117     }
0118 
0119     KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &) Q_DECL_OVERRIDE
0120     {
0121         SinkLog() << " Synchronizing with the source";
0122         SinkTrace() << "Synchronize with source and sending a notification about it";
0123         Sink::Notification n;
0124         n.id = "connected";
0125         n.type = Sink::Notification::Status;
0126         n.message = "We're connected";
0127         n.code = Sink::ApplicationDomain::ConnectedStatus;
0128         emit notify(n);
0129         return KAsync::start([this]() {
0130             synchronize(ENTITY_TYPE_EVENT, DummyStore::instance().events(), [this](const QByteArray &ridBuffer, const QMap<QString, QVariant> &data) {
0131                 return createEvent(ridBuffer, data);
0132             });
0133             synchronize(ENTITY_TYPE_MAIL, DummyStore::instance().mails(), [this](const QByteArray &ridBuffer, const QMap<QString, QVariant> &data) {
0134                 return createMail(ridBuffer, data);
0135             });
0136             synchronize(ENTITY_TYPE_FOLDER, DummyStore::instance().folders(), [this](const QByteArray &ridBuffer, const QMap<QString, QVariant> &data) {
0137                 return createFolder(ridBuffer, data);
0138             });
0139         });
0140     }
0141 
0142     bool canReplay(const QByteArray &type, const QByteArray &key, const QByteArray &value) Q_DECL_OVERRIDE { return false; }
0143 
0144 };
0145 
0146 class DummyInspector : public Sink::Inspector {
0147 public:
0148     DummyInspector(const Sink::ResourceContext &resourceContext)
0149         : Sink::Inspector(resourceContext)
0150     {
0151 
0152     }
0153 
0154 protected:
0155     KAsync::Job<void> inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) Q_DECL_OVERRIDE
0156     {
0157         SinkTrace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue;
0158         if (property == "testInspection") {
0159             if (expectedValue.toBool()) {
0160                 //Success
0161                 return KAsync::null<void>();
0162             } else {
0163                 //Failure
0164                 return KAsync::error<void>(1, "Failed.");
0165             }
0166         }
0167         return KAsync::null<void>();
0168     }
0169 };
0170 
0171 DummyResource::DummyResource(const Sink::ResourceContext &resourceContext, const QSharedPointer<Sink::Pipeline> &pipeline)
0172     : Sink::GenericResource(resourceContext, pipeline)
0173 {
0174     setupSynchronizer(QSharedPointer<DummySynchronizer>::create(resourceContext));
0175     setupInspector(QSharedPointer<DummyInspector>::create(resourceContext));
0176     setupPreprocessors(ENTITY_TYPE_MAIL, {new MailPropertyExtractor, new SpecialPurposeProcessor});
0177     setupPreprocessors(ENTITY_TYPE_FOLDER, {});
0178     setupPreprocessors(ENTITY_TYPE_EVENT, {new EventPropertyExtractor});
0179     setupPreprocessors(ENTITY_TYPE_TODO, {new TodoPropertyExtractor});
0180     setupPreprocessors(ENTITY_TYPE_CALENDAR, {});
0181     setupPreprocessors(ENTITY_TYPE_CONTACT, {new ContactPropertyExtractor});
0182     setupPreprocessors(ENTITY_TYPE_ADDRESSBOOK, {});
0183 }
0184 
0185 DummyResource::~DummyResource()
0186 {
0187 
0188 }
0189 
0190 DummyResourceFactory::DummyResourceFactory(QObject *parent)
0191     : Sink::ResourceFactory(parent, {
0192         Sink::ApplicationDomain::ResourceCapabilities::Todo::todo,
0193         Sink::ApplicationDomain::ResourceCapabilities::Todo::calendar,
0194         Sink::ApplicationDomain::ResourceCapabilities::Todo::storage,
0195         Sink::ApplicationDomain::ResourceCapabilities::Event::event,
0196         Sink::ApplicationDomain::ResourceCapabilities::Event::calendar,
0197         Sink::ApplicationDomain::ResourceCapabilities::Event::storage,
0198         Sink::ApplicationDomain::ResourceCapabilities::Contact::contact,
0199         Sink::ApplicationDomain::ResourceCapabilities::Contact::addressbook,
0200         Sink::ApplicationDomain::ResourceCapabilities::Contact::storage,
0201         Sink::ApplicationDomain::ResourceCapabilities::Mail::mail,
0202         Sink::ApplicationDomain::ResourceCapabilities::Mail::folder,
0203         Sink::ApplicationDomain::ResourceCapabilities::Mail::storage,
0204         Sink::ApplicationDomain::ResourceCapabilities::Mail::drafts,
0205         "-folder.rename",
0206         Sink::ApplicationDomain::ResourceCapabilities::Mail::sent}
0207     )
0208 {
0209 
0210 }
0211 
0212 Sink::Resource *DummyResourceFactory::createResource(const Sink::ResourceContext &resourceContext)
0213 {
0214     return new DummyResource(resourceContext);
0215 }
0216 
0217 void DummyResourceFactory::registerFacades(const QByteArray &resourceName, Sink::FacadeFactory &factory)
0218 {
0219     using namespace Sink::ApplicationDomain;
0220     factory.registerFacade<Contact, DefaultFacade<Contact>>(resourceName);
0221     factory.registerFacade<Addressbook, DefaultFacade<Addressbook>>(resourceName);
0222     factory.registerFacade<Todo, DefaultFacade<Todo>>(resourceName);
0223     factory.registerFacade<Event, DefaultFacade<Event>>(resourceName);
0224     factory.registerFacade<Calendar, DefaultFacade<Calendar>>(resourceName);
0225     factory.registerFacade<Mail, DefaultFacade<Mail>>(resourceName);
0226     factory.registerFacade<Folder, DefaultFacade<Folder>>(resourceName);
0227 }
0228 
0229 void DummyResourceFactory::registerAdaptorFactories(const QByteArray &resourceName, Sink::AdaptorFactoryRegistry &registry)
0230 {
0231     using namespace Sink::ApplicationDomain;
0232     registry.registerFactory<Contact, DomainTypeAdaptorFactory<Contact>>(resourceName);
0233     registry.registerFactory<Addressbook, DomainTypeAdaptorFactory<Addressbook>>(resourceName);
0234     registry.registerFactory<Todo, DomainTypeAdaptorFactory<Todo>>(resourceName);
0235     registry.registerFactory<Event, DomainTypeAdaptorFactory<Event>>(resourceName);
0236     registry.registerFactory<Calendar, DomainTypeAdaptorFactory<Calendar>>(resourceName);
0237     registry.registerFactory<Mail, DomainTypeAdaptorFactory<Mail>>(resourceName);
0238     registry.registerFactory<Folder, DomainTypeAdaptorFactory<Folder>>(resourceName);
0239 }
0240 
0241 void DummyResourceFactory::removeDataFromDisk(const QByteArray &instanceIdentifier)
0242 {
0243     DummyResource::removeFromDisk(instanceIdentifier);
0244 }
0245