/** * 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_def::Operator && recipientAddr.addressId() != data.operatorId()) continue; if (data.workstationId() > 0 && recipientAddr.addressType() == AddressType_def::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_def::Operator && recipientAddr.addressId() != data.operatorId()) continue; if (data.workstationId() > 0 && recipientAddr.addressType() == AddressType_def::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().underlying(); dbData.notificationType = ddsData.notificationType().underlying(); 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.underlying()); 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().underlying(); 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