From 41006b5cab7b0260f8abc42aa2d2e959a013764e Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 2 Dec 2016 21:32:56 +0100 Subject: interresource move --- common/commands/modifyentity.fbs | 2 ++ common/domain/applicationdomaintype.cpp | 5 ++++ common/domain/applicationdomaintype.h | 1 + common/facade.cpp | 14 +++++++++- common/facade.h | 1 + common/facadeinterface.h | 12 +++++++++ common/pipeline.cpp | 48 +++++++++++++++++++++++++++++++++ common/resourceaccess.cpp | 7 +++-- common/resourceaccess.h | 4 +-- common/resourcefacade.cpp | 6 +++++ common/resourcefacade.h | 1 + common/store.cpp | 10 +++++++ common/store.h | 6 +++++ common/test.cpp | 5 ++++ 14 files changed, 115 insertions(+), 7 deletions(-) (limited to 'common') diff --git a/common/commands/modifyentity.fbs b/common/commands/modifyentity.fbs index da6f0e2..d81bacf 100644 --- a/common/commands/modifyentity.fbs +++ b/common/commands/modifyentity.fbs @@ -8,6 +8,8 @@ table ModifyEntity { delta: [ubyte]; //Contains an entity buffer with all changed properties set replayToSource: bool = true; modifiedProperties: [string]; + targetResource: string; //Contains the target resource for a move/copy operation + removeEntity: bool = false; //This modification removes the entity } root_type ModifyEntity; diff --git a/common/domain/applicationdomaintype.cpp b/common/domain/applicationdomaintype.cpp index b30eb36..105ae56 100644 --- a/common/domain/applicationdomaintype.cpp +++ b/common/domain/applicationdomaintype.cpp @@ -98,6 +98,11 @@ void ApplicationDomainType::setProperty(const QByteArray &key, const QVariant &v mAdaptor->setProperty(key, value); } +void ApplicationDomainType::setResource(const QByteArray &identifier) +{ + mResourceInstanceIdentifier = identifier; +} + void ApplicationDomainType::setProperty(const QByteArray &key, const ApplicationDomainType &value) { Q_ASSERT(!value.identifier().isEmpty()); diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h index 4621316..d6bbdd4 100644 --- a/common/domain/applicationdomaintype.h +++ b/common/domain/applicationdomaintype.h @@ -168,6 +168,7 @@ public: QByteArrayList availableProperties() const; qint64 revision() const; QByteArray resourceInstanceIdentifier() const; + void setResource(const QByteArray &identifier); QByteArray identifier() const; private: diff --git a/common/facade.cpp b/common/facade.cpp index 3ec58e3..c618d4e 100644 --- a/common/facade.cpp +++ b/common/facade.cpp @@ -68,7 +68,19 @@ KAsync::Job GenericFacade::modify(const DomainType &domainObje SinkWarning() << "No domain type adaptor factory available"; return KAsync::error(); } - return mResourceAccess->sendModifyCommand(domainObject.identifier(), domainObject.revision(), bufferTypeForDomainType(), QByteArrayList(), BufferUtils::extractBuffer(entityFbb), domainObject.changedProperties()); + return mResourceAccess->sendModifyCommand(domainObject.identifier(), domainObject.revision(), bufferTypeForDomainType(), QByteArrayList(), BufferUtils::extractBuffer(entityFbb), domainObject.changedProperties(), QByteArray(), false); +} + +template +KAsync::Job GenericFacade::move(const DomainType &domainObject, const QByteArray &newResource) +{ + SinkTrace() << "Moving entity: " << domainObject.identifier() << domainObject.changedProperties() << newResource; + flatbuffers::FlatBufferBuilder entityFbb; + if (!mResourceContext.adaptorFactory().createBuffer(domainObject, entityFbb)) { + SinkWarning() << "No domain type adaptor factory available"; + return KAsync::error(); + } + return mResourceAccess->sendModifyCommand(domainObject.identifier(), domainObject.revision(), bufferTypeForDomainType(), QByteArrayList(), BufferUtils::extractBuffer(entityFbb), domainObject.changedProperties(), newResource, false); } template diff --git a/common/facade.h b/common/facade.h index 50d93e0..0fba34a 100644 --- a/common/facade.h +++ b/common/facade.h @@ -63,6 +63,7 @@ public: static QByteArray bufferTypeForDomainType(); KAsync::Job create(const DomainType &domainObject) Q_DECL_OVERRIDE; KAsync::Job modify(const DomainType &domainObject) Q_DECL_OVERRIDE; + KAsync::Job move(const DomainType &domainObject, const QByteArray &newResource) Q_DECL_OVERRIDE; KAsync::Job remove(const DomainType &domainObject) Q_DECL_OVERRIDE; virtual QPair, typename ResultEmitter::Ptr> load(const Sink::Query &query) Q_DECL_OVERRIDE; diff --git a/common/facadeinterface.h b/common/facadeinterface.h index 7d5dd7d..136791e 100644 --- a/common/facadeinterface.h +++ b/common/facadeinterface.h @@ -62,6 +62,13 @@ public: */ virtual KAsync::Job modify(const DomainType &domainObject) = 0; + /** + * Move an entity to a new resource. + * + * The job returns succefully once the task has been successfully placed in the queue + */ + virtual KAsync::Job move(const DomainType &domainObject, const QByteArray &newResource) = 0; + /** * Remove an entity from the store. * @@ -90,6 +97,11 @@ public: return KAsync::error(-1, "Failed to create a facade"); } + KAsync::Job move(const DomainType &domainObject, const QByteArray &newResource) + { + return KAsync::error(-1, "Failed to create a facade"); + } + KAsync::Job remove(const DomainType &domainObject) { return KAsync::error(-1, "Failed to create a facade"); diff --git a/common/pipeline.cpp b/common/pipeline.cpp index 1eea631..8ace855 100644 --- a/common/pipeline.cpp +++ b/common/pipeline.cpp @@ -34,10 +34,12 @@ #include "entitybuffer.h" #include "log.h" #include "domain/applicationdomaintype.h" +#include "domain/applicationdomaintype_p.h" #include "adaptorfactoryregistry.h" #include "definitions.h" #include "bufferutils.h" #include "storage/entitystore.h" +#include "store.h" SINK_DEBUG_AREA("pipeline") @@ -186,6 +188,13 @@ KAsync::Job Pipeline::newEntity(void const *command, size_t size) return KAsync::value(d->entityStore.maxRevision()); } +template +struct CreateHelper { + KAsync::Job operator()(const ApplicationDomain::ApplicationDomainType &arg) const { + return Sink::Store::create(arg); + } +}; + KAsync::Job Pipeline::modifiedEntity(void const *command, size_t size) { d->transactionItemCount++; @@ -239,6 +248,45 @@ KAsync::Job Pipeline::modifiedEntity(void const *command, size_t size) deletions = BufferUtils::fromVector(*modifyEntity->deletions()); } + if (modifyEntity->targetResource()) { + auto targetResource = BufferUtils::extractBuffer(modifyEntity->targetResource()); + auto changeset = diff.changedProperties(); + const auto current = d->entityStore.readLatest(bufferType, diff.identifier()); + if (current.identifier().isEmpty()) { + SinkWarning() << "Failed to read current version: " << diff.identifier(); + return KAsync::error(0); + } + + auto newEntity = *ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation(current, current.availableProperties()); + + // Apply diff + for (const auto &property : changeset) { + const auto value = diff.getProperty(property); + if (value.isValid()) { + newEntity.setProperty(property, value); + } + } + + // Remove deletions + for (const auto property : deletions) { + newEntity.setProperty(property, QVariant()); + } + newEntity.setResource(targetResource); + newEntity.setChangedProperties(newEntity.availableProperties().toSet()); + + SinkTrace() << "Moving entity to new resource " << newEntity.identifier() << newEntity.resourceInstanceIdentifier() << targetResource; + auto job = TypeHelper{bufferType}.operator(), ApplicationDomain::ApplicationDomainType&>(newEntity); + job = job.syncThen([=](const KAsync::Error &error) { + if (!error) { + SinkTrace() << "Move of " << newEntity.identifier() << "was successfull"; + } else { + SinkError() << "Failed to move entity " << targetResource << " to resource " << newEntity.identifier(); + } + }); + job.exec(); + return KAsync::value(0); + } + auto preprocess = [&, this](const ApplicationDomain::ApplicationDomainType &oldEntity, ApplicationDomain::ApplicationDomainType &newEntity) { foreach (const auto &processor, d->processors[bufferType]) { processor->modifiedEntity(oldEntity, newEntity); diff --git a/common/resourceaccess.cpp b/common/resourceaccess.cpp index b46e8b2..81715e5 100644 --- a/common/resourceaccess.cpp +++ b/common/resourceaccess.cpp @@ -323,16 +323,16 @@ KAsync::Job ResourceAccess::sendCreateCommand(const QByteArray &uid, const } KAsync::Job -ResourceAccess::sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer, const QByteArrayList &changedProperties) +ResourceAccess::sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer, const QByteArrayList &changedProperties, const QByteArray &newResource, bool remove) { flatbuffers::FlatBufferBuilder fbb; auto entityId = fbb.CreateString(uid.constData()); - // This is the resource buffer type and not the domain type auto type = fbb.CreateString(resourceBufferType.constData()); auto modifiedProperties = BufferUtils::toVector(fbb, changedProperties); auto deletions = BufferUtils::toVector(fbb, deletedProperties); auto delta = Sink::EntityBuffer::appendAsVector(fbb, buffer.constData(), buffer.size()); - auto location = Sink::Commands::CreateModifyEntity(fbb, revision, entityId, deletions, type, delta, true, modifiedProperties); + auto resource = newResource.isEmpty() ? 0 : fbb.CreateString(newResource.constData()); + auto location = Sink::Commands::CreateModifyEntity(fbb, revision, entityId, deletions, type, delta, true, modifiedProperties, resource, remove); Sink::Commands::FinishModifyEntityBuffer(fbb, location); open(); return sendCommand(Sink::Commands::ModifyEntityCommand, fbb); @@ -342,7 +342,6 @@ KAsync::Job ResourceAccess::sendDeleteCommand(const QByteArray &uid, qint6 { flatbuffers::FlatBufferBuilder fbb; auto entityId = fbb.CreateString(uid.constData()); - // This is the resource buffer type and not the domain type auto type = fbb.CreateString(resourceBufferType.constData()); auto location = Sink::Commands::CreateDeleteEntity(fbb, revision, entityId, type); Sink::Commands::FinishDeleteEntityBuffer(fbb, location); diff --git a/common/resourceaccess.h b/common/resourceaccess.h index 4229161..de15125 100644 --- a/common/resourceaccess.h +++ b/common/resourceaccess.h @@ -57,7 +57,7 @@ public: { return KAsync::null(); }; - virtual KAsync::Job sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer, const QByteArrayList &changedProperties) + virtual KAsync::Job sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer, const QByteArrayList &changedProperties, const QByteArray &newResource, bool remove) { return KAsync::null(); }; @@ -116,7 +116,7 @@ public: KAsync::Job synchronizeResource(const Sink::QueryBase &filter) Q_DECL_OVERRIDE; KAsync::Job sendCreateCommand(const QByteArray &uid, const QByteArray &resourceBufferType, const QByteArray &buffer) Q_DECL_OVERRIDE; KAsync::Job - sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer, const QByteArrayList &changedProperties) Q_DECL_OVERRIDE; + sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer, const QByteArrayList &changedProperties, const QByteArray &newResource, bool remove) Q_DECL_OVERRIDE; KAsync::Job sendDeleteCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType) Q_DECL_OVERRIDE; KAsync::Job sendRevisionReplayedCommand(qint64 revision) Q_DECL_OVERRIDE; KAsync::Job diff --git a/common/resourcefacade.cpp b/common/resourcefacade.cpp index e5b4496..0a05bd9 100644 --- a/common/resourcefacade.cpp +++ b/common/resourcefacade.cpp @@ -218,6 +218,12 @@ KAsync::Job LocalStorageFacade::modify(const DomainType &domai }); } +template +KAsync::Job LocalStorageFacade::move(const DomainType &, const QByteArray &) +{ + return KAsync::error(1, "Resources and Accounts cannot be moved."); +} + template KAsync::Job LocalStorageFacade::remove(const DomainType &domainObject) { diff --git a/common/resourcefacade.h b/common/resourcefacade.h index d259d4f..ea552c2 100644 --- a/common/resourcefacade.h +++ b/common/resourcefacade.h @@ -81,6 +81,7 @@ public: virtual ~LocalStorageFacade(); virtual KAsync::Job create(const DomainType &resource) Q_DECL_OVERRIDE; virtual KAsync::Job modify(const DomainType &resource) Q_DECL_OVERRIDE; + virtual KAsync::Job move(const DomainType &resource, const QByteArray &) Q_DECL_OVERRIDE; virtual KAsync::Job remove(const DomainType &resource) Q_DECL_OVERRIDE; virtual QPair, typename Sink::ResultEmitter::Ptr> load(const Sink::Query &query) Q_DECL_OVERRIDE; diff --git a/common/store.cpp b/common/store.cpp index f91973d..fad8c5e 100644 --- a/common/store.cpp +++ b/common/store.cpp @@ -215,6 +215,15 @@ KAsync::Job Store::modify(const DomainType &domainObject) return facade->modify(domainObject).addToContext(std::shared_ptr(facade)).onError([](const KAsync::Error &error) { SinkWarning() << "Failed to modify"; }); } +template +KAsync::Job Store::move(const DomainType &domainObject, const QByteArray &newResource) +{ + SinkTrace() << "Move: " << domainObject << newResource; + // Potentially move to separate thread as well + auto facade = getFacade(domainObject.resourceInstanceIdentifier()); + return facade->move(domainObject, newResource).addToContext(std::shared_ptr(facade)).onError([](const KAsync::Error &error) { SinkWarning() << "Failed to move"; }); +} + template KAsync::Job Store::remove(const DomainType &domainObject) { @@ -386,6 +395,7 @@ QList Store::read(const Sink::Query &q) template KAsync::Job Store::remove(const T &domainObject); \ template KAsync::Job Store::create(const T &domainObject); \ template KAsync::Job Store::modify(const T &domainObject); \ + template KAsync::Job Store::move(const T &domainObject, const QByteArray &newResource); \ template QSharedPointer Store::loadModel(Query query); \ template KAsync::Job Store::fetchOne(const Query &); \ template KAsync::Job> Store::fetchAll(const Query &); \ diff --git a/common/store.h b/common/store.h index c9bd9cf..7c7d2fe 100644 --- a/common/store.h +++ b/common/store.h @@ -81,6 +81,12 @@ KAsync::Job SINK_EXPORT modify(const DomainType &domainObject); template KAsync::Job SINK_EXPORT remove(const DomainType &domainObject); +/** + * Move an entity to a new resource. + */ +template +KAsync::Job SINK_EXPORT move(const DomainType &domainObject, const QByteArray &newResource); + /** * Synchronize data to local cache. */ diff --git a/common/test.cpp b/common/test.cpp index 1a0d9bc..74c499c 100644 --- a/common/test.cpp +++ b/common/test.cpp @@ -125,6 +125,11 @@ public: // mTestAccount->modifyEntity(domainObject); return KAsync::null(); }; + KAsync::Job move(const T &domainObject, const QByteArray &newResource) Q_DECL_OVERRIDE + { + // mTestAccount->moveEntity(domainObject, newResource); + return KAsync::null(); + }; KAsync::Job remove(const T &domainObject) Q_DECL_OVERRIDE { //FIXME -- cgit v1.2.3