/** * @RDE_HEADER@ * FlmHandler for AdlerJson Plugin * $Id: pdm_handler.cpp 62304 2024-03-21 08:17:45Z ewert_j $ * $HeadURL: svn://slssvn/TDS/branches/product/features/ufom/Lts/Proxies/TrainingAreaBase/Plugins/UFomHlaJson/pdm_handler.cpp $ * $Author: ewert_j $ * Created by Hanna E. Rathje, 2025-11-18 */ #include "flm_handler.h" #include "FileManagement/flm_operator_rights.h" #include "main_dispatcher.h" #include "nglsettings/nglsettings_settings.h" #include "ngltools/ngltools_filesystem.h" #include #include #include #include namespace AdlerJson { FlmHandler::FlmHandler(QObject *parent) : QObject(parent) , m_exerciseId(-1) , m_parentFolderId(-1) , m_partyId(-1) , m_folderHXMessagesId(-1) , m_dtcFlm(nullptr) , m_ftcFlm(nullptr) , m_ftcNom(nullptr) , m_opmDtc(nullptr) , m_logger(getLogger("FlmHandler")) { } bool FlmHandler::init(MainDispatcher *mainDispatcher) { m_mainDispatcher = mainDispatcher; m_exerciseId = mainDispatcher->exerciseId(); m_dtcFlm = FileManagement::Interface::Dtc::create(mainDispatcher->ddsHandler()->ddsConnector()); m_ftcFlm = FileManagement::Interface::Ftc::create(mainDispatcher->ddsHandler()->ddsConnector()); m_dtcFlm->enableFileContent(); m_dtcFlm->enableFolder(); m_ftcFlm->enableFileContentModify(); m_ftcFlm->enablePathCreate(); m_ftcNom = NotificationManagement::Interface::Ftc::create(mainDispatcher->ddsHandler()->ddsConnector()); m_ftcNom->enableAll(); m_opmDtc = OperatorManagement::Interface::Dtc::create(mainDispatcher->ddsHandler()->ddsConnector()); m_opmDtc->enableUser(); return true; } bool FlmHandler::processHQMessage(int partyId, const QString &name, int meldungsnummer, const QJsonObject &obj) { ERROR_LOG(m_logger) << "exerciseId: " << m_exerciseId << ", partyId: " << partyId << ", name: " << name << ", meldungsnummer: " << meldungsnummer; // get FolderId for PartyId int partyFolderId = m_dtcFlm->getPartyFolderId(m_exerciseId, partyId); const QString folderName = QStringLiteral("Messages"); int folderHXMessagesId = m_dtcFlm->findFolder(partyFolderId, folderName); ERROR_LOG(m_logger) << "folderHXMessagesId: " << folderHXMessagesId; if (folderHXMessagesId <= 0) { ERROR_LOG(m_logger) << "Folder Messages does not exist for exerciseId: " << m_exerciseId << ", partyId: " << partyId; return false; } FileManagement::FileContentModifyRequest fileContentReq; fileContentReq.isTemplate(false); fileContentReq.isHidden(true); fileContentReq.folderId(folderHXMessagesId); const QVector fldPath = LtsUtils::convert>(m_dtcFlm->folder(folderHXMessagesId).path()); fileContentReq.fileCategory(FileManagement::FileCategory::Exercise); fileContentReq.fileType(FileManagement::FileType::AdlerJson); fileContentReq.fileStatus(FileManagement::FileStatus::Valid); QByteArray content = QJsonDocument(obj).toJson(QJsonDocument::Compact).constData(); fileContentReq.content(LtsUtils::convert>(content)); fileContentReq.isUsedBy(false); fileContentReq.usedBy(0); fileContentReq.lastModified(m_mainDispatcher->ddsHandler()->partitionTime()); fileContentReq.exerciseId(m_exerciseId); fileContentReq.operatorId(99); // organizer DEBUG_LOG(m_logger) << "HQ: name: " << fileContentReq.name() << ", folderId: " << folderHXMessagesId << ", exerciseId: " << m_exerciseId << ", partyId: " << partyId; // Check if Filename already exists QRegularExpression re(QStringLiteral("_\\d+$")); QString baseName = name + QStringLiteral(" (") + QString::number(meldungsnummer) + QStringLiteral(")"); baseName.remove(re); // nornalized (important for Umlaute in baseName) baseName = baseName.normalized(QString::NormalizationForm_C); ERROR_LOG(m_logger) << "BaseName: " << baseName << "|"; QStringList fileNames; if (!m_dtcFlm->getAllFiles(fileContentReq.fileType(), folderHXMessagesId, fileNames, true)) { ERROR_LOG(m_logger) << "Error while reading fileNames for folderId: " << folderHXMessagesId; return false; } int maxNumber = 0; for (const QString &fileName : qAsConst(fileNames)) { QString normalizedName = fileName.normalized(QString::NormalizationForm_C); DEBUG_LOG(m_logger) << "normalized fileName: " << normalizedName << "|"; if (!normalizedName.startsWith(baseName)) continue; QString rest = fileName.mid(baseName.length()); DEBUG_LOG(m_logger) << "rest: " << rest; if (rest.contains(QStringLiteral("."))) rest = rest.section(QStringLiteral("."), 0, 0); if (rest.startsWith(QStringLiteral("_"))) rest = rest.mid(1); if (rest.isEmpty()) maxNumber = std::max(maxNumber, 0); else { bool ok; int currentNum = rest.toInt(&ok); if (ok) maxNumber = std::max(maxNumber, currentNum); } DEBUG_LOG(m_logger) << " maxNumber: " << maxNumber; } const QString newName = baseName + QStringLiteral("_") + QString::number(++maxNumber); DEBUG_LOG(m_logger) << "newName : " << newName; fileContentReq.name(newName.toStdString()); // fileId will be in reply m_partyId = partyId; m_folderHXMessagesId = folderHXMessagesId; m_ftcFlm->fileContentModifyRequest(fileContentReq, this); return true; } void FlmHandler::createHQNotification(const int partyId, const int folderId, const int fileId) { qint64 currentTime = m_mainDispatcher->ddsHandler()->partitionTime(); QScopedPointer s(new NGL::Settings(NGL::findProjectConfigFile())); qint64 expiryTime = currentTime + s->getInteger(QStringLiteral("NOM/expiryIntervalMSec"), 2 * 24 * 60 * 60 * 1000); // default 2 day NotificationManagement::NomNotification notif; notif.title(tr("HQ Report").toStdString()); /// for more see in nom_test.cpp QString linkName = tr("Open HQ Report Dialog"); QString content = QStringLiteral("[%1](//flmHQReport/?party=%2&folder=%3&file=%4)").arg(linkName).arg(partyId).arg(folderId).arg(fileId); QMap linkMap; parseContent(content, linkMap); // now replace the strings QMapIterator it(linkMap); while (it.hasNext()) { it.next(); content = content.replace(QStringLiteral("[%1](%2)").arg(it.value(), it.key()), QStringLiteral("%2").arg(it.key(), it.value())); } notif.content(content.toStdString()); notif.timeStamp(currentTime); notif.expiryTime(expiryTime); int prio = s->getInteger(QStringLiteral("NOM/notificationPriority"), 3); // default prio 3: normal DEBUG_LOG(m_logger) << " Setting: NotificationPriority: " << prio; notif.priority(static_cast(prio)); notif.processedPriority(NotificationManagement::Priority_def::Low); notif.exerciseId(m_exerciseId); for (const auto &userId : m_opmDtc->getOperatorsByOperatorRight(OperatorRights::FileManagementFilesEdit)) { NotificationManagement::Address addr; addr.addressId(userId); addr.isRead(false); addr.name(m_opmDtc->user(userId).name()); addr.addressType(NotificationManagement::AddressType_def::Operator); notif.recipientIds().push_back(addr); } NotificationManagement::CreateNotificationRequest notifReq; notifReq.notification(notif); if (!m_ftcNom->createNotificationRequest(notifReq, this)) ERROR_LOG(m_logger) << "Error requesting create Notification data"; } void FlmHandler::initHQFolders(int partyId) { // get FolderId for Exercise int exerciseFolderId = m_dtcFlm->getExerciseFolderId(m_exerciseId); if (exerciseFolderId <= 0) { ERROR_LOG(m_logger) << "No exercise Folder for exerciseId: " << m_exerciseId; return; } const QString &partyName = m_dtcFlm->getPartyFolderName(partyId); std::vector vecFolderNames = {"HQ Data", partyName.toStdString(), "Messages"}; FileManagement::PathCreateRequest req; req.path(vecFolderNames); req.parentId(exerciseFolderId); req.isEditable(false); req.operatorId(99); // Organizer m_ftcFlm->pathCreateRequest(req, this); } void FlmHandler::onFileContentModifyReply(const Core::FunctionReplyObject &reply) { DEBUG_LOG(m_logger) << "Got Function Reply: " << reply.translated(); if (reply.error()) ERROR_LOG(m_logger) << "Error while insert HX Message: " << reply.translated() << ", error: " << reply.error(); else createHQNotification(m_partyId, m_folderHXMessagesId, reply.id()); } void FlmHandler::onPathCreateReply(const Core::FunctionReplyObject &reply) { DEBUG_LOG(m_logger) << "Got Function Reply: " << reply.translated(); if (reply.error()) { ERROR_LOG(m_logger) << "Error while creating folders: " << reply.translated() << ", error: " << reply.error(); } } void FlmHandler::onCreateNotificationReply(const Core::FunctionReplyObject &replyObject) { INFO_LOG(m_logger) << "FlmHandler: Got createReply with id " << replyObject.id() << " and errorString " << replyObject.translated(); } bool FlmHandler::parseContent(const QString &contentString, QMap &retMap) { if (contentString.isEmpty()) return false; // Mark Down Regex lookig for String between ]( and ) eg: TestLingk "[LinkName](http::blahblah)" QRegularExpression regLink(QStringLiteral("(?<=\\]\\()(.*?)(?=\\))")); QRegularExpressionMatch matchLink = regLink.match(contentString); QRegularExpression regDesc(QStringLiteral("(?<=\\[)(.*?)(?=\\]\\()")); QRegularExpressionMatch matchDesc = regDesc.match(contentString); QRegularExpressionMatchIterator itLink = regLink.globalMatch(contentString); QRegularExpressionMatchIterator itDesc = regDesc.globalMatch(contentString); while (itLink.hasNext() && itDesc.hasNext()) { QString linkRef = itLink.next().captured(); QString linkDesc = itDesc.next().captured(); if (!linkRef.isEmpty() && !linkDesc.isEmpty()) { retMap.insert(linkRef, linkDesc); } } return retMap.size(); } } // namespace AdlerJson