summaryrefslogtreecommitdiffstats
path: root/common/domainadaptor.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/domainadaptor.h')
-rw-r--r--common/domainadaptor.h187
1 files changed, 161 insertions, 26 deletions
diff --git a/common/domainadaptor.h b/common/domainadaptor.h
index e46e893..e356692 100644
--- a/common/domainadaptor.h
+++ b/common/domainadaptor.h
@@ -21,59 +21,194 @@
21 21
22#include "entity_generated.h" 22#include "entity_generated.h"
23#include <QVariant> 23#include <QVariant>
24#include <QString> 24#include <QByteArray>
25#include <functional> 25#include <functional>
26#include "clientapi.h" //for domain parts 26#include "clientapi.h" //for domain parts
27 27
28#include "event_generated.h"
29#include "entity_generated.h"
30#include "metadata_generated.h"
31#include "entitybuffer.h"
32
28/** 33/**
29 * The property mapper holds accessor functions for all properties. 34 * The property mapper is a non-typesafe virtual dispatch.
30 * 35 *
31 * It is by default initialized with accessors that access the local-only buffer, 36 * Instead of using an interface and requring each implementation to override
32 * and resource simply have to overwrite those accessors. 37 * a virtual method per property, the property mapper can be filled with accessors
38 * that extract the properties from resource types.
33 */ 39 */
34template<typename BufferType> 40template<typename BufferType>
35class PropertyMapper 41class ReadPropertyMapper
42{
43public:
44 virtual QVariant getProperty(const QByteArray &key, BufferType const *buffer) const
45 {
46 if (mReadAccessors.contains(key)) {
47 auto accessor = mReadAccessors.value(key);
48 return accessor(buffer);
49 }
50 return QVariant();
51 }
52 bool hasMapping(const QByteArray &key) const { return mReadAccessors.contains(key); }
53 QList<QByteArray> availableProperties() const { return mReadAccessors.keys(); }
54 void addMapping(const QByteArray &property, const std::function<QVariant(BufferType const *)> &mapping) {
55 mReadAccessors.insert(property, mapping);
56 }
57private:
58 QHash<QByteArray, std::function<QVariant(BufferType const *)> > mReadAccessors;
59};
60
61template<typename BufferBuilder>
62class WritePropertyMapper
36{ 63{
37public: 64public:
38 void setProperty(const QString &key, const QVariant &value, BufferType *buffer) 65 virtual void setProperty(const QByteArray &key, const QVariant &value, QList<std::function<void(BufferBuilder &)> > &builderCalls, flatbuffers::FlatBufferBuilder &fbb) const
39 { 66 {
40 if (mWriteAccessors.contains(key)) { 67 if (mWriteAccessors.contains(key)) {
41 auto accessor = mWriteAccessors.value(key); 68 auto accessor = mWriteAccessors.value(key);
42 return accessor(value, buffer); 69 builderCalls << accessor(value, fbb);
43 } 70 }
44 } 71 }
72 bool hasMapping(const QByteArray &key) const { return mWriteAccessors.contains(key); }
73 void addMapping(const QByteArray &property, const std::function<std::function<void(BufferBuilder &)>(const QVariant &, flatbuffers::FlatBufferBuilder &)> &mapping) {
74 mWriteAccessors.insert(property, mapping);
75 }
76private:
77 QHash<QByteArray, std::function<std::function<void(BufferBuilder &)>(const QVariant &, flatbuffers::FlatBufferBuilder &)> > mWriteAccessors;
78};
79
80/**
81 * Defines how to convert qt primitives to flatbuffer ones
82 * TODO: rename to createProperty or so?
83 */
84template <class T>
85flatbuffers::uoffset_t extractProperty(const QVariant &, flatbuffers::FlatBufferBuilder &fbb);
86
87/**
88 * Create a buffer from a domain object using the provided mappings
89 */
90template <class Builder, class Buffer>
91flatbuffers::Offset<Buffer> createBufferPart(const Akonadi2::ApplicationDomain::ApplicationDomainType &domainObject, flatbuffers::FlatBufferBuilder &fbb, const WritePropertyMapper<Builder> &mapper)
92{
93 //First create a primitives such as strings using the mappings
94 QList<std::function<void(Builder &)> > propertiesToAddToResource;
95 for (const auto &property : domainObject.changedProperties()) {
96 qWarning() << "copying property " << property;
97 const auto value = domainObject.getProperty(property);
98 if (mapper.hasMapping(property)) {
99 mapper.setProperty(property, domainObject.getProperty(property), propertiesToAddToResource, fbb);
100 } else {
101 qWarning() << "no mapping for property available " << property;
102 }
103 }
104
105 //Then create all porperties using the above generated builderCalls
106 Builder builder(fbb);
107 for (auto propertyBuilder : propertiesToAddToResource) {
108 propertyBuilder(builder);
109 }
110 return builder.Finish();
111}
112
113/**
114 * A generic adaptor implementation that uses a property mapper to read/write values.
115 *
116 * TODO: this is the read-only part. Create a write only equivalent
117 */
118template <class LocalBuffer, class ResourceBuffer>
119class GenericBufferAdaptor : public Akonadi2::ApplicationDomain::BufferAdaptor
120{
121public:
122 GenericBufferAdaptor()
123 : BufferAdaptor()
124 {
125
126 }
45 127
46 virtual QVariant getProperty(const QString &key, BufferType const *buffer) const 128 //TODO remove
129 void setProperty(const QByteArray &key, const QVariant &value)
47 { 130 {
48 if (mReadAccessors.contains(key)) { 131 }
49 auto accessor = mReadAccessors.value(key); 132
50 return accessor(buffer); 133 virtual QVariant getProperty(const QByteArray &key) const
134 {
135 if (mResourceBuffer && mResourceMapper->hasMapping(key)) {
136 return mResourceMapper->getProperty(key, mResourceBuffer);
137 } else if (mLocalBuffer && mLocalMapper->hasMapping(key)) {
138 return mLocalMapper->getProperty(key, mLocalBuffer);
51 } 139 }
140 qWarning() << "no mapping available for key " << key;
52 return QVariant(); 141 return QVariant();
53 } 142 }
54 QHash<QString, std::function<QVariant(BufferType const *)> > mReadAccessors; 143
55 QHash<QString, std::function<void(const QVariant &, BufferType*)> > mWriteAccessors; 144 virtual QList<QByteArray> availableProperties() const
145 {
146 QList<QByteArray> props;
147 props << mResourceMapper->availableProperties();
148 props << mLocalMapper->availableProperties();
149 return props;
150 }
151
152 LocalBuffer const *mLocalBuffer;
153 ResourceBuffer const *mResourceBuffer;
154 QSharedPointer<ReadPropertyMapper<LocalBuffer> > mLocalMapper;
155 QSharedPointer<ReadPropertyMapper<ResourceBuffer> > mResourceMapper;
56}; 156};
57 157
58//The factory should define how to go from an entitybuffer (local + resource buffer), to a domain type adapter. 158/**
59//It defines how values are split accross local and resource buffer. 159 * Initializes the local property mapper.
60//This is required by the facade the read the value, and by the pipeline preprocessors to access the domain values in a generic way. 160 *
61// template<typename DomainType, typename LocalBuffer, typename ResourceBuffer> 161 * Provide an implementation for each application domain type.
62// class DomainTypeAdaptorFactory 162 */
63// { 163template <class T>
64// }; 164QSharedPointer<ReadPropertyMapper<T> > initializeReadPropertyMapper();
165
166template <class T>
167QSharedPointer<WritePropertyMapper<T> > initializeWritePropertyMapper();
65 168
66template<typename DomainType, typename LocalBuffer, typename ResourceBuffer> 169/**
67class DomainTypeAdaptorFactory/* <typename DomainType, LocalBuffer, ResourceBuffer> */ 170 * The factory should define how to go from an entitybuffer (local + resource buffer), to a domain type adapter.
171 * It defines how values are split accross local and resource buffer.
172 * This is required by the facade the read the value, and by the pipeline preprocessors to access the domain values in a generic way.
173 */
174template<typename DomainType, typename LocalBuffer, typename ResourceBuffer, typename LocalBuilder, typename ResourceBuilder>
175class DomainTypeAdaptorFactory
68{ 176{
69public: 177public:
178 DomainTypeAdaptorFactory() :
179 mLocalMapper(initializeReadPropertyMapper<LocalBuffer>()),
180 mResourceMapper(QSharedPointer<ReadPropertyMapper<ResourceBuffer> >::create()),
181 mLocalWriteMapper(initializeWritePropertyMapper<LocalBuilder>()),
182 mResourceWriteMapper(QSharedPointer<WritePropertyMapper<ResourceBuilder> >::create())
183 {};
70 virtual ~DomainTypeAdaptorFactory() {}; 184 virtual ~DomainTypeAdaptorFactory() {};
71 virtual QSharedPointer<Akonadi2::Domain::BufferAdaptor> createAdaptor(const Akonadi2::Entity &entity) = 0; 185
72 virtual void createBuffer(const Akonadi2::Domain::Event &event, flatbuffers::FlatBufferBuilder &fbb) {}; 186 /**
187 * Creates an adaptor for the given domain and resource types.
188 *
189 * This returns by default a GenericBufferAdaptor initialized with the corresponding property mappers.
190 */
191 virtual QSharedPointer<Akonadi2::ApplicationDomain::BufferAdaptor> createAdaptor(const Akonadi2::Entity &entity)
192 {
193 const auto resourceBuffer = Akonadi2::EntityBuffer::readBuffer<ResourceBuffer>(entity.resource());
194 const auto localBuffer = Akonadi2::EntityBuffer::readBuffer<LocalBuffer>(entity.local());
195 // const auto metadataBuffer = Akonadi2::EntityBuffer::readBuffer<Akonadi2::Metadata>(entity.metadata());
196
197 auto adaptor = QSharedPointer<GenericBufferAdaptor<LocalBuffer, ResourceBuffer> >::create();
198 adaptor->mLocalBuffer = localBuffer;
199 adaptor->mLocalMapper = mLocalMapper;
200 adaptor->mResourceBuffer = resourceBuffer;
201 adaptor->mResourceMapper = mResourceMapper;
202 return adaptor;
203 }
204
205 virtual void createBuffer(const Akonadi2::ApplicationDomain::Event &event, flatbuffers::FlatBufferBuilder &fbb) {};
73 206
74protected: 207protected:
75 QSharedPointer<PropertyMapper<LocalBuffer> > mLocalMapper; 208 QSharedPointer<ReadPropertyMapper<LocalBuffer> > mLocalMapper;
76 QSharedPointer<PropertyMapper<ResourceBuffer> > mResourceMapper; 209 QSharedPointer<ReadPropertyMapper<ResourceBuffer> > mResourceMapper;
210 QSharedPointer<WritePropertyMapper<LocalBuilder> > mLocalWriteMapper;
211 QSharedPointer<WritePropertyMapper<ResourceBuilder> > mResourceWriteMapper;
77}; 212};
78 213
79 214