summaryrefslogtreecommitdiffstats
path: root/common/resourcefacade.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-04-12 22:03:27 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-04-12 22:03:27 +0200
commit2cbbdaca7c6e96e40b17b6af4672af2b6735bf8e (patch)
tree1ecd446af60b78ac788f7873c8926ee283178d68 /common/resourcefacade.cpp
parent68fcd3e123e9c0e345d95728d0c8742e53be940a (diff)
downloadsink-2cbbdaca7c6e96e40b17b6af4672af2b6735bf8e.tar.gz
sink-2cbbdaca7c6e96e40b17b6af4672af2b6735bf8e.zip
Generalized LocalStorageFacade
Diffstat (limited to 'common/resourcefacade.cpp')
-rw-r--r--common/resourcefacade.cpp242
1 files changed, 131 insertions, 111 deletions
diff --git a/common/resourcefacade.cpp b/common/resourcefacade.cpp
index 2969c44..935c613 100644
--- a/common/resourcefacade.cpp
+++ b/common/resourcefacade.cpp
@@ -24,6 +24,136 @@
24#include "storage.h" 24#include "storage.h"
25#include <QDir> 25#include <QDir>
26 26
27template <typename DomainType>
28ConfigNotifier LocalStorageFacade<DomainType>::sConfigNotifier;
29
30template <typename DomainType>
31LocalStorageFacade<DomainType>::LocalStorageFacade(const QByteArray &identifier) : Sink::StoreFacade<DomainType>(), mConfigStore(identifier)
32{
33}
34
35template <typename DomainType>
36LocalStorageFacade<DomainType>::~LocalStorageFacade()
37{
38}
39
40template <typename DomainType>
41typename DomainType::Ptr LocalStorageFacade<DomainType>::readFromConfig(const QByteArray &id, const QByteArray &type)
42{
43 auto object = DomainType::Ptr::create(id);
44 object->setProperty("type", type);
45 const auto configurationValues = mConfigStore.get(id);
46 for (auto it = configurationValues.constBegin(); it != configurationValues.constEnd(); it++) {
47 object->setProperty(it.key(), it.value());
48 }
49 return object;
50}
51
52template <typename DomainType>
53KAsync::Job<void> LocalStorageFacade<DomainType>::create(const DomainType &domainObject)
54{
55 return KAsync::start<void>([domainObject, this]() {
56 const QByteArray type = domainObject.getProperty("type").toByteArray();
57 //FIXME use .identifier() instead
58 const QByteArray providedIdentifier = domainObject.getProperty("identifier").toByteArray();
59 const QByteArray identifier = providedIdentifier.isEmpty() ? ResourceConfig::newIdentifier(type) : providedIdentifier;
60 mConfigStore.add(identifier, type);
61 auto changedProperties = domainObject.changedProperties();
62 changedProperties.removeOne("identifier");
63 changedProperties.removeOne("type");
64 if (!changedProperties.isEmpty()) {
65 // We have some configuration values
66 QMap<QByteArray, QVariant> configurationValues;
67 for (const auto &property : changedProperties) {
68 configurationValues.insert(property, domainObject.getProperty(property));
69 }
70 mConfigStore.modify(identifier, configurationValues);
71 }
72 sConfigNotifier.add(readFromConfig(identifier, type));
73 });
74}
75
76template <typename DomainType>
77KAsync::Job<void> LocalStorageFacade<DomainType>::modify(const DomainType &domainObject)
78{
79 return KAsync::start<void>([domainObject, this]() {
80 const QByteArray identifier = domainObject.identifier();
81 if (identifier.isEmpty()) {
82 Warning() << "We need an \"identifier\" property to identify the entity to configure.";
83 return;
84 }
85 auto changedProperties = domainObject.changedProperties();
86 changedProperties.removeOne("identifier");
87 changedProperties.removeOne("type");
88 if (!changedProperties.isEmpty()) {
89 // We have some configuration values
90 QMap<QByteArray, QVariant> configurationValues;
91 for (const auto &property : changedProperties) {
92 configurationValues.insert(property, domainObject.getProperty(property));
93 }
94 mConfigStore.modify(identifier, configurationValues);
95 }
96
97 const auto type = mConfigStore.getEntries().value(identifier);
98 sConfigNotifier.modify(readFromConfig(identifier, type));
99 });
100}
101
102template <typename DomainType>
103KAsync::Job<void> LocalStorageFacade<DomainType>::remove(const DomainType &domainObject)
104{
105 return KAsync::start<void>([domainObject, this]() {
106 const QByteArray identifier = domainObject.identifier();
107 if (identifier.isEmpty()) {
108 Warning() << "We need an \"identifier\" property to identify the entity to configure";
109 return;
110 }
111 mConfigStore.remove(identifier);
112 sConfigNotifier.remove(QSharedPointer<DomainType>::create(domainObject));
113 });
114}
115
116template <typename DomainType>
117QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr> LocalStorageFacade<DomainType>::load(const Sink::Query &query)
118{
119 QObject *guard = new QObject;
120 auto resultProvider = new Sink::ResultProvider<typename DomainType::Ptr>();
121 auto emitter = resultProvider->emitter();
122 resultProvider->setFetcher([](const QSharedPointer<DomainType> &) {});
123 resultProvider->onDone([=]() { delete resultProvider; delete guard; });
124 auto job = KAsync::start<void>([=]() {
125 const auto entries = mConfigStore.getEntries();
126 for (const auto &res : entries.keys()) {
127 const auto type = entries.value(res);
128 if (!query.ids.isEmpty() && !query.ids.contains(res)) {
129 continue;
130 }
131 resultProvider->add(readFromConfig(res, type));
132 }
133 if (query.liveQuery) {
134 QObject::connect(&sConfigNotifier, &ConfigNotifier::modified, guard, [resultProvider](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &entry) {
135 resultProvider->modify(entry.staticCast<DomainType>());
136 });
137 QObject::connect(&sConfigNotifier, &ConfigNotifier::added, guard, [resultProvider](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &entry) {
138 resultProvider->add(entry.staticCast<DomainType>());
139 });
140 QObject::connect(&sConfigNotifier, &ConfigNotifier::removed, guard,[resultProvider](const Sink::ApplicationDomain::ApplicationDomainType::Ptr &entry) {
141 resultProvider->remove(entry.staticCast<DomainType>());
142 });
143 }
144 // TODO initialResultSetComplete should be implicit
145 resultProvider->initialResultSetComplete(typename DomainType::Ptr());
146 resultProvider->complete();
147 });
148 return qMakePair(job, emitter);
149}
150
151
152
153
154
155
156
27ResourceFacade::ResourceFacade(const QByteArray &) : Sink::StoreFacade<Sink::ApplicationDomain::SinkResource>() 157ResourceFacade::ResourceFacade(const QByteArray &) : Sink::StoreFacade<Sink::ApplicationDomain::SinkResource>()
28{ 158{
29} 159}
@@ -145,22 +275,7 @@ QPair<KAsync::Job<void>, typename Sink::ResultEmitter<Sink::ApplicationDomain::S
145 275
146 276
147 277
148Q_GLOBAL_STATIC(ConfigNotifier, sConfig); 278AccountFacade::AccountFacade(const QByteArray &) : LocalStorageFacade<Sink::ApplicationDomain::SinkAccount>("accounts")
149
150static Sink::ApplicationDomain::SinkAccount::Ptr readAccountFromConfig(const QByteArray &id, const QByteArray &type)
151{
152 auto account = Sink::ApplicationDomain::SinkAccount::Ptr::create(id);
153
154 account->setProperty("type", type);
155 const auto configurationValues = ConfigStore("accounts").get(id);
156 for (auto it = configurationValues.constBegin(); it != configurationValues.constEnd(); it++) {
157 account->setProperty(it.key(), it.value());
158 }
159 return account;
160}
161
162
163AccountFacade::AccountFacade(const QByteArray &) : Sink::StoreFacade<Sink::ApplicationDomain::SinkAccount>(), mConfigStore("accounts")
164{ 279{
165} 280}
166 281
@@ -168,98 +283,3 @@ AccountFacade::~AccountFacade()
168{ 283{
169} 284}
170 285
171KAsync::Job<void> AccountFacade::create(const Sink::ApplicationDomain::SinkAccount &account)
172{
173 return KAsync::start<void>([account, this]() {
174 const QByteArray type = account.getProperty("type").toByteArray();
175 const QByteArray providedIdentifier = account.getProperty("identifier").toByteArray();
176 // It is currently a requirement that the account starts with the type
177 const QByteArray identifier = providedIdentifier.isEmpty() ? ResourceConfig::newIdentifier(type) : providedIdentifier;
178 mConfigStore.add(identifier, type);
179 auto changedProperties = account.changedProperties();
180 changedProperties.removeOne("identifier");
181 changedProperties.removeOne("type");
182 if (!changedProperties.isEmpty()) {
183 // We have some configuration values
184 QMap<QByteArray, QVariant> configurationValues;
185 for (const auto &property : changedProperties) {
186 configurationValues.insert(property, account.getProperty(property));
187 }
188 mConfigStore.modify(identifier, configurationValues);
189 }
190 sConfig->add(readAccountFromConfig(identifier, type));
191 });
192}
193
194KAsync::Job<void> AccountFacade::modify(const Sink::ApplicationDomain::SinkAccount &account)
195{
196 return KAsync::start<void>([account, this]() {
197 const QByteArray identifier = account.identifier();
198 if (identifier.isEmpty()) {
199 Warning() << "We need an \"identifier\" property to identify the account to configure.";
200 return;
201 }
202 auto changedProperties = account.changedProperties();
203 changedProperties.removeOne("identifier");
204 changedProperties.removeOne("type");
205 if (!changedProperties.isEmpty()) {
206 // We have some configuration values
207 QMap<QByteArray, QVariant> configurationValues;
208 for (const auto &property : changedProperties) {
209 configurationValues.insert(property, account.getProperty(property));
210 }
211 mConfigStore.modify(identifier, configurationValues);
212 }
213
214 const auto type = mConfigStore.getEntries().value(identifier);
215 sConfig->modify(readAccountFromConfig(identifier, type));
216 });
217}
218
219KAsync::Job<void> AccountFacade::remove(const Sink::ApplicationDomain::SinkAccount &account)
220{
221 return KAsync::start<void>([account, this]() {
222 const QByteArray identifier = account.identifier();
223 if (identifier.isEmpty()) {
224 Warning() << "We need an \"identifier\" property to identify the account to configure";
225 return;
226 }
227 mConfigStore.remove(identifier);
228 sConfig->remove(Sink::ApplicationDomain::SinkAccount::Ptr::create(account));
229 });
230}
231
232QPair<KAsync::Job<void>, typename Sink::ResultEmitter<Sink::ApplicationDomain::SinkAccount::Ptr>::Ptr> AccountFacade::load(const Sink::Query &query)
233{
234 QObject *guard = new QObject;
235 auto resultProvider = new Sink::ResultProvider<typename Sink::ApplicationDomain::SinkAccount::Ptr>();
236 auto emitter = resultProvider->emitter();
237 resultProvider->setFetcher([](const QSharedPointer<Sink::ApplicationDomain::SinkAccount> &) {});
238 resultProvider->onDone([=]() { delete resultProvider; delete guard; });
239 auto job = KAsync::start<void>([=]() {
240 const auto configuredAccounts = mConfigStore.getEntries();
241 for (const auto &res : configuredAccounts.keys()) {
242 const auto type = configuredAccounts.value(res);
243 if (!query.ids.isEmpty() && !query.ids.contains(res)) {
244 continue;
245 }
246
247 resultProvider->add(readAccountFromConfig(res, type));
248 }
249 if (query.liveQuery) {
250 QObject::connect(sConfig, &ConfigNotifier::modified, guard, [resultProvider](const Sink::ApplicationDomain::SinkAccount::Ptr &account) {
251 resultProvider->modify(account);
252 });
253 QObject::connect(sConfig, &ConfigNotifier::added, guard, [resultProvider](const Sink::ApplicationDomain::SinkAccount::Ptr &account) {
254 resultProvider->add(account);
255 });
256 QObject::connect(sConfig, &ConfigNotifier::removed, guard,[resultProvider](const Sink::ApplicationDomain::SinkAccount::Ptr &account) {
257 resultProvider->remove(account);
258 });
259 }
260 // TODO initialResultSetComplete should be implicit
261 resultProvider->initialResultSetComplete(Sink::ApplicationDomain::SinkAccount::Ptr());
262 resultProvider->complete();
263 });
264 return qMakePair(job, emitter);
265}