mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-01-02 02:48:51 -05:00
277 lines
9.6 KiB
C++
277 lines
9.6 KiB
C++
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
|
|
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
|
|
|
|
#include "NotificationsRecord.hpp"
|
|
#include "module-db/queries/notifications/QueryNotificationsGet.hpp"
|
|
#include "module-db/queries/notifications/QueryNotificationsIncrement.hpp"
|
|
#include "module-db/queries/notifications/QueryNotificationsDecrement.hpp"
|
|
#include "module-db/queries/notifications/QueryNotificationsMultipleIncrement.hpp"
|
|
#include "module-db/queries/notifications/QueryNotificationsClear.hpp"
|
|
#include "module-db/queries/notifications/QueryNotificationsGetAll.hpp"
|
|
#include "module-db/databases/NotificationsDB.hpp"
|
|
|
|
#include <log/log.hpp>
|
|
#include <Utils.hpp>
|
|
|
|
#include <cassert>
|
|
#include <vector>
|
|
#include <gsl/assert>
|
|
|
|
NotificationsRecord::NotificationsRecord(const NotificationsTableRow &tableRow, std::optional<ContactRecord> record)
|
|
: Record{tableRow.ID}, value{tableRow.value}, contactRecord{std::move(record)}
|
|
{
|
|
if (tableRow.key > static_cast<uint32_t>(Key::NotValidKey) &&
|
|
tableRow.key < static_cast<uint32_t>(Key::NumberOfKeys)) {
|
|
key = static_cast<Key>(tableRow.key);
|
|
return;
|
|
}
|
|
LOG_ERROR("Invalid record");
|
|
key = Key::NotValidKey;
|
|
ID = DB_ID_NONE;
|
|
}
|
|
|
|
bool NotificationsRecord::isValidKey(Key key)
|
|
{
|
|
return key != Key::NotValidKey && key != Key::NumberOfKeys;
|
|
}
|
|
|
|
std::ostream &operator<<(std::ostream &out, const NotificationsRecord &rec)
|
|
{
|
|
out << " <id> " << rec.ID << " <key> " << static_cast<int>(rec.key) << " <value> " << rec.value;
|
|
if (rec.contactRecord.has_value()) {
|
|
out << " <contact_id> " << rec.contactRecord.value().ID;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
NotificationsRecordInterface::NotificationsRecordInterface(NotificationsDB *notificationsDb,
|
|
ContactRecordInterface *contactsDb)
|
|
: notificationsDb(notificationsDb), contactsDb(contactsDb)
|
|
{
|
|
Expects(contactsDb != nullptr);
|
|
}
|
|
|
|
bool NotificationsRecordInterface::Add(const NotificationsRecord &rec)
|
|
{
|
|
assert(0 && "Not implemented");
|
|
|
|
return false;
|
|
}
|
|
|
|
std::unique_ptr<std::vector<NotificationsRecord>> NotificationsRecordInterface::GetLimitOffsetByField(
|
|
uint32_t offset, uint32_t limit, NotificationsRecordField field, const char *str)
|
|
{
|
|
assert(0 && "Not implemented");
|
|
|
|
return GetLimitOffset(offset, limit);
|
|
}
|
|
|
|
std::unique_ptr<std::vector<NotificationsRecord>> NotificationsRecordInterface::GetLimitOffset(uint32_t offset,
|
|
uint32_t limit)
|
|
{
|
|
if (limit == 0) {
|
|
limit = GetCount();
|
|
}
|
|
|
|
auto rows = notificationsDb->notifications.getLimitOffset(offset, limit);
|
|
|
|
auto records = std::make_unique<std::vector<NotificationsRecord>>();
|
|
|
|
for (auto &r : rows) {
|
|
records->push_back(NotificationsRecord{r, getContactRecord(r.contactID)});
|
|
}
|
|
|
|
return records;
|
|
}
|
|
|
|
bool NotificationsRecordInterface::Update(const NotificationsRecord &rec)
|
|
{
|
|
auto entry = notificationsDb->notifications.getById(rec.ID);
|
|
if (!entry.isValid() || entry.key != static_cast<uint32_t>(rec.key)) {
|
|
return false;
|
|
}
|
|
|
|
uint32_t contactId = rec.contactRecord.has_value() ? rec.contactRecord.value().ID : DB_ID_NONE;
|
|
|
|
return notificationsDb->notifications.update(NotificationsTableRow{
|
|
Record(rec.ID), .key = static_cast<uint32_t>(rec.key), .value = rec.value, .contactID = contactId});
|
|
}
|
|
|
|
bool NotificationsRecordInterface::RemoveByID(uint32_t id)
|
|
{
|
|
assert(0 && "Not implemented");
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NotificationsRecordInterface::RemoveByField(NotificationsRecordField field, const char *str)
|
|
{
|
|
assert(0 && "Not implemented");
|
|
|
|
return false;
|
|
}
|
|
std::optional<ContactRecord> NotificationsRecordInterface::getContactRecord(uint32_t id) const
|
|
{
|
|
if (id != DB_ID_NONE) {
|
|
if (auto contactRecord = contactsDb->GetByIdWithTemporary(id); contactRecord.isValid()) {
|
|
return std::make_optional(std::move(contactRecord));
|
|
}
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
|
|
NotificationsRecord NotificationsRecordInterface::GetByID(uint32_t id)
|
|
{
|
|
auto tableRow = notificationsDb->notifications.getById(id);
|
|
return NotificationsRecord{tableRow, getContactRecord(tableRow.contactID)};
|
|
}
|
|
|
|
uint32_t NotificationsRecordInterface::GetCount()
|
|
{
|
|
return notificationsDb->notifications.count();
|
|
}
|
|
|
|
NotificationsRecord NotificationsRecordInterface::GetByKey(NotificationsRecord::Key key)
|
|
{
|
|
if (!NotificationsRecord::isValidKey(key)) {
|
|
return NotificationsRecord();
|
|
}
|
|
|
|
auto tableRow = notificationsDb->notifications.getByKey(static_cast<uint32_t>(key));
|
|
return NotificationsRecord{tableRow, getContactRecord(tableRow.contactID)};
|
|
}
|
|
|
|
std::unique_ptr<db::QueryResult> NotificationsRecordInterface::runQuery(std::shared_ptr<db::Query> query)
|
|
{
|
|
if (const auto local_query = dynamic_cast<const db::query::notifications::Get *>(query.get())) {
|
|
return runQueryImpl(local_query);
|
|
}
|
|
if (const auto local_query = dynamic_cast<const db::query::notifications::Increment *>(query.get())) {
|
|
return runQueryImpl(local_query);
|
|
}
|
|
if (const auto local_query = dynamic_cast<const db::query::notifications::Decrement *>(query.get())) {
|
|
return runQueryImpl(local_query);
|
|
}
|
|
if (const auto local_query = dynamic_cast<const db::query::notifications::MultipleIncrement *>(query.get())) {
|
|
return runQueryImpl(local_query);
|
|
}
|
|
if (const auto local_query = dynamic_cast<const db::query::notifications::Clear *>(query.get())) {
|
|
return runQueryImpl(local_query);
|
|
}
|
|
if (const auto local_query = dynamic_cast<const db::query::notifications::GetAll *>(query.get())) {
|
|
return runQueryImpl(local_query);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<db::query::notifications::GetResult> NotificationsRecordInterface::runQueryImpl(
|
|
const db::query::notifications::Get *query)
|
|
{
|
|
auto value = GetByKey(query->getKey());
|
|
return std::make_unique<db::query::notifications::GetResult>(std::move(value));
|
|
}
|
|
|
|
std::unique_ptr<db::query::notifications::IncrementResult> NotificationsRecordInterface::runQueryImpl(
|
|
const db::query::notifications::Increment *query)
|
|
{
|
|
auto ret = processIncrement(query->getKey(), query->getNumber(), 1);
|
|
|
|
return std::make_unique<db::query::notifications::IncrementResult>(ret);
|
|
}
|
|
|
|
std::unique_ptr<db::query::notifications::DecrementResult> NotificationsRecordInterface::runQueryImpl(
|
|
const db::query::notifications::Decrement *query)
|
|
{
|
|
auto ret = processDecrement(query->getKey(), query->getCount());
|
|
|
|
return std::make_unique<db::query::notifications::DecrementResult>(ret);
|
|
}
|
|
|
|
std::unique_ptr<db::query::notifications::MultipleIncrementResult> NotificationsRecordInterface::runQueryImpl(
|
|
const db::query::notifications::MultipleIncrement *query)
|
|
{
|
|
auto ret = false;
|
|
const auto &numbers = query->getNumbers();
|
|
std::optional<utils::PhoneNumber::View> number;
|
|
|
|
if (!numbers.empty()) {
|
|
if (all_of(numbers.begin(), numbers.end(), [&](const auto &number) { return number == numbers.at(0); })) {
|
|
number = std::make_optional(numbers.at(0));
|
|
}
|
|
|
|
ret = processIncrement(query->getKey(), std::move(number), numbers.size());
|
|
}
|
|
return std::make_unique<db::query::notifications::MultipleIncrementResult>(ret);
|
|
}
|
|
|
|
std::unique_ptr<db::query::notifications::ClearResult> NotificationsRecordInterface::runQueryImpl(
|
|
const db::query::notifications::Clear *query)
|
|
{
|
|
auto ret = false;
|
|
if (auto record = GetByKey(query->getKey()); record.isValid()) {
|
|
record.value = 0;
|
|
record.contactRecord.reset();
|
|
ret = Update(record);
|
|
}
|
|
return std::make_unique<db::query::notifications::ClearResult>(ret);
|
|
}
|
|
|
|
std::unique_ptr<db::query::notifications::GetAllResult> NotificationsRecordInterface::runQueryImpl(
|
|
const db::query::notifications::GetAll *query)
|
|
{
|
|
auto numberOfNotifications = GetCount();
|
|
auto records = GetLimitOffset(0, numberOfNotifications);
|
|
return std::make_unique<db::query::notifications::GetAllResult>(std::move(records));
|
|
}
|
|
|
|
bool NotificationsRecordInterface::processIncrement(NotificationsRecord::Key key,
|
|
std::optional<utils::PhoneNumber::View> &&number,
|
|
size_t size)
|
|
{
|
|
auto ret = false;
|
|
|
|
if (auto record = GetByKey(key); record.isValid() && number.has_value()) {
|
|
auto ¤tContactRecord = record.contactRecord;
|
|
if (size == 1) {
|
|
if (auto numberMatch = contactsDb->MatchByNumber(number.value()); numberMatch.has_value()) {
|
|
if (record.value == 0) {
|
|
currentContactRecord = std::move(numberMatch.value().contact);
|
|
}
|
|
else if (currentContactRecord.has_value() &&
|
|
numberMatch.value().contactId != currentContactRecord.value().ID) {
|
|
currentContactRecord.reset();
|
|
}
|
|
}
|
|
else {
|
|
currentContactRecord.reset();
|
|
}
|
|
}
|
|
else if (size > 1) {
|
|
currentContactRecord.reset();
|
|
}
|
|
record.value += size;
|
|
ret = Update(record);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool NotificationsRecordInterface::processDecrement(NotificationsRecord::Key key, size_t delta)
|
|
{
|
|
auto ret = false;
|
|
|
|
if (auto record = GetByKey(key); record.isValid() && record.value > 0) {
|
|
if (delta >= record.value) {
|
|
record.contactRecord.reset();
|
|
record.value = 0;
|
|
}
|
|
else {
|
|
record.value -= delta;
|
|
}
|
|
|
|
ret = Update(record);
|
|
}
|
|
|
|
return ret;
|
|
}
|