This repository was archived by the owner on Mar 4, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathdatastore.h
360 lines (310 loc) · 10.5 KB
/
datastore.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
#ifndef QTDATASYNC_DATASTORE_H
#define QTDATASYNC_DATASTORE_H
#include <functional>
#include <QtCore/qobject.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qvariant.h>
#include "QtDataSync/qtdatasync_global.h"
#include "QtDataSync/objectkey.h"
#include "QtDataSync/exception.h"
#include "QtDataSync/qtdatasync_helpertypes.h"
namespace QtDataSync {
class Defaults;
class DataStorePrivate;
//! Main store to generically access all stored data synchronously
class Q_DATASYNC_EXPORT DataStore : public QObject
{
Q_OBJECT
friend class DataStoreModel;
public:
//! Possible pattern modes for the search mechanism
enum SearchMode
{
RegexpMode, //!< Interpret the search string as a regular expression. See QRegularExpression
WildcardMode, //!< Interpret the search string as a wildcard string (with * and ?)
ContainsMode, //!< The data key must contain the search string
StartsWithMode, //!< The data key must start with the search string
EndsWithMode //!< The data key must end with the search string
};
Q_ENUM(SearchMode)
//! Default constructor, uses the default setup
explicit DataStore(QObject *parent = nullptr);
//! Constructor with an explicit setup
explicit DataStore(const QString &setupName, QObject *parent = nullptr);
~DataStore() override;
//! Returns the name of the setup this class operates on
QString setupName() const;
//! @copybrief DataStore::count() const
qint64 count(int metaTypeId) const;
//! @copybrief DataStore::keys() const
QStringList keys(int metaTypeId) const;
//! @copybrief DataStore::loadAll() const
QVariantList loadAll(int metaTypeId) const;
//! @copybrief DataStore::contains(const QString &) const
bool contains(int metaTypeId, const QString &key) const;
//! @copybrief DataStore::contains(const QString &) const
inline bool contains(int metaTypeId, const QVariant &key) const {
return contains(metaTypeId, key.toString());
}
//! @copybrief DataStore::load(const QString &) const
QVariant load(int metaTypeId, const QString &key) const;
//! @copybrief DataStore::load(int, const QString &) const
inline QVariant load(int metaTypeId, const QVariant &key) const {
return load(metaTypeId, key.toString());
}
//! @copybrief DataStore::save(const T &)
void save(int metaTypeId, QVariant value);
//! @copybrief DataStore::remove(const QString &)
bool remove(int metaTypeId, const QString &key);
//! @copybrief DataStore::remove(int, const QString &)
inline bool remove(int metaTypeId, const QVariant &key) {
return remove(metaTypeId, key.toString());
}
//! @copybrief DataStore::update(T) const
void update(int metaTypeId, QObject *object) const;
//! @copybrief DataStore::search(const QString &, SearchMode) const
QVariantList search(int metaTypeId, const QString &query, SearchMode mode = RegexpMode) const;
//! @copybrief DataStore::iterate(const std::function<bool(T)> &, bool) const
void iterate(int metaTypeId,
const std::function<bool(QVariant)> &iterator) const;
//! @copybrief DataStore::iterate(const std::function<bool(T)> &, bool) const
void iterate(int metaTypeId,
const std::function<bool(QVariant)> &iterator,
bool skipBroken) const; //MAJOR merge overloads
//! @copybrief DataStore::clear()
void clear(int metaTypeId);
//! Counts the number of datasets for the given type
template<typename T>
quint64 count() const;
//! Returns all saved keys for the given type
template<typename T>
QStringList keys() const;
/*! @copybrief DataStore::keys() const
* @tparam K The type of the key to be returned as list
* @copydetails DataStore::keys() const
* @note The given type K must be convertible from a QString
*/
template<typename T, typename K>
QList<K> keys() const;
//! Loads all existing datasets for the given type
template<typename T>
QList<T> loadAll() const;
//! Checks if a dataset exists in the store for the given key
template<typename T>
bool contains(const QString &key) const;
//! @copybrief DataStore::contains(const QString &) const
template<typename T, typename K>
bool contains(const K &key) const;
//! Loads the dataset with the given key for the given type
template<typename T>
T load(const QString &key) const;
//! @copybrief DataStore::load(const QString &) const
template<typename T, typename K>
T load(const K &key) const;
//! Saves the given dataset in the store
template<typename T>
void save(const T &value);
//! Removes the dataset with the given key for the given type
template<typename T>
bool remove(const QString &key);
//! @copybrief DataStore::remove(const QString &)
template<typename T, typename K>
bool remove(const K &key);
//! Loads the dataset with the given key for the given type into the existing object by updating it's properties
template<typename T>
void update(T object) const;
//! Searches the store for datasets of the given type where the key matches the query
template<typename T>
QList<T> search(const QString &query, SearchMode mode = RegexpMode) const;
//! Iterates over all existing datasets of the given types
template<typename T>
void iterate(const std::function<bool(T)> &iterator, bool skipBroken = false) const;
//! Removes all datasets of the given type from the store
template<typename T>
void clear();
Q_SIGNALS:
//! Is emitted whenever a dataset has been changed
void dataChanged(int metaTypeId, const QString &key, bool deleted, QPrivateSignal);
//! Is emitted when a datatypes has been cleared
Q_DECL_DEPRECATED void dataCleared(int metaTypeId, QPrivateSignal);
//! Is emitted when the store is resetted due to an account reset
void dataResetted(QPrivateSignal);
protected:
//! @private
explicit DataStore(QObject *parent, void*);
//! @private
void initStore(const QString &setupName);
private:
QScopedPointer<DataStorePrivate> d;
};
//! Exception that is thrown from DataStore operations in case of an error
class Q_DATASYNC_EXPORT DataStoreException : public Exception
{
protected:
//! @private
DataStoreException(const Defaults &defaults, const QString &message);
//! @private
DataStoreException(const DataStoreException * const other);
};
//! Exception that is thrown when an internal (critical) error occurs
class Q_DATASYNC_EXPORT LocalStoreException : public DataStoreException
{
public:
//! @private
LocalStoreException(const Defaults &defaults, const ObjectKey &key, const QString &context, const QString &message);
//! The object key of the dataset that triggered the error
ObjectKey key() const;
//! The context in which the error occured
QString context() const;
QByteArray className() const noexcept override;
QString qWhat() const override;
void raise() const override;
QException *clone() const override;
protected:
//! @private
LocalStoreException(const LocalStoreException * const other);
//! @private
ObjectKey _key;
//! @private
QString _context;
};
//! Exception that is thrown in case no data can be found for a key
class Q_DATASYNC_EXPORT NoDataException : public DataStoreException
{
public:
//! @private
NoDataException(const Defaults &defaults, const ObjectKey &key);
//! The object key of the dataset that does not exist
ObjectKey key() const;
QByteArray className() const noexcept override;
QString qWhat() const override;
void raise() const override;
QException *clone() const override;
protected:
//! @private
NoDataException(const NoDataException * const other);
//! @private
ObjectKey _key;
};
//! Exception that is thrown when unsaveable/unloadable data is passed to the store
class Q_DATASYNC_EXPORT InvalidDataException : public DataStoreException
{
public:
//! @private
InvalidDataException(const Defaults &defaults, const QByteArray &typeName, const QString &message);
//! The name of the type that cannot be saved/loaded
QByteArray typeName() const;
QByteArray className() const noexcept override;
QString qWhat() const override;
void raise() const override;
QException *clone() const override;
protected:
//! @private
InvalidDataException(const InvalidDataException * const other);
//! @private
QByteArray _typeName;
};
// ------------- GENERIC IMPLEMENTATION -------------
template<typename T>
quint64 DataStore::count() const
{
QTDATASYNC_STORE_ASSERT(T);
return count(qMetaTypeId<T>());
}
template<typename T>
QStringList DataStore::keys() const
{
QTDATASYNC_STORE_ASSERT(T);
return keys(qMetaTypeId<T>());
}
template<typename T, typename K>
QList<K> DataStore::keys() const
{
QTDATASYNC_STORE_ASSERT(T);
QList<K> rList;
for(auto k : keys<T>())
rList.append(QVariant(k).template value<K>());
return rList;
}
template<typename T>
QList<T> DataStore::loadAll() const
{
QTDATASYNC_STORE_ASSERT(T);
QList<T> rList;
for(auto v : loadAll(qMetaTypeId<T>()))
rList.append(v.template value<T>());
return rList;
}
template<typename T>
bool DataStore::contains(const QString &key) const
{
QTDATASYNC_STORE_ASSERT(T);
return contains(qMetaTypeId<T>(), key);
}
template<typename T, typename K>
bool DataStore::contains(const K &key) const
{
QTDATASYNC_STORE_ASSERT(T);
return contains(qMetaTypeId<T>(), QVariant::fromValue(key));
}
template<typename T>
T DataStore::load(const QString &key) const
{
QTDATASYNC_STORE_ASSERT(T);
return load(qMetaTypeId<T>(), key).template value<T>();
}
template<typename T, typename K>
T DataStore::load(const K &key) const
{
QTDATASYNC_STORE_ASSERT(T);
return load(qMetaTypeId<T>(), QVariant::fromValue(key)).template value<T>();
}
template<typename T>
void DataStore::save(const T &value)
{
QTDATASYNC_STORE_ASSERT(T);
save(qMetaTypeId<T>(), QVariant::fromValue(value));
}
template<typename T>
bool DataStore::remove(const QString &key)
{
QTDATASYNC_STORE_ASSERT(T);
return remove(qMetaTypeId<T>(), key);
}
template<typename T, typename K>
bool DataStore::remove(const K &key)
{
QTDATASYNC_STORE_ASSERT(T);
return remove(qMetaTypeId<T>(), QVariant::fromValue(key));
}
template<typename T>
void DataStore::update(T object) const
{
static_assert(__helpertypes::is_object<T>::value, "loadInto can only be used for pointers to QObject extending classes");
update(qMetaTypeId<T>(), object);
}
template<typename T>
QList<T> DataStore::search(const QString &query, SearchMode mode) const
{
QTDATASYNC_STORE_ASSERT(T);
QList<T> rList;
for(auto v : search(qMetaTypeId<T>(), query, mode))
rList.append(v.template value<T>());
return rList;
}
template<typename T>
void DataStore::iterate(const std::function<bool (T)> &iterator, bool skipBroken) const
{
QTDATASYNC_STORE_ASSERT(T);
iterate(qMetaTypeId<T>(), [iterator](const QVariant &v) {
return iterator(v.template value<T>());
}, skipBroken);
}
template<typename T>
void DataStore::clear()
{
QTDATASYNC_STORE_ASSERT(T);
clear(qMetaTypeId<T>());
}
}
#endif // QTDATASYNC_DATASTORE_H