From 4067462b0a27984df84b0379c19122d574253dfb Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Sat, 3 Jan 2015 00:08:44 +0100 Subject: Shared domain adaptors between resource and facade. --- dummyresource/CMakeLists.txt | 2 +- dummyresource/domainadaptor.cpp | 101 ++++++++++++++++++++++++++++++++++++++ dummyresource/domainadaptor.h | 14 ++++++ dummyresource/facade.cpp | 92 +--------------------------------- dummyresource/facade.h | 50 +------------------ dummyresource/resourcefactory.cpp | 12 ++--- 6 files changed, 126 insertions(+), 145 deletions(-) create mode 100644 dummyresource/domainadaptor.cpp create mode 100644 dummyresource/domainadaptor.h (limited to 'dummyresource') diff --git a/dummyresource/CMakeLists.txt b/dummyresource/CMakeLists.txt index a2caf29..abd315f 100644 --- a/dummyresource/CMakeLists.txt +++ b/dummyresource/CMakeLists.txt @@ -5,7 +5,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) generate_flatbuffers(dummycalendar) -add_library(${PROJECT_NAME} SHARED facade.cpp resourcefactory.cpp) +add_library(${PROJECT_NAME} SHARED facade.cpp resourcefactory.cpp domainadaptor.cpp) qt5_use_modules(${PROJECT_NAME} Core Network) target_link_libraries(${PROJECT_NAME} akonadi2common) diff --git a/dummyresource/domainadaptor.cpp b/dummyresource/domainadaptor.cpp new file mode 100644 index 0000000..5d046ff --- /dev/null +++ b/dummyresource/domainadaptor.cpp @@ -0,0 +1,101 @@ + +#include "domainadaptor.h" + +#include +#include + +#include "dummycalendar_generated.h" +#include "event_generated.h" +#include "entity_generated.h" +#include "metadata_generated.h" +#include "domainadaptor.h" +#include + +using namespace DummyCalendar; +using namespace flatbuffers; + +using namespace DummyCalendar; +using namespace flatbuffers; + +//This will become a generic implementation that simply takes the resource buffer and local buffer pointer +class DummyEventAdaptor : public Akonadi2::Domain::BufferAdaptor +{ +public: + DummyEventAdaptor() + : BufferAdaptor() + { + + } + + void setProperty(const QString &key, const QVariant &value) + { + if (mResourceMapper->mWriteAccessors.contains(key)) { + // mResourceMapper.setProperty(key, value, mResourceBuffer); + } else { + // mLocalMapper.; + } + } + + virtual QVariant getProperty(const QString &key) const + { + if (mResourceBuffer && mResourceMapper->mReadAccessors.contains(key)) { + return mResourceMapper->getProperty(key, mResourceBuffer); + } else if (mLocalBuffer) { + return mLocalMapper->getProperty(key, mLocalBuffer); + } + return QVariant(); + } + + Akonadi2::Domain::Buffer::Event const *mLocalBuffer; + DummyEvent const *mResourceBuffer; + + QSharedPointer > mLocalMapper; + QSharedPointer > mResourceMapper; +}; + + +DummyEventAdaptorFactory::DummyEventAdaptorFactory() + : DomainTypeAdaptorFactory() +{ + mResourceMapper = QSharedPointer >::create(); + mResourceMapper->mReadAccessors.insert("summary", [](DummyEvent const *buffer) -> QVariant { + return QString::fromStdString(buffer->summary()->c_str()); + }); + //TODO set accessors for all properties + +} + +QSharedPointer DummyEventAdaptorFactory::createAdaptor(const Akonadi2::Entity &entity) +{ + DummyEvent const *resourceBuffer = 0; + if (auto resourceData = entity.resource()) { + flatbuffers::Verifier verifyer(resourceData->Data(), resourceData->size()); + if (VerifyDummyEventBuffer(verifyer)) { + resourceBuffer = GetDummyEvent(resourceData); + } + } + + Akonadi2::Metadata const *metadataBuffer = 0; + if (auto metadataData = entity.metadata()) { + flatbuffers::Verifier verifyer(metadataData->Data(), metadataData->size()); + if (Akonadi2::VerifyMetadataBuffer(verifyer)) { + metadataBuffer = Akonadi2::GetMetadata(metadataData); + } + } + + Akonadi2::Domain::Buffer::Event const *localBuffer = 0; + if (auto localData = entity.local()) { + flatbuffers::Verifier verifyer(localData->Data(), localData->size()); + if (Akonadi2::Domain::Buffer::VerifyEventBuffer(verifyer)) { + localBuffer = Akonadi2::Domain::Buffer::GetEvent(localData); + } + } + + auto adaptor = QSharedPointer::create(); + adaptor->mLocalBuffer = localBuffer; + adaptor->mResourceBuffer = resourceBuffer; + adaptor->mResourceMapper = mResourceMapper; + adaptor->mLocalMapper = mLocalMapper; + return adaptor; +} + diff --git a/dummyresource/domainadaptor.h b/dummyresource/domainadaptor.h new file mode 100644 index 0000000..881b7f3 --- /dev/null +++ b/dummyresource/domainadaptor.h @@ -0,0 +1,14 @@ + +#pragma once + +#include "common/domainadaptor.h" +#include "event_generated.h" +#include "dummycalendar_generated.h" +#include "entity_generated.h" + +class DummyEventAdaptorFactory : public DomainTypeAdaptorFactory +{ +public: + DummyEventAdaptorFactory(); + virtual QSharedPointer createAdaptor(const Akonadi2::Entity &entity); +}; diff --git a/dummyresource/facade.cpp b/dummyresource/facade.cpp index c167297..b4d98c6 100644 --- a/dummyresource/facade.cpp +++ b/dummyresource/facade.cpp @@ -28,92 +28,17 @@ #include "event_generated.h" #include "entity_generated.h" #include "metadata_generated.h" +#include "domainadaptor.h" #include using namespace DummyCalendar; using namespace flatbuffers; -//This will become a generic implementation that simply takes the resource buffer and local buffer pointer -class DummyEventAdaptor : public Akonadi2::Domain::BufferAdaptor -{ -public: - DummyEventAdaptor() - : BufferAdaptor() - { - - } - - void setProperty(const QString &key, const QVariant &value) - { - if (mResourceMapper->mWriteAccessors.contains(key)) { - // mResourceMapper.setProperty(key, value, mResourceBuffer); - } else { - // mLocalMapper.; - } - } - - virtual QVariant getProperty(const QString &key) const - { - if (mResourceBuffer && mResourceMapper->mReadAccessors.contains(key)) { - return mResourceMapper->getProperty(key, mResourceBuffer); - } else if (mLocalBuffer) { - return mLocalMapper->getProperty(key, mLocalBuffer); - } - return QVariant(); - } - - Akonadi2::Domain::Buffer::Event const *mLocalBuffer; - DummyEvent const *mResourceBuffer; - - QSharedPointer > mLocalMapper; - QSharedPointer > mResourceMapper; -}; - -template<> -QSharedPointer DomainTypeAdaptorFactory::createAdaptor(const Akonadi2::Entity &entity) -{ - DummyEvent const *resourceBuffer = 0; - if (auto resourceData = entity.resource()) { - flatbuffers::Verifier verifyer(resourceData->Data(), resourceData->size()); - if (VerifyDummyEventBuffer(verifyer)) { - resourceBuffer = GetDummyEvent(resourceData); - } - } - - Akonadi2::Metadata const *metadataBuffer = 0; - if (auto metadataData = entity.metadata()) { - flatbuffers::Verifier verifyer(metadataData->Data(), metadataData->size()); - if (Akonadi2::VerifyMetadataBuffer(verifyer)) { - metadataBuffer = Akonadi2::GetMetadata(metadataData); - } - } - - Akonadi2::Domain::Buffer::Event const *localBuffer = 0; - if (auto localData = entity.local()) { - flatbuffers::Verifier verifyer(localData->Data(), localData->size()); - if (Akonadi2::Domain::Buffer::VerifyEventBuffer(verifyer)) { - localBuffer = Akonadi2::Domain::Buffer::GetEvent(localData); - } - } - - auto adaptor = QSharedPointer::create(); - adaptor->mLocalBuffer = localBuffer; - adaptor->mResourceBuffer = resourceBuffer; - adaptor->mResourceMapper = mResourceMapper; - adaptor->mLocalMapper = mLocalMapper; - return adaptor; -} - DummyResourceFacade::DummyResourceFacade() : Akonadi2::StoreFacade(), mResourceAccess(new Akonadi2::ResourceAccess("org.kde.dummy")), - mFactory(new DomainTypeAdaptorFactory()) + mFactory(new DummyEventAdaptorFactory) { - auto mapper = QSharedPointer >::create(); - mapper->mReadAccessors.insert("summary", [](DummyEvent const *buffer) -> QVariant { - return QString::fromStdString(buffer->summary()->c_str()); - }); - mFactory->mResourceMapper = mapper; } DummyResourceFacade::~DummyResourceFacade() @@ -135,19 +60,6 @@ void DummyResourceFacade::remove(const Akonadi2::Domain::Event &domainObject) //Create message buffer and send to resource } -//Key.value property map using enum or strings with qvariant, or rather typesafe API? -//typesafe is a shitload more work that we can avoid -// -//The Event base implementaiton could take a pointer to a single property mapper, -//and a void pointer to the mmapped region. => event is copyable and stack allocatable and we avoid large amounts of heap allocated objects -//-The mapper should in this case live in the other thread -//-default property mapper implementation can answer "is property X supported?" -//-how do we free/munmap the data if we don't know when no one references it any longer? => no munmap needed, but read transaction to keep pointer alive -//-we could bind the lifetime to the query -//=> perhaps do heap allocate and use smart pointer? -// - - static std::function prepareQuery(const Akonadi2::Query &query) { //Compose some functions to make query matching fast. diff --git a/dummyresource/facade.h b/dummyresource/facade.h index 46b27ef..e01d254 100644 --- a/dummyresource/facade.h +++ b/dummyresource/facade.h @@ -21,62 +21,16 @@ #include "common/clientapi.h" #include "common/storage.h" +#include "resourcefactory.h" #include "entity_generated.h" #include "event_generated.h" #include "dummycalendar_generated.h" +#include "common/domainadaptor.h" namespace Akonadi2 { class ResourceAccess; } -/** - * The property mapper holds accessor functions for all properties. - * - * It is by default initialized with accessors that access the local-only buffer, - * and resource simply have to overwrite those accessors. - */ -template -class PropertyMapper -{ -public: - void setProperty(const QString &key, const QVariant &value, BufferType *buffer) - { - if (mWriteAccessors.contains(key)) { - auto accessor = mWriteAccessors.value(key); - return accessor(value, buffer); - } - } - - virtual QVariant getProperty(const QString &key, BufferType const *buffer) const - { - if (mReadAccessors.contains(key)) { - auto accessor = mReadAccessors.value(key); - return accessor(buffer); - } - return QVariant(); - } - QHash > mReadAccessors; - QHash > mWriteAccessors; -}; - -//The factory should define how to go from an entitybuffer (local + resource buffer), to a domain type adapter. -//It defines how values are split accross local and resource buffer. -//This is required by the facade the read the value, and by the pipeline preprocessors to access the domain values in a generic way. -template -class DomainTypeAdaptorFactory -{ -}; - -template -class DomainTypeAdaptorFactory -{ -public: - QSharedPointer createAdaptor(const Akonadi2::Entity &entity); - -// private: - QSharedPointer > mLocalMapper; - QSharedPointer > mResourceMapper; -}; class DummyResourceFacade : public Akonadi2::StoreFacade { diff --git a/dummyresource/resourcefactory.cpp b/dummyresource/resourcefactory.cpp index 08222c0..da6969a 100644 --- a/dummyresource/resourcefactory.cpp +++ b/dummyresource/resourcefactory.cpp @@ -23,6 +23,7 @@ #include "pipeline.h" #include "dummycalendar_generated.h" #include "metadata_generated.h" +#include "domainadaptor.h" #include /* @@ -101,14 +102,13 @@ DummyResource::DummyResource() void DummyResource::configurePipeline(Akonadi2::Pipeline *pipeline) { + auto factory = QSharedPointer::create(); //TODO setup preprocessors for each domain type and pipeline type allowing full customization //Eventually the order should be self configuring, for now it's hardcoded. - auto eventIndexer = new SimpleProcessor([](const Akonadi2::PipelineState &state) { - //FIXME - // auto adaptor = QSharedPointer::create(); - // adaptor->mLocalBuffer = localBuffer; - // adaptor->mResourceBuffer = resourceBuffer; - // adaptor->storage = storage; + auto eventIndexer = new SimpleProcessor([factory](const Akonadi2::PipelineState &state) { + auto adaptor = factory->createAdaptor(state.entity()); + //Here we can plug in generic preprocessors + qDebug() << adaptor->getProperty("summary").toString(); }); pipeline->setPreprocessors(Akonadi2::Pipeline::NewPipeline, QVector() << eventIndexer); } -- cgit v1.2.3