From 3fe20509c29c40305d0362adbc787edfc29e96d4 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Wed, 8 Jul 2015 16:48:41 +0200 Subject: Filter queries by available resources, and filter resources by resource-types --- common/clientapi.cpp | 2 +- common/clientapi.h | 32 +++++++++++++++++++++++++++--- common/resourceconfig.cpp | 33 ++++++++++++++++++------------- common/resourceconfig.h | 5 +++-- common/resourcefacade.cpp | 14 ++++++++----- tests/clientapitest.cpp | 50 +++++++++++++++++++++++++---------------------- 6 files changed, 88 insertions(+), 48 deletions(-) diff --git a/common/clientapi.cpp b/common/clientapi.cpp index 88349db..06bf5ab 100644 --- a/common/clientapi.cpp +++ b/common/clientapi.cpp @@ -19,7 +19,7 @@ namespace Akonadi2 void FacadeFactory::registerStaticFacades() { - FacadeFactory::instance().registerFacade("resourceconfig"); + registerFacade("resourceconfig"); } void Store::shutdown(const QByteArray &identifier) diff --git a/common/clientapi.h b/common/clientapi.h index d658003..a01db23 100644 --- a/common/clientapi.h +++ b/common/clientapi.h @@ -34,6 +34,7 @@ #include "threadboundary.h" #include "resultprovider.h" #include "domain/applicationdomaintype.h" +#include "resourceconfig.h" namespace async { //This should abstract if we execute from eventloop or in thread. @@ -110,7 +111,7 @@ class FacadeFactory { public: typedef std::function(const QByteArray &)> FactoryFunction; - static void registerStaticFacades(); + void registerStaticFacades(); //FIXME: proper singleton implementation static FacadeFactory &instance() @@ -165,6 +166,11 @@ public: } private: + FacadeFactory() + { + registerStaticFacades(); + } + QHash mFacadeRegistry; }; @@ -188,6 +194,27 @@ public: return split.join('.'); } + static QList getResources(const QList &resourceFilter) + { + QList resources; + const auto configuredResources = ResourceConfig::getResources(); + if (resourceFilter.isEmpty()) { + for (const auto &res : configuredResources) { + //TODO filter by type + resources << res; + } + } else { + for (const auto &res : resourceFilter) { + if (configuredResources.contains(res)) { + resources << res; + } else { + qWarning() << "Resource is not existing: " << res; + } + } + } + return resources; + } + /** * Asynchronusly load a dataset */ @@ -200,9 +227,8 @@ public: //We must guarantee that the emitter is returned before the first result is emitted. //The result provider must be threadsafe. async::run([query, resultSet](){ - //TODO if query.resources is empty, search for all resource that provide the type we're looking for // Query all resources and aggregate results - KAsync::iterate(query.resources) + KAsync::iterate(getResources(query.resources)) .template each([query, resultSet](const QByteArray &resource, KAsync::Future &future) { //TODO pass resource identifier to factory auto facade = FacadeFactory::instance().getFacade(resourceName(resource), resource); diff --git a/common/resourceconfig.cpp b/common/resourceconfig.cpp index 1f8fcda..ec72fb9 100644 --- a/common/resourceconfig.cpp +++ b/common/resourceconfig.cpp @@ -30,33 +30,38 @@ static QSharedPointer getSettings() void ResourceConfig::addResource(const QByteArray &identifier, const QByteArray &type) { auto settings = getSettings(); - settings->beginGroup("resources"); - settings->setValue(QString::fromLatin1(identifier), type); + settings->beginGroup(QString::fromLatin1(identifier)); + settings->setValue("type", type); + settings->setValue("enabled", true); settings->endGroup(); - // settings->beginGroup(identifier); - // //Add some settings? - // settings->endGroup(); settings->sync(); } void ResourceConfig::removeResource(const QByteArray &identifier) { auto settings = getSettings(); - settings->beginGroup("resources"); - settings->remove(QString::fromLatin1(identifier)); + settings->beginGroup(QString::fromLatin1(identifier)); + settings->remove(""); settings->endGroup(); settings->sync(); } -QList > ResourceConfig::getResources() +QMap ResourceConfig::getResources() { - QList > resources; + QMap resources; auto settings = getSettings(); - settings->beginGroup("resources"); - for (const auto &identifier : settings->childKeys()) { - const auto type = settings->value(identifier).toByteArray(); - resources << qMakePair(identifier.toLatin1(), type); + for (const auto &identifier : settings->childGroups()) { + settings->beginGroup(identifier); + const auto type = settings->value("type").toByteArray(); + resources.insert(identifier.toLatin1(), type); + settings->endGroup(); } - settings->endGroup(); return resources; } + +void ResourceConfig::clear() +{ + auto settings = getSettings(); + settings->clear(); + settings->sync(); +} diff --git a/common/resourceconfig.h b/common/resourceconfig.h index eda870f..e1ba2bc 100644 --- a/common/resourceconfig.h +++ b/common/resourceconfig.h @@ -21,12 +21,13 @@ #include #include -#include +#include class ResourceConfig { public: - static QList > getResources(); + static QMap getResources(); static void addResource(const QByteArray &identifier, const QByteArray &type); static void removeResource(const QByteArray &identifier); + static void clear(); }; diff --git a/common/resourcefacade.cpp b/common/resourcefacade.cpp index 63b3126..9792934 100644 --- a/common/resourcefacade.cpp +++ b/common/resourcefacade.cpp @@ -56,11 +56,15 @@ KAsync::Job ResourceFacade::remove(const Akonadi2::ApplicationDomain::Akon KAsync::Job ResourceFacade::load(const Akonadi2::Query &query, const QSharedPointer > &resultProvider) { return KAsync::start([query, resultProvider]() { - for (const auto &res : ResourceConfig::getResources()) { - auto resource = Akonadi2::ApplicationDomain::AkonadiResource::Ptr::create(); - resource->setProperty("identifier", res.first); - resource->setProperty("type", res.second); - resultProvider->add(resource); + const auto configuredResources = ResourceConfig::getResources(); + for (const auto &res : configuredResources.keys()) { + const auto type = configuredResources.value(res); + if (!query.propertyFilter.contains("type") || query.propertyFilter.value("type").toByteArray() == type) { + auto resource = Akonadi2::ApplicationDomain::AkonadiResource::Ptr::create(); + resource->setProperty("identifier", res); + resource->setProperty("type", type); + resultProvider->add(resource); + } } //TODO initialResultSetComplete should be implicit resultProvider->initialResultSetComplete(); diff --git a/tests/clientapitest.cpp b/tests/clientapitest.cpp index 5eb16da..9b8c27e 100644 --- a/tests/clientapitest.cpp +++ b/tests/clientapitest.cpp @@ -5,6 +5,7 @@ #include "clientapi.h" #include "facade.h" #include "synclistresult.h" +#include "resourceconfig.h" class RevisionNotifier : public QObject { @@ -99,21 +100,29 @@ class ClientAPITest : public QObject Q_OBJECT private Q_SLOTS: + static std::shared_ptr registerDummyFacade() + { + auto facade = std::make_shared(); + Akonadi2::FacadeFactory::instance().registerFacade("dummyresource", + [facade](const QByteArray &instanceIdentifier) { + return facade; + } + ); + return facade; + } + void initTestCase() { Akonadi2::FacadeFactory::instance().resetFactory(); + ResourceConfig::clear(); } + void testLoad() { - auto facade = std::make_shared(); + auto facade = registerDummyFacade(); facade->results << QSharedPointer::create("resource", "id", 0, QSharedPointer()); - - Akonadi2::FacadeFactory::instance().registerFacade("dummyresource", - [facade](const QByteArray &instanceIdentifier) { - return facade; - } - ); + ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); Akonadi2::Query query; query.resources << "dummyresource.instance1"; @@ -126,14 +135,9 @@ private Q_SLOTS: void testLiveQuery() { - auto facade = std::make_shared(); + auto facade = registerDummyFacade(); facade->results << QSharedPointer::create("resource", "id", 0, QSharedPointer()); - - Akonadi2::FacadeFactory::instance().registerFacade("dummyresource", - [facade](const QByteArray &instanceIdentifier){ - return facade; - } - ); + ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); Akonadi2::Query query; query.resources << "dummyresource.instance1"; @@ -152,14 +156,9 @@ private Q_SLOTS: void testQueryLifetime() { - auto facade = std::make_shared(); + auto facade = registerDummyFacade(); facade->results << QSharedPointer::create("resource", "id", 0, QSharedPointer()); - - Akonadi2::FacadeFactory::instance().registerFacade("dummyresource", - [facade](const QByteArray &instanceIdentifier){ - return facade; - } - ); + ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); Akonadi2::Query query; query.resources << "dummyresource.instance1"; @@ -176,9 +175,12 @@ private Q_SLOTS: void resourceManagement() { - Akonadi2::FacadeFactory::registerStaticFacades(); + ResourceConfig::clear(); + Akonadi2::FacadeFactory::instance().registerStaticFacades(); + ResourceConfig::addResource("resourceconfig", "resourceconfig"); + Akonadi2::ApplicationDomain::AkonadiResource res; - res.setProperty("identifier", "identifier1"); + res.setProperty("identifier", "dummyresource.identifier1"); res.setProperty("type", "dummyresource"); Akonadi2::Store::create(res, "resourceconfig"); @@ -186,6 +188,7 @@ private Q_SLOTS: { Akonadi2::Query query; query.resources << "resourceconfig"; + query.propertyFilter.insert("type", "dummyresource"); async::SyncListResult result(Akonadi2::Store::load(query)); result.exec(); QCOMPARE(result.size(), 1); @@ -195,6 +198,7 @@ private Q_SLOTS: { Akonadi2::Query query; query.resources << "resourceconfig"; + query.propertyFilter.insert("type", "dummyresource"); async::SyncListResult result(Akonadi2::Store::load(query)); result.exec(); QCOMPARE(result.size(), 0); -- cgit v1.2.3