6 #ifndef SWIFT_MISC_DB_DATABASEOBJECTLIST_H
7 #define SWIFT_MISC_DB_DATABASEOBJECTLIST_H
20 namespace swift::misc::db
25 template <
class OBJ,
class CONTAINER,
typename KEYTYPE>
28 static constexpr
bool hasIntegerKey =
29 std::is_base_of_v<IDatastoreObjectWithIntegerKey, OBJ> && std::is_same_v<int, KEYTYPE>;
30 static constexpr
bool hasStringKey =
31 std::is_base_of_v<IDatastoreObjectWithStringKey, OBJ> && std::is_base_of_v<QString, KEYTYPE>;
32 static_assert(hasIntegerKey || hasStringKey,
33 "ObjectType needs to implement IDatastoreObjectWithXXXXKey and have appropriate KeyType");
37 OBJ
findByKey(KEYTYPE key,
const OBJ ¬Found = OBJ())
const
39 return this->
container().findFirstByOrDefault(&OBJ::getDbKey, key, notFound);
46 if (keys.isEmpty()) {
return objects; }
49 if (!keys.contains(obj.getDbKey())) {
continue; }
50 objects.push_back(obj);
61 if (!obj.hasValidDbKey()) {
continue; }
62 objects.push_back(obj);
73 if (obj.hasValidDbKey()) {
continue; }
74 objects.push_back(obj);
82 if (this->
container().isEmpty()) {
return OBJ(); }
84 [](
const OBJ &obj1,
const OBJ &obj2) {
85 bool v1 = obj1.hasValidDbKey();
86 bool v2 = obj2.hasValidDbKey();
87 if (v1 && v2) {
return obj1.getDbKey() < obj2.getDbKey(); }
102 if (!obj.hasValidDbKey()) {
continue; }
103 keys.
insert(obj.getDbKey());
114 if (!obj.hasValidDbKey()) {
continue; }
115 map.
insert(obj.getDbKey(), obj);
126 if (!obj.hasValidDbKey()) {
continue; }
127 keys.
insert(obj.getDbKeyAsString());
138 for (
const QString &k : keys)
140 if (s.isEmpty()) { s += k; }
141 else { s += separator + k; }
152 if (ok) { *ok =
false; }
155 KEYTYPE max = *std::max_element(keys.begin(), keys.end());
156 if (ok) { *ok =
true; }
163 if (keys.isEmpty()) {
return 0; }
164 if (this->
container().isEmpty()) {
return 0; }
168 if (keys.contains(obj.getDbKey())) {
continue; }
169 newValues.push_back(obj);
171 const int delta = this->
container().size() - newValues.size();
172 if (delta > 0) { this->
container() = newValues; }
179 if (this->
container().isEmpty()) {
return 0; }
183 if (!obj.hasValidDbKey()) {
continue; }
184 newValues.push_back(obj);
186 int delta = this->
container().size() - newValues.size();
201 const QSet<KEYTYPE> keys(
container.toDbKeySet());
202 newValues.removeObjectsWithKeys(keys);
203 int removeSize = newValues.size();
206 return newValues.size() - removeSize;
213 objs.removeObjectsWithoutDbKey();
214 if (objs.isEmpty()) {
return QDateTime(); }
215 return objs.latestTimestamp();
222 objs.removeObjectsWithoutDbKey();
223 if (objs.isEmpty()) {
return QDateTime(); }
224 return objs.oldestDbTimestamp();
233 if (obj.hasValidDbKey() && withKey) { count++; }
246 if (!obj.hasValidDbKey()) {
return true; }
256 if (!obj.hasValidDbKey()) {
continue; }
257 if (obj.getDbKey() == key) {
return true; }
267 if (jsonObject.isEmpty())
274 if (json::looksLikeSwiftDataObjectJson(jsonObject))
276 const QJsonObject cacheObj = json::swiftDataObjectValue(jsonObject);
278 private_ns::CValueObjectMetaInfoHelper::convertFromMemoizedJson(
284 if (json::looksLikeSwiftContainerJson(jsonObject))
292 if (json::looksLikeSwiftTypeValuePairJson(jsonObject))
294 const QJsonObject valueObject = jsonObject.value(
"value").toObject();
296 private_ns::CValueObjectMetaInfoHelper::convertFromMemoizedJson(
302 if (jsonObject.contains(
"data"))
316 if (jsonString.isEmpty())
331 for (
const QJsonValue &value : array) {
container.push_back(OBJ::fromDatabaseJson(value.toObject())); }
340 for (
const QJsonValue &value : array)
342 container.push_back(OBJ::fromDatabaseJson(value.toObject(), prefix));
Thrown when a convertFromJson method encounters an unrecoverable error in JSON data.
Build a QMap more efficiently when calling insert() in a for loop.
void insert(Ts &&...keyAndValue)
Add an key/value pair to the map. Runs in amortized constant time.
Build a QSet more efficiently when calling insert() in a for loop.
void insert(const T &value)
Add an element to the set. Runs in amortized constant time.
List of objects with timestamp. Such objects should implement.
const CONTAINER & container() const
Container.
List of objects read from database. Such objects should implement.
int replaceOrAddObjectsByKey(const CONTAINER &container)
Update or insert data (based on DB key)
void sortByKey()
Sort by timestamp.
QDateTime oldestDbTimestamp() const
Latest DB timestamp (means objects with DB key)
QSet< QString > toDbKeyStringSet() const
All keys as string set (also integer keys will be converted to string)
int removeObjectsWithKeys(const QSet< KEYTYPE > &keys)
Remove objects with keys.
int removeObjectsWithoutDbKey()
Remove objects without key.
OBJ findByKey(KEYTYPE key, const OBJ ¬Found=OBJ()) const
Object with key, notFound otherwise.
static CONTAINER fromDatabaseJson(const QJsonArray &array, const QString &prefix)
From DB JSON.
OBJ maxKeyObject() const
Object with max.key.
KEYTYPE getMaxKey(bool *ok=nullptr) const
Max.key value (making sense with integer key)
QDateTime latestDbTimestamp() const
Latest DB timestamp (means objects with DB key)
QMap< KEYTYPE, OBJ > toDbKeyValueMap() const
As map with DB key/object.
static CONTAINER fromDatabaseJson(const QJsonArray &array)
From DB JSON with default prefixes.
QSet< KEYTYPE > toDbKeySet() const
All keys as set.
QString dbKeysAsString(const QString &separator) const
The DB keys as string.
IDatastoreObjectList()=default
Constructor.
static CONTAINER fromMultipleJsonFormats(const QJsonObject &jsonObject)
From multiple JSON formats.
int countWithValidDbKey() const
Number of entries with valid DB key.
CONTAINER findObjectsWithoutDbKey() const
Objects without DB key.
CONTAINER findByKeys(const QSet< KEYTYPE > &keys) const
Object with key, notFound otherwise.
static CONTAINER fromMultipleJsonFormats(const QString &jsonString)
From multiple JSON formats.
bool containsAnyObjectWithoutKey() const
Any object without key?
int countWithValidDbKey(bool withKey) const
Number of objects with/without key.
bool containsDbKey(KEYTYPE key) const
Contains object with key?
CONTAINER findObjectsWithDbKey() const
Objects with DB key.
QJsonObject jsonObjectFromString(const QString &json, bool acceptCacheFormat)
JSON Object from string.
auto MemberLess(Ts... vs)
Predicate which compares the return values of some member functions of two objects.
T::const_iterator begin(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
T::const_iterator end(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.