diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-04-12 22:03:27 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-04-12 22:03:27 +0200 |
commit | 2cbbdaca7c6e96e40b17b6af4672af2b6735bf8e (patch) | |
tree | 1ecd446af60b78ac788f7873c8926ee283178d68 /common/resourcefacade.cpp | |
parent | 68fcd3e123e9c0e345d95728d0c8742e53be940a (diff) | |
download | sink-2cbbdaca7c6e96e40b17b6af4672af2b6735bf8e.tar.gz sink-2cbbdaca7c6e96e40b17b6af4672af2b6735bf8e.zip |
Generalized LocalStorageFacade
Diffstat (limited to 'common/resourcefacade.cpp')
-rw-r--r-- | common/resourcefacade.cpp | 242 |
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 | ||
27 | template <typename DomainType> | ||
28 | ConfigNotifier LocalStorageFacade<DomainType>::sConfigNotifier; | ||
29 | |||
30 | template <typename DomainType> | ||
31 | LocalStorageFacade<DomainType>::LocalStorageFacade(const QByteArray &identifier) : Sink::StoreFacade<DomainType>(), mConfigStore(identifier) | ||
32 | { | ||
33 | } | ||
34 | |||
35 | template <typename DomainType> | ||
36 | LocalStorageFacade<DomainType>::~LocalStorageFacade() | ||
37 | { | ||
38 | } | ||
39 | |||
40 | template <typename DomainType> | ||
41 | typename 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 | |||
52 | template <typename DomainType> | ||
53 | KAsync::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 | |||
76 | template <typename DomainType> | ||
77 | KAsync::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 | |||
102 | template <typename DomainType> | ||
103 | KAsync::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 | |||
116 | template <typename DomainType> | ||
117 | QPair<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 | |||
27 | ResourceFacade::ResourceFacade(const QByteArray &) : Sink::StoreFacade<Sink::ApplicationDomain::SinkResource>() | 157 | ResourceFacade::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 | ||
148 | Q_GLOBAL_STATIC(ConfigNotifier, sConfig); | 278 | AccountFacade::AccountFacade(const QByteArray &) : LocalStorageFacade<Sink::ApplicationDomain::SinkAccount>("accounts") |
149 | |||
150 | static 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 | |||
163 | AccountFacade::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 | ||
171 | KAsync::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 | |||
194 | KAsync::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 | |||
219 | KAsync::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 | |||
232 | QPair<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 | } | ||