/** * @RDE_HEADER@ * Handler for file content * $Id$ * $HeadURL$ * $Author$ * Created by Iuliana Ojog, SLSE, 2017-04-03 */ #include "handler_file_content.h" #include "object_file_content.h" #include "main_handler.h" #include "flm_db.h" #include "convert_db_to_dds.h" #include #include //---------------------------------------------------------------------------------------------------------------------------- namespace FileManagement { HandlerFileContent::HandlerFileContent(MainHandler *mainHandler) : Base(mainHandler, getLogger("HandlerFileContent")) , Interface::Fts::FileContentModifyRequestHandler(fts()) , Interface::Fts::FileContentRemoveRequestHandler(fts()) , Interface::Fts::FileContentExportRequestHandler(fts()) , Interface::Fts::FileContentChangeStatusRequestHandler(fts()) , Interface::Fts::GetFileContentDataRequestHandler(fts()) , Interface::Fts::FileContentSetUsedRequestHandler(fts()) { connect(db().get(), &DatabaseInterface::notifyDeleteFileContent, this, &HandlerFileContent::onDbDeletedFileContent); connect(db().get(), &DatabaseInterface::notifyInsertFileContent, this, &HandlerFileContent::onDbInsertedFileContent); connect(db().get(), &DatabaseInterface::notifyUpdateFileContent, this, &HandlerFileContent::onDbUpdatedFileContent); } //---------------------------------------------------------------------------------------------------------------------------- HandlerFileContent::~HandlerFileContent() { qDeleteAll(m_objectFileContentMap); } //---------------------------------------------------------------------------------------------------------------------------- bool HandlerFileContent::init() { // create file content objects auto cb = [this] (const Database::FlmFileContent &data) { ObjectFileContent *ifs(new ObjectFileContent(convert(data), m_mainHandler)); // TODO: not a good idea to load the whole file content from database... // load on demand and store data in temporary file (for filesize > 1MB or so) //ifs->setContent(LtsUtils::convert>(data.content)); //DEBUG_LOG(m_logger) << "Content size for id = " << data.id << " : " << data.content.size(); m_objectFileContentMap.insert(ifs->getId(), ifs); ifs->onPublishData(); }; if (!db()->select(cb)) { ERROR_LOG(m_logger) << "Error reading data from database!"; return false; } INFO_LOG(m_logger) << "m_ObjectFileContentMap.size() = " << m_objectFileContentMap.size(); return true; } //---------------------------------------------------------------------------------------------------------------------------- void HandlerFileContent::onFileContentModifyRequest(const rti::core::SampleIdentity &cookie, const FileManagement::FileContentModifyRequest &request) { auto ret = request.id() > 0 ? fileContentModifyRequest(request) : fileContentCreateRequest(request); if (ret.error()) WARNING_LOG(m_logger) << ret(); fts()->fileContentModifyReply(cookie, ret); } //---------------------------------------------------------------------------------------------------------------------------- Core::FunctionReplyObject HandlerFileContent::fileContentCreateRequest(const FileContentModifyRequest &request) { ObjectFileContent *ifs(new ObjectFileContent(m_mainHandler)); Core::FunctionReplyObject ret = ifs->createObject(request); if (ret.error()) delete ifs; else m_objectFileContentMap.insert(ifs->getId(), ifs); return ret; } //---------------------------------------------------------------------------------------------------------------------------- Core::FunctionReplyObject HandlerFileContent::fileContentModifyRequest(const FileManagement::FileContentModifyRequest &request) { ObjectFileContent *ifs = m_objectFileContentMap.value(request.id()); if (ifs == nullptr) return Core::FunctionReplyObject(request.id(), tr_lts("dds", "FileContent with id %1 not found")).arg(request.id()); return ifs->updateObject(request); } //---------------------------------------------------------------------------------------------------------------------------- void HandlerFileContent::onFileContentChangeStatusRequest(const rti::core::SampleIdentity &cookie, const FileManagement::FileContentChangeStatusRequest &request) { ObjectFileContent *ifs = m_objectFileContentMap.value(request.id()); if (ifs == nullptr) { Core::FunctionReplyObject ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "FileContent with id %1 not found")).arg(request.id()); fts()->fileContentChangeStatusReply(cookie, ret); return; } Core::FunctionReplyObject ret = ifs->changeStatus(request); if (ret.error()) ERROR_LOG(m_logger) << ret(); fts()->fileContentChangeStatusReply(cookie, ret); } //---------------------------------------------------------------------------------------------------------------------------- void HandlerFileContent::onFileContentRemoveRequest(const rti::core::SampleIdentity &cookie, const Core::RemoveElementRequest &request) { auto ret = fileContentRemoveRequest(request); if (ret.error()) WARNING_LOG(m_logger) << ret(); fts()->fileContentRemoveReply(cookie, ret); } Core::FunctionReplyObject HandlerFileContent::fileContentRemoveRequest(const Core::RemoveElementRequest &request) { ObjectFileContent *ifs = m_objectFileContentMap.value(request.id()); if (ifs == nullptr) return Core::FunctionReplyObject(request.id(), tr_lts("dds", "FileContent with id %1 not found")).arg(request.id()); if (m_mainHandler->dds()->topicLockMaster()->isLocked(ifs->getData(), m_mainHandler->exerciseId())) return Core::FunctionReplyObject(request.id(), tr_lts("dds", "FileContent '%1' is used by another user!")).arg(ifs->getName()); auto ret = ifs->removeObject(); if (!ret.error()) { // delete ObjectFileContent delete ifs; m_objectFileContentMap.remove(request.id()); } return ret; } //---------------------------------------------------------------------------------------------------------------------------- void HandlerFileContent::onFileContentExportRequest(const rti::core::SampleIdentity &cookie, const FileManagement::FileContentExportRequest &request) { Core::FunctionReplyObject ret; ObjectFileContent *ifs = m_objectFileContentMap.value(request.id()); if (ifs == nullptr) { ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "FileContent with id %1 not found")).arg(request.id()); fts()->fileContentExportReply(cookie, ret); return; } // get content on demand from DB Database::FlmFileContent flmContent; if (!db()->selectFlmFileContent(request.id(), flmContent)) ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "FileContent with id %1 not found in database")).arg(request.id()); QByteArray content = flmContent.content; DEBUG_LOG(m_logger) << "Content size: " << content.size(); // creating an unique file name: temp path + folderId + file name + file extension (NN_FileName.FileExt) QString fileName = QDir::tempPath() + QLatin1Char('/') + QString::number(ifs->getFolderId()) + QLatin1Char('-'); fileName += QString::fromStdString(ifs->getData().name()).simplified().replace(QLatin1Char(' '), QLatin1Char('_')); // add extension FileType fileType = ifs->getData().fileType().underlying(); QString fileExt = m_mainHandler->getHandlerFileTypeInfo()->getFileExtension(fileType); if (!fileExt.isEmpty()) fileName += QLatin1Char('.') + fileExt; DEBUG_LOG(m_logger) << "Trying to export File Content to " << fileName; // save content QFile file(fileName); if (!file.open(QIODevice::WriteOnly)) { ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "Failed to write to %1")).arg(fileName); fts()->fileContentExportReply(cookie, ret); delete ifs; return; } file.write(content); file.close(); DEBUG_LOG(m_logger) << "Successfully exported File Content to " << fileName; // update exportFileName ifs->setExportFileName(fileName.toStdString()); // publish the modified object ifs->onPublishData(); fts()->fileContentExportReply(cookie, ret); return; } //---------------------------------------------------------------------------------------------------------------------------- void HandlerFileContent::onGetFileContentDataRequest(const rti::core::SampleIdentity &cookie, const GetFileContentDataRequest &request) { Core::FunctionReplyObject fro; GetFileContentDataReply reply; ObjectFileContent *ifs = m_objectFileContentMap.value(request.fileContentId()); if (ifs) { reply.id(ifs->getId()); // get content on demand from DB Database::FlmFileContent flmContent; if (!db()->selectFlmFileContent(request.fileContentId(), flmContent)) fro = Core::FunctionReplyObject(request.fileContentId(), tr_lts("dds", "File content with id %1 not found in database")).arg(request.fileContentId()); /* no need to set content of object else ifs->setContent(LtsUtils::convert>(flmContent.content)); if (ifs->getContent().size() <= 0) fro = Core::FunctionReplyObject(request.fileContentId(), tr_lts("dds", "No content available")); else reply.content(ifs->getContent()); */ if (flmContent.content.size() <= 0) fro = Core::FunctionReplyObject(request.fileContentId(), tr_lts("dds", "No content available")); else reply.content(LtsUtils::convert>(flmContent.content)); } else fro = Core::FunctionReplyObject(request.fileContentId(), tr_lts("dds", "No valid id = %1 for retrieving file content")).arg(request.fileContentId()); if (fro.error()) { reply.id(fro.id()); reply.errorString(fro.str()); reply.errorParams(fro.args()); } DEBUG_LOG(m_logger) << "Got content size: " << reply.content().size(); fts()->getFileContentDataReply(cookie, reply); } //---------------------------------------------------------------------------------------------------------------------------- void HandlerFileContent::onDbDeletedFileContent(const QVariant &id_) { int id = id_.toInt(); DEBUG_LOG(m_logger) << "DB deleted File Content with id: " << id; if (!dts()->removeFileContentByKey(id)) ERROR_LOG(m_logger) << "FileContent can not be taken from DDS, id = " << id; } //---------------------------------------------------------------------------------------------------------------------------- void HandlerFileContent::onDbInsertedFileContent(const QVariant &id_) { int id = id_.toInt(); DEBUG_LOG(m_logger) << "DB inserted File Content with id: " << id; if (!m_objectFileContentMap.contains(id)) initByDbId(id); } //---------------------------------------------------------------------------------------------------------------------------- void HandlerFileContent::onDbUpdatedFileContent(const QVariant &id_) { int id = id_.toInt(); DEBUG_LOG(m_logger) << "DB updated File Content with id: " << id; initByDbId(id); } //---------------------------------------------------------------------------------------------------------------------------- bool HandlerFileContent::initByDbId(int dbId) { Database::FlmFileContent data; DEBUG_LOG(m_logger) << "Reading FileContent from database!"; if (!db()->selectFlmFileContent(dbId, data)) { ERROR_LOG(m_logger) << "Error reading data from database: id not found " << dbId; return false; } // create file content object if (data.id == dbId) { ObjectFileContent *ifs(new ObjectFileContent(convert(data), m_mainHandler)); //ifs->setContent(LtsUtils::convert>(data.content)); m_objectFileContentMap.insert(ifs->getId(), ifs); ifs->onPublishData(); } return true; } //---------------------------------------------------------------------------------------------------------------------------- void HandlerFileContent::onFileContentSetUsedRequest(const rti::core::SampleIdentity &cookie, const FileManagement::FileContentSetUsedRequest &request) { ObjectFileContent *ifs = m_objectFileContentMap.value(request.id()); if (ifs == nullptr) { Core::FunctionReplyObject ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "FileContent with id %1 not found")).arg(request.id()); fts()->fileContentSetUsedReply(cookie, ret); return; } Core::FunctionReplyObject ret = ifs->setUsedBy(request); if (ret.error()) ERROR_LOG(m_logger) << ret(); fts()->fileContentSetUsedReply(cookie, ret); } } // Namespace FileManagement