/** * NomNotification object * $Id$ * $HeadURL$ * $Author$ * Created by Hanna E. Rathje, ESZS, 2025-06-23 */ #include "object_notification.h" #include "dds_handler.h" #include #include #include #include namespace NotificationManagement { const QString TRANSLATION_ARGS = QStringLiteral("translationsArgs"); const QString CONTENT_ID = QStringLiteral("id"); const QString CONTENT_ARG = QStringLiteral("contentArg"); ObjectNotification::ObjectNotification(const std::shared_ptr &ddsHandler, const std::shared_ptr &db) : m_ddsHandler(ddsHandler) , m_db(db) , m_logger(getLogger("ObjectNotification")) { } // end of ctor() //----------------------------------------------------------------------------- ObjectNotification::~ObjectNotification() { m_ddsHandler->dts()->removeNomNotificationByKey(m_dataNotificationObject.id); } // end of dtor() //----------------------------------------------------------------------------- Core::FunctionReplyObject ObjectNotification::createObject(const NomNotification &data) { m_dataNotificationObject = data; if (data.id <= 0) { Database::NomNotification dbDataNotification = toDbData(data); dbDataNotification.timeStamp = QDateTime::currentMSecsSinceEpoch(); DBTransaction trans(m_db->database()); if (!m_db->insert(dbDataNotification)) return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting NomNotification-data into database")); // Neue DB Id in lokale Struktur uebernehmen m_dataNotificationObject.id = dbDataNotification.id; DEBUG_LOG(m_logger) << "New NotificationId: " << dbDataNotification.id; DEBUG_LOG(m_logger) << "Handle Address for notificationId:" << dbDataNotification.id << " number of depending recipients: " << data.recipientIds.size(); // Behandlung von Recipients for (size_t i = 0; i < data.recipientIds.size(); ++i) { Address &recipientAddress = m_dataNotificationObject.recipientIds[i]; Database::NomAddress dbDataRecipientAddr = toDbData(recipientAddress); // Struct Address vorbereiten dbDataRecipientAddr.notificationId = dbDataNotification.id; // FK auf NotificationId dbDataRecipientAddr.id = 0; dbDataRecipientAddr.isRead = false; dbDataRecipientAddr.isSender = false; if (!m_db->insert(dbDataRecipientAddr)) return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting RecipientAddress-data into database")); // Neue DB Id in lokale Struktur uebernehmen recipientAddress.id = dbDataRecipientAddr.id; } Address &senderAddress = m_dataNotificationObject.sender; Database::NomAddress dbDataSenderAddr = toDbData(senderAddress); // Struct Address vorbereiten dbDataSenderAddr.notificationId = dbDataNotification.id; // FK auf NotificationId dbDataSenderAddr.isRead = false; dbDataSenderAddr.isSender = true; dbDataSenderAddr.id = 0; if (!m_db->insert(dbDataSenderAddr)) return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting SenderAddress-data into database")); // Neue DB Id in lokale Struktur uebernehmen senderAddress.id = dbDataSenderAddr.id; trans.commit(); } // Publish Data via DTS onPublishData(); return Core::FunctionReplyObject(m_dataNotificationObject.id); } // end of createObject() //----------------------------------------------------------------------------- QString ObjectNotification::contentArgsToJson() { int i = 1; QJsonArray jsonArray; for (const std::string& arg : qAsConst(m_dataNotificationObject.contentArgs)) { DEBUG_LOG(m_logger) << ".arg() ersetzt immer den kleinsten freien Platzhalter" << ", arg=" << arg; QJsonObject argObj; argObj[CONTENT_ID] = i; argObj[CONTENT_ARG] = QString::fromStdString(arg); jsonArray.append(argObj); i++; } QJsonObject mainObject; mainObject[TRANSLATION_ARGS] = jsonArray; QJsonDocument doc(mainObject); DEBUG_LOG(m_logger) << "ObjectNotification::contentArgsToJson properties=" << QString::fromUtf8(doc.toJson(QJsonDocument::Compact)); return QString::fromUtf8(doc.toJson(QJsonDocument::Compact)); } std::vector ObjectNotification::jsonToContentArgs(const QString &jsonString) { //DEBUG_LOG(m_logger) << "jsonToContentArgs jsonString=" << jsonString; std::vector result; // 1. String parsen QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8()); if (!doc.isObject()) { //WARNING_LOG(m_logger) << "properties: Invalid JSON-Object"; return result; } QJsonObject hauptObjekt = doc.object(); // 2. Das Array aus "translationsArgs" herausholen if (!hauptObjekt.contains(TRANSLATION_ARGS) || !hauptObjekt[TRANSLATION_ARGS].isArray()) { //WARNING_LOG(m_logger) << "Missing or invalid 'translationsArgs' key (must be an array)."; return result; } QJsonArray jsonArray = hauptObjekt[TRANSLATION_ARGS].toArray(); for ( int gesuchteId = 1; gesuchteId <= jsonArray.size(); gesuchteId++) { // 3. Für schnellen Zugriff nach ID indizieren QHash sucheMap; for (const QJsonValue &wert : qAsConst(jsonArray)) { QJsonObject obj = wert.toObject(); int id = obj[CONTENT_ID].toInt(); sucheMap[id] = obj; } // 4. Zugriff über die ID testen if (sucheMap.contains(gesuchteId)) { QJsonObject treffer = sucheMap[gesuchteId]; //DEBUG_LOG(m_logger) << "ID" << gesuchteId << "gefunden!"; //DEBUG_LOG(m_logger) << "Inhalt:" << treffer[CONTENT_ARG].toString(); QString contentStr = treffer[CONTENT_ARG].toString(); result.emplace_back(contentStr.toStdString()); } else { //qDebug() << "ID" << gesuchteId << "nicht im System."; } } return result; } Core::FunctionReplyObject ObjectNotification::readReceipt(const ReadReceipt &data, int notificationId) { if (!isValid()) return Core::FunctionReplyObject(notificationId, tr_lts("dds", "Object not valid/blocked")); Database::NomNotification dbDataNotification = toDbData(m_dataNotificationObject); Database::NomAddress dbDataAddr; for (const Address &recipientAddr : qAsConst(m_dataNotificationObject.recipientIds)) { if (data.operatorId > 0 && recipientAddr.addressType == AddressType::Operator && recipientAddr.addressId != data.operatorId) continue; if (data.workstationId > 0 && recipientAddr.addressType == AddressType::Workstation && recipientAddr.addressId != data.workstationId) continue; dbDataAddr = toDbData(recipientAddr); DEBUG_LOG(m_logger) << "Found Operator " << data.operatorId << " with repicpentID " << dbDataAddr.id; dbDataAddr.notificationId = dbDataNotification.id; break; } if (dbDataAddr.id <= 0) return Core::FunctionReplyObject(data.addressId, tr_lts("dds", "No Address found")); dbDataAddr.isRead = true; DBTransaction trans(m_db->database()); // NomNotification shall be marked as processed if (data.processed) { // but hasn't been so yet if (dbDataNotification.processed <= 0) { dbDataNotification.processed = dbDataAddr.id; dbDataNotification.processTime = QDateTime::currentMSecsSinceEpoch(); if (dbDataNotification.priorityId != dbDataNotification.processedPriority) dbDataNotification.priorityId = dbDataNotification.processedPriority; if (!m_db->update(dbDataNotification)) return Core::FunctionReplyObject(notificationId, tr_lts("dds", "Error updating notification-data")); } else { DEBUG_LOG(m_logger) << "Notification already processed id=" << notificationId; return Core::FunctionReplyObject(dbDataNotification.processed, {}, {}, tr_lts("dds", "Notification already processed")); } } if (!m_db->update(dbDataAddr)) return Core::FunctionReplyObject(dbDataAddr.id, tr_lts("dds", "Error updating address-data into database")); trans.commit(); INFO_LOG(m_logger) << "Data changed for NotificationId: " << m_dataNotificationObject.id; const std::vector
recipients = m_dataNotificationObject.recipientIds; const Address sender = m_dataNotificationObject.sender; m_dataNotificationObject = toDdsData(dbDataNotification); m_dataNotificationObject.sender = sender; for (const Address &addr : qAsConst(recipients)) { if (addr.id == dbDataAddr.id) m_dataNotificationObject.recipientIds.push_back(toDdsData(dbDataAddr)); else m_dataNotificationObject.recipientIds.push_back(addr); } // Publish Data via DTS onPublishData(); return Core::FunctionReplyObject(m_dataNotificationObject.id); } // end of updateObject() //----------------------------------------------------------------------------- Core::FunctionReplyObject ObjectNotification::deleteMessage(const DeleteMessage &data, int notificationId) { if (!isValid()) return Core::FunctionReplyObject(notificationId, tr_lts("dds", "Object not valid/blocked")); Database::NomNotification dbDataNotification = toDbData(m_dataNotificationObject); Database::NomAddress dbDataAddr; for (const Address &recipientAddr : qAsConst(m_dataNotificationObject.recipientIds)) { DEBUG_LOG(m_logger) << "recipientAddr=" << ", id: " << recipientAddr.id << ", addressId: " << recipientAddr.addressId << ", isDeleted: " << recipientAddr.isDeleted; if (data.operatorId > 0 && recipientAddr.addressType == AddressType::Operator && recipientAddr.addressId != data.operatorId) continue; if (data.workstationId > 0 && recipientAddr.addressType == AddressType::Workstation && recipientAddr.addressId != data.workstationId) continue; dbDataAddr = toDbData(recipientAddr); dbDataAddr.notificationId = dbDataNotification.id; break; } if (dbDataAddr.id <= 0) return Core::FunctionReplyObject(data.addressId, tr_lts("dds", "No Address found")); dbDataAddr.isDeleted = true; DBTransaction trans(m_db->database()); if (!m_db->update(dbDataAddr)) return Core::FunctionReplyObject(dbDataAddr.id, tr_lts("dds", "Error updating address-data into database")); trans.commit(); INFO_LOG(m_logger) << "Data changed for NotificationId: " << m_dataNotificationObject.id; std::vector
recipients = m_dataNotificationObject.recipientIds; Address sender = m_dataNotificationObject.sender; m_dataNotificationObject = toDdsData(dbDataNotification); m_dataNotificationObject.sender = sender; for (const Address &addr : qAsConst(recipients)) { DEBUG_LOG(m_logger) << "addr=" << ", id: " << addr.id << ", addressId: " << addr.addressId << ", isDeleted: " << addr.isDeleted; if (addr.id == dbDataAddr.id) m_dataNotificationObject.recipientIds.push_back(toDdsData(dbDataAddr)); else m_dataNotificationObject.recipientIds.push_back(addr); } // Publish Data via DTS onPublishData(); return Core::FunctionReplyObject(m_dataNotificationObject.id); } // end of updateObject() //----------------------------------------------------------------------------- Core::FunctionReplyObject ObjectNotification::deleteObject(const DeleteMessage &data, int notificationId) { DEBUG_LOG(m_logger) << "ObjectNotification::deleteObject" << ", notificationId: " << notificationId << ", addressId: " << data.addressId << ", operatorId: " << data.operatorId << ", workstationId: " << data.workstationId; deleteMessage(data, notificationId); return Core::FunctionReplyObject(m_dataNotificationObject.id); } Core::FunctionReplyObject ObjectNotification::removeObject() { if (!m_db->removeNomNotification(m_dataNotificationObject.id)) return Core::FunctionReplyObject(m_dataNotificationObject.id, tr_lts("dds", "NomNotification with id %1 can not be removed from DB")) .arg(m_dataNotificationObject.id); if (!m_ddsHandler->dts()->removeNomNotificationByKey(m_dataNotificationObject.id)) return Core::FunctionReplyObject(m_dataNotificationObject.id, tr_lts("dds", "NomNotification with id %1 can not be removed from DDS")) .arg(m_dataNotificationObject.id); return Core::FunctionReplyObject(m_dataNotificationObject.id); } // end of removeObject() //----------------------------------------------------------------------------- bool ObjectNotification::isValid() const { return m_dataNotificationObject.id > 0; } // end of isValid() //----------------------------------------------------------------------------- void ObjectNotification::onPublishData() { INFO_LOG(m_logger) << "Publish NomNotification-data to dds notificationId:" << m_dataNotificationObject.id; if (!m_ddsHandler->dts()->publish(m_dataNotificationObject)) WARNING_LOG(m_logger) << "Error publishing NomNotification-data to dds"; } // end of onPublishData() //----------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // convert methods // ---------------------------------------------------------------------------- // NotificationManagement::NomNotification => Database::NomNotification Database::NomNotification ObjectNotification::toDbData(const NomNotification &ddsData) { Database::NomNotification dbData; dbData.id = ddsData.id; dbData.exerciseId = ddsData.exerciseId; dbData.content = QString::fromStdString(ddsData.content); QString properties = contentArgsToJson(); dbData.properties = properties; dbData.title = QString::fromStdString(ddsData.title); dbData.messageType = ddsData.messageType; dbData.notificationType = ddsData.notificationType; dbData.processTime = ddsData.processTime; dbData.processed = ddsData.processed; dbData.processedPriority = ddsData.processedPriority; dbData.expiryTime = ddsData.expiryTime; dbData.priorityId = ddsData.priority; dbData.timeStamp = ddsData.timeStamp; return dbData; } // end of toDbData() //----------------------------------------------------------------------------- // Database::NomNotification => NotificationManagement::NomNotification NomNotification ObjectNotification::toDdsData(const Database::NomNotification &dbData) { NomNotification ddsData; ddsData.id = dbData.id; ddsData.content = dbData.content.toStdString(); std::vector< std::string > contentArgs = jsonToContentArgs(dbData.properties); ddsData.contentArgs = contentArgs; ddsData.title = dbData.title.toStdString(); ddsData.messageType = static_cast(dbData.messageType); ddsData.notificationType = static_cast(dbData.notificationType); ddsData.timeStamp = dbData.timeStamp; ddsData.priority = dbData.priorityId; ddsData.exerciseId = dbData.exerciseId; ddsData.expiryTime = dbData.expiryTime; ddsData.processTime = dbData.processTime; ddsData.processed = dbData.processed; ddsData.processedPriority = dbData.processedPriority; return ddsData; } // end of toDdsData() //----------------------------------------------------------------------------- // NotificationManagement::Address => Database::NomAddress Database::NomAddress ObjectNotification::toDbData(const Address &ddsData) { Database::NomAddress dbData; dbData.id = ddsData.id; dbData.addressId = ddsData.addressId; dbData.addressSubId = ddsData.addressSubId; dbData.addressSubSubId = ddsData.addressSubSubId; dbData.addressTypeId = ddsData.addressType; dbData.isRead = ddsData.isRead; dbData.isDeleted = ddsData.isDeleted; dbData.name = QString::fromStdString(ddsData.name); return dbData; } // end of toDbData() //----------------------------------------------------------------------------- // Database::NomAddress => NotificationManagement::Address Address ObjectNotification::toDdsData(const Database::NomAddress &dbData) { Address ddsData; ddsData.id = dbData.id; ddsData.addressType = dbData.addressTypeId; ddsData.name = dbData.name.toStdString(); ddsData.addressId = dbData.addressId; ddsData.addressSubId = dbData.addressSubId; ddsData.addressSubSubId = dbData.addressSubSubId; ddsData.isRead = dbData.isRead; ddsData.isDeleted = dbData.isDeleted; return ddsData; } // end of toDdsData() //----------------------------------------------------------------------------- } // namespace NotificationManagement