From e85967518b9041e9943ec5f1765c6694bb153840 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Sun, 12 Apr 2015 16:02:10 +0200 Subject: More generic domainadpator code. This should cover read and write for entites that have a 1:1 mapping to the resource buffers. --- common/domainadaptor.cpp | 23 ++++++++++ common/domainadaptor.h | 95 +++++++++++++++++++--------------------- dummyresource/domainadaptor.cpp | 91 ++++++-------------------------------- dummyresource/domainadaptor.h | 6 +-- dummyresource/facade.cpp | 2 +- dummyresource/facade.h | 2 +- tests/domainadaptortest.cpp | 96 ++++++++--------------------------------- 7 files changed, 101 insertions(+), 214 deletions(-) diff --git a/common/domainadaptor.cpp b/common/domainadaptor.cpp index 5e6f062..aa8c3d9 100644 --- a/common/domainadaptor.cpp +++ b/common/domainadaptor.cpp @@ -19,6 +19,15 @@ #include "domainadaptor.h" +template <> +flatbuffers::uoffset_t extractProperty(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) +{ + if (property.isValid()) { + return fbb.CreateString(property.toString().toStdString()).o; + } + return 0; +} + template <> QSharedPointer > initializeReadPropertyMapper() { @@ -38,3 +47,17 @@ QSharedPointer > return propertyMapper; } +template <> +QSharedPointer > initializeWritePropertyMapper() +{ + auto propertyMapper = QSharedPointer >::create(); + propertyMapper->addMapping("summary", [](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function { + auto offset = extractProperty(value, fbb); + return [offset](Akonadi2::ApplicationDomain::Buffer::EventBuilder &builder) { builder.add_summary(offset); }; + }); + propertyMapper->addMapping("uid", [](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function { + auto offset = extractProperty(value, fbb); + return [offset](Akonadi2::ApplicationDomain::Buffer::EventBuilder &builder) { builder.add_uid(offset); }; + }); + return propertyMapper; +} diff --git a/common/domainadaptor.h b/common/domainadaptor.h index 5d9574b..e356692 100644 --- a/common/domainadaptor.h +++ b/common/domainadaptor.h @@ -77,6 +77,39 @@ private: QHash(const QVariant &, flatbuffers::FlatBufferBuilder &)> > mWriteAccessors; }; +/** + * Defines how to convert qt primitives to flatbuffer ones + * TODO: rename to createProperty or so? + */ +template +flatbuffers::uoffset_t extractProperty(const QVariant &, flatbuffers::FlatBufferBuilder &fbb); + +/** + * Create a buffer from a domain object using the provided mappings + */ +template +flatbuffers::Offset createBufferPart(const Akonadi2::ApplicationDomain::ApplicationDomainType &domainObject, flatbuffers::FlatBufferBuilder &fbb, const WritePropertyMapper &mapper) +{ + //First create a primitives such as strings using the mappings + QList > propertiesToAddToResource; + for (const auto &property : domainObject.changedProperties()) { + qWarning() << "copying property " << property; + const auto value = domainObject.getProperty(property); + if (mapper.hasMapping(property)) { + mapper.setProperty(property, domainObject.getProperty(property), propertiesToAddToResource, fbb); + } else { + qWarning() << "no mapping for property available " << property; + } + } + + //Then create all porperties using the above generated builderCalls + Builder builder(fbb); + for (auto propertyBuilder : propertiesToAddToResource) { + propertyBuilder(builder); + } + return builder.Finish(); +} + /** * A generic adaptor implementation that uses a property mapper to read/write values. * @@ -95,11 +128,6 @@ public: //TODO remove void setProperty(const QByteArray &key, const QVariant &value) { - // if (mResourceMapper && mResourceMapper->hasMapping(key)) { - // // mResourceMapper->setProperty(key, value, mResourceBuffer); - // } else { - // // mLocalMapper.; - // } } virtual QVariant getProperty(const QByteArray &key) const @@ -127,49 +155,6 @@ public: QSharedPointer > mResourceMapper; }; -/** - * A generic adaptor implementation that uses a property mapper to read/write values. - */ -template -class GenericWriteBufferAdaptor : public Akonadi2::ApplicationDomain::BufferAdaptor -{ -public: - GenericWriteBufferAdaptor(const BufferAdaptor &buffer) - : BufferAdaptor() - { - for(const auto &property : buffer.availableProperties()) { - setProperty(property, buffer.getProperty(property)); - } - } - - void setProperty(const QByteArray &key, const QVariant &value) - { - // if (mResourceMapper && mResourceMapper->hasMapping(key)) { - // // mResourceMapper->setProperty(key, value, mResourceBuffer); - // } else { - // // mLocalMapper.; - // } - } - - //TODO remove - virtual QVariant getProperty(const QByteArray &key) const - { - Q_ASSERT(false); - } - - virtual QList availableProperties() const - { - Q_ASSERT(false); - QList props; - return props; - } - - // LocalBuffer const *mLocalBuffer; - // ResourceBuffer const *mResourceBuffer; - QSharedPointer > mLocalMapper; - QSharedPointer > mResourceMapper; -}; - /** * Initializes the local property mapper. * @@ -178,16 +163,24 @@ public: template QSharedPointer > initializeReadPropertyMapper(); +template +QSharedPointer > initializeWritePropertyMapper(); + /** * 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 +template class DomainTypeAdaptorFactory { public: - DomainTypeAdaptorFactory() : mLocalMapper(initializeReadPropertyMapper()) {}; + DomainTypeAdaptorFactory() : + mLocalMapper(initializeReadPropertyMapper()), + mResourceMapper(QSharedPointer >::create()), + mLocalWriteMapper(initializeWritePropertyMapper()), + mResourceWriteMapper(QSharedPointer >::create()) + {}; virtual ~DomainTypeAdaptorFactory() {}; /** @@ -214,6 +207,8 @@ public: protected: QSharedPointer > mLocalMapper; QSharedPointer > mResourceMapper; + QSharedPointer > mLocalWriteMapper; + QSharedPointer > mResourceWriteMapper; }; diff --git a/dummyresource/domainadaptor.cpp b/dummyresource/domainadaptor.cpp index 00af3fe..fa00bbc 100644 --- a/dummyresource/domainadaptor.cpp +++ b/dummyresource/domainadaptor.cpp @@ -9,49 +9,12 @@ #include "entity_generated.h" #include "metadata_generated.h" #include "domainadaptor.h" +#include "log.h" #include using namespace DummyCalendar; using namespace flatbuffers; -/** - * Defines how to convert qt primitives to flatbuffer ones - * TODO: rename to createProperty or so? - */ -template -uoffset_t extractProperty(const QVariant &, flatbuffers::FlatBufferBuilder &fbb); - -template <> -uoffset_t extractProperty(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) -{ - if (property.isValid()) { - return fbb.CreateString(property.toString().toStdString()).o; - } - return 0; -} - -/** - * Create a buffer from a domain object using the provided mappings - */ -template -void createBufferPart(const Akonadi2::ApplicationDomain::ApplicationDomainType &domainObject, flatbuffers::FlatBufferBuilder &fbb, const WritePropertyMapper &mapper) -{ - //First create a primitives such as strings using the mappings - QList > propertiesToAddToResource; - for (const auto &property : domainObject.changedProperties()) { - const auto value = domainObject.getProperty(property); - if (mapper.hasMapping(property)) { - mapper.setProperty(property, domainObject.getProperty(property), propertiesToAddToResource, fbb); - } - } - - //Then create all porperties using the above generated builderCalls - Builder builder(fbb); - for (auto propertyBuilder : propertiesToAddToResource) { - propertyBuilder(builder); - } - builder.Finish(); -} @@ -59,7 +22,6 @@ DummyEventAdaptorFactory::DummyEventAdaptorFactory() : DomainTypeAdaptorFactory() { //TODO turn this into initializeReadPropertyMapper as well? - mResourceMapper = QSharedPointer >::create(); mResourceMapper->addMapping("summary", [](DummyEvent const *buffer) -> QVariant { if (buffer->summary()) { return QString::fromStdString(buffer->summary()->c_str()); @@ -76,51 +38,24 @@ DummyEventAdaptorFactory::DummyEventAdaptorFactory() void DummyEventAdaptorFactory::createBuffer(const Akonadi2::ApplicationDomain::Event &event, flatbuffers::FlatBufferBuilder &fbb) { - // flatbuffers::FlatBufferBuilder resFbb; - // flatbuffers::FlatBufferBuilder localFbb; - - // QList > propertiesToAddToResource; - // QList > propertiesToAddToLocal; - // for (const auto &property : event.changedProperties()) { - // const auto value = event.getProperty(property); - // if (mResourceWriteMapper && mResourceWriteMapper->hasMapping(property)) { - // mResourceWriteMapper->setProperty(property, value, propertiesToAddToResource, resFbb); - // } if (mLocalWriteMapper && mLocalWriteMapper->hasMapping(property)) { - // mLocalWriteMapper->setProperty(property, value, propertiesToAddToLocal, localFbb); - // } - // } - - // DummyEventBuilder resBuilder(resFbb); - // for (auto propertyBuilder : propertiesToAddToResource) { - // propertyBuilder(resBuilder); - // } - // resBuilder.Finish(); - - // DummyEventBuilder localBuilder(localFbb); - // for (auto propertyBuilder : propertiesToAddToResource) { - // propertyBuilder(localBuilder); - // } - // localBuilder.Finish(); - - // TODO: how does a resource specify what goes to a local buffer and what it stores separately? - // flatbuffers::FlatBufferBuilder eventFbb; - // { - // auto summary = extractProperty(event.getProperty("summary"), fbb); - // DummyCalendar::DummyEventBuilder eventBuilder(eventFbb); - // eventBuilder.add_summary(summary); - // auto eventLocation = eventBuilder.Finish(); - // DummyCalendar::FinishDummyEventBuffer(eventFbb, eventLocation); - // } - - //TODO we should only copy values into the local buffer that haven't already been copied by the resource buffer flatbuffers::FlatBufferBuilder localFbb; if (mLocalWriteMapper) { - createBufferPart(event, localFbb, *mLocalWriteMapper); + auto pos = createBufferPart(event, localFbb, *mLocalWriteMapper); + Akonadi2::ApplicationDomain::Buffer::FinishEventBuffer(localFbb, pos); + flatbuffers::Verifier verifier(localFbb.GetBufferPointer(), localFbb.GetSize()); + if (!verifier.VerifyBuffer()) { + Warning() << "Created invalid local buffer"; + } } flatbuffers::FlatBufferBuilder resFbb; if (mResourceWriteMapper) { - createBufferPart(event, resFbb, *mResourceWriteMapper); + auto pos = createBufferPart(event, resFbb, *mResourceWriteMapper); + DummyCalendar::FinishDummyEventBuffer(resFbb, pos); + flatbuffers::Verifier verifier(resFbb.GetBufferPointer(), resFbb.GetSize()); + if (!verifier.VerifyBuffer()) { + Warning() << "Created invalid resource buffer"; + } } Akonadi2::EntityBuffer::assembleEntityBuffer(fbb, 0, 0, resFbb.GetBufferPointer(), resFbb.GetSize(), localFbb.GetBufferPointer(), localFbb.GetSize()); diff --git a/dummyresource/domainadaptor.h b/dummyresource/domainadaptor.h index 39028c9..9d351e7 100644 --- a/dummyresource/domainadaptor.h +++ b/dummyresource/domainadaptor.h @@ -5,14 +5,10 @@ #include "dummycalendar_generated.h" #include "entity_generated.h" -class DummyEventAdaptorFactory : public DomainTypeAdaptorFactory +class DummyEventAdaptorFactory : public DomainTypeAdaptorFactory { public: DummyEventAdaptorFactory(); virtual ~DummyEventAdaptorFactory() {}; virtual void createBuffer(const Akonadi2::ApplicationDomain::Event &event, flatbuffers::FlatBufferBuilder &fbb); - -private: - QSharedPointer > mResourceWriteMapper; - QSharedPointer > mLocalWriteMapper; }; diff --git a/dummyresource/facade.cpp b/dummyresource/facade.cpp index af8c187..1477fcf 100644 --- a/dummyresource/facade.cpp +++ b/dummyresource/facade.cpp @@ -122,7 +122,7 @@ void DummyResourceFacade::readValue(QSharedPointer storage, c const auto localBuffer = Akonadi2::EntityBuffer::readBuffer(buffer.entity().local()); const auto metadataBuffer = Akonadi2::EntityBuffer::readBuffer(buffer.entity().metadata()); - if (!resourceBuffer || !metadataBuffer) { + if ((!resourceBuffer && !localBuffer) || !metadataBuffer) { qWarning() << "invalid buffer " << QByteArray::fromRawData(static_cast(keyValue), keySize); return true; } diff --git a/dummyresource/facade.h b/dummyresource/facade.h index 7bef2cc..37ed81d 100644 --- a/dummyresource/facade.h +++ b/dummyresource/facade.h @@ -41,5 +41,5 @@ public: private: void readValue(QSharedPointer storage, const QByteArray &key, const std::function &resultCallback, std::function); - QSharedPointer > mFactory; + QSharedPointer > mFactory; }; diff --git a/tests/domainadaptortest.cpp b/tests/domainadaptortest.cpp index 74c0d62..1e285dc 100644 --- a/tests/domainadaptortest.cpp +++ b/tests/domainadaptortest.cpp @@ -13,89 +13,12 @@ #include "metadata_generated.h" #include "entity_generated.h" -class TestEventAdaptor : public Akonadi2::ApplicationDomain::BufferAdaptor -{ -public: - TestEventAdaptor() - : Akonadi2::ApplicationDomain::BufferAdaptor() - { - } - - void setProperty(const QByteArray &key, const QVariant &value) - { - // if (mResourceMapper->mWriteAccessors.contains(key)) { - // // mResourceMapper.setProperty(key, value, mResourceBuffer); - // } else { - // // mLocalMapper.; - // } - } - - virtual QVariant getProperty(const QByteArray &key) const - { - if (mResourceBuffer && mResourceMapper->hasMapping(key)) { - return mResourceMapper->getProperty(key, mResourceBuffer); - } else if (mLocalBuffer) { - return mLocalMapper->getProperty(key, mLocalBuffer); - } - return QVariant(); - } - - Akonadi2::ApplicationDomain::Buffer::Event const *mLocalBuffer; - Akonadi2::ApplicationDomain::Buffer::Event const *mResourceBuffer; - - QSharedPointer > mLocalMapper; - QSharedPointer > mResourceMapper; -}; - -class TestFactory : public DomainTypeAdaptorFactory +class TestFactory : public DomainTypeAdaptorFactory { public: TestFactory() { - mResourceMapper = QSharedPointer >::create(); - mResourceMapper->addMapping("summary", [](Akonadi2::ApplicationDomain::Buffer::Event const *buffer) -> QVariant { - if (buffer->summary()) { - return QString::fromStdString(buffer->summary()->c_str()); - } - return QVariant(); - }); - } - - virtual QSharedPointer createAdaptor(const Akonadi2::Entity &entity) - { - Akonadi2::ApplicationDomain::Buffer::Event const *resourceBuffer = 0; - if (auto resourceData = entity.resource()) { - flatbuffers::Verifier verifyer(resourceData->Data(), resourceData->size()); - if (Akonadi2::ApplicationDomain::Buffer::VerifyEventBuffer(verifyer)) { - resourceBuffer = Akonadi2::ApplicationDomain::Buffer::GetEvent(resourceData->Data()); - if (resourceBuffer->summary()) { - qDebug() << QString::fromStdString(std::string(resourceBuffer->summary()->c_str())); - } - } - } - - // 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::ApplicationDomain::Buffer::Event const *localBuffer = 0; - if (auto localData = entity.local()) { - flatbuffers::Verifier verifyer(localData->Data(), localData->size()); - if (Akonadi2::ApplicationDomain::Buffer::VerifyEventBuffer(verifyer)) { - localBuffer = Akonadi2::ApplicationDomain::Buffer::GetEvent(localData); - } - } - - auto adaptor = QSharedPointer::create(); - adaptor->mLocalBuffer = localBuffer; - adaptor->mResourceBuffer = resourceBuffer; - adaptor->mResourceMapper = mResourceMapper; - adaptor->mLocalMapper = mLocalMapper; - return adaptor; + mResourceWriteMapper = initializeWritePropertyMapper(); } }; @@ -111,6 +34,21 @@ private Q_SLOTS: { } + void testCreateBufferPart() + { + auto writeMapper = initializeWritePropertyMapper(); + + Akonadi2::ApplicationDomain::Event event; + event.setProperty("summary", "foo"); + + flatbuffers::FlatBufferBuilder fbb; + auto pos = createBufferPart(event, fbb, *writeMapper); + Akonadi2::ApplicationDomain::Buffer::FinishEventBuffer(fbb, pos); + + flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize()); + QVERIFY(verifier.VerifyBuffer()); + } + void testAdaptor() { //Create entity buffer -- cgit v1.2.3