diff options
-rw-r--r-- | common/domainadaptor.h | 15 | ||||
-rw-r--r-- | common/facade.h | 52 | ||||
-rw-r--r-- | examples/dummyresource/facade.cpp | 24 | ||||
-rw-r--r-- | examples/dummyresource/facade.h | 4 |
4 files changed, 62 insertions, 33 deletions
diff --git a/common/domainadaptor.h b/common/domainadaptor.h index d07a2bd..fd015b5 100644 --- a/common/domainadaptor.h +++ b/common/domainadaptor.h | |||
@@ -171,13 +171,22 @@ QSharedPointer<ReadPropertyMapper<T> > initializeReadPropertyMapper(); | |||
171 | template <class T> | 171 | template <class T> |
172 | QSharedPointer<WritePropertyMapper<T> > initializeWritePropertyMapper(); | 172 | QSharedPointer<WritePropertyMapper<T> > initializeWritePropertyMapper(); |
173 | 173 | ||
174 | template<typename DomainType> | ||
175 | class DomainTypeAdaptorFactoryInterface | ||
176 | { | ||
177 | public: | ||
178 | virtual ~DomainTypeAdaptorFactoryInterface() {}; | ||
179 | virtual QSharedPointer<Akonadi2::ApplicationDomain::BufferAdaptor> createAdaptor(const Akonadi2::Entity &entity) = 0; | ||
180 | virtual void createBuffer(const DomainType &event, flatbuffers::FlatBufferBuilder &fbb) = 0; | ||
181 | }; | ||
182 | |||
174 | /** | 183 | /** |
175 | * The factory should define how to go from an entitybuffer (local + resource buffer), to a domain type adapter. | 184 | * The factory should define how to go from an entitybuffer (local + resource buffer), to a domain type adapter. |
176 | * It defines how values are split accross local and resource buffer. | 185 | * It defines how values are split accross local and resource buffer. |
177 | * This is required by the facade the read the value, and by the pipeline preprocessors to access the domain values in a generic way. | 186 | * This is required by the facade the read the value, and by the pipeline preprocessors to access the domain values in a generic way. |
178 | */ | 187 | */ |
179 | template<typename DomainType, typename LocalBuffer, typename ResourceBuffer, typename LocalBuilder, typename ResourceBuilder> | 188 | template<typename DomainType, typename LocalBuffer, typename ResourceBuffer, typename LocalBuilder, typename ResourceBuilder> |
180 | class DomainTypeAdaptorFactory | 189 | class DomainTypeAdaptorFactory : public DomainTypeAdaptorFactoryInterface<DomainType> |
181 | { | 190 | { |
182 | public: | 191 | public: |
183 | DomainTypeAdaptorFactory() : | 192 | DomainTypeAdaptorFactory() : |
@@ -193,7 +202,7 @@ public: | |||
193 | * | 202 | * |
194 | * This returns by default a GenericBufferAdaptor initialized with the corresponding property mappers. | 203 | * This returns by default a GenericBufferAdaptor initialized with the corresponding property mappers. |
195 | */ | 204 | */ |
196 | virtual QSharedPointer<Akonadi2::ApplicationDomain::BufferAdaptor> createAdaptor(const Akonadi2::Entity &entity) | 205 | virtual QSharedPointer<Akonadi2::ApplicationDomain::BufferAdaptor> createAdaptor(const Akonadi2::Entity &entity) Q_DECL_OVERRIDE |
197 | { | 206 | { |
198 | const auto resourceBuffer = Akonadi2::EntityBuffer::readBuffer<ResourceBuffer>(entity.resource()); | 207 | const auto resourceBuffer = Akonadi2::EntityBuffer::readBuffer<ResourceBuffer>(entity.resource()); |
199 | const auto localBuffer = Akonadi2::EntityBuffer::readBuffer<LocalBuffer>(entity.local()); | 208 | const auto localBuffer = Akonadi2::EntityBuffer::readBuffer<LocalBuffer>(entity.local()); |
@@ -207,7 +216,7 @@ public: | |||
207 | return adaptor; | 216 | return adaptor; |
208 | } | 217 | } |
209 | 218 | ||
210 | virtual void createBuffer(const Akonadi2::ApplicationDomain::Event &event, flatbuffers::FlatBufferBuilder &fbb) {}; | 219 | virtual void createBuffer(const Akonadi2::ApplicationDomain::Event &event, flatbuffers::FlatBufferBuilder &fbb) Q_DECL_OVERRIDE {}; |
211 | 220 | ||
212 | protected: | 221 | protected: |
213 | QSharedPointer<ReadPropertyMapper<LocalBuffer> > mLocalMapper; | 222 | QSharedPointer<ReadPropertyMapper<LocalBuffer> > mLocalMapper; |
diff --git a/common/facade.h b/common/facade.h index 6c1ad67..a5858d5 100644 --- a/common/facade.h +++ b/common/facade.h | |||
@@ -84,14 +84,29 @@ namespace Akonadi2 { | |||
84 | class ResourceAccess; | 84 | class ResourceAccess; |
85 | /** | 85 | /** |
86 | * Default facade implementation for resources that are implemented in a separate process using the ResourceAccess class. | 86 | * Default facade implementation for resources that are implemented in a separate process using the ResourceAccess class. |
87 | * | ||
88 | * Ideally a basic resource has no implementation effort for the facades and can simply instanciate default implementations (meaning it only has to implement the factory with all supported types). | ||
89 | * A resource has to implement: | ||
90 | * * A facade factory registering all available facades | ||
91 | * * An adaptor factory if it uses special resource buffers (default implementation can be used otherwise) | ||
92 | * * A mapping between resource and buffertype if default can't be used. | ||
93 | * | ||
94 | * Additionally a resource only has to provide a synchronizer plugin to execute the synchronization | ||
87 | */ | 95 | */ |
88 | template <typename DomainType> | 96 | template <typename DomainType> |
89 | class GenericFacade: public Akonadi2::StoreFacade<DomainType> | 97 | class GenericFacade: public Akonadi2::StoreFacade<DomainType> |
90 | { | 98 | { |
91 | public: | 99 | public: |
92 | GenericFacade(const QByteArray &resourceIdentifier) | 100 | /** |
101 | * Create a new GenericFacade | ||
102 | * | ||
103 | * @param resourceIdentifier is the identifier of the resource instance | ||
104 | * @param adaptorFactory is the adaptor factory used to generate the mappings from domain to resource types and vice versa | ||
105 | */ | ||
106 | GenericFacade(const QByteArray &resourceIdentifier, const QSharedPointer<DomainTypeAdaptorFactoryInterface<DomainType> > &adaptorFactory = QSharedPointer<DomainTypeAdaptorFactoryInterface<DomainType> >()) | ||
93 | : Akonadi2::StoreFacade<DomainType>(), | 107 | : Akonadi2::StoreFacade<DomainType>(), |
94 | mResourceAccess(new ResourceAccess(resourceIdentifier)) | 108 | mResourceAccess(new ResourceAccess(resourceIdentifier)), |
109 | mDomainTypeAdaptorFactory(adaptorFactory) | ||
95 | { | 110 | { |
96 | } | 111 | } |
97 | 112 | ||
@@ -99,6 +114,34 @@ public: | |||
99 | { | 114 | { |
100 | } | 115 | } |
101 | 116 | ||
117 | static QByteArray bufferTypeForDomainType() | ||
118 | { | ||
119 | //We happen to have a one to one mapping | ||
120 | return Akonadi2::ApplicationDomain::getTypeName<DomainType>(); | ||
121 | } | ||
122 | |||
123 | Async::Job<void> create(const Akonadi2::ApplicationDomain::Event &domainObject) Q_DECL_OVERRIDE | ||
124 | { | ||
125 | if (!mDomainTypeAdaptorFactory) { | ||
126 | Warning() << "No domain type adaptor factory available"; | ||
127 | } | ||
128 | flatbuffers::FlatBufferBuilder entityFbb; | ||
129 | mDomainTypeAdaptorFactory->createBuffer(domainObject, entityFbb); | ||
130 | return sendCreateCommand(bufferTypeForDomainType(), QByteArray::fromRawData(reinterpret_cast<const char*>(entityFbb.GetBufferPointer()), entityFbb.GetSize())); | ||
131 | } | ||
132 | |||
133 | Async::Job<void> modify(const Akonadi2::ApplicationDomain::Event &domainObject) Q_DECL_OVERRIDE | ||
134 | { | ||
135 | //TODO | ||
136 | return Async::null<void>(); | ||
137 | } | ||
138 | |||
139 | Async::Job<void> remove(const Akonadi2::ApplicationDomain::Event &domainObject) Q_DECL_OVERRIDE | ||
140 | { | ||
141 | //TODO | ||
142 | return Async::null<void>(); | ||
143 | } | ||
144 | |||
102 | //TODO JOBAPI return job from sync continuation to execute it as subjob? | 145 | //TODO JOBAPI return job from sync continuation to execute it as subjob? |
103 | Async::Job<void> load(const Akonadi2::Query &query, const QSharedPointer<Akonadi2::ResultProvider<typename DomainType::Ptr> > &resultProvider) Q_DECL_OVERRIDE | 146 | Async::Job<void> load(const Akonadi2::Query &query, const QSharedPointer<Akonadi2::ResultProvider<typename DomainType::Ptr> > &resultProvider) Q_DECL_OVERRIDE |
104 | { | 147 | { |
@@ -142,11 +185,11 @@ public: | |||
142 | } | 185 | } |
143 | 186 | ||
144 | protected: | 187 | protected: |
145 | Async::Job<void> sendCreateCommand(const QByteArray &t, const QByteArray &buffer) | 188 | Async::Job<void> sendCreateCommand(const QByteArray &resourceBufferType, const QByteArray &buffer) |
146 | { | 189 | { |
147 | flatbuffers::FlatBufferBuilder fbb; | 190 | flatbuffers::FlatBufferBuilder fbb; |
148 | //This is the resource buffer type and not the domain type | 191 | //This is the resource buffer type and not the domain type |
149 | auto type = fbb.CreateString(t.constData()); | 192 | auto type = fbb.CreateString(resourceBufferType.constData()); |
150 | auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, buffer.constData(), buffer.size()); | 193 | auto delta = Akonadi2::EntityBuffer::appendAsVector(fbb, buffer.constData(), buffer.size()); |
151 | auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta); | 194 | auto location = Akonadi2::Commands::CreateCreateEntity(fbb, type, delta); |
152 | Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); | 195 | Akonadi2::Commands::FinishCreateEntityBuffer(fbb, location); |
@@ -177,6 +220,7 @@ protected: | |||
177 | protected: | 220 | protected: |
178 | //TODO use one resource access instance per application => make static | 221 | //TODO use one resource access instance per application => make static |
179 | QSharedPointer<Akonadi2::ResourceAccess> mResourceAccess; | 222 | QSharedPointer<Akonadi2::ResourceAccess> mResourceAccess; |
223 | QSharedPointer<DomainTypeAdaptorFactoryInterface<DomainType> > mDomainTypeAdaptorFactory; | ||
180 | }; | 224 | }; |
181 | 225 | ||
182 | } | 226 | } |
diff --git a/examples/dummyresource/facade.cpp b/examples/dummyresource/facade.cpp index e50e4f3..37f75ae 100644 --- a/examples/dummyresource/facade.cpp +++ b/examples/dummyresource/facade.cpp | |||
@@ -38,8 +38,7 @@ using namespace flatbuffers; | |||
38 | 38 | ||
39 | 39 | ||
40 | DummyResourceFacade::DummyResourceFacade() | 40 | DummyResourceFacade::DummyResourceFacade() |
41 | : Akonadi2::GenericFacade<Akonadi2::ApplicationDomain::Event>("org.kde.dummy"), | 41 | : Akonadi2::GenericFacade<Akonadi2::ApplicationDomain::Event>("org.kde.dummy", QSharedPointer<DummyEventAdaptorFactory>::create()) |
42 | mFactory(new DummyEventAdaptorFactory) | ||
43 | { | 42 | { |
44 | } | 43 | } |
45 | 44 | ||
@@ -47,25 +46,6 @@ DummyResourceFacade::~DummyResourceFacade() | |||
47 | { | 46 | { |
48 | } | 47 | } |
49 | 48 | ||
50 | Async::Job<void> DummyResourceFacade::create(const Akonadi2::ApplicationDomain::Event &domainObject) | ||
51 | { | ||
52 | flatbuffers::FlatBufferBuilder entityFbb; | ||
53 | mFactory->createBuffer(domainObject, entityFbb); | ||
54 | return sendCreateCommand("event", QByteArray::fromRawData(reinterpret_cast<const char*>(entityFbb.GetBufferPointer()), entityFbb.GetSize())); | ||
55 | } | ||
56 | |||
57 | Async::Job<void> DummyResourceFacade::modify(const Akonadi2::ApplicationDomain::Event &domainObject) | ||
58 | { | ||
59 | //Create message buffer and send to resource | ||
60 | return Async::null<void>(); | ||
61 | } | ||
62 | |||
63 | Async::Job<void> DummyResourceFacade::remove(const Akonadi2::ApplicationDomain::Event &domainObject) | ||
64 | { | ||
65 | //Create message buffer and send to resource | ||
66 | return Async::null<void>(); | ||
67 | } | ||
68 | |||
69 | static std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)> prepareQuery(const Akonadi2::Query &query) | 49 | static std::function<bool(const std::string &key, DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)> prepareQuery(const Akonadi2::Query &query) |
70 | { | 50 | { |
71 | //Compose some functions to make query matching fast. | 51 | //Compose some functions to make query matching fast. |
@@ -133,7 +113,7 @@ void DummyResourceFacade::readValue(QSharedPointer<Akonadi2::Storage> storage, c | |||
133 | qint64 revision = metadataBuffer ? metadataBuffer->revision() : -1; | 113 | qint64 revision = metadataBuffer ? metadataBuffer->revision() : -1; |
134 | //This only works for a 1:1 mapping of resource to domain types. | 114 | //This only works for a 1:1 mapping of resource to domain types. |
135 | //Not i.e. for tags that are stored as flags in each entity of an imap store. | 115 | //Not i.e. for tags that are stored as flags in each entity of an imap store. |
136 | auto adaptor = mFactory->createAdaptor(buffer.entity()); | 116 | auto adaptor = mDomainTypeAdaptorFactory->createAdaptor(buffer.entity()); |
137 | //TODO only copy requested properties | 117 | //TODO only copy requested properties |
138 | auto memoryAdaptor = QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create(*adaptor); | 118 | auto memoryAdaptor = QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create(*adaptor); |
139 | // here we could copy additional properties that don't have a 1:1 mapping, such as separately stored tags. | 119 | // here we could copy additional properties that don't have a 1:1 mapping, such as separately stored tags. |
diff --git a/examples/dummyresource/facade.h b/examples/dummyresource/facade.h index 91ae351..2fd2fa9 100644 --- a/examples/dummyresource/facade.h +++ b/examples/dummyresource/facade.h | |||
@@ -34,12 +34,8 @@ class DummyResourceFacade : public Akonadi2::GenericFacade<Akonadi2::Application | |||
34 | public: | 34 | public: |
35 | DummyResourceFacade(); | 35 | DummyResourceFacade(); |
36 | virtual ~DummyResourceFacade(); | 36 | virtual ~DummyResourceFacade(); |
37 | Async::Job<void> create(const Akonadi2::ApplicationDomain::Event &domainObject) Q_DECL_OVERRIDE; | ||
38 | Async::Job<void> modify(const Akonadi2::ApplicationDomain::Event &domainObject) Q_DECL_OVERRIDE; | ||
39 | Async::Job<void> remove(const Akonadi2::ApplicationDomain::Event &domainObject) Q_DECL_OVERRIDE; | ||
40 | Async::Job<qint64> load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::ApplicationDomain::Event::Ptr &)> &resultCallback) Q_DECL_OVERRIDE; | 37 | Async::Job<qint64> load(const Akonadi2::Query &query, const std::function<void(const Akonadi2::ApplicationDomain::Event::Ptr &)> &resultCallback) Q_DECL_OVERRIDE; |
41 | 38 | ||
42 | private: | 39 | private: |
43 | void readValue(QSharedPointer<Akonadi2::Storage> storage, const QByteArray &key, const std::function<void(const Akonadi2::ApplicationDomain::Event::Ptr &)> &resultCallback, std::function<bool(const std::string &key, DummyCalendar::DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)>); | 40 | void readValue(QSharedPointer<Akonadi2::Storage> storage, const QByteArray &key, const std::function<void(const Akonadi2::ApplicationDomain::Event::Ptr &)> &resultCallback, std::function<bool(const std::string &key, DummyCalendar::DummyEvent const *buffer, Akonadi2::ApplicationDomain::Buffer::Event const *local)>); |
44 | QSharedPointer<DomainTypeAdaptorFactory<Akonadi2::ApplicationDomain::Event, Akonadi2::ApplicationDomain::Buffer::Event, DummyCalendar::DummyEvent, Akonadi2::ApplicationDomain::Buffer::EventBuilder, DummyCalendar::DummyEventBuilder> > mFactory; | ||
45 | }; | 41 | }; |