/** * Handler for all notification objects * $Id$ * $HeadURL$ * $Author$ * Created by Hanna E. Rathje, ESZS, 2025-06-23 */ #include "handler_notification.h" #include "object_notification.h" #include "dds_handler.h" #include "settings.h" #include namespace NotificationManagement { HandlerNotification::HandlerNotification(const std::shared_ptr &ddsHandler, const std::shared_ptr &db) : Interface::Fts::CreateNotificationRequestHandler(ddsHandler->fts()) , Interface::Fts::ReadReceiptRequestHandler(ddsHandler->fts()) , Interface::Fts::DeleteMessageRequestHandler(ddsHandler->fts()) , m_removeNotificationTimer(new QTimer()) , m_ddsHandler(ddsHandler) , m_db(db) , m_logger(getLogger("HandlerNotification")) { } // end of ctor() //----------------------------------------------------------------------------- HandlerNotification::~HandlerNotification() { qDeleteAll(m_objectNotificationMap); } // end of dtor() //----------------------------------------------------------------------------- bool HandlerNotification::init() { INFO_LOG(m_logger) << "--- Start NotificationManagement HandlerNotification."; QVector dataAddressVec; // read all addresses from database if (!m_db->select(dataAddressVec)) { ERROR_LOG(m_logger) << "Error reading address data from database!"; return false; } // create NotificationObjects bool bRet = true; QList removeNotificationIds; auto cb = [this, &bRet, &dataAddressVec, &removeNotificationIds] (const Database::NomNotification &dbNotif) { static NomNotification notif = ObjectNotification::toDdsData(dbNotif); // Remove old notifications if (isRemoveable(notif)) { INFO_LOG(m_logger) << "Remove old notification " << notif.title() << ", id = " << notif.id(); removeNotificationIds.append(notif.id()); return; } // alle Addressen zu der NomNotification eintragen for (const Database::NomAddress &addr : qAsConst(dataAddressVec)) { if (addr.notificationId == notif.id()) { if (addr.isSender) notif.sender(ObjectNotification::toDdsData(addr)); else notif.recipientIds().push_back(ObjectNotification::toDdsData(addr)); } } ObjectNotification *ifs(new ObjectNotification(m_ddsHandler, m_db)); Core::FunctionReplyObject ret = ifs->createObject(notif); if (ret.error()) { delete ifs; ERROR_LOG(m_logger) << ret(); bRet = false; return; } m_objectNotificationMap.insert(ifs->id(), ifs); }; if (!m_db->select(cb) || !bRet) { ERROR_LOG(m_logger) << "Error reading data from database!"; return false; } // Remove old notifications here - not possible in select DBTransaction trans(m_db->database()); for (int notificationId : removeNotificationIds) m_db->removeNomNotification(notificationId); trans.commit(); DEBUG_LOG(m_logger) << "m_objectNotificationMap.size() = " << m_objectNotificationMap.size(); if (!m_ddsHandler->fts()) { ERROR_LOG(m_logger) << "m_ddsHandler->fts() == nullptr!"; return false; } // ExerciseChanged for removing notifications connect(m_ddsHandler->dtcExm().get(), &ExerciseManagement::Interface::Dtc::exerciseChanged, this, &HandlerNotification::onExerciseChanged); // Setup removeNotificaitonTimer m_removeNotificationTimer->setTimerType(Qt::TimerType::VeryCoarseTimer); // Check every 10 seconds (default) m_removeNotificationTimer->setInterval(Settings::removeTimerIntervalMSec()); connect(m_removeNotificationTimer, &QTimer::timeout, this, &HandlerNotification::onCheckRemove); m_removeNotificationTimer->start(); DEBUG_LOG(m_logger) << "removeTimerInterval: " << Settings::removeTimerIntervalMSec(); DEBUG_LOG(m_logger) << "expiryTime: " << Settings::expiryIntervalMSec(); return true; } // end of init() //----------------------------------------------------------------------------- void HandlerNotification::onCreateNotificationRequest(const rti::core::SampleIdentity &cookie, const CreateNotification &request) { DEBUG_LOG(m_logger) << "onCreateNotificationRequest: " << request; ObjectNotification *ifs(new ObjectNotification(m_ddsHandler, m_db)); const Core::FunctionReplyObject ret = ifs->createObject(request.notification()); if (ret.error()) { delete ifs; WARNING_LOG(m_logger) << ret(); m_ddsHandler->fts()->createNotificationReply(cookie, ret); return; } m_objectNotificationMap.insert(ifs->id(), ifs); m_ddsHandler->fts()->createNotificationReply(cookie, ret); } // end of onCreateNotificationRequest //----------------------------------------------------------------------------- void HandlerNotification::onReadReceiptRequest(const rti::core::SampleIdentity &cookie, const ReadReceipt &request) { DEBUG_LOG(m_logger) << "onReadReceiptRequest: " << request; Core::FunctionReplyObject ret; for (const auto notificationId : request.notificationIds()) { ObjectNotification *ifs = m_objectNotificationMap.value(notificationId); if (ifs == nullptr) { ret = Core::FunctionReplyObject(notificationId, tr_lts("dds", "NomNotification with id %1 not found")).arg(notificationId); m_ddsHandler->fts()->readReceiptReply(cookie, ret); return; } ret = ifs->readReceipt(request, notificationId); } m_ddsHandler->fts()->readReceiptReply(cookie, ret); } void HandlerNotification::onDeleteMessageRequest(const rti::core::SampleIdentity &cookie, const DeleteMessage &request) { DEBUG_LOG(m_logger) << "onDeleteMessageRequest: " << request; Core::FunctionReplyObject ret; for (const auto notificationId : request.notificationIds()) { ObjectNotification *ifs = m_objectNotificationMap.value(notificationId); if (ifs == nullptr) { ret = Core::FunctionReplyObject(notificationId, tr_lts("dds", "NomNotification with id %1 not found")).arg(notificationId); m_ddsHandler->fts()->deleteMessageReply(cookie, ret); return; } ret = ifs->deleteObject(request, notificationId); } m_ddsHandler->fts()->deleteMessageReply(cookie, ret); } void HandlerNotification::onExerciseChanged(const ExerciseManagement::Exercise &data, DataModification modType) { if (modType == DataModification::eAdded || (modType == DataModification::eModified && data.state() != ExerciseManagement::ExerciseState::Stopped)) return; // Remove notification for given exercise QHashIterator it(m_objectNotificationMap); while(it.hasNext()) { it.next(); ObjectNotification* obj = it.value(); if (obj->notification().exerciseId() != data.id()) continue; DEBUG_LOG(m_logger) << "Remove notification " << obj->id(); Core::FunctionReplyObject ret = obj->removeObject(); if (ret.error()) ERROR_LOG(m_logger) << ret(); else { // delete ObjectNotification delete obj; m_objectNotificationMap.remove(it.key()); } } } void HandlerNotification::onCheckRemove() { QHashIterator it(m_objectNotificationMap); while(it.hasNext()) { it.next(); ObjectNotification* obj = it.value(); NomNotification notif = obj->notification(); if (!isRemoveable(notif)) continue; DEBUG_LOG(m_logger) << "Remove notification " << obj->id(); Core::FunctionReplyObject ret = obj->removeObject(); if (ret.error()) ERROR_LOG(m_logger) << ret(); else { // delete ObjectNotification delete obj; m_objectNotificationMap.remove(it.key()); } } } bool HandlerNotification::isRemoveable(const NomNotification ¬if) { // NomNotification from exercises will not be removed if (notif.exerciseId() != 0) return false; qint64 expiryInterval = Settings::expiryIntervalMSec(); qint64 currentTime = QDateTime::currentMSecsSinceEpoch(); // Remove notification if expiryTime + expiryInterval / processTime + expiryInterval if (currentTime > ( notif.expiryTime() + expiryInterval) || (notif.processed() > 0 && currentTime > ( notif.processTime() + expiryInterval))) return true; return false; } } // namespace NotificationManagement