From 4eb94786232aee936cd6371824764705c9359538 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Wed, 17 Jun 2015 00:57:24 +0200 Subject: An almost generic query implementation. With equality filter on arbitrary properties as a bonus. --- examples/dummyresource/facade.cpp | 48 +++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 12 deletions(-) (limited to 'examples/dummyresource/facade.cpp') diff --git a/examples/dummyresource/facade.cpp b/examples/dummyresource/facade.cpp index 9d4f64b..002b836 100644 --- a/examples/dummyresource/facade.cpp +++ b/examples/dummyresource/facade.cpp @@ -74,7 +74,7 @@ static void scan(const QSharedPointer &storage, const QByteAr }); } -void DummyResourceFacade::readValue(const QSharedPointer &storage, const QByteArray &key, const std::function &resultCallback) +static void readValue(const QSharedPointer &storage, const QByteArray &key, const std::function &resultCallback, const QSharedPointer > &adaptorFactory) { scan(storage, key, [=](const QByteArray &key, const Akonadi2::Entity &entity, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local, Akonadi2::Metadata const *metadataBuffer) { qint64 revision = metadataBuffer ? metadataBuffer->revision() : -1; @@ -82,19 +82,21 @@ void DummyResourceFacade::readValue(const QSharedPointer &sto //Not i.e. for tags that are stored as flags in each entity of an imap store. //additional properties that don't have a 1:1 mapping (such as separately stored tags), //could be added to the adaptor - auto event = QSharedPointer::create("org.kde.dummy.instance1", key, revision, mDomainTypeAdaptorFactory->createAdaptor(entity)); + auto event = QSharedPointer::create("org.kde.dummy.instance1", key, revision, adaptorFactory->createAdaptor(entity)); resultCallback(event); return true; }); } -static ResultSet getResultSet(const Akonadi2::Query &query, const QSharedPointer &storage) +static ResultSet getResultSet(const Akonadi2::Query &query, const QSharedPointer &storage, const QSharedPointer > &adaptorFactory) { QSet appliedFilters; ResultSet resultSet = Akonadi2::ApplicationDomain::TypeImplementation::queryIndexes(query, "org.kde.dummy.instance1", appliedFilters); const auto remainingFilters = query.propertyFilter.keys().toSet() - appliedFilters; - if (resultSet.isEmpty()) { + //We do a full scan if there were no indexes available to create the initial set. + //TODO use a result set with an iterator, to read values on demand + if (appliedFilters.isEmpty()) { QVector keys; scan(storage, QByteArray(), [=, &keys](const QByteArray &key, const Akonadi2::Entity &entity, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local, Akonadi2::Metadata const *metadataBuffer) { keys << key; @@ -103,9 +105,34 @@ static ResultSet getResultSet(const Akonadi2::Query &query, const QSharedPointer resultSet = ResultSet(keys); } - return resultSet; + auto filter = [remainingFilters, query](const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &event) -> bool { + for (const auto &filterProperty : remainingFilters) { + //TODO implement other comparison operators than equality + if (event->getProperty(filterProperty) != query.propertyFilter.value(filterProperty)) { + return false; + } + } + return true; + }; + + auto resultSetPtr = QSharedPointer::create(resultSet); + + //Read through the source values and return whatever matches the filter + std::function)> generator = [resultSetPtr, storage, adaptorFactory, filter](std::function callback) -> bool { + while (resultSetPtr->next()) { + Akonadi2::ApplicationDomain::Event::Ptr event; + readValue(storage, resultSetPtr->id(), [filter, callback](const Akonadi2::ApplicationDomain::Event::Ptr &event) { + if (filter(event)) { + callback(event); + } + }, adaptorFactory); + } + return false; + }; + return ResultSet(generator); } +//TODO generalize KAsync::Job DummyResourceFacade::load(const Akonadi2::Query &query, const QSharedPointer > &resultProvider, qint64 oldRevision, qint64 newRevision) { return KAsync::start([=]() { @@ -118,17 +145,14 @@ KAsync::Job DummyResourceFacade::load(const Akonadi2::Query &query, cons //TODO start transaction on indexes as well const qint64 revision = storage->maxRevision(); - auto resultSet = getResultSet(query, storage); + auto resultSet = getResultSet(query, storage, mDomainTypeAdaptorFactory); // TODO only emit changes and don't replace everything resultProvider->clear(); auto resultCallback = std::bind(&Akonadi2::ResultProvider::add, resultProvider, std::placeholders::_1); - while (resultSet.next()) { - readValue(storage, resultSet.id(), [resultCallback](const Akonadi2::ApplicationDomain::Event::Ptr &event) { - //We create an in-memory copy because the result provider will store the value, and the result we get back is only valid during the callback - resultCallback(Akonadi2::ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation(event)); - }); - } + while(resultSet.next([resultCallback](const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &value) -> bool { + resultCallback(Akonadi2::ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation(value)); + })){}; storage->abortTransaction(); return revision; }); -- cgit v1.2.3