From 319a303bdceba18d0e5629f3de7a2b85646223be Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Tue, 6 Dec 2016 18:32:32 +0100 Subject: Wrap blob properties in type so we can distinguish it from other properties. When moving an entity to another resource we have to move the blob properties to a temporary directory first, and that requires that we are able to distinguish blob properties from the rest at runtime. --- common/domain/applicationdomaintype.cpp | 26 +++++++++++++++++++++----- common/domain/applicationdomaintype.h | 30 ++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 9 deletions(-) (limited to 'common/domain') diff --git a/common/domain/applicationdomaintype.cpp b/common/domain/applicationdomaintype.cpp index 105ae56..1e54622 100644 --- a/common/domain/applicationdomaintype.cpp +++ b/common/domain/applicationdomaintype.cpp @@ -31,6 +31,25 @@ namespace ApplicationDomain { constexpr const char *Mail::ThreadId::name; +void copyBuffer(Sink::ApplicationDomain::BufferAdaptor &buffer, Sink::ApplicationDomain::BufferAdaptor &memoryAdaptor, const QList &properties, bool copyBlobs) +{ + auto propertiesToCopy = properties; + if (properties.isEmpty()) { + propertiesToCopy = buffer.availableProperties(); + } + for (const auto &property : propertiesToCopy) { + const auto value = buffer.getProperty(property); + if (copyBlobs && value.canConvert()) { + auto oldPath = value.value().value; + auto newPath = oldPath + "copy"; + QFile::copy(oldPath, newPath); + memoryAdaptor.setProperty(property, QVariant::fromValue(BLOB{newPath})); + } else { + memoryAdaptor.setProperty(property, value); + } + } +} + ApplicationDomainType::ApplicationDomainType() :mAdaptor(new MemoryBufferAdaptor()) { @@ -85,9 +104,6 @@ bool ApplicationDomainType::hasProperty(const QByteArray &key) const QVariant ApplicationDomainType::getProperty(const QByteArray &key) const { Q_ASSERT(mAdaptor); - if (!mAdaptor->availableProperties().contains(key)) { - return QVariant(); - } return mAdaptor->getProperty(key); } @@ -111,7 +127,7 @@ void ApplicationDomainType::setProperty(const QByteArray &key, const Application QByteArray ApplicationDomainType::getBlobProperty(const QByteArray &key) const { - const auto path = getProperty(key).toByteArray(); + const auto path = getProperty(key).value().value; QFile file(path); if (!file.open(QIODevice::ReadOnly)) { SinkError() << "Failed to open the file: " << file.errorString() << path; @@ -131,7 +147,7 @@ void ApplicationDomainType::setBlobProperty(const QByteArray &key, const QByteAr file.write(value); //Ensure that the file is written to disk immediately file.close(); - setProperty(key, path); + setProperty(key, QVariant::fromValue(BLOB{path})); } void ApplicationDomainType::setChangedProperties(const QSet &changeset) diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h index d6bbdd4..621a512 100644 --- a/common/domain/applicationdomaintype.h +++ b/common/domain/applicationdomaintype.h @@ -63,12 +63,12 @@ #define SINK_BLOB_PROPERTY(NAME, LOWERCASENAME) \ struct NAME { \ static constexpr const char *name = #LOWERCASENAME; \ - typedef QString Type; \ + typedef BLOB Type; \ }; \ void set##NAME(const QByteArray &value) { setBlobProperty(NAME::name, value); } \ - void set##NAME##Path(const QString &path) { setProperty(NAME::name, QVariant::fromValue(path)); } \ + void set##NAME##Path(const QString &path) { setProperty(NAME::name, QVariant::fromValue(BLOB{path})); } \ QByteArray get##NAME() const { return getBlobProperty(NAME::name); } \ - QString get##NAME##Path() const { return getProperty(NAME::name).value(); } \ + QString get##NAME##Path() const { return getProperty(NAME::name).value().value; } \ #define SINK_REFERENCE_PROPERTY(TYPE, NAME, LOWERCASENAME) \ struct NAME { \ @@ -98,6 +98,12 @@ struct SINK_EXPORT Progress { }; +struct BLOB { + QString value; +}; + +void copyBuffer(Sink::ApplicationDomain::BufferAdaptor &buffer, Sink::ApplicationDomain::BufferAdaptor &memoryAdaptor, const QList &properties, bool copyBlobs); + /** * The domain type interface has two purposes: * * provide a unified interface to read buffers (for zero-copy reading) @@ -115,14 +121,29 @@ public: ApplicationDomainType(const ApplicationDomainType &other); ApplicationDomainType& operator=(const ApplicationDomainType &other); + /** + * Returns an in memory representation of the same entity. + */ template static typename DomainType::Ptr getInMemoryRepresentation(const ApplicationDomainType &domainType, const QList properties = QList()) { auto memoryAdaptor = QSharedPointer::create(*(domainType.mAdaptor), properties); - //The identifier still internal refers to the memory-mapped pointer, we need to copy the memory or it will become invalid + //mIdentifier internally still refers to the memory-mapped memory, we need to copy the memory or it will become invalid return QSharedPointer::create(domainType.mResourceInstanceIdentifier, QByteArray(domainType.mIdentifier.constData(), domainType.mIdentifier.size()), domainType.mRevision, memoryAdaptor); } + /** + * Returns an in memory copy without id and resource set. + */ + template + static typename DomainType::Ptr getInMemoryCopy(const ApplicationDomainType &domainType, const QList properties = QList()) + { + auto memoryAdaptor = QSharedPointer::create(); + Q_ASSERT(domainType.mAdaptor); + copyBuffer(*(domainType.mAdaptor), *memoryAdaptor, properties, true); + return QSharedPointer::create(QByteArray{}, QByteArray{}, 0, memoryAdaptor); + } + static QByteArray generateUid(); template @@ -430,3 +451,4 @@ Q_DECLARE_METATYPE(Sink::ApplicationDomain::Identity::Ptr) Q_DECLARE_METATYPE(Sink::ApplicationDomain::Mail::Contact) Q_DECLARE_METATYPE(Sink::ApplicationDomain::Error) Q_DECLARE_METATYPE(Sink::ApplicationDomain::Progress) +Q_DECLARE_METATYPE(Sink::ApplicationDomain::BLOB) -- cgit v1.2.3