/* * Copyright (C) 2014 Christian Mollekopf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #pragma once #include #include "query.h" #include "domainadaptor.h" #include "entitybuffer.h" #include "log.h" #include "storage.h" #include "resultset.h" #include "resultprovider.h" #include "definitions.h" /** * Wraps storage, entity adaptor factory and indexes into one. * */ class EntityStorageBase { public: typedef std::function &remainingFilters)> InitialResultLoader; typedef std::function &remainingFilters)> IncrementalResultLoader; typedef std::function &resultCallback)> EntityReader; /** * Returns the initial result set that still needs to be filtered. * * To make this efficient indexes should be chosen that are as selective as possible. */ InitialResultLoader loadInitialResultSet; /** * Returns the incremental result set that still needs to be filtered. */ IncrementalResultLoader loadIncrementalResultSet; /** * Loads a single entity by uid from storage. */ EntityReader readEntity; protected: EntityStorageBase(const QByteArray &instanceIdentifier) : mResourceInstanceIdentifier(instanceIdentifier) { } virtual Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr copy(const Akonadi2::ApplicationDomain::ApplicationDomainType &) = 0; ResultSet getResultSet(const Akonadi2::Query &query, Akonadi2::Storage::Transaction &transaction, qint64 baseRevision); QByteArray mResourceInstanceIdentifier; private: ResultSet filteredSet(const ResultSet &resultSet, const std::function &filter, const Akonadi2::Storage::Transaction &transaction, bool isInitialQuery); }; template class EntityStorage : public EntityStorageBase { public: EntityStorage(const QByteArray &instanceIdentifier) : EntityStorageBase(instanceIdentifier) { } protected: Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr copy(const Akonadi2::ApplicationDomain::ApplicationDomainType &object) Q_DECL_OVERRIDE { return Akonadi2::ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation(object); } public: virtual qint64 read(const Akonadi2::Query &query, qint64 baseRevision, const QSharedPointer > &resultProvider) { Akonadi2::Storage storage(Akonadi2::storageLocation(), mResourceInstanceIdentifier); storage.setDefaultErrorHandler([](const Akonadi2::Storage::Error &error) { Warning() << "Error during query: " << error.store << error.message; }); auto transaction = storage.createTransaction(Akonadi2::Storage::ReadOnly); Log() << "Querying" << baseRevision << Akonadi2::Storage::maxRevision(transaction); auto resultSet = getResultSet(query, transaction, baseRevision); while(resultSet.next([this, resultProvider](const Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr &value, Akonadi2::Operation operation) -> bool { switch (operation) { case Akonadi2::Operation_Creation: Trace() << "Got creation"; resultProvider->add(copy(*value).template staticCast()); break; case Akonadi2::Operation_Modification: Trace() << "Got modification"; resultProvider->modify(copy(*value).template staticCast()); break; case Akonadi2::Operation_Removal: Trace() << "Got removal"; resultProvider->remove(copy(*value).template staticCast()); break; } return true; })){}; return Akonadi2::Storage::maxRevision(transaction); } };