Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+200
View File
@@ -0,0 +1,200 @@
#
# $Id$
# $HeadURL$
# $Author$
#
INCLUDE(MacroRTIDDSGen)
INCLUDE(MacroCodeGenIdl)
SET(xml_FILE flm_service.xml)
#
# --- Library svcFlmCommon --------------------------------------------------------------------------------
#
SET(SRCS_common
flm_export.h
flm_db_impl_custom.cpp
flm_db_impl_custom.h
logger.cpp
logger.h
)
# Generate flm_enums.idl / flm.idl
CODEGEN_IDL_SVC(SRCS_common ${xml_FILE})
# Generate flm_db_impl.cpp/.h, flm_db.h
CODEGEN_DATABASE(SRCS_common ${xml_FILE})
# Generate *.cpp/*.hpp from idl
RTIDDSGEN(SRCS_common flm_enums.idl)
RTIDDSGEN(SRCS_common flm.idl)
# Generate flm_dt[s,c]_types.h, flm_ft[s,c]_types.h
CODEGEN_TOPIC_TYPEDEFS(SRCS_common ${xml_FILE})
# generate flm_[d|f]tc.h
CODEGEN_CLIENT_TOPICS_IFC(SRCS_common ${xml_FILE})
NGL_ADD_LIBRARY(AAR SV WS svcFlmCommon SHARED ${SRCS_common})
NGL_TARGET_INCLUDE_DIRECTORIES(svcFlmCommon
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcFlmCommon
PRIVATE
RTI::nddscpp2
PUBLIC
Qt5::Core
ddscore
ngldb
LtsUtilsCore
NGLLogger
)
NGL_INSTALL_TARGET(svcFlmCommon)
#
# --- Library svcFlmClient --------------------------------------------------------------------------------
#
SET(SRCS_client
flm_dtc_impl_custom.cpp
flm_dtc_impl_custom.h
flm_export.h
)
# generate flm_ftc_impl.[cpp|h]
CODEGEN_CLIENT_TOPICS_IMPL(SRCS_client ${xml_FILE})
NGL_ADD_LIBRARY(WS AAR SV svcFlmClient SHARED ${SRCS_client})
NGL_TARGET_INCLUDE_DIRECTORIES(svcFlmClient
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcFlmClient
PRIVATE
RTI::nddscpp2
ddsconnector
PUBLIC
svcFlmCommon
ddsftc
)
NGL_INSTALL_TARGET(svcFlmClient)
#
# --- Library svcFlmServer --------------------------------------------------------------------------------
#
SET(SRCS_server
flm_export.h
convert_db_to_dds.h
)
# generate flm_[d|f]ts.h, flm_[d|f]ts_impl.[cpp|h]
CODEGEN_SERVER_TOPICS(SRCS_server ${xml_FILE})
NGL_ADD_LIBRARY(WS AAR SV svcFlmServer SHARED ${SRCS_server})
NGL_TARGET_INCLUDE_DIRECTORIES(svcFlmServer
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcFlmServer
PRIVATE
RTI::nddscpp2
ddsconnector
ddsfts
PUBLIC
svcFlmCommon
ngldb
LtsUtilsCore
)
NGL_INSTALL_TARGET(svcFlmServer)
#
# --- Topic Type Plugin --------------------------------------------------------------
#
CREATE_TOPIC_TYPE_PLUGIN(${xml_FILE})
#
# --- Executable svcFileManagement (sFlm) -------------------------------------------------
#
SET(HDRS_exe
)
SET(SRCS_exe
base.cpp
base.h
dds_handler.cpp
dds_handler.h
main.cpp
main_handler.cpp
main_handler.h
settings.cpp
settings.h
handler_file_type_info.cpp
handler_file_type_info.h
object_file_type_info.cpp
object_file_type_info.h
handler_folder.cpp
handler_folder.h
object_folder.cpp
object_folder.h
handler_file_content.cpp
handler_file_content.h
object_file_content.cpp
object_file_content.h
thp_script_httq.h
thp_script_httq.cpp
pdf_server.cpp
pdf_server.h
pdf_download.cpp
pdf_download.h
WebSocketInterface/data_manager.cpp
WebSocketInterface/data_manager.h
WebSocketInterface/json_keys.h
WebSocketInterface/websocket_interface_handler.cpp
WebSocketInterface/websocket_interface_handler.h
WebSocketInterface/Messages/client_message.cpp
WebSocketInterface/Messages/client_message.h
WebSocketInterface/Messages/reply_message.cpp
WebSocketInterface/Messages/reply_message.h
${xml_FILE}
)
# Generate flm.sql, flm.xml
CODEGEN_SQL(SRCS_exe ${xml_FILE})
NGL_ADD_SVC_ICON(SRCS_exe)
NGL_ADD_EXECUTABLE(AAR SV svcFileManagement ${SRCS_exe})
NGL_TARGET_LINK_LIBRARIES(svcFileManagement
Qt5::Core
svcCoreClient
svcFlmCommon
svcFlmServer
svcFlmClient
ddsconnector
nglsettings
ProjectConfig
LtsCommandLineParser
LtsWebSocketServer
NGLLogger
nglcoreapplication
ngltools
tcpserver
httq
Thp2CommonCore
)
NGL_INSTALL_TARGET(svcFileManagement)
NGL_INSTALL(AAR SV FILES log4cxx_flm.props DESTINATION bin)
NGL_ADD_TARGET_LINK(svcFileManagement sFlm)
# Uncomment if necessary
#ADD_SUBDIRECTORY(UnitTests)
ADD_SUBDIRECTORY(ModuleTests)
+45
View File
@@ -0,0 +1,45 @@
#
# $Id$
# $HeadURL$
# $Author$
#
SET(SRCS_TEST
flm_tests.cpp
flm_tests.h
../settings.h
../settings.cpp
)
SET(test_FILES
logo_Project.jpg
titel_logo_RDE.jpg
)
IF(TARGET svcFlmClient AND TARGET svcFlmServer)
IF(BUILD_TESTING)
# Testing FunctionTopic Functionality (FTC)
ADD_EXECUTABLE(flmTests ${SRCS_TEST})
TARGET_LINK_LIBRARIES(flmTests
Qt5::Core
Qt5::Test
Qt5::Gui
RTI::nddscpp2
ddsconnector
nglcoreapplication
ngldb
nglsettings
ngltools
svcFlmClient
svcFlmServer
LtsCommandLineParser
LtsUtilsCoreHeaderOnly
ProjectConfig
)
IF(NOT BUILD_RPM)
NGL_INSTALL(AAR SV TARGETS flmTests DESTINATION bin/test)
NGL_INSTALL(AAR SV FILES ../log4cxx_flm.props DESTINATION bin/test)
NGL_INSTALL(AAR SV FILES ${test_FILES} DESTINATION /bin/test)
ENDIF()
ENDIF()
ENDIF()
+885
View File
@@ -0,0 +1,885 @@
/**
* @RDE_HEADER@
* ISM Function Topic test executable
* $Id$
* @RDE_HEADER@
* Module Tests for FLM
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-05
*/
#include "flm_tests.h"
#include <nglapplication/nglcoreapplication.h>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
#include <QTimer>
#include <QDateTime>
#include <QTest>
#include <QSet>
#include <QVector>
#include <QJsonObject>
#include <QJsonDocument>
#include <LtsUtilsCore/pgarray.h>
#include <LtsUtilsCore/dds_vector.h>
#include <FileManagement/flm_ftc.h>
#include <FileManagement/flm_dtc.h>
#include <FileManagement/settings.h>
/* ----------------------------------------------------------------------------------
* HOW TO RUN THE TESTS (for example)
* ----------------------------------------------------------------------------------
* 0. Preconditions:
* Start with an empty database (BUILD)
* make db
* Start services: (SV)
* ./bin/svcExerciseManagement -d 74 &
* ./bin/svcFileManagement -d 74 &
* Test steps (sample):
* 1. ./bin/tests/flmTests -d 74 -t 11 -f 11
*/
// ------------------------------------------------------------------------------
using namespace FileManagement;
FlmTests::FlmTests(QObject *parent)
: QObject(parent)
, m_testId(-1)
, m_folderId(0)
, m_fileContentId(-1)
, m_operatorId(99)
, m_bTestsSuccessful(true)
, m_logger(getLogger("Test"))
{
qRegisterMetaType<Core::FunctionReply>("Core::FunctionReply");
}
// ------------------------------------------------------------------------------
FlmTests::~FlmTests()
{
}
// ------------------------------------------------------------------------------
bool FlmTests::init(int domainId, int testId, int folderId, int fileContentId, int operatorId)
{
INFO_LOG(m_logger) << "init begin";
m_testId = testId;
m_folderId = folderId;
m_fileContentId = fileContentId;
m_operatorId = operatorId;
m_content.clear();
// initialize DDS, always on exercise 0
m_ddsConnector.reset(new DDSConnector::DdsConnector(domainId, IDL::PartitionType::Global));
if (!m_ddsConnector->init())
return false;
m_ddsConnector->initPublisherSubscriber();
TRACE_LOG(m_logger) << "create dtc";
m_dtc = FileManagement::Interface::Dtc::create(m_ddsConnector);
TRACE_LOG(m_logger) << "init dtc";
bool bRet = m_dtc->enableAll();
TRACE_LOG(m_logger) << "init dtc end - bRet = " << bRet;
TRACE_LOG(m_logger) << "create ftc";
m_ftc = FileManagement::Interface::Ftc::create(m_ddsConnector);
TRACE_LOG(m_logger) << "init ftc";
bRet &= m_ftc->enableAll();
TRACE_LOG(m_logger) << "init ftc end - bRet = " << bRet;
// initialize database
m_dbHandler = std::make_shared<DbHandler>();
if(!m_dbHandler->init(0, Settings::settings()))
{
ERROR_LOG(m_logger) << "Initialisation dbHandler failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation dbHandler succesful.";
m_db = m_dbHandler->db();
DEBUG_LOG(m_logger) << "########### Domain Id = " << domainId;
DEBUG_LOG(m_logger) << "########### Test Id = " << testId;
DEBUG_LOG(m_logger) << "########### Folder Id = " << folderId;
DEBUG_LOG(m_logger) << "########### File Content Id = " << fileContentId;
DEBUG_LOG(m_logger) << "########### Operator Id = " << operatorId;
return bRet;
}
// ------------------------------------------------------------------------------
void FlmTests::startTest()
{
INFO_LOG(m_logger) << "********* startTest **************";
switch (m_testId)
{
// folder
case 1:
tryCreateFolder();
break;
case 2:
tryModifyFolder();
break;
case 3:
tryRemoveFolder();
break;
// file content
case 11:
tryCreateFileContent();
break;
case 12:
tryModifyFileContent();
break;
case 13:
tryRemoveFileContent();
break;
case 14:
tryExportFileContent();
break;
case 15:
tryGetContent();
break;
case 16:
tryUpdateStatus();
break;
case 20:
tryGetAllTemplates();
break;
case 21:
tryGetAllPlans();
break;
case 22:
tryGetAllFavs();
break;
case 23:
tryGetAllSymbols();
break;
// plans
case 31:
tryCreatePlan();
break;
case 32:
tryCreateFav();
break;
case 33:
tryCreateSymbol();
break;
default:
ERROR_LOG(m_logger) << "Unknown test case !";
failExit();
break;
}
INFO_LOG(m_logger) << "********* endTest **************";
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
// ************* FOLDER **********************************************************
// ------------------------------------------------------------------------------
void FlmTests::tryCreateFolder()
{
INFO_LOG(m_logger) << "trying to send FolderCreateRequest";
int parentFolderId = m_folderId;
if (parentFolderId == 0)
parentFolderId = 1;
DEBUG_LOG(m_logger) << "Creating Folder under folder id = " << parentFolderId;
// Creating hidden folder
m_folderId = createFolder(parentFolderId, QStringLiteral("Test Folder"), true);
QTRY_VERIFY(m_folderId != 0);
parentFolderId = m_folderId;
m_folderId = 0;
DEBUG_LOG(m_logger) << "Creating Subfolder for folder id = " << parentFolderId;
m_folderId = createFolder(parentFolderId, QStringLiteral("Test Sub Folder"));
QTRY_VERIFY(m_folderId != 0);
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
// ------------------------------------------------------------------------------
void FlmTests::tryModifyFolder()
{
INFO_LOG(m_logger) << "trying to send folder modify request ";
DEBUG_LOG(m_logger) << "m_folderId = " << m_folderId;
m_dtc->waitForHistoricalDataFolder();
const FileManagement::Folder &fld = m_dtc->folder(m_folderId);
FileManagement::FolderModifyRequest data;
DEBUG_LOG(m_logger) << "fld.id() = " << fld.id();
if (fld.id() == 0)
{
ERROR_LOG(m_logger) << "Cannot find Folder Id = " << m_folderId;
failExit();
}
else
{
m_folderId = 0;
data.id(fld.id());
data.name(fld.name());
data.path(fld.path());
data.isEditable(fld.isEditable());
data.isHidden(fld.isHidden());
data.parentId(fld.parentId());
data.operatorId(m_operatorId);
// changing only name
data.name("Folder-Updated");
if (!m_ftc->folderModifyRequest(FolderModifyRequest(data), this))
{
ERROR_LOG(m_logger) << "Error requesting modify data";
failExit();
}
QTRY_VERIFY(m_folderId > 0);
}
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
// ------------------------------------------------------------------------------
void FlmTests::tryRemoveFolder()
{
INFO_LOG(m_logger) << "trying to send FolderRemoveRequest ";
m_dtc->waitForHistoricalDataFolder();
if (!m_ftc->folderRemoveRequest(FolderRemoveRequest(m_folderId), this))
{
ERROR_LOG(m_logger) << "Error requesting delete data";
failExit();
}
QTest::qWait(1000);
}
// ------------------------------------------------------------------------------
int FlmTests::createFolder(int parentFolderId, const QString &folderName, bool isHidden)
{
FileManagement::Folder parentFolder = m_dtc->folder(parentFolderId);
const std::vector<int32_t> &parentPath = parentFolder.path();
FileManagement::FolderModifyRequest req;
req.name(folderName.toStdString());
req.path(parentPath);
req.isEditable(false);
req.isHidden(isHidden);
req.parentId(parentFolderId);
req.operatorId(m_operatorId);
if (!m_ftc->folderModifyRequest(req, this))
{
ERROR_LOG(m_logger) << "Error creating folder with parent = " << parentFolderId << " and name = " << folderName ;
failExit();
}
return m_folderId;
}
//********************* FILE CONTENT ********************************************
// ------------------------------------------------------------------------------
void FlmTests::tryCreateFileContent()
{
INFO_LOG(m_logger) << "trying to send file content create request ";
m_dtc->waitForHistoricalDataFileContent();
FileContentModifyRequest data;
data.name("Test Document");
data.isTemplate(false);
data.isUsedBy(false);
data.usedBy(0);
data.folderId(m_folderId);
data.fileStatus(FileManagement::FileStatus::Valid);
data.fileCategory(FileManagement::FileCategory::User); // user docs
data.fileType(FileManagement::FileType::MSOfficeDocument); // doc
data.operatorId(m_operatorId);
data.lastModified(QDateTime::currentMSecsSinceEpoch());
QByteArray vmTest;
vmTest += "bla-bla-bla";
data.content(LtsUtils::convert<std::vector<uint8_t>>(vmTest));
m_fileContentId = 0;
if (!m_ftc->fileContentModifyRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
}
QTRY_VERIFY(m_fileContentId > 0);
data.name("Test PDF");
data.isTemplate(false);
data.folderId(m_folderId);
data.fileStatus(FileManagement::FileStatus::Valid);
data.fileCategory(FileManagement::FileCategory::User); // user docs
data.fileType(FileManagement::FileType::Pdf); // pdf
data.operatorId(m_operatorId);
data.lastModified(QDateTime::currentMSecsSinceEpoch());
vmTest += "\npdf-pdf-pdf";
data.content(LtsUtils::convert<std::vector<uint8_t>>(vmTest));
m_fileContentId = 0;
if (!m_ftc->fileContentModifyRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
}
QTRY_VERIFY(m_fileContentId > 0);
data.name("Test JPG");
data.isTemplate(false);
data.folderId(m_folderId);
data.fileStatus(FileManagement::FileStatus::Valid);
data.fileCategory(FileManagement::FileCategory::User); // user docs
data.fileType(FileManagement::FileType::Jpg);
data.operatorId(m_operatorId);
data.lastModified(QDateTime::currentMSecsSinceEpoch());
QString fileName = QLatin1String("/titel_logo_RDE.jpg");
QFile file;
file.setFileName(QCoreApplication::applicationDirPath()+fileName);
if (!file.open(QFile::ReadOnly))
{
ERROR_LOG(m_logger) << "Error opening file " << fileName;
failExit();
}
QByteArray rawImage = file.readAll();
DEBUG_LOG(m_logger) << "Read file " << fileName;
file.close();
data.content(LtsUtils::convert<std::vector<uint8_t>>(rawImage));
m_fileContentId = 0;
if (!m_ftc->fileContentModifyRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
}
QTRY_VERIFY(m_fileContentId > 0);
data.name("Test big JPG");
data.isTemplate(false);
data.folderId(m_folderId);
data.fileStatus(FileManagement::FileStatus::Valid);
data.fileCategory(FileManagement::FileCategory::User); // user docs
data.fileType(FileManagement::FileType::Jpg);
data.operatorId(m_operatorId);
data.lastModified(QDateTime::currentMSecsSinceEpoch());
fileName = QLatin1String("/logo_Project.jpg");
file.setFileName(QCoreApplication::applicationDirPath()+fileName);
if (!file.open(QFile::ReadOnly))
{
ERROR_LOG(m_logger) << "Error opening file " << fileName;
failExit();
}
rawImage = file.readAll();
DEBUG_LOG(m_logger) << "Read file " << fileName;
file.close();
data.content(LtsUtils::convert<std::vector<uint8_t>>(rawImage));
m_fileContentId = 0;
if (!m_ftc->fileContentModifyRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
}
QTRY_VERIFY(m_fileContentId > 0);
}
// ------------------------------------------------------------------------------
void FlmTests::tryModifyFileContent()
{
INFO_LOG(m_logger) << "trying to send file content modify request ";
DEBUG_LOG(m_logger) << "m_fileContentId = " << m_fileContentId;
m_dtc->waitForHistoricalDataFileContent();
const FileManagement::FileContent &flc = m_dtc->fileContent(m_fileContentId);
FileManagement::FileContentModifyRequest data;
DEBUG_LOG(m_logger) << "flc.id() = " << flc.id();
if (flc.id() == 0)
{
ERROR_LOG(m_logger) << "Cannot find File Content Id = " << m_fileContentId;
failExit();
}
else
{
if (!checkContentSize(m_fileContentId))
{
ERROR_LOG(m_logger) << "Content size 0";
failExit();
}
DEBUG_LOG(m_logger) << "Content size = " << m_content.size();
data.id(flc.id());
data.name(flc.name());
if (flc.exerciseId().is_set())
{
data.exerciseId(flc.exerciseId().get());
if (flc.phaseId().is_set())
data.phaseId(flc.phaseId().get());
}
data.fileCategory(flc.fileCategory());
data.fileStatus(flc.fileStatus());
data.fileType(flc.fileType());
data.folderId(flc.folderId());
data.isTemplate(flc.isTemplate());
data.isUsedBy(flc.isUsedBy());
data.usedBy(flc.usedBy());
data.operatorId(flc.operatorId());
data.properties(flc.properties());
data.content(m_content);
// changing only name, template, last modified
data.name("Test File Content Updated");
data.isTemplate(true);
data.lastModified(QDateTime::currentMSecsSinceEpoch());
if (!m_ftc->fileContentModifyRequest(FileContentModifyRequest(data), this))
{
ERROR_LOG(m_logger) << "Error requesting modify data";
failExit();
}
QTest::qWait(1000);
}
}
// ------------------------------------------------------------------------------
bool FlmTests::checkContentSize(int fileId)
{
GetFileContentDataRequest request;
request.fileContentId(fileId);
m_content.clear();
if (!m_ftc->getFileContentDataRequest(request, this))
{
ERROR_LOG(m_logger) << "Cannot retrieve file content for id = " << fileId;
return false;
}
QTest::qWait(1000);
return (m_content.size() > 0);
}
// ------------------------------------------------------------------------------
void FlmTests::tryUpdateStatus()
{
INFO_LOG(m_logger) << "trying update status file content";
DEBUG_LOG(m_logger) << "m_fileContentId = " << m_fileContentId;
m_dtc->waitForHistoricalDataFileContent();
const FileManagement::FileContent &flc = m_dtc->fileContent(m_fileContentId);
DEBUG_LOG(m_logger) << "flc.id() = " << flc.id();
if (flc.id() == 0)
{
ERROR_LOG(m_logger) << "Cannot find File Content Id = " << m_fileContentId;
failExit();
}
else
{
if (!m_db->updateStatus(m_fileContentId, FileManagement::FileStatus::Deleted, m_operatorId))
{
ERROR_LOG(m_logger) << "Cannot update status for File Content Id = " << m_fileContentId;
failExit();
}
QTest::qWait(1000);
if (!checkContentSize(m_fileContentId))
{
ERROR_LOG(m_logger) << "Content size 0";
failExit();
}
QTest::qWait(1000);
}
}
// ------------------------------------------------------------------------------
void FlmTests::tryRemoveFileContent()
{
INFO_LOG(m_logger) << "trying to send FileContentRemoveRequest ";
m_dtc->waitForHistoricalDataFileContent();
if (!m_ftc->fileContentRemoveRequest(FileContentRemoveRequest(m_fileContentId), this))
{
ERROR_LOG(m_logger) << "Error requesting delete data";
failExit();
}
QTest::qWait(1000);
}
// ------------------------------------------------------------------------------
void FlmTests::tryExportFileContent()
{
INFO_LOG(m_logger) << "trying to send FileContentExportRequest ";
m_dtc->waitForHistoricalDataFileContent();
if (!m_ftc->fileContentExportRequest(FileContentExportRequest(m_fileContentId), this))
{
ERROR_LOG(m_logger) << "Error requesting export data";
failExit();
}
QTest::qWait(1000);
if (!checkContentSize(m_fileContentId))
{
ERROR_LOG(m_logger) << "Content size 0";
failExit();
}
QTest::qWait(1000);
}
// ------------------------------------------------------------------------------
void FlmTests::tryCreatePlan()
{
INFO_LOG(m_logger) << "trying to send file content create request ";
FileContentModifyRequest data;
data.name("Test Plan");
data.isTemplate(false);
data.folderId(m_folderId);
data.fileStatus(FileManagement::FileStatus::Valid);
data.fileCategory(FileManagement::FileCategory::Global); // global
data.fileType(FileManagement::FileType::TacticalPlan); // plan
data.operatorId(m_operatorId);
data.lastModified(QDateTime::currentMSecsSinceEpoch());
QByteArray vmTest;
vmTest += "bla-bla-bla";
data.content(LtsUtils::convert<std::vector<uint8_t>>(vmTest));
m_fileContentId = 0;
if (!m_ftc->fileContentModifyRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
}
QTRY_VERIFY(m_fileContentId > 0);
}
// ------------------------------------------------------------------------------
void FlmTests::tryCreateFav()
{
INFO_LOG(m_logger) << "trying to send file content create request ";
FileContentModifyRequest data;
data.name("Test Fav");
data.isTemplate(false);
data.folderId(m_folderId);
data.fileStatus(FileManagement::FileStatus::Valid);
data.fileCategory(FileManagement::FileCategory::User); // user
data.fileType(FileManagement::FileType::OperatorFavourite); // fav
data.operatorId(m_operatorId);
data.lastModified(QDateTime::currentMSecsSinceEpoch());
QByteArray vmTest;
vmTest += "bla-bla-bla";
data.content(LtsUtils::convert<std::vector<uint8_t>>(vmTest));
m_fileContentId = 0;
if (!m_ftc->fileContentModifyRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
}
QTRY_VERIFY(m_fileContentId > 0);
}
// ------------------------------------------------------------------------------
void FlmTests::tryCreateSymbol()
{
INFO_LOG(m_logger) << "trying to send file content create request ";
FileContentModifyRequest data;
data.name("Test Symbol");
data.isTemplate(false);
data.folderId(m_folderId);
data.fileStatus(FileManagement::FileStatus::Valid);
data.fileCategory(FileManagement::FileCategory::Global); // global
data.fileType(FileManagement::FileType::OperatorDefinedSymbol);
data.operatorId(m_operatorId);
data.lastModified(QDateTime::currentMSecsSinceEpoch());
QByteArray vmTest;
vmTest += "bla-bla-bla";
data.content(LtsUtils::convert<std::vector<uint8_t>>(vmTest));
m_fileContentId = 0;
if (!m_ftc->fileContentModifyRequest(data, this))
{
ERROR_LOG(m_logger) << "Error requesting create data";
failExit();
}
QTRY_VERIFY(m_fileContentId > 0);
}
// ------------------------------------------------------------------------------
void FlmTests::tryGetContent()
{
GetFileContentDataRequest request;
request.fileContentId(m_fileContentId);
INFO_LOG(m_logger) << "trying to send content request for file Id = " << m_fileContentId;
if (!m_ftc->getFileContentDataRequest(request, this))
{
ERROR_LOG(m_logger) << "Error requesting content for id : " << m_fileContentId;
failExit();
}
QTRY_VERIFY(m_content.size() > 0);
DEBUG_LOG(m_logger) << "Got content size: " << m_content.size();
}
// ------------------------------------------------------------------------------
void FlmTests::onGetFileContentDataReply(const GetFileContentDataReply &replyObject)
{
if (replyObject.errorString().size() > 0)
{
ERROR_LOG(m_logger) << "Got onGetFileContentDataReply error: " << replyObject.errorString();
failExit();
}
INFO_LOG(m_logger) << "Got reply with id " << replyObject.id()
<< " and errorString " << replyObject.errorString();
m_content = replyObject.content();
DEBUG_LOG(m_logger) << "Content size: " << m_content.size();
// QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
// ************* CUSTOM DTC's*****************************************************
// ------------------------------------------------------------------------------
void FlmTests::tryGetAllTemplates()
{
INFO_LOG(m_logger) << "tryGetAllTemplates";
QList<FileContent> allTemplates;
m_dtc->waitForHistoricalDataFileContent();
if (!m_dtc->getAllTemplates(allTemplates))
{
ERROR_LOG(m_logger) << "Error requesting dtc data";
failExit();
}
DEBUG_LOG(m_logger) << "Found " << allTemplates.size() << " templates";
for (const FileContent &fc : qAsConst(allTemplates))
DEBUG_LOG(m_logger) << "Found template (id, name) = (" << fc.id() << ", " << fc.name() << ")";
QTest::qWait(1000);
}
// ------------------------------------------------------------------------------
void FlmTests::tryGetAllPlans()
{
INFO_LOG(m_logger) << "tryGetAllPlans";
QStringList allPlans;
m_dtc->waitForHistoricalDataFileContent();
if (!m_dtc->getAllFiles(FileManagement::FileType::TacticalPlan, m_folderId, allPlans))
{
ERROR_LOG(m_logger) << "Error requesting dtc data";
failExit();
}
DEBUG_LOG(m_logger) << "Found " << allPlans.size() << " plans";
for (const QString &plan : qAsConst(allPlans))
DEBUG_LOG(m_logger) << "Found plan = " << plan;
QTest::qWait(1000);
}
// ------------------------------------------------------------------------------
void FlmTests::tryGetAllFavs()
{
INFO_LOG(m_logger) << "tryGetAllFavs";
QStringList allFavs;
m_dtc->waitForHistoricalDataFileContent();
if (!m_dtc->getAllFiles(FileManagement::FileType::OperatorFavourite, m_folderId, allFavs))
{
ERROR_LOG(m_logger) << "Error requesting dtc data";
failExit();
}
DEBUG_LOG(m_logger) << "Found " << allFavs.size() << " favs";
for (const QString &fav : qAsConst(allFavs))
DEBUG_LOG(m_logger) << "Found fav = " << fav;
QTest::qWait(1000);
}
// ------------------------------------------------------------------------------
void FlmTests::tryGetAllSymbols()
{
INFO_LOG(m_logger) << "tryGetAllSymbols";
QStringList allSymbols;
m_dtc->waitForHistoricalDataFileContent();
if (!m_dtc->getAllFiles(FileManagement::FileType::OperatorDefinedSymbol, m_folderId, allSymbols))
{
ERROR_LOG(m_logger) << "Error requesting dtc data";
failExit();
}
DEBUG_LOG(m_logger) << "Found " << allSymbols.size() << " symbols";
for (const QString &symbol : qAsConst(allSymbols))
DEBUG_LOG(m_logger) << "Found symbol = " << symbol;
QTest::qWait(1000);
}
//********************* GENERAL *************************************************
// ------------------------------------------------------------------------------
void FlmTests::onError(const QString &reason)
{
ERROR_LOG(m_logger) << "Got Reply error: " << reason;
failExit();
}
// ------------------------------------------------------------------------------
void FlmTests::onReply(const Core::FunctionReplyObject &replyObject)
{
if (replyObject.error())
{
onError(replyObject.translated());
return;
}
INFO_LOG(m_logger) << "Got Reply with id " << replyObject.id()
<< " and errorString " << replyObject.translated();
// QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
// ------------------------------------------------------------------------------
void FlmTests::failExit()
{
ERROR_LOG(m_logger) << "FAIL EXIT !";
m_bTestsSuccessful = false;
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
//--------------------------------------------------------------------------
void FlmTests::onFolderModifyReply(const Core::FunctionReplyObject &replyObject)
{
if (replyObject.error())
{
ERROR_LOG(m_logger) << "Got onFolderModifyReply error: " << replyObject();
failExit();
return;
}
INFO_LOG(m_logger) << "Got modifyFolderReply with id " << replyObject.id()
<< " and errorString " << replyObject.translated();
m_folderId = replyObject.id();
}
//--------------------------------------------------------------------------
void FlmTests::onFileContentModifyReply(const Core::FunctionReplyObject &replyObject)
{
if (replyObject.error())
{
ERROR_LOG(m_logger) << "Got onFileContentModifyReply error: " << replyObject();
failExit();
return;
}
INFO_LOG(m_logger) << "Got modifyFileReply with id " << replyObject.id()
<< " and errorString " << replyObject.translated();
m_fileContentId = replyObject.id();
}
// ------------------------------------------------------------------
class CmdLineParser : public LtsCommandLineParser::LtsCommandLineParser
{
public:
CmdLineParser()
: LtsCommandLineParser()
{
addOption({ QStringList() << QLatin1String("t") << QLatin1String("testId")
, QLatin1String("TestId.")
, QLatin1String("Default: -1")
, QLatin1String("-1")
});
addOption({ QStringList() << QLatin1String("f") << QLatin1String("folderId")
, QLatin1String("FolderId.")
, QLatin1String("Default: 0 (root folder)")
, QLatin1String("-1")
});
addOption({ QStringList() << QLatin1String("c") << QLatin1String("fileContentId")
, QLatin1String("FileContentId.")
, QLatin1String("Default: -1")
, QLatin1String("-1")
});
addOption({ QStringList() << QLatin1String("o") << QLatin1String("operatorId")
, QLatin1String("OperatorId.")
, QLatin1String("Default: 99 (Organisator)")
, QLatin1String("-1")
});
}
int testId() const { return isSet(QLatin1String("t")) ? value(QLatin1String("t")).toInt() : -1; }
int folderId() const { return isSet(QLatin1String("f")) ? value(QLatin1String("f")).toInt() : 0; }
int fileContentId() const { return isSet(QLatin1String("c")) ? value(QLatin1String("c")).toInt() : -1; }
int operatorId() const { return isSet(QLatin1String("o")) ? value(QLatin1String("o")).toInt() : 99; }
};
// ------------------------------------------------------------------
int main(int argc, char **argv)
{
int iRet = -1;
NGLCoreApplication app(argc, argv);
app.createLogger("FLM", 0);
CmdLineParser options;
if (!options.init())
return iRet;
std::unique_ptr<FileManagement::FlmTests> FlmTests(new FileManagement::FlmTests());
if (!FlmTests->init(options.domainId(), options.testId(), options.folderId(), options.fileContentId(), options.operatorId()))
return iRet;
QTimer::singleShot(0, FlmTests.get(), &FileManagement::FlmTests::startTest);
STARTUP_LOG(app.baseLogger());
app.exec();
iRet = FlmTests->testsSuccessful() ? 0 : 1;
fprintf(stderr, "\n%d\n\n", iRet);
INFO_LOG(app.baseLogger()) << "** TEST result = " << iRet;
SHUTDOWN_LOG(app.baseLogger());
return iRet;
}
+111
View File
@@ -0,0 +1,111 @@
/**
* @RDE_HEADER@
* ISM Function Topic test executable
* $Id$
* @RDE_HEADER@
* Module Tests for FLM
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-05
*/
#pragma once
#include <FileManagement/flm_ftc.h>
#include <FileManagement/flm_dtc.h>
#include <FileManagement/flm_db.h>
#include <FileManagement/flm_db_impl_custom.h>
#include <FileManagement/flm_ftc_types.h>
#include <DDS/DDSConnector/dds_connector.h>
#include <FileManagement/logger.h>
#include <QPixmap>
#include <ngldb/db_service_handler.h>
namespace FileManagement
{
using DbHandler = NGLDB::DbServiceHandler<DatabaseInterface>;
class FlmTests : public QObject
, protected FileManagement::Interface::Ftc::FolderModifyReplyHandler
, protected FileManagement::Interface::Ftc::FolderRemoveReplyHandler
, protected FileManagement::Interface::Ftc::FileContentModifyReplyHandler
, protected FileManagement::Interface::Ftc::FileContentRemoveReplyHandler
, protected FileManagement::Interface::Ftc::FileContentExportReplyHandler
, protected FileManagement::Interface::Ftc::GetFileContentDataReplyHandler
{
Q_OBJECT
public:
explicit FlmTests(QObject *parent = nullptr);
~FlmTests();
bool init(int domainId, int testId, int folderId, int fileContentId, int operatorId);
bool testsSuccessful() const { return m_bTestsSuccessful; }
public Q_SLOTS:
void startTest();
protected Q_SLOTS:
// folder
void tryCreateFolder();
void tryModifyFolder();
void tryRemoveFolder();
int createFolder(int parentFolderId, const QString &folderName, bool isHidden = false);
// file content
void tryCreateFileContent();
void tryModifyFileContent();
void tryRemoveFileContent();
void tryExportFileContent();
void tryGetContent();
void tryUpdateStatus();
// plans etc.
void tryCreatePlan();
void tryCreateFav();
void tryCreateSymbol();
// custom dtc's
void tryGetAllTemplates();
void tryGetAllPlans();
void tryGetAllFavs();
void tryGetAllSymbols();
protected:
// folder
void onFolderModifyReply(const Core::FunctionReplyObject &replyObject) override final;
void onFolderRemoveReply(const Core::FunctionReplyObject &replyObject) override final { onReply(replyObject); }
// file content
void onFileContentModifyReply(const Core::FunctionReplyObject &replyObject) override final;
void onFileContentRemoveReply(const Core::FunctionReplyObject &replyObject) override final { onReply(replyObject); }
void onFileContentExportReply(const Core::FunctionReplyObject &replyObject) override final { onReply(replyObject); }
void onGetFileContentDataReply(const GetFileContentDataReply &replyObject) override final;
// general
void onError(const QString &reason);
void onReply(const Core::FunctionReplyObject &replyObject);
void failExit();
bool checkContentSize(int fileId);
private:
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
std::shared_ptr<FileManagement::Interface::Ftc> m_ftc;
std::shared_ptr<FileManagement::Interface::Dtc> m_dtc;
std::shared_ptr<FileManagement::DatabaseInterface> m_db;
std::shared_ptr<FileManagement::DbHandler> m_dbHandler;
std::vector<uint8_t> m_content;
// given
int m_testId;
int m_folderId;
int m_fileContentId;
int m_operatorId;
bool m_bTestsSuccessful;
LOGGER_T m_logger;
};
} // namespace FileManagement
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

@@ -0,0 +1,103 @@
/**
* @RDE_HEADER@
* The ClientMessage class is an abstract base class for concrete ClientMessage objects
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#include "client_message.h"
#include "WebSocketInterface/Messages/reply_message.h"
#include "WebSocketInterface/json_keys.h"
#include "WebSocketInterface/data_manager.h"
#include <QtCore/QJsonDocument>
#include <QtCore/QUuid>
namespace FileManagement
{
namespace WebSocketInterface
{
namespace ClientMessages
{
using namespace JsonKeys;
// ####### ClientMessageFactory begin #######
ClientMessageFactory::ClientMessageFactory(DataManager *dataManager)
: LtsWebSocket::AbstractClientMessageFactory(getLogger("ClientMessageFactory"))
, m_dataManager(dataManager)
{}
LtsWebSocket::AbstractClientMessage *ClientMessageFactory::createMessage(LtsWebSocket::ReplyHandler *client,
const QString &message)
{
LtsWebSocket::AbstractClientMessage *result = checkAttributes(client, message);
if (result)
return result;
if (m_type == OcBaseDownload::WebSocketInterface::JsonKeys::BASE_DL_REQUEST())
result = new BaseDlRequest(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == OcBaseDownload::WebSocketInterface::JsonKeys::PDF_LIST_REQUEST())
result = new PdfListRequest(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
return checkResult(client, message, result);
}
// ####### ClientMessageFactory end #######
// ####### ClientMessage begin #######
ClientMessage::ClientMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: LtsWebSocket::AbstractClientMessage(client, type, typeId, uuid, data)
, m_dataManager(dataManager)
, m_logger(getLogger("ClientMessage"))
{}
// ####### ClientMessage end #######
// ####### BaseDlRequest begin #######
BaseDlRequest::BaseDlRequest(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: ClientMessage(dataManager, client, type, typeId, uuid, data)
{}
void BaseDlRequest::process()
{
if (m_data.toObject().contains(OcBaseDownload::WebSocketInterface::JsonKeys::EXERCISE_ID()))
{
int exerciseId = m_data.toObject().value(OcBaseDownload::WebSocketInterface::JsonKeys::EXERCISE_ID()).toInt();
m_client->addReply(m_dataManager->folderBaseData(m_uuid));
m_client->addReply(m_dataManager->fileContentBaseData(m_uuid, exerciseId));
}
else
{
LtsWebSocket::ErrorMessage::ErrorData errorData;
errorData.uuid = m_uuid;
errorData.errorMessage = QStringLiteral("No exercise ID specified for FLM base DL.");
m_client->addReply(new LtsWebSocket::ErrorMessage(errorData));
}
}
bool BaseDlRequest::hasValidData() const
{
return true;
}
// ####### BaseDlRequest end #######
// ####### PdfListRequest begin #######
PdfListRequest::PdfListRequest(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: ClientMessage(dataManager, client, type, typeId, uuid, data)
{}
void PdfListRequest::process()
{
m_client->addReply(m_dataManager->pdfList(m_uuid,
m_data.toObject().value(OcBaseDownload::WebSocketInterface::JsonKeys::EXERCISE_ID()).toInt()));
}
bool PdfListRequest::hasValidData() const
{
return true;
}
// ####### PdfListRequest end #######
} // namespace ClientMessages
} // namespace WebSocketInterface
} // namespace FileManagement
@@ -0,0 +1,87 @@
/**
* @RDE_HEADER@
* The ClientMessage class is an abstract base class for concrete ClientMessage objects
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <QtCore/QJsonObject>
#include <LtsWebSocket/client_message_factory.h>
#include <LtsWebSocket/client_message.h>
#include "logger.h"
namespace FileManagement
{
namespace WebSocketInterface
{
class DataManager;
namespace ClientMessages
{
/**
* @brief The ClientMessageFactory class creates ClientMessages which will then be processed
*/
class ClientMessageFactory final : public LtsWebSocket::AbstractClientMessageFactory
{
public:
explicit ClientMessageFactory(DataManager *dataManager);
/**
* @brief create Only way to create a ClientMessage object
* @param message Text message which will be converted to a ClientMessage object
* @return A ClientMessage object, which represents a concrete ClientMessage
*/
LtsWebSocket::AbstractClientMessage *createMessage(LtsWebSocket::ReplyHandler *client,
const QString &message);
private:
DataManager *m_dataManager;
}; // class ClientMessageFactory
/**
* @brief The ClientMessage class is an abstract base class for concrete ClientMessage objects
*/
class ClientMessage : public LtsWebSocket::AbstractClientMessage
{
protected: // method
explicit ClientMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data = QJsonValue());
protected: // attributes
DataManager *m_dataManager;
LOGGER_T m_logger;
}; // class ClientMessage
/**
* @brief The BaseDlRequest class handles the base DL request and sends multiple replys depending on the data requested
*/
class BaseDlRequest : public ClientMessage
{
public:
explicit BaseDlRequest(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data);
void process();
bool hasValidData() const;
}; // class BaseDlRequest
/**
* @brief The PdfListRequest class handles the PdfList request and sends a list of all available PDF documents
*/
class PdfListRequest : public ClientMessage
{
public:
explicit PdfListRequest(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data);
void process();
bool hasValidData() const;
}; // class PdfListRequest
} // namespace ClientMessages
} // namespace WebSocketInterface
} // namespace FileManagement
@@ -0,0 +1,50 @@
/**
* @RDE_HEADER@
* The ReplyMessage class is an abstract base class for all possible messages which are sent to the client
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#include "reply_message.h"
#include <LtsWebSocket/json_keys.h>
#include "WebSocketInterface/json_keys.h"
namespace FileManagement
{
namespace WebSocketInterface
{
namespace ReplyMessages
{
using namespace JsonKeys;
using namespace LtsWebSocket::JsonKeys;
// ####### FolderBaseData begin #######
FolderBaseData::FolderBaseData(const QJsonArray &data, const QString &uuid)
: LtsWebSocket::ReplyMessage(FOLDER_BASE_DATA(), 1, uuid) // Todo: Check whether typeId is correct
{
m_jsonRepresentation.insert(DATA(), data);
}
// ####### FolderBaseData end #######
// ####### FileContentBaseData begin #######
FileContentBaseData::FileContentBaseData(const QJsonArray &data, const QString &uuid)
: LtsWebSocket::ReplyMessage(FILE_CONTENT_BASE_DATA(), 2, uuid) // Todo: Check whether typeId is correct
{
m_jsonRepresentation.insert(DATA(), data);
}
// ####### FileContentBaseData end #######
// ####### PdfListData begin #######
PdfListData::PdfListData(const QJsonArray &data, const QString &uuid)
: LtsWebSocket::ReplyMessage(PDF_LIST_DATA(), 3, uuid) // Todo: Check whether typeId is correct
{
m_jsonRepresentation.insert(DATA(), data);
}
// ####### PdfListData end #######
} // namespace ReplyMessages
} // namespace WebSocketInterface
} // namespace FileManagement
@@ -0,0 +1,53 @@
/**
* @RDE_HEADER@
* The ReplyMessage class is an abstract base class for all possible messages which are sent to the client
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <LtsWebSocket/reply_message.h>
#include <QJsonArray>
#include <QString>
namespace FileManagement
{
namespace WebSocketInterface
{
namespace ReplyMessages
{
/**
* @brief The FolderBaseData class training area data for base DL
*/
class FolderBaseData : public LtsWebSocket::ReplyMessage
{
public:
explicit FolderBaseData(const QJsonArray &data, const QString &uuid);
}; // class FolderBaseData
/**
* @brief The FileContentBaseData class map description data for base DL
*/
class FileContentBaseData : public LtsWebSocket::ReplyMessage
{
public:
explicit FileContentBaseData(const QJsonArray &data, const QString &uuid);
}; // class FileContentBaseData
/**
* @brief The PdfListData class contains a list of all available PDF documents
*/
class PdfListData : public LtsWebSocket::ReplyMessage
{
public:
explicit PdfListData(const QJsonArray &data, const QString &uuid);
}; // class PdfListData
} // namespace ReplyMessages
} // namespace WebSocketInterface
} // namespace FileManagement
@@ -0,0 +1,212 @@
/**
* @RDE_HEADER@
* The DataManager class handles data to be send to the websocket
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#include "data_manager.h"
#include "Messages/reply_message.h"
#include "main_handler.h"
#include "flm_db.h"
#include "json_keys.h"
#include <ngldb/nsqlquery.h>
namespace FileManagement
{
namespace WebSocketInterface
{
//---------------------------------------------------------------------------------------------------------
DataManager::DataManager(MainHandler *mainHandler)
: LtsWebSocket::DataManagerBaseDl<DatabaseInterface>(mainHandler->db(), getLogger("DataManager"))
{}
//---------------------------------------------------------------------------------------------------------
LtsWebSocket::ReplyMessage *DataManager::folderBaseData(const QString &uuid) const
{
return toBaseDataMessageFromDb<Database::FlmFolder, ReplyMessages::FolderBaseData>(uuid);
}
LtsWebSocket::ReplyMessage *DataManager::fileContentBaseData(const QString &uuid, int exerciseId) const
{
DEBUG_LOG(m_logger) << "preparing file content base data for exercise " << exerciseId;
QVector<Database::FlmFolder> folderVec;
m_dbInterface->select(folderVec);
int snapshotFolderId = getFolderId(folderVec, QStringLiteral("Snapshots"), exerciseId);
// Filter for everything that is in the given exercise + global tactical plans and symbols
QVector<Database::FlmFileContent> dataVec;
//this is DONE BY HAND!!!! so very uncool
//I HATE YOU SO MUCH YOU FUCKING FUCK FUCK!
const QString where = QStringLiteral(" WHERE exercise_id is null OR exercise_id = ") + QString::number(exerciseId) + QStringLiteral(" and file_type_id in (1,2,4,5,6,7,8)");
const QString tableName(QStringLiteral("flm.flm_file_content"));
const QString stmt(QStringLiteral("SELECT id, name, is_template, folder_id, file_category_id, file_type_id, file_status_id, exercise_id, phase_id, operator_id, content, properties, is_used_by, used_by, last_modified"
" FROM ") + tableName + where);
std::unique_ptr<NSqlQuery> query = std::unique_ptr<NSqlQuery>(new NSqlQuery(m_dbInterface->database(), m_logger));
query->prepare(stmt);
if(query->exec())
{
Database::FlmFileContent data;
while (query->next())
{
int i = 0;
data.id = query->value(i++).toLongLong();
data.name = query->value(i++).toString();
data.isTemplate = query->value(i++).toBool();
data.folderId = query->value(i++).toLongLong();
data.fileCategoryId = static_cast<FileManagement::FileCategory_def::type>(query->value(i++).toInt());
data.fileTypeId = static_cast<FileManagement::FileType_def::type>(query->value(i++).toInt());
data.fileStatusId = static_cast<FileManagement::FileStatus_def::type>(query->value(i++).toInt());
data.exerciseId = query->value(i++);
data.phaseId = query->value(i++);
data.operatorId = query->value(i++).toInt();
data.content = query->value(i++).toByteArray();
QVariant xx = query->value(i++);
data.properties = xx.isNull() ? QStringLiteral("{}") : xx.toString();
data.isUsedBy = query->value(i++).toBool();
data.usedBy = query->value(i++).toInt();
data.lastModified = query->value(i++).toLongLong();
if ((data.fileTypeId == FileManagement::FileType::Jpg ||
data.fileTypeId == FileManagement::FileType::Png)
&& data.folderId == snapshotFolderId )
{
//ERROR_LOG(m_logger) << "errorMessage";
continue;
}
//ERROR_LOG(m_logger) << "ADD " << data.name;
dataVec.append(data);
}
}else
{
const QString errorMessage = QStringLiteral("Error reading data from database!");
ERROR_LOG(m_logger) << errorMessage;
LtsWebSocket::ErrorMessage::ErrorData errData;
errData.errorMessage = errorMessage;
errData.uuid = uuid;
return new LtsWebSocket::ErrorMessage(errData);
}
DEBUG_LOG(m_logger) << "filtering file content base data for exercise ID: " << exerciseId;
DEBUG_LOG(m_logger) << "sending file content base data" << dataVec.size();
return new ReplyMessages::FileContentBaseData(DatabaseInterface::toJson(dataVec), uuid);
/*
auto cb = [&dataVec, snapshotFolderId, exerciseId](const Database::FlmFileContent & content)
{
if ((content.exerciseId != exerciseId) && (content.exerciseId != 0))
return;
//now skip all unneeded document types -> i prefer opt out instead of opt in
if (content.fileTypeId == FileManagement::FileType::MSOfficeDocument || 12
content.fileTypeId == FileManagement::FileType::MSOfficeDocument97 || 13
content.fileTypeId == FileManagement::FileType::MSOfficeSpreadsheet || 10
content.fileTypeId == FileManagement::FileType::MSOfficeSpreadsheet97 || 13
content.fileTypeId == FileManagement::FileType::MSOfficePresentation || 16
content.fileTypeId == FileManagement::FileType::MSOfficePresentation97 || 17
content.fileTypeId == FileManagement::FileType::OpenOfficePresentation || 11
content.fileTypeId == FileManagement::FileType::OpenOfficeSpreadsheet || 10
content.fileTypeId == FileManagement::FileType::OpenOfficeDocument || 9
content.fileTypeId == FileManagement::FileType::Unknown || 0
content.fileTypeId == FileManagement::FileType::Pdf) 3
* 1 2 4 5 6 7 8 18*
return;
if ((content.fileTypeId == FileManagement::FileType::Jpg ||
content.fileTypeId == FileManagement::FileType::Png)
&& content.folderId == snapshotFolderId)
return; //no snapsholts
dataVec += content;
};
// read all data from database
if (!m_dbInterface->select(cb))
{
const QString errorMessage = QStringLiteral("Error reading data from database!");
ERROR_LOG(m_logger) << errorMessage;
LtsWebSocket::ErrorMessage::ErrorData errData;
errData.errorMessage = errorMessage;
errData.uuid = uuid;
return new LtsWebSocket::ErrorMessage(errData);
}
DEBUG_LOG(m_logger) << "filtering file content base data for exercise ID: " << exerciseId;
DEBUG_LOG(m_logger) << "sending file content base data";
return new ReplyMessages::FileContentBaseData(DatabaseInterface::toJson(dataVec), uuid);
*/
}
LtsWebSocket::ReplyMessage *DataManager::pdfList(const QString &uuid, int exerciseId) const
{
DEBUG_LOG(m_logger) << "Preparing file content base data for PDF list";
QJsonArray dataArr;
auto cb = [&dataArr, exerciseId] (const Database::FlmFileContent &current)
{
if ((current.exerciseId != exerciseId) && (current.exerciseId != 0))
return;
if (current.fileTypeId != FileManagement::FileType::Pdf)
return;
QJsonObject obj({{JsonKeys::NAME(), current.name},
{JsonKeys::FILE_ID(), current.id},
{JsonKeys::FILE_SIZE(), current.content.size()},
{JsonKeys::FILE_CATEGORY(), current.fileCategoryId.underlying()},
{JsonKeys::IS_TEMPLATE(), current.isTemplate},
{JsonKeys::PROPERTIES(), current.properties},
{JsonKeys::FILE_STATUS(), current.fileStatusId.underlying() },
{JsonKeys::FOLDER_ID(), current.folderId },
{JsonKeys::PHASE_ID(), current.phaseId.toInt() },
{JsonKeys::OPERATOR_ID(), current.operatorId},
{JsonKeys::EXERCISE_ID(), current.exerciseId.toInt()}});
dataArr.append(obj);
};
if (!m_dbInterface->select(cb))
{
const QString errorMessage = QStringLiteral("Error reading data from database!");
ERROR_LOG(m_logger) << errorMessage;
LtsWebSocket::ErrorMessage::ErrorData errData;
errData.errorMessage = errorMessage;
errData.uuid = uuid;
return new LtsWebSocket::ErrorMessage(errData);
}
return new ReplyMessages::PdfListData(dataArr, uuid);
}
int DataManager::getFolderId(const QVector<Database::FlmFolder> &dataVec, const QString &folderName, int exerciseId) const
{
int parentFolder = 0;
if (exerciseId > 0)
{
const QString exName = QLatin1String("$EX_")+QString::number(exerciseId);
parentFolder = getFolderId(dataVec, exName, 0);
}
for (const auto &fld :dataVec)
{
if (fld.name == folderName)
{
if (exerciseId > 0 && parentFolder > 0)
{
if (fld.path().size() > 1 && fld.path().at(fld.path().size() - 2) == parentFolder)
return fld.id;
}
else
return fld.id;
}
}
return 0;
}
} // namespace WebSocketInterface
} // namespace FileManagement
@@ -0,0 +1,41 @@
/**
* @RDE_HEADER@
* The DataManager class handles data to be send to the websocket
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <LtsWebSocket/data_manager_base_dl.h>
#include <FileManagement/flm_db.h>
#include "logger.h"
namespace FileManagement
{
class MainHandler;
namespace WebSocketInterface
{
/**
* @brief The DataManager class is a convenience class for managing base DL data
*/
class DataManager final : public LtsWebSocket::DataManagerBaseDl<DatabaseInterface>
{
public:
/**
* @brief DataManager Constructor
* @param mainHandler Source for needed handlers
*/
explicit DataManager(MainHandler *mainHandler);
LtsWebSocket::ReplyMessage *folderBaseData(const QString &uuid) const;
LtsWebSocket::ReplyMessage *fileContentBaseData(const QString &uuid, int exerciseId) const;
LtsWebSocket::ReplyMessage *pdfList(const QString &uuid, int exerciseId) const;
int getFolderId(const QVector<Database::FlmFolder> &dataVec, const QString &folderName, int exerciseId ) const;
}; // class DataManager
} // namespace WebSocketInterface
} // namespace FileManagement
+46
View File
@@ -0,0 +1,46 @@
/**
* @RDE_HEADER@
* Header file which holds all occuring JSON keys
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <QString>
#include <OcBaseDownload/WebSocketInterface/json_keys.h>
namespace FileManagement
{
namespace WebSocketInterface
{
/**
* @brief Namespace which holds all occuring JSON keys as const QString objects
*/
namespace JsonKeys
{
// types for client --> server messages
// types for server --> client messages
inline QString FILE_CONTENT_BASE_DATA() { return QStringLiteral("fileContentBaseData"); }
inline QString FOLDER_BASE_DATA() { return QStringLiteral("folderBaseData"); }
inline QString PDF_LIST_DATA() { return QStringLiteral("pdfListData"); }
// data keys
inline QString EXERCISE_ID() { return QStringLiteral("exerciseId"); }
inline QString FILE_CATEGORY() { return QStringLiteral("fileCategory"); }
inline QString FILE_ID() { return QStringLiteral("fileId"); }
inline QString FILE_SIZE() { return QStringLiteral("fileSize"); }
inline QString FILE_STATUS() { return QStringLiteral("fileStatus"); }
inline QString FOLDER_ID() { return QStringLiteral("folderId"); }
inline QString IS_TEMPLATE() { return QStringLiteral("isTemplate"); }
inline QString NAME() { return QStringLiteral("name"); }
inline QString OPERATOR_ID() { return QStringLiteral("operatorID"); }
inline QString PHASE_ID() { return QStringLiteral("phaseId"); }
inline QString PROPERTIES() { return QStringLiteral("properties"); }
} // namespace JsonKeys
} // namespace WebSocketInterface
} // namespace FileManagement
@@ -0,0 +1,70 @@
/**
* @RDE_HEADER@
* Handler for the WebSocket Interface
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#include "websocket_interface_handler.h"
#include "main_handler.h"
#include "data_manager.h"
#include "WebSocketInterface/Messages/client_message.h"
#include "settings.h"
namespace FileManagement
{
namespace WebSocketInterface
{
WebSocketInterfaceHandler::WebSocketInterfaceHandler(MainHandler *mainHandler, QObject *parent)
: QObject(parent)
, m_webSocketServer(nullptr)
, m_messageFactory(nullptr)
, m_dataManager(nullptr)
, m_mainHandler(mainHandler)
, m_logger(getLogger("WebSocketInterfaceHandler"))
{
}
WebSocketInterfaceHandler::~WebSocketInterfaceHandler()
{
cleanup();
}
bool WebSocketInterfaceHandler::init()
{
cleanup();
DEBUG_LOG(m_logger) << "... ok";
m_dataManager = new DataManager(m_mainHandler);
m_messageFactory = new ClientMessages::ClientMessageFactory(m_dataManager);
m_webSocketServer = new LtsWebSocket::LtsWebSocketServer(m_messageFactory, this);
DEBUG_LOG(m_logger) << "Initialising LtsWebSocketServer";
if (!m_webSocketServer->init(QStringLiteral("FLM"), Settings::getWebSocketServerPortRange(1)))
{
ERROR_LOG(m_logger) << "Failed to initialise LtsWebSocketServer";
return false;
}
DEBUG_LOG(m_logger) << "... ok";
DEBUG_LOG(m_logger) << "Connection signals and slots";
DEBUG_LOG(m_logger) << "... ok";
return true;
}
void WebSocketInterfaceHandler::cleanup()
{
delete m_webSocketServer;
delete m_messageFactory;
delete m_dataManager;
}
} // namespace WebSocketInterface
} // namespace FileManagement
@@ -0,0 +1,70 @@
/**
* @RDE_HEADER@
* Handler for the WebSocket Interface
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <QtCore/QObject>
#include <LtsWebSocket/lts_web_socket_server.h>
#include "logger.h"
namespace FileManagement
{
class MainHandler;
namespace WebSocketInterface
{
namespace ClientMessages
{
class ClientMessageFactory;
}
class DataManager;
/**
* @brief The WebSocketInterfaceHandler class is the main class for the WebSocketInterface
*/
class WebSocketInterfaceHandler final : public QObject
{
Q_OBJECT
public:
/**
* @brief WebSocketInterfaceHandler Constructor
* @param mainHandler MainHandler to get the HandlerStructureElement from
*/
explicit WebSocketInterfaceHandler(MainHandler *mainHandler, QObject *parent = nullptr);
/**
* @brief ~WebSocketInterfaceHandler Destructor
*/
~WebSocketInterfaceHandler();
/**
* @brief init Initialises all needed classes for the WebSocketInterface
* @return True on success, otherwise false
*/
bool init();
/**
* @brief webSocketPort returns the listen port
* @return listen port
*/
unsigned short serverWebSocketPort() { return m_webSocketServer->webSocketPort(); }
private:
void cleanup();
private:
LtsWebSocket::LtsWebSocketServer *m_webSocketServer;
ClientMessages::ClientMessageFactory *m_messageFactory;
DataManager *m_dataManager;
MainHandler *m_mainHandler;
LOGGER_T m_logger;
}; // class WebSocketInterfaceHandle
} // namespace WebSocketInterface
} // namespace FileManagement
+44
View File
@@ -0,0 +1,44 @@
/**
* @RDE_HEADER@
* Base Class for all handlers in FLM
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-11-18
*/
#include "base.h"
#include "main_handler.h"
namespace FileManagement
{
Base::Base(MainHandler *mainHandler, NGL::INGLLogger &logger, QObject* parent)
: QObject(parent)
, m_mainHandler(mainHandler)
, m_logger(logger)
{}
Base::~Base()
{}
std::shared_ptr<DatabaseInterface> Base::db() const
{
return m_mainHandler->db();
}
std::shared_ptr<Interface::Dts> Base::dts() const
{
return m_mainHandler->dds()->dts();
}
std::shared_ptr<Interface::Dtc> Base::dtc() const
{
return m_mainHandler->dds()->dtc();
}
std::shared_ptr<Interface::Fts> Base::fts() const
{
return m_mainHandler->dds()->fts();
}
} // FileManagement
+37
View File
@@ -0,0 +1,37 @@
/**
* @RDE_HEADER@
* Base Class for all handlers in FLM
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-11-18
*/
#pragma once
#include <FileManagement/flm_db.h>
#include <FileManagement/flm_dts.h>
#include <FileManagement/flm_dtc.h>
#include <FileManagement/flm_fts.h>
#include "logger.h"
namespace FileManagement
{
class MainHandler;
class Base : public QObject
{
Q_OBJECT
protected:
explicit Base(MainHandler *mainHandler, NGL::INGLLogger &logger, QObject *parent = nullptr);
virtual ~Base();
std::shared_ptr<DatabaseInterface> db() const;
std::shared_ptr<Interface::Dts> dts() const;
std::shared_ptr<Interface::Dtc> dtc() const;
std::shared_ptr<Interface::Fts> fts() const;
protected:
MainHandler *m_mainHandler;
LOGGER_T m_logger;
};
}
+86
View File
@@ -0,0 +1,86 @@
/**
* Convert db structures to dds structures
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-07-20
*/
#pragma once
#include <FileManagement/flm_db.h>
#include <FileManagement/flm.hpp>
#include <LtsUtilsCore/dds_vector.h>
namespace FileManagement
{
namespace Database
{
inline FileContent convert(const FlmFileContent &dbData)
{
FileContent ddsData;
ddsData.id(dbData.id);
ddsData.name(dbData.name.toStdString());
ddsData.isTemplate(dbData.isTemplate);
ddsData.isHidden(dbData.isHidden);
ddsData.fileCategory(dbData.fileCategoryId);
ddsData.folderId(dbData.folderId);
ddsData.fileType(dbData.fileTypeId);
ddsData.operatorId(dbData.operatorId);
if (!dbData.exerciseId.isNull() && dbData.exerciseId.canConvert<int>())
ddsData.exerciseId(dbData.exerciseId.toInt());
if (!dbData.phaseId.isNull() && dbData.phaseId.canConvert<int>())
ddsData.phaseId(dbData.phaseId.toInt());
ddsData.fileStatus(dbData.fileStatusId);
ddsData.isUsedBy(dbData.isUsedBy);
ddsData.usedBy(dbData.usedBy);
if (!dbData.properties.isEmpty())
ddsData.properties(dbData.properties.toStdString());
ddsData.lastModified(dbData.lastModified);
// init data not in db
ddsData.isDeleted(false);
ddsData.isUsed(false);
return ddsData;
}
inline FileTypeInfo convert(const FlmFileTypeInfo &dbData)
{
FileTypeInfo ddsData;
ddsData.id(dbData.id);
ddsData.description(dbData.description.toStdString());
ddsData.extension(dbData.extension.toStdString());
// init data not in db
ddsData.isDeleted(false);
ddsData.isUsed(false);
return ddsData;
}
inline Folder convert(const FlmFolder &dbData)
{
Folder ddsData;
ddsData.id(dbData.id);
ddsData.name(dbData.name.toStdString());
ddsData.path(dbData.path());
ddsData.isEditable(dbData.isEditable);
ddsData.isHidden(dbData.isHidden);
ddsData.operatorId(dbData.operatorId);
ddsData.parentId(dbData.parentId);
ddsData.lastModified(dbData.lastModified);
// init data not in db
ddsData.isDeleted(false);
ddsData.isUsed(false);
return ddsData;
}
}
}
+55
View File
@@ -0,0 +1,55 @@
/**
* @RDE_HEADER@
* DdsHandler for FLM
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#include "dds_handler.h"
#include <DDS/Core/pacemaker.h>
namespace FileManagement
{
DdsHandler::DdsHandler(int domainId)
: m_ddsConnector(std::make_shared<DDSConnector::DdsConnector>(domainId, IDL::PartitionType::Any))
, m_logger(getLogger("DdsHandler"))
{
DEBUG_LOG(m_logger) << "DdsHandler(" << domainId << ") for partition: " << m_ddsConnector->getDefaultPartition();
}
bool DdsHandler::init(const QStringList &qosFileList)
{
if (!m_ddsConnector->init(qosFileList))
{
ERROR_LOG(m_logger) << "Error initializing dds connections - aborting";
return false;
}
// default initialize Publisher and Subscriber
m_ddsConnector->initPublisherSubscriber();
// Pacemaker
m_pacemaker = std::make_shared<Core::Pacemaker>(m_ddsConnector);
m_topicLockMaster = std::make_shared<Core::TopicLockMaster>(m_ddsConnector);
m_ddsDts = FileManagement::Interface::Dts::create(m_ddsConnector);
m_ddsDtc = FileManagement::Interface::Dtc::create(m_ddsConnector);
m_ddsFts = FileManagement::Interface::Fts::create(m_ddsConnector);
bool bRet = m_ddsDts->enableAll();
INFO_LOG(m_logger) << "Dts initialised";
bRet &= m_ddsDtc->enableAll();
INFO_LOG(m_logger) << "Dtc initialised";
bRet &= m_ddsFts->enableAll();
INFO_LOG(m_logger) << "Fts initialised";
return bRet;
}
} // Namespace FLM
+53
View File
@@ -0,0 +1,53 @@
/**
* @RDE_HEADER@
* DdsHandler for FLM
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include <DDS/DDSConnector/dds_connector.h>
#include <DDS/Core/topic_lock_master.h>
#include <FileManagement/flm_dts.h>
#include <FileManagement/flm_dtc.h>
#include <FileManagement/flm_fts.h>
#include "logger.h"
namespace Core
{
class Pacemaker;
}
namespace FileManagement
{
class DdsHandler final
{
public:
explicit DdsHandler(int domainId);
~DdsHandler() = default;
bool init(const QStringList &qosFileList = QStringList());
std::shared_ptr<Core::Pacemaker> pacemaker() const {return m_pacemaker; }
std::shared_ptr<Core::TopicLockMaster> topicLockMaster() const { return m_topicLockMaster; }
std::shared_ptr<DDSConnector::DdsConnector> ddsConnector() const { return m_ddsConnector; }
std::shared_ptr<FileManagement::Interface::Dts> dts() const { return m_ddsDts; }
std::shared_ptr<FileManagement::Interface::Dtc> dtc() const { return m_ddsDtc; }
std::shared_ptr<FileManagement::Interface::Fts> fts() const { return m_ddsFts; }
private:
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
std::shared_ptr<Core::Pacemaker> m_pacemaker;
std::shared_ptr<Core::TopicLockMaster> m_topicLockMaster;
std::shared_ptr<FileManagement::Interface::Dts> m_ddsDts;
std::shared_ptr<FileManagement::Interface::Dtc> m_ddsDtc;
std::shared_ptr<FileManagement::Interface::Fts> m_ddsFts;
NGL::INGLLogger &m_logger;
};
}
+136
View File
@@ -0,0 +1,136 @@
/**
* @RDE_HEADER@
* Custom db functions (extends tab_db_impl.cpp/.h)
* $Id$
* $HeadURL$
* $Author$
*/
#include "flm_db_impl_custom.h"
#include <ngldb/nsqlquery.h>
#include <ngldb/sql_query_janitor.h>
#include <QRegularExpression>
namespace FileManagement
{
// custom procs, body must be implemented by user
bool DatabaseInterfaceImplCustom::updateStatus(int fileId, const FileStatus &status, int operatorId)
{
const QString tableName = getTableName(QStringLiteral("flm_file_content"));
const QString stmtSelect = QStringLiteral("SELECT name FROM ") + tableName + QStringLiteral(" WHERE id = :id");
const QString stmtUpdate = QStringLiteral("UPDATE ") + tableName +
QStringLiteral(" SET file_status_id = :st, name = :name, operator_id = :opId, last_modified = :lastMod") +
QStringLiteral(" WHERE id = :id;");
DEBUG_LOG(m_logger) << "Select statement: " << stmtSelect;
DEBUG_LOG(m_logger) << "Update statement: " << stmtUpdate;
DEBUG_LOG(m_logger) << "File Id = " << fileId;
DEBUG_LOG(m_logger) << "New status = " << status;
DEBUG_LOG(m_logger) << "Operator Id = " << operatorId;
if (!m_query)
{
ERROR_LOG(m_logger) << "m_query not initialized";
return false;
}
QString fileName;
{
SqlQueryJanitor janitor(m_query);
if (!m_query->prepare(stmtSelect))
{
ERROR_LOG(m_logger) << "Could not prepare statement: " << stmtSelect;
return false;
}
m_query->bindValue(QStringLiteral(":id"), fileId);
if (!m_query->execAndFetch())
{
ERROR_LOG(m_logger) << "Could not execute statement: " << stmtSelect;
return false;
}
fileName = m_query->value(0).toString();
} // query scope
DEBUG_LOG(m_logger) << "File name before = " << fileName;
if (status.underlying() == 1) // Delete
fileName = QStringLiteral("{")+QString::number(fileId)+QStringLiteral("}_")+fileName;
if (status.underlying() == 0 && fileName.startsWith(QStringLiteral("{"))) // Restore
fileName.remove(QRegularExpression(QStringLiteral("^[{](\\d+)[}][_]")));
DEBUG_LOG(m_logger) << "File name after = " << fileName;
{
SqlQueryJanitor janitor(m_query);
if (!m_query->prepare(stmtUpdate))
{
ERROR_LOG(m_logger) << "Could not prepare statement: " << stmtUpdate;
return false;
}
m_query->bindValue(QStringLiteral(":id"), fileId);
m_query->bindValue(QStringLiteral(":st"), status.underlying());
m_query->bindValue(QStringLiteral(":opId"), operatorId);
m_query->bindValue(QStringLiteral(":lastMod"), QDateTime::currentMSecsSinceEpoch());
m_query->bindValue(QStringLiteral(":name"), fileName);
if (!m_query->exec())
{
ERROR_LOG(m_logger) << "Could not execute statement: " << stmtUpdate;
return false;
}
return true;
} // query scope
}
bool DatabaseInterfaceImplCustom::setUsedBy(int fileId, const bool &usedBy, int usedNo, int operatorId)
{
const QString tableName = getTableName(QStringLiteral("flm_file_content"));
const QString stmtUpdate = QStringLiteral("UPDATE ") + tableName +
QStringLiteral(" SET is_used_by = :usd, used_by = :useNo, operator_id = :opId, last_modified = :lastMod") +
QStringLiteral(" WHERE id = :id;");
DEBUG_LOG(m_logger) << "Update statement: " << stmtUpdate;
DEBUG_LOG(m_logger) << "File Id = " << fileId;
DEBUG_LOG(m_logger) << "Used By = " << usedBy;
DEBUG_LOG(m_logger) << "Used No = " << usedNo;
DEBUG_LOG(m_logger) << "Operator Id = " << operatorId;
if (!m_query)
{
ERROR_LOG(m_logger) << "m_query not initialized";
return false;
}
SqlQueryJanitor janitor(m_query);
if (!m_query->prepare(stmtUpdate))
{
ERROR_LOG(m_logger) << "Could not prepare statement: " << stmtUpdate;
return false;
}
m_query->bindValue(QStringLiteral(":id"), fileId);
m_query->bindValue(QStringLiteral(":usd"), usedBy);
m_query->bindValue(QStringLiteral(":useNo"), usedNo);
m_query->bindValue(QStringLiteral(":opId"), operatorId);
m_query->bindValue(QStringLiteral(":lastMod"), QDateTime::currentMSecsSinceEpoch());
if (!m_query->exec())
{
ERROR_LOG(m_logger) << "Could not execute statement: " << stmtUpdate;
return false;
}
return true;
}
}
+23
View File
@@ -0,0 +1,23 @@
/**
* @RDE_HEADER@
* Custom db functions (extends tab_db_impl.cpp/.h)
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <FileManagement/flm_db_impl.h>
namespace FileManagement
{
class DatabaseInterfaceImplCustom final : public DatabaseInterfaceImpl
{
Q_OBJECT
public:
using DatabaseInterfaceImpl::DatabaseInterfaceImpl;
bool updateStatus(int fileId, const FileStatus &status, int operatorId) override final;
bool setUsedBy(int fileId, const bool &usedBy, int usedNo, int operatorId) override final;
};
} // namespace FileManagement
+196
View File
@@ -0,0 +1,196 @@
/**
* @RDE_HEADER@
* ISM Custom functions (extends flm_db_impl.cpp/.h)
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2016-11-26
*/
#include "flm_dtc_impl_custom.h"
#include <DDS/DTC/generic_dtc.h>
#include <DDS/Generic/generic_data_reader.h>
#include <QSet>
#include <QVector>
#include <unordered_map>
//---------------------------------------------------------------------------------------------------------------------------------------------
namespace FileManagement
{
namespace Interface
{
DtcImplCustom::DtcImplCustom(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector)
: DtcImpl(ddsConnector)
{
}
//---------------------------------------------------------------------------------------------------------------------------------------------
bool DtcImplCustom::getAllTemplates(QList<FileContent> &allTemplates)
{
if(!isFileContentEnabled())
{
enableFileContent();
waitForHistoricalDataFileContent(4000);
}
for (const auto &fc : m_dtcFileContent->readAlive())
if (fc.data().isTemplate())
allTemplates.append(fc);
return true;
}
//---------------------------------------------------------------------------------------------------------------------------------------------
bool DtcImplCustom::getAllFiles(const FileType &fileType, int folderId, QStringList &allFiles, bool showHidden)
{
if(!isFileContentEnabled())
{
enableFileContent();
waitForHistoricalDataFileContent(4000);
}
for (const auto &fc : m_dtcFileContent->readAlive())
if (fc.data().fileType() == fileType && fc.data().folderId() == folderId)
{
if (showHidden || !fc.data().isHidden())
allFiles << QString::fromStdString(fc.data().name());
}
return true;
}
//---------------------------------------------------------------------------------------------------------------------------------------------
bool DtcImplCustom::getFilesOperator(const FileType &fileType, int folderId, int operatorId, QStringList &allFiles)
{
if(!isFileContentEnabled())
{
enableFileContent();
waitForHistoricalDataFileContent(4000);
}
for (const auto &fc : m_dtcFileContent->readAlive())
if (fc.data().fileType() == fileType && fc.data().folderId() == folderId && fc.data().operatorId() == operatorId)
allFiles << QString::fromStdString(fc.data().name());
return true;
}
//---------------------------------------------------------------------------------------------------------------------------------------------
bool DtcImplCustom::getFile(const FileType &fileType, int folderId, const QString &fileName, FileContent &fileMetadata)
{
if(!isFileContentEnabled())
{
enableFileContent();
waitForHistoricalDataFileContent(4000);
}
const auto stdFileName = fileName.toStdString();
for (const auto &fc : m_dtcFileContent->readAlive())
{
if (fc.data().fileType() == fileType && fc.data().folderId() == folderId && fc.data().name() == stdFileName)
{
fileMetadata = fc;
return true;
}
}
return false;
}
//---------------------------------------------------------------------------------------------------------------------------------------------
int DtcImplCustom::findFolder(int parentId, const QString &name) const
{
QVector<int> foldersVec;
std::string stdName = name.toStdString();
for (const auto &fld : m_dtcFolder->readAlive())
{
if (fld.data().parentId() == parentId)
{
if (fld.data().name() == stdName)
return fld.data().id();
else
foldersVec.append(fld.data().id());
}
}
int folderId = 0;
for (int subParentId : foldersVec)
{
folderId = findFolder(subParentId, name);
if (folderId > 0)
return folderId;
}
return folderId;
}
//---------------------------------------------------------------------------------------------------------------------------------------------
int DtcImplCustom::getExerciseFolderId(int exerciseId) const
{
const QString exerciseFolder = getExerciseFolderName(exerciseId);
return findFolder(0, exerciseFolder);
}
//---------------------------------------------------------------------------------------------------------------------------------------------
int DtcImplCustom::getPhaseFolderId(int exerciseId, int phaseId) const
{
const QString phaseFolder = getPhaseFolderName(phaseId);
int exerciseFolderId = getExerciseFolderId(exerciseId);
return findFolder(exerciseFolderId, phaseFolder);
}
//---------------------------------------------------------------------------------------------------------------------------------------------
int DtcImplCustom::getPartyFolderId(int exerciseId, int partyId) const
{
const QString partyFolder = getPartyFolderName(partyId);
int exerciseFolderId = getExerciseFolderId(exerciseId);
return findFolder(exerciseFolderId, partyFolder);
}
//---------------------------------------------------------------------------------------------------------------------------------------------
int DtcImplCustom::getExerciseId(int folderId)
{
if (!isFolderEnabled())
{
enableFolder();
waitForHistoricalDataFolder(4000);
}
for (const auto &fld : m_dtcFolder->readAlive())
{
if (fld.data().id() == folderId)
{
int exId = QString::fromStdString(fld.data().name()).remove(0,4).toInt();
// can be "$EX_" or "$PH_"
if (exId > 0)
return exId;
}
}
return 0;
}
//---------------------------------------------------------------------------------------------------------------------------------------------
int DtcImplCustom::getFileId(const FileType &fileType, const QString &fileName, int exerciseId, int phaseId)
{
ERROR_LOG(m_logger) << "fileName: " << fileName;
if (fileName.size() <= 0)
return 0;
const auto strFileName = fileName.toStdString();
DEBUG_LOG(m_logger) << "Searching for " << fileName << ", " << exerciseId << ", " << phaseId << ", " << fileType;
for (const auto &fc : m_dtcFileContent->readAlive())
{
const FileContent &content = fc.data();
bool cond = (content.fileType() == fileType && content.name() == strFileName);
if (content.exerciseId().is_set())
cond &= (content.exerciseId() == exerciseId);
if (content.phaseId().is_set())
cond &= (content.phaseId() == phaseId);
if (cond)
{
DEBUG_LOG(m_logger) << "Found file content id = " << content.id();
return content.id();
}
}
return 0;
}
} // namespace Interface
} // namespace FileManagement
+44
View File
@@ -0,0 +1,44 @@
/**
* @RDE_HEADER@
* ISM Custom functions (extends flm_db_impl.cpp/.h)
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2016-11-26
*/
#pragma once
#include <FileManagement/flm_dtc_impl.h>
#include <functional>
//-------------------------------------------------------------------------------------------------------------
namespace FileManagement
{
namespace Interface
{
class DtcImplCustom final : public Interface::DtcImpl
{
Q_OBJECT
public:
explicit DtcImplCustom(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector);
bool getAllTemplates(QList<FileContent> &allTemplates) override;
bool getAllFiles(const FileType &fileType, int folderId, QStringList &allFiles, bool showHidden = false) override;
bool getFilesOperator(const FileType &fileType, int folderId, int operatorId, QStringList &allFiles) override;
bool getFile(const FileType &fileType, int folderId, const QString &fileName, FileContent &fileMetadata) override;
int getExerciseId(int folderId) override;
int getFileId(const FileType &fileType, const QString &fileName, int exerciseId, int phaseId) override;
int findFolder(int parentId, const QString &name) const override;
QString getExerciseFolderName(int exerciseId) const override { return QLatin1String("$EX_")+ QString::number(exerciseId);}
QString getPartyFolderName(int partyId) const override { return QLatin1String("$PY_")+ QString::number(partyId);}
QString getPhaseFolderName(int phaseId) const override { return QLatin1String("$PH_")+ QString::number(phaseId);}
int getExerciseFolderId(int exerciseId) const override;
int getPhaseFolderId(int exerciseId, int phaseId) const override;
int getPartyFolderId(int exerciseId, int partyId) const override;
};
} //Interface
} // namespace FileManagement
+54
View File
@@ -0,0 +1,54 @@
/**
* @RDE_HEADER@
* Export definitions
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include <QtCore/qglobal.h>
#ifndef FLM_COMMON_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define FLM_COMMON_EXPORT
# else
# if defined(MAKE_SVCFLMCOMMON_LIB)
# define FLM_COMMON_EXPORT Q_DECL_EXPORT
# ifndef WIN32
# ifdef NDDSUSERDllExport
# undef NDDSUSERDllExport
# endif
# define NDDSUSERDllExport Q_DECL_EXPORT
# endif
# else
# define FLM_COMMON_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef FLM_CLIENT_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define FLM_CLIENT_EXPORT
# else
# if defined(MAKE_SVCFLMCLIENT_LIB)
# define FLM_CLIENT_EXPORT Q_DECL_EXPORT
# else
# define FLM_CLIENT_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef FLM_SERVER_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define FLM_SERVER_EXPORT
# else
# if defined(MAKE_SVCFLMSERVER_LIB)
# define FLM_SERVER_EXPORT Q_DECL_EXPORT
# else
# define FLM_SERVER_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
+393
View File
@@ -0,0 +1,393 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<service namespace="FileManagement" abbreviation="FLM" procNames="FileManagement" exerciseDependency="Global" groups="Core" prio="1">
<rcs>
<Id Id="$Id$"/>
<HeadURL HeadURL="$HeadURL$"/>
<Author Author="$Author$"/>
</rcs>
<operatorRights offset="13">
<guiPlugin name="FileManagement" offset="1">
<operatorRightGroup name="File Library Organisation" description="Rights to modify Files and Folders">
<operatorRight right="FileManagementFoldersEdit" value="4" description="Edit Folders"/>
<operatorRight right="FileManagementFileAdmin" value="5" description="Administrative Rights to modify Files and Folders"/>
</operatorRightGroup>
<operatorRightGroup name="File Management" description="Edit Files">
<operatorRight right="FileManagementDialogsShow" value="1" description="Show the File Management Dialog"/>
<operatorRight right="FileManagementFilesShow" value="2" description="Show Files and Folder"/>
<operatorRight right="FileManagementFilesEdit" value="3" description="Edit Files"/>
</operatorRightGroup>
</guiPlugin>
</operatorRights>
<tables>
<table name="flm_file_category">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="name" datatype="text"/>
</table>
<table name="flm_file_content">
<column name="id" datatype="bigint" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="name" datatype="text"/>
<column name="is_template" datatype="boolean" default="false"/>
<column name="is_hidden" datatype="boolean" default="false"/>
<column name="folder_id" datatype="bigint" isForeignKey="1"/>
<column name="file_category_id" datatype="integer" isForeignKey="1"/>
<column name="file_type_id" datatype="integer" isForeignKey="1"/>
<column name="file_status_id" datatype="integer" isForeignKey="1"/>
<column name="exercise_id" datatype="bigint" isOptional="1" isForeignKey="1"/>
<column name="phase_id" datatype="integer" isOptional="1" isForeignKey="1"/>
<column name="operator_id" datatype="integer" isForeignKey="1"/>
<column name="content" datatype="bytea"/>
<column name="properties" datatype="jsonb" default="'{}'"/>
<column name="is_used_by" datatype="boolean" default="false"/>
<column name="used_by" datatype="integer" default="0"/>
<column name="last_modified" datatype="bigint"/>
<constraint name="UQ_flm_file_content_name" type="unique">
<column name="folder_id"/>
<column name="name"/>
<column name="file_type_id"/>
<column name="file_status_id"/>
<column name="operator_id"/>
</constraint>
<foreignKey name="FK_flm_file_content_flm_file_type">
<source table="flm_file_content" column="file_type_id"/>
<destination table="flm_file_type" column="id"/>
</foreignKey>
<foreignKey name="FK_flm_file_content_flm_file_status">
<source table="flm_file_content" column="file_status_id"/>
<destination table="flm_file_status" column="id"/>
</foreignKey>
<foreignKey name="FK_flm_file_content_flm_folder">
<source table="flm_file_content" column="folder_id"/>
<destination table="flm_folder" column="id"/>
</foreignKey>
<foreignKey name="FK_flm_file_content_flm_file_category">
<source table="flm_file_content" column="file_category_id"/>
<destination table="flm_file_category" column="id"/>
</foreignKey>
<foreignKey name="FK_flm_file_content_exercise">
<source table="flm_file_content" column="exercise_id"/>
<destination service="ExerciseManagement" serviceAbbr="exm" schema="exm" table="exercise" column="id"/>
</foreignKey>
<foreignKey name="FK_flm_file_content_opm_operator">
<source table="flm_file_content" column="operator_id"/>
<destination service="OperatorManagement" serviceAbbr="opm" schema="opm" table="opm_operator" column="id"/>
</foreignKey>
<foreignKey name="FK_flm_file_content_exercise_phase">
<source table="flm_file_content" column="phase_id"/>
<destination service="ExerciseManagement" serviceAbbr="exm" schema="exm" table="exercise_phase" column="id"/>
</foreignKey>
</table>
<table name="flm_file_status">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="name" datatype="text"/>
</table>
<table name="flm_file_type">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="name" datatype="text"/>
</table>
<table name="flm_file_type_info">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="file_type_id" datatype="integer" isForeignKey="1"/>
<column name="description" datatype="text"/>
<column name="extension" datatype="text"/>
<foreignKey name="FK_flm_file_type_info_flm_file_type">
<source table="flm_file_type_info" column="file_type_id"/>
<destination table="flm_file_type" column="id"/>
</foreignKey>
</table>
<table name="flm_folder">
<column name="id" datatype="bigint" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="name" datatype="text"/>
<column name="path" datatype="integer[]"/>
<column name="is_editable" datatype="boolean" default="true"/>
<column name="is_hidden" datatype="boolean" default="false"/>
<column name="parent_id" datatype="bigint"/>
<column name="operator_id" datatype="integer" isForeignKey="1"/>
<column name="last_modified" datatype="bigint"/>
<constraint name="UQ_flm_folder_name" type="unique">
<column name="parent_id"/>
<column name="name"/>
</constraint>
<foreignKey name="FK_flm_folder_opm_operator">
<source table="flm_folder" column="operator_id"/>
<destination service="OperatorManagement" serviceAbbr="opm" schema="opm" table="opm_operator" column="id"/>
</foreignKey>
</table>
</tables>
<views>
<view name="flm_file_content_exercise" exerciseDependency="Exercise" filter="exercise_id" base="flm_file_content"/>
</views>
<dbServiceStructs>
<serviceStruct name="FlmFileContent" table="flm_file_content">
<notification name="notifyDeleteFileContent" returns="void" notificationTypes="AfterDelete">
<parameter pos="1" name="id" type="qint64"/>
</notification>
<notification name="notifyInsertFileContent" returns="void" notificationTypes="AfterInsert">
<parameter pos="1" name="id" type="qint64"/>
</notification>
<notification name="notifyUpdateFileContent" returns="void" notificationTypes="AfterUpdate">
<parameter pos="1" name="id" type="qint64"/>
</notification>
<function name="updateStatus" returns="bool">
<parameter pos="1" name="fileId" type="int"/>
<parameter pos="2" name="status" type="const FileStatus &amp;"/>
<parameter pos="3" name="operatorId" type="int"/>
</function>
<function name="setUsedBy" returns="bool">
<parameter pos="1" name="fileId" type="int"/>
<parameter pos="2" name="usedBy" type="const bool &amp;"/>
<parameter pos="3" name="usedNo" type="int"/>
<parameter pos="4" name="operatorId" type="int"/>
</function>
</serviceStruct>
<serviceStruct name="FlmFileTypeInfo" table="flm_file_type_info"/>
<serviceStruct name="FlmFolder" table="flm_folder">
<notification name="notifyDeleteFolder" returns="void" notificationTypes="AfterDelete">
<parameter pos="1" name="id" type="qint64"/>
</notification>
<notification name="notifyInsertFolder" returns="void" notificationTypes="AfterInsert">
<parameter pos="1" name="id" type="qint64"/>
</notification>
<notification name="notifyUpdateFolder" returns="void" notificationTypes="AfterUpdate">
<parameter pos="1" name="id" type="qint64"/>
</notification>
</serviceStruct>
<table name="flm_file_content"/>
<table name="flm_file_type"/>
<table name="flm_file_type_info"/>
<table name="flm_folder"/>
</dbServiceStructs>
<topicTypes>
<topicType name="FileContent" isDataObject="1" autosubscribe="1" routeToClient="1" routeToServer="0" routeInReplay="1" baseValueType="Core::BaseEntity">
<column name="isTemplate" idlType="boolean"/>
<column name="isHidden" idlType="boolean"/>
<column name="folderId" idlType="long"/>
<column name="fileCategory" idlType="FileCategory"/>
<column name="fileType" idlType="FileType"/>
<column name="fileStatus" idlType="FileStatus"/>
<column name="operatorId" idlType="long"/>
<column name="isUsedBy" idlType="boolean"/>
<column name="usedBy" idlType="long"/>
<column name="lastModified" idlType="long long"/>
<column name="exerciseId" idlType="long" isOptional="1"/>
<column name="phaseId" idlType="long" isOptional="1"/>
<column name="properties" idlType="string"/>
<column name="exportFileName" idlType="string" isOptional="1"/>
</topicType>
<topicType name="FileContentChangeStatusRequest">
<column name="id" idlType="long"/>
<column name="fileStatus" idlType="FileStatus"/>
<column name="operatorId" idlType="long"/>
<column name="lastModified" idlType="long long"/>
</topicType>
<topicType name="FileContentExportRequest">
<column name="id" idlType="long"/>
</topicType>
<topicType name="FileContentModifyRequest">
<column name="id" idlType="long"/>
<column name="name" idlType="string"/>
<column name="isTemplate" idlType="boolean"/>
<column name="isHidden" idlType="boolean"/>
<column name="folderId" idlType="long"/>
<column name="fileCategory" idlType="FileCategory"/>
<column name="fileType" idlType="FileType"/>
<column name="fileStatus" idlType="FileStatus"/>
<column name="operatorId" idlType="long"/>
<column name="content" idlType="sequence&lt;octet&gt;"/>
<column name="isUsedBy" idlType="boolean"/>
<column name="usedBy" idlType="long"/>
<column name="lastModified" idlType="long long"/>
<column name="exerciseId" idlType="long" isOptional="1"/>
<column name="phaseId" idlType="long" isOptional="1"/>
<column name="properties" idlType="string"/>
<column name="exportFileName" idlType="string" isOptional="1"/>
</topicType>
<topicType name="FileContentSetUsedRequest">
<column name="id" idlType="long"/>
<column name="isUsedBy" idlType="boolean"/>
<column name="usedBy" idlType="long"/>
<column name="operatorId" idlType="long"/>
<column name="lastModified" idlType="long long"/>
</topicType>
<topicType name="FileTypeInfo" isDataObject="1" autosubscribe="1" routeToClient="1" routeToServer="0" routeInReplay="1" baseValueType="Core::BaseEntity">
<column name="description" idlType="string"/>
<column name="extension" idlType="string"/>
</topicType>
<topicType name="Folder" isDataObject="1" autosubscribe="1" routeToClient="1" routeToServer="0" routeInReplay="1" baseValueType="Core::BaseEntityTranslatable">
<column name="path" idlType="sequence&lt;long&gt;"/>
<column name="isEditable" idlType="boolean"/>
<column name="isHidden" idlType="boolean"/>
<column name="parentId" idlType="long"/>
<column name="operatorId" idlType="long"/>
<column name="lastModified" idlType="long long"/>
</topicType>
<topicType name="FolderModifyRequest">
<column name="id" idlType="long"/>
<column name="name" idlType="string"/>
<column name="path" idlType="sequence&lt;long&gt;"/>
<column name="isEditable" idlType="boolean"/>
<column name="isHidden" idlType="boolean"/>
<column name="parentId" idlType="long"/>
<column name="operatorId" idlType="long"/>
<column name="lastModified" idlType="long long"/>
</topicType>
<topicType name="PathCreateRequest">
<column name="path" idlType="sequence&lt;string&gt;"/>
<column name="isEditable" idlType="boolean"/>
<column name="isHidden" idlType="boolean"/>
<column name="parentId" idlType="long"/>
<column name="operatorId" idlType="long"/>
</topicType>
<topicType name="GetFileContentDataReply" baseValueType="Core::FunctionReply">
<column name="content" idlType="sequence&lt;octet&gt;"/>
</topicType>
<topicType name="GetFileContentDataRequest">
<column name="fileContentId" idlType="long"/>
</topicType>
</topicTypes>
<functionTopics>
<functionTopic name="FileContentChangeStatus" requestTopicType="FileContentChangeStatusRequest" replyTopicType="Core::FunctionReply" requestTopicName="FileContentChangeStatusRequest" replyTopicName="FileContentChangeStatusReply" routeInReplay="1"/>
<functionTopic name="FileContentExport" requestTopicType="FileContentExportRequest" replyTopicType="Core::FunctionReply" requestTopicName="FileContentExportRequest" replyTopicName="FileContentExportReply" routeInReplay="0"/>
<functionTopic name="FileContentModify" requestTopicType="FileContentModifyRequest" replyTopicType="Core::FunctionReply" requestTopicName="FileContentModifyRequest" replyTopicName="FileContentModifyReply" routeInReplay="1"/>
<functionTopic name="FileContentRemove" requestTopicType="Core::RemoveElementRequest" replyTopicType="Core::FunctionReply" requestTopicName="FileContentRemoveRequest" replyTopicName="FileContentRemoveReply" routeInReplay="1"/>
<functionTopic name="FileContentSetUsed" requestTopicType="FileContentSetUsedRequest" replyTopicType="Core::FunctionReply" requestTopicName="FileContentSetUsedRequest" replyTopicName="FileContentSetUsedReply" routeInReplay="1"/>
<functionTopic name="FolderModify" requestTopicType="FolderModifyRequest" replyTopicType="Core::FunctionReply" requestTopicName="FolderModifyRequest" replyTopicName="FolderModifyReply" routeInReplay="1"/>
<functionTopic name="FolderRemove" requestTopicType="Core::RemoveElementRequest" replyTopicType="Core::FunctionReply" requestTopicName="FolderRemoveRequest" replyTopicName="FolderRemoveReply" routeInReplay="1"/>
<functionTopic name="PathCreate" requestTopicType="PathCreateRequest" replyTopicType="Core::FunctionReply" requestTopicName="PathCreateRequest" replyTopicName="PathCreateReply" routeInReplay="1"/>
<functionTopic name="GetFileContentData" requestTopicType="GetFileContentDataRequest" replyTopicType="GetFileContentDataReply" requestTopicName="GetFileContentDataRequest" replyTopicName="GetFileContentDataReply" routeInReplay="1"/>
</functionTopics>
<customDtcFunctions>
<customDtcFunction>
<function name="getAllTemplates" returns="bool">
<parameter pos="1" name="allTemplates" type="QList&lt;FileContent &gt; &amp;"/>
</function>
<function name="getAllFiles" returns="bool">
<parameter pos="1" name="fileType" type="const FileType &amp;"/>
<parameter pos="2" name="folderId" type="int"/>
<parameter pos="3" name="allFiles" type="QStringList &amp;"/>
<parameter pos="4" name="showHidden" type="bool" default="false"/>
</function>
<function name="getFilesOperator" returns="bool">
<parameter pos="1" name="fileType" type="const FileType &amp;"/>
<parameter pos="2" name="folderId" type="int"/>
<parameter pos="3" name="operatorId" type="int"/>
<parameter pos="4" name="allFiles" type="QStringList &amp;"/>
</function>
<function name="getFile" returns="bool">
<parameter pos="1" name="fileType" type="const FileType &amp;"/>
<parameter pos="2" name="folderId" type="int"/>
<parameter pos="3" name="fileName" type="const QString &amp;"/>
<parameter pos="4" name="fileMetadata" type="FileContent &amp;"/>
</function>
<function name="getExerciseId" returns="int">
<parameter pos="1" name="folderId" type="int"/>
</function>
<function name="getExerciseFolderName" returns="QString" isConst="1">
<parameter pos="1" name="exerciseId" type="int"/>
</function>
<function name="getPhaseFolderName" returns="QString" isConst="1">
<parameter pos="1" name="phaseId" type="int"/>
</function>
<function name="getPartyFolderName" returns="QString" isConst="1">
<parameter pos="1" name="partyId" type="int"/>
</function>
<function name="getExerciseFolderId" returns="int" isConst="1">
<parameter pos="1" name="exerciseId" type="int"/>
</function>
<function name="getPhaseFolderId" returns="int" isConst="1">
<parameter pos="1" name="exerciseId" type="int"/>
<parameter pos="2" name="phaseId" type="int"/>
</function>
<function name="getPartyFolderId" returns="int" isConst="1">
<parameter pos="1" name="exerciseId" type="int"/>
<parameter pos="2" name="partyId" type="int"/>
</function>
<function name="getFileId" returns="int">
<parameter pos="1" name="fileType" type="const FileType &amp;"/>
<parameter pos="2" name="fileName" type="const QString &amp;"/>
<parameter pos="3" name="exerciseId" type="int"/>
<parameter pos="4" name="phaseId" type="int"/>
</function>
<function name="findFolder" returns="int" isConst="1">
<parameter pos="1" name="parentId" type="int"/>
<parameter pos="2" name="name" type="const QString &amp;"/>
</function>
</customDtcFunction>
</customDtcFunctions>
<enumerations>
<enumeration name="FileStatus" table="flm_file_status">
<attribute key="Valid" value="0"/>
<attribute key="Deleted" value="1"/>
</enumeration>
<enumeration name="FileCategory" table="flm_file_category">
<attribute key="Global" value="1"/>
<attribute key="Exercise" value="2"/>
<attribute key="User" value="3"/>
</enumeration>
<enumeration name="FileType" table="flm_file_type">
<attribute key="Unknown" value="0"/>
<attribute key="Text" value="1"/>
<attribute key="Xml" value="2"/>
<attribute key="Pdf" value="3"/>
<attribute key="Jpg" value="4"/>
<attribute key="Png" value="5"/>
<attribute key="TacticalPlan" value="6"/>
<attribute key="OperatorFavourite" value="7"/>
<attribute key="OperatorDefinedSymbol" value="8"/>
<attribute key="OpenOfficeDocument" value="9"/>
<attribute key="OpenOfficeSpreadsheet" value="10"/>
<attribute key="OpenOfficePresentation" value="11"/>
<attribute key="MSOfficeDocument" value="12"/>
<attribute key="MSOfficeDocument97" value="13"/>
<attribute key="MSOfficeSpreadsheet" value="14"/>
<attribute key="MSOfficeSpreadsheet97" value="15"/>
<attribute key="MSOfficePresentation" value="16"/>
<attribute key="MSOfficePresentation97" value="17"/>
<attribute key="EvaluationSchema" value="18"/>
<attribute key="AdlerJson" value="19"/>
</enumeration>
<enumeration name="MainFolder">
<attribute key="GlobalDocuments" value="1"/>
<attribute key="ExerciseDocuments" value="2"/>
<attribute key="UserDocuments" value="3"/>
</enumeration>
<enumeration name="XmlType">
<attribute key="Unknown" value="0"/>
<attribute key="AESBorderlineEdit" value="1"/>
<attribute key="AESBorderlineList" value="2"/>
<attribute key="AESGasPipeList" value="3"/>
<attribute key="AVMCombatNetRadio" value="4"/>
<attribute key="AVMEditCombatNetRadio" value="5"/>
<attribute key="AVMEditFrequencyPlanning" value="6"/>
<attribute key="AVMFrequencyPlanning" value="7"/>
<attribute key="AVMMenuEditView" value="8"/>
<attribute key="AVMMvsDialog" value="9"/>
<attribute key="AVMTrainingVoiceCommunication" value="10"/>
<attribute key="CESParticipantMove" value="11"/>
<attribute key="EVLCriteriumEdit" value="12"/>
<attribute key="EXMExerciseDescription" value="13"/>
<attribute key="FLTSymbolAppearance" value="14"/>
<attribute key="FLTTypeFilter" value="15"/>
<attribute key="SMOSingleServiceEquipmentCheck" value="16"/>
<attribute key="TLNTimelineFilter" value="17"/>
<attribute key="TLNEventListConfiguration" value="18"/>
<attribute key="PDMChargeFilter" value="19"/>
<attribute key="PDMUleisCodeFilter" value="20"/>
<attribute key="TGTShootbackTargetBaseConfiguration" value="21"/>
<attribute key="TGTShootbackAssignment" value="22"/>
<attribute key="TGTShootbackArea" value="23"/>
</enumeration>
</enumerations>
</service>
+324
View File
@@ -0,0 +1,324 @@
/**
* @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 <QDir>
#include <QFile>
//----------------------------------------------------------------------------------------------------------------------------
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<std::vector<uint8_t>>(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<std::vector<uint8_t>>(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<std::vector<uint8_t>>(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<std::vector<uint8_t>>(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
+63
View File
@@ -0,0 +1,63 @@
/**
* @RDE_HEADER@
* Handler for file content
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include <QMap>
#include <QVariant>
#include "base.h"
namespace FileManagement
{
class ObjectFileContent;
class HandlerFileContent final : public Base
, protected Interface::Fts::FileContentModifyRequestHandler
, protected Interface::Fts::FileContentRemoveRequestHandler
, protected Interface::Fts::FileContentExportRequestHandler
, protected Interface::Fts::FileContentChangeStatusRequestHandler
, protected Interface::Fts::GetFileContentDataRequestHandler
, protected Interface::Fts::FileContentSetUsedRequestHandler
{
Q_OBJECT
public:
explicit HandlerFileContent(MainHandler *mainHandler);
~HandlerFileContent();
bool init();
bool initByDbId(int dbId);
QMap<int, ObjectFileContent *> getObjectFileContentMap() { return m_objectFileContentMap; }
Core::FunctionReplyObject fileContentRemoveRequest(const Core::RemoveElementRequest &request);
private:
void onFileContentModifyRequest(const rti::core::SampleIdentity &cookie,
const FileContentModifyRequest &request) override final;
Core::FunctionReplyObject fileContentModifyRequest(const FileContentModifyRequest &request);
Core::FunctionReplyObject fileContentCreateRequest(const FileContentModifyRequest &request);
void onFileContentRemoveRequest(const rti::core::SampleIdentity &cookie,
const Core::RemoveElementRequest &request) override final;
void onFileContentExportRequest(const rti::core::SampleIdentity &cookie,
const FileContentExportRequest &request) override final;
void onFileContentChangeStatusRequest(const rti::core::SampleIdentity &cookie,
const FileContentChangeStatusRequest &request) override final;
void onGetFileContentDataRequest(const rti::core::SampleIdentity &cookie,
const GetFileContentDataRequest &request) override final;
void onFileContentSetUsedRequest(const rti::core::SampleIdentity &cookie,
const FileContentSetUsedRequest &request) override final;
void onDbDeletedFileContent(const QVariant &id_);
void onDbInsertedFileContent(const QVariant &id_);
void onDbUpdatedFileContent(const QVariant &id_);
private:
QMap<int, ObjectFileContent *> m_objectFileContentMap;
};
}
+70
View File
@@ -0,0 +1,70 @@
/**
* @RDE_HEADER@
* Handler for file type
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#include "handler_file_type_info.h"
#include "object_file_type_info.h"
#include "convert_db_to_dds.h"
#include "flm_db.h"
//------------------------------------------------------------------------------------------------------
namespace FileManagement
{
HandlerFileTypeInfo::HandlerFileTypeInfo(MainHandler *mainHandler)
: Base(mainHandler, getLogger("HandlerFileTypeInfo"))
{}
//------------------------------------------------------------------------------------------------------
HandlerFileTypeInfo::~HandlerFileTypeInfo()
{
qDeleteAll(m_objectFileTypeInfoMap);
}
//------------------------------------------------------------------------------------------------------
bool HandlerFileTypeInfo::init()
{
bool bRet = true;
// create file type objects
auto cb = [this, &bRet] (const Database::FlmFileTypeInfo &data)
{
ObjectFileTypeInfo *ifs(new ObjectFileTypeInfo(m_mainHandler));
Core::FunctionReplyObject ret = ifs->createObject(convert(data));
if (ret.error())
{
delete ifs;
ERROR_LOG(m_logger) << ret();
bRet = false;
return;
}
m_objectFileTypeInfoMap.insert(ifs->getId(), ifs);
};
if (!db()->select(cb) || !bRet)
{
ERROR_LOG(m_logger) << "Error reading data from database!";
return false;
}
DEBUG_LOG(m_logger) << "m_ObjectFileTypeInfoMap.size() = " << m_objectFileTypeInfoMap.size();
return true;
}
//------------------------------------------------------------------------------------------------------
QString HandlerFileTypeInfo::getFileExtension(const FileManagement::FileType &fileType) const
{
for (FileManagement::ObjectFileTypeInfo *ft : m_objectFileTypeInfoMap)
{
if (ft->getId() == fileType.underlying())
return ft->getExtension();
}
return QString();
}
} // Namespace FileManagement
+34
View File
@@ -0,0 +1,34 @@
/**
* @RDE_HEADER@
* Handler for file type
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include <QMap>
#include "base.h"
namespace FileManagement
{
class ObjectFileTypeInfo;
class HandlerFileTypeInfo : public Base
{
Q_OBJECT
public:
explicit HandlerFileTypeInfo(MainHandler *mainHandler);
~HandlerFileTypeInfo();
bool init();
QString getFileExtension(const FileManagement::FileType &fileType) const;
private:
QMap<int, ObjectFileTypeInfo *> m_objectFileTypeInfoMap;
};
}
+388
View File
@@ -0,0 +1,388 @@
/**
* @RDE_HEADER@
* Handler for folders
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#include "handler_folder.h"
#include "object_folder.h"
#include "handler_file_content.h"
#include "object_file_content.h"
#include "main_handler.h"
#include "convert_db_to_dds.h"
#include "flm_db.h"
#include <ngldb/dbtransaction.h>
namespace FileManagement
{
HandlerFolder::HandlerFolder(MainHandler *mainHandler)
: Base(mainHandler, getLogger("HandlerFolder"))
, Interface::Fts::FolderModifyRequestHandler(fts())
, Interface::Fts::FolderRemoveRequestHandler(fts())
, Interface::Fts::PathCreateRequestHandler(fts())
, Interface::Fts::FileContentRemoveRequestHandler(fts())
{
connect(db().get(), &DatabaseInterface::notifyDeleteFolder, this, &HandlerFolder::onDbDeletedFolder);
connect(db().get(), &DatabaseInterface::notifyInsertFolder, this, &HandlerFolder::onDbInsertedFolder);
connect(db().get(), &DatabaseInterface::notifyUpdateFolder, this, &HandlerFolder::onDbUpdatedFolder);
}
HandlerFolder::~HandlerFolder()
{
qDeleteAll(m_objectFolderMap);
}
bool HandlerFolder::init()
{
bool bRet = true;
// create file type objects
auto cb = [this, &bRet] (const Database::FlmFolder &data)
{
ObjectFolder *ifs(new ObjectFolder(m_mainHandler));
Core::FunctionReplyObject ret = ifs->createObject(convert(data));
if (ret.error())
{
delete ifs;
ERROR_LOG(m_logger) << ret();
bRet = false;
return;
}
m_objectFolderMap.insert(ifs->getId(), ifs);
};
if (!db()->select(cb) || !bRet)
{
ERROR_LOG(m_logger) << "Error reading data from database!";
return false;
}
DEBUG_LOG(m_logger) << "m_objectFolderMap.size() = " << m_objectFolderMap.size();
return true;
}
//---------------------------------------------------
void HandlerFolder::onFolderModifyRequest(const rti::core::SampleIdentity &cookie,
const FileManagement::FolderModifyRequest &request)
{
auto ret = request.id() > 0 ? folderModifyRequest(request) : folderCreateRequest(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
fts()->folderModifyReply(cookie, ret);
}
//---------------------------------------------------
Core::FunctionReplyObject HandlerFolder::folderCreateRequest(const FileManagement::FolderModifyRequest &request)
{
DEBUG_LOG(m_logger) << "Creating folder with name = " << request.name() << " under parent folder " << request.parentId();
Core::FunctionReplyObject ret;
Folder data;
std::vector<int> parentPath;
if (request.parentId() > 0 && m_objectFolderMap.contains(request.parentId()))
parentPath = m_objectFolderMap.value(request.parentId())->getPath();
if (parentPath.size() == 0)
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting Folder on root level"));
std::vector<int> path = parentPath;
path.push_back(9999); // dummy id, only needed to retrieve later the proper id
data.name(request.name());
data.path(path);
data.isEditable(request.isEditable());
data.isHidden(request.isHidden());
data.parentId(request.parentId());
data.operatorId(request.operatorId());
data.lastModified(QDateTime::currentMSecsSinceEpoch());
ObjectFolder *ifs(new ObjectFolder(m_mainHandler));
ret = ifs->createObject(data);
if (ret.error())
{
delete ifs;
ifs = nullptr;
ERROR_LOG(m_logger) << ret();
}
else
{
data.id(ifs->getId());
// update path with the real id
path = parentPath;
path.resize(parentPath.size() + 1, ifs->getId());
data.path(path);
data.lastModified(QDateTime::currentMSecsSinceEpoch());
ret = ifs->updateObject(data);
if (ret.error())
{
delete ifs;
ifs = nullptr;
ERROR_LOG(m_logger) << ret();
}
else
{
m_objectFolderMap.insert(ifs->getId(), ifs);
ret.setId(ifs->getId());
}
}
return ret;
}
//-------------------------------------------------------------------------------------------------------------
Core::FunctionReplyObject HandlerFolder::folderModifyRequest(const FileManagement::FolderModifyRequest &request)
{
ObjectFolder *ifs = m_objectFolderMap.value(request.id());
if (ifs == nullptr)
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Folder with id %1 not found")).arg(request.id());
Folder newData;
newData.id(request.id());
newData.name(request.name());
newData.path(request.path());
newData.isEditable(request.isEditable());
newData.parentId(request.parentId());
newData.operatorId(request.operatorId());
newData.lastModified(QDateTime::currentMSecsSinceEpoch());
newData.isHidden(request.isHidden());
return ifs->updateObject(newData);
}
//------------------------------------------------------------------------------------------
void HandlerFolder::onPathCreateRequest(const rti::core::SampleIdentity &cookie,
const FileManagement::PathCreateRequest &request)
{
Core::FunctionReplyObject ret;
int parentFolderId = request.parentId();
DEBUG_LOG(m_logger) << "parentFolderId: " << parentFolderId;
for (const std::string &folderName : request.path())
{
int folderId = dtc()->findFolder(parentFolderId, QString::fromStdString(folderName));
DEBUG_LOG(m_logger) << "folderId: " << folderId << ", folderName: " << folderName;
ObjectFolder *ifs = m_objectFolderMap.value(parentFolderId);
if (ifs == nullptr)
{
ret = Core::FunctionReplyObject(parentFolderId, tr_lts("dds", "Folder with id %1 not found")).arg(parentFolderId);
break;
}
if (folderId <= 0)
{
DEBUG_LOG(m_logger) << "Folder " << folderName << " does not exist => creating ...";
// Folder does not exist => create folder
FolderModifyRequest folderRequest;
folderRequest.name(folderName);
folderRequest.parentId(parentFolderId);
folderRequest.path(ifs->getPath());
folderRequest.isEditable(request.isEditable());
folderRequest.isHidden(request.isHidden());
folderRequest.operatorId(request.operatorId());
ret = folderCreateRequest(folderRequest);
if (ret.error())
break;
parentFolderId = ret.id();
DEBUG_LOG(m_logger) << "parentFolderId: " << parentFolderId;
}
else
parentFolderId = folderId;
}
fts()->pathCreateReply(cookie, ret);
}
//------------------------------------------------------------------------------------------
void HandlerFolder::onFolderRemoveRequest(const rti::core::SampleIdentity &cookie,
const Core::RemoveElementRequest &request)
{
Core::FunctionReplyObject ret;
ObjectFolder *ifs = m_objectFolderMap.value(request.id());
if (ifs == nullptr)
{
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "Folder with id %1 not found")).arg(request.id());
fts()->folderRemoveReply(cookie, ret);
return;
}
if (m_mainHandler->dds()->topicLockMaster()->isLocked(ifs->getData(), m_mainHandler->exerciseId()))
{
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "Folder '%1' is used by another user!")).arg(ifs->getName());
fts()->folderRemoveReply(cookie, ret);
return;
}
ret = removeFolder(request.id());
delete ifs;
fts()->folderRemoveReply(cookie, ret);
return;
}
//---------------------------------------------------
Core::FunctionReplyObject HandlerFolder::removeFolder(int folderId)
{
Core::FunctionReplyObject ret;
DBTransaction trans(m_mainHandler->db()->database());
// remove object and all children
for (auto it = m_objectFolderMap.begin(); it != m_objectFolderMap.end();)
{
DEBUG_LOG(m_logger) << "Checking ObjectFolder with id " << it.value()->getId() << " and parent id " << it.value()->getParentId();
if (it.value()->pathContains(folderId))
{
DEBUG_LOG(m_logger) << "Removing ObjectFolder with id " << it.value()->getId();
ret = it.value()->removeObject();
if (!ret.error())
{
removeFilesForFolder(it.value()->getId());
it = m_objectFolderMap.erase(it);
}
else
{
ERROR_LOG(m_logger) << ret();
++it;
}
}
else
++it;
}
if (!ret.error())
trans.commit();
return ret;
}
//---------------------------------------------------
void HandlerFolder::onFileContentRemoveRequest(const rti::core::SampleIdentity &cookie,
const Core::RemoveElementRequest &request)
{
Core::FunctionReplyObject ret;
ObjectFileContent *ifs = m_mainHandler->getHandlerFileContent()->getObjectFileContentMap().value(request.id());
if (ifs == nullptr)
{
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "FileContent with id %1 not found")).arg(request.id());
fts()->fileContentRemoveReply(cookie, ret);
return;
}
if (m_mainHandler->dds()->topicLockMaster()->isLocked(ifs->getData(), m_mainHandler->exerciseId()))
{
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "FileContent '%1' is used by another user!")).arg(ifs->getName());
fts()->folderRemoveReply(cookie, ret);
return;
}
ret = ifs->removeObject();
if (ret.error())
ERROR_LOG(m_logger) << ret();
else
{
// delete ObjectFileContent
delete ifs;
m_mainHandler->getHandlerFileContent()->getObjectFileContentMap().remove(request.id());
}
fts()->fileContentRemoveReply(cookie, ret);
return;
}
//---------------------------------------------------
void HandlerFolder::removeFilesForFolder(int folderId)
{
DEBUG_LOG(m_logger) << "Removing Files for Folder id " << folderId;
Core::RemoveElementRequest request;
const auto files = m_mainHandler->getHandlerFileContent()->getObjectFileContentMap();
for (auto file : files)
{
if (file->getFolderId() == folderId)
{
request.id(file->getId());
auto ret = m_mainHandler->getHandlerFileContent()->fileContentRemoveRequest(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
}
}
}
//----------------------------------------------------------------------------------------------------------------------------
void HandlerFolder::onDbDeletedFolder(const QVariant &id_)
{
int id = id_.toInt();
DEBUG_LOG(m_logger) << "DB deleted Folder with id: " << id;
Core::FunctionReplyObject ret = removeFolder(id);
if (ret.error())
ERROR_LOG(m_logger) << ret();
if (!dts()->removeFolderByKey(id))
ERROR_LOG(m_logger) << "Folder can not be taken from DDS, id = " << id;
}
//----------------------------------------------------------------------------------------------------------------------------
void HandlerFolder::onDbInsertedFolder(const QVariant &id_)
{
int id = id_.toInt();
DEBUG_LOG(m_logger) << "DB inserted Folder with id: " << id;
if (!m_objectFolderMap.contains(id))
initByDbId(id);
}
//----------------------------------------------------------------------------------------------------------------------------
void HandlerFolder::onDbUpdatedFolder(const QVariant &id_)
{
int id = id_.toInt();
DEBUG_LOG(m_logger) << "DB updated Folder with id: " << id;
initByDbId(id);
}
//----------------------------------------------------------------------------------------------------------------------------
bool HandlerFolder::initByDbId(int dbId)
{
Database::FlmFolder data;
DEBUG_LOG(m_logger) << "Reading Folder from database!";
if (!db()->selectFlmFolder(dbId, data))
{
ERROR_LOG(m_logger) << "Error reading data from database: id not found " << dbId;
return false;
}
// create folder object
if (data.id == dbId)
{
ObjectFolder *ifs(new ObjectFolder(m_mainHandler));
Core::FunctionReplyObject ret = ifs->createObject(convert(data));
if (ret.error())
{
delete ifs;
ERROR_LOG(m_logger) << ret();
return false;
}
m_objectFolderMap.insert(ifs->getId(), ifs);
ifs->onPublishData();
}
return true;
}
} // Namespace FileManagement
+56
View File
@@ -0,0 +1,56 @@
/**
* @RDE_HEADER@
* Handler for folders
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include <QMap>
#include "base.h"
namespace FileManagement
{
class ObjectFolder;
class HandlerFolder final : public Base
, protected Interface::Fts::FolderModifyRequestHandler
, protected Interface::Fts::FolderRemoveRequestHandler
, protected Interface::Fts::PathCreateRequestHandler
, protected Interface::Fts::FileContentRemoveRequestHandler
{
Q_OBJECT
public:
explicit HandlerFolder(MainHandler *mainHandler);
~HandlerFolder();
bool init();
bool initByDbId(int dbId);
private:
void onFolderModifyRequest(const rti::core::SampleIdentity &cookie,
const FolderModifyRequest &request) override final;
Core::FunctionReplyObject folderCreateRequest(const FolderModifyRequest &request);
Core::FunctionReplyObject folderModifyRequest(const FolderModifyRequest &request);
void onFolderRemoveRequest(const rti::core::SampleIdentity &cookie,
const Core::RemoveElementRequest &request) override final;
void onFileContentRemoveRequest(const rti::core::SampleIdentity &cookie,
const Core::RemoveElementRequest &request) override final;
void onPathCreateRequest(const rti::core::SampleIdentity &cookie,
const PathCreateRequest &request) override final;
void removeFilesForFolder(int folderId);
Core::FunctionReplyObject removeFolder(int folderId);
void onDbDeletedFolder(const QVariant &id_);
void onDbInsertedFolder(const QVariant &id_);
void onDbUpdatedFolder(const QVariant &id_);
private:
QMap<int, ObjectFolder *> m_objectFolderMap;
};
}
+88
View File
@@ -0,0 +1,88 @@
log4j.reset=true
log4j.rootLogger=WARN, file
# Service: FileManagement
###########################################################
log4j.logger.FLM=DEBUG
#log4j.logger.FLM.main=INFO
#log4j.logger.FLM.DbHandler=INFO
#log4j.logger.FLM.DdsHandler=INFO
#log4j.logger.FLM.MainHandler=INFO
#log4j.logger.FLM.HandlerFileType=INFO
#log4j.logger.FLM.ObjectFileType=INFO
#log4j.logger.FLM.HandlerFileCategory=INFO
#log4j.logger.FLM.ObjectFileCategory=INFO
#log4j.logger.FLM.HandlerFileContent=INFO
#log4j.logger.FLM.ObjectFileContent=INFO
log4j.logger.FLM.HandlerFolder=DEBUG
#log4j.logger.FLM.ObjectFolder=INFO
#log4j.logger.FLM.Test=DEBUG
# File
###########################################################
log4j.appender.file=Lts::RollingFileAppender
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=9
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
# Appnd_Console
###########################################################
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d %p %c %c{1} - %m (%-.30F:%L) %n
# Appnd_Syslog
###########################################################
log4j.appender.syslog=org.apache.log4j.SyslogAppender
log4j.appender.syslog.Threshold=ERROR
log4j.appender.syslog.SysLogHost=localhost
log4j.appender.syslog.Facility=LOCAL7
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
###########################################################
###########################################################
###########################################################
# 1) Available Levels in LOG4CXX Version 0.10.0:
# TRACE,
# DEBUG,
# INFO,
# WARN,
# ERROR
# FATAL
#
# d = date/time
# p = priority (Level)
# c = category/channel
# m = message
# F = file
# L = line
# n = platform dependent line separator character or characters.
# ....
#
# Examples for console:
# a)
# %d %p %c #%m# (%.50F:%L)%n
# date/time
# priority
# category/channel
# #message#
# (Maximal 50Character des Filename von rechts:Line)
# line separator
#
# b)
# %d (%.15F:%L) %-5p %c |#| %m%n
# date/time
# (Maximal 15Character des Filename von rechts:Line)
# priority, Right pad with spaces if the priority name is less than 5 characters long.
# category/channel
# message
# line separator
#
# Examples for files:
+38
View File
@@ -0,0 +1,38 @@
/**
* @RDE_HEADER@
* Logging for FileManagement
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#include "logger.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace FileManagement
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "FLM.";
std::string loggerName;
const size_t len = strlen(name);
loggerName.reserve(sizeof(ns) + len);
loggerName.append(ns, sizeof(ns) - 1);
loggerName.append(name, len);
try
{
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
getNGLLogger(loggerName);
}
catch (const std::exception &ex)
{
fprintf(stderr, "Error retrieving logger: %s", ex.what());
abort();
}
}
} // namespace FileManagement
+24
View File
@@ -0,0 +1,24 @@
/**
* @RDE_HEADER@
* Logging for FileManagement
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include <NGLLogger/INGLLogger.h>
#include "flm_export.h"
namespace FileManagement
{
using LOGGER_T = NGL::INGLLogger &;
FLM_COMMON_EXPORT LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
} // namespace FileManagement
+43
View File
@@ -0,0 +1,43 @@
/**
* @RDE_HEADER@
* Main for FileManagement
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#include <nglapplication/nglcoreapplication.h>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
#include "main_handler.h"
#include "logger.h"
#include "settings.h"
int main(int argc, char **argv)
{
NGLCoreApplication app(argc, argv);
LtsCommandLineParser::LtsCommandLineParser options;
if (!options.init())
return -1;
app.createLogger("FLM", options.exerciseId());
FileManagement::Settings::setIniFile(options.iniFile());
int iRet = -3;
{
std::unique_ptr<FileManagement::MainHandler> mainHandler(new FileManagement::MainHandler);
if (!mainHandler->init(options.domainId()))
return iRet;
STARTUP_LOG(app.baseLogger());
iRet = app.exec();
SHUTDOWN_LOG(app.baseLogger());
}
return iRet;
}
+161
View File
@@ -0,0 +1,161 @@
/**
* @RDE_HEADER@
* MainHandler for FileManagement
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#include "main_handler.h"
#include "handler_file_type_info.h"
#include "handler_folder.h"
#include "handler_file_content.h"
#include "settings.h"
//#include "thp_script_server.h"
#include "thp_script_httq.h"
#include "pdf_server.h"
#include <DDS/DDSConnector/dds_connector.h>
#include <DDS/Core/pacemaker.h>
namespace FileManagement
{
MainHandler::MainHandler(QObject *parent)
: QObject(parent)
, m_ddsHandler(nullptr)
, m_dbHandler(nullptr)
, m_handlerFileTypeInfo(nullptr)
, m_handlerFolder(nullptr)
, m_handlerFileContent(nullptr)
, m_handlerWebSocket(nullptr)
, m_logger(getLogger("MainHandler"))
{}
MainHandler::~MainHandler()
{
m_thpScriptServer = nullptr;
m_pdfServer = nullptr;
m_handlerFileTypeInfo = nullptr;
m_handlerFolder = nullptr;
m_handlerFileContent = nullptr;
m_ddsHandler = nullptr;
m_dbHandler = nullptr;
}
bool MainHandler::init(int domainId)
{
// initialize database
m_dbHandler = std::make_shared<DbHandler>();
if (!m_dbHandler->init(0, Settings::settings()))
{
ERROR_LOG(m_logger) << "Initialisation dbHandler failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation dbHandler succesful.";
// initialize DDS
m_ddsHandler.reset(new DdsHandler(domainId));
if (!m_ddsHandler->init())
{
ERROR_LOG(m_logger) << "Initialisation ddsHandler failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation ddsHandler succesful.";
// read project specific data from database
// publish project specific data
// initialize all handlers
if (!initFlmHandler())
{
ERROR_LOG(m_logger) << "Initialisation FlmHandler failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation FlmHandler succesful.";
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::Running);
return true;
}
int MainHandler::exerciseId() const
{
if (dds())
return dds()->ddsConnector()->getPartitionId();
return -1;
}
bool MainHandler::initFlmHandler()
{
DEBUG_LOG(m_logger) << "Start Initialisation FlmHandler";
// FileTypeInfo
m_handlerFileTypeInfo.reset(new HandlerFileTypeInfo(this));
DEBUG_LOG(m_logger) << "Reset HandlerFileTypeInfo successful.";
if (!m_handlerFileTypeInfo->init())
{
ERROR_LOG(m_logger) << "Initialisation of HandlerFileTypeInfo failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation HandlerFileTypeInfo succesful.";
// Folder
m_handlerFolder.reset(new HandlerFolder(this));
DEBUG_LOG(m_logger) << "Reset HandlerFolder successful.";
if (!m_handlerFolder->init())
{
ERROR_LOG(m_logger) << "Initialisation of HandlerFolder failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation HandlerFolder successful.";
// FileContent
m_handlerFileContent.reset(new HandlerFileContent(this));
DEBUG_LOG(m_logger) << "Reset HandlerFileContent successful.";
if (!m_handlerFileContent->init())
{
ERROR_LOG(m_logger) << "Initialisation of HandlerFileContent failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation HandlerFileContent successful.";
// WebSocketServer
m_handlerWebSocket = std::make_shared<WebSocketInterface::WebSocketInterfaceHandler>(this);
DEBUG_LOG(m_logger) << "Reset WebSocketInterfaceHandler successful.";
if (!m_handlerWebSocket->init())
{
ERROR_LOG(m_logger) << "Initialisation WebSocketInterfaceHandler failed.";
return false;
}
m_ddsHandler->pacemaker()->addPort(m_handlerWebSocket->serverWebSocketPort(), Core::PortType::WebSocketServer);
DEBUG_LOG(m_logger) << "Initialisation WebSocketInterfaceHandler successful.";
m_thpScriptServer.reset(new ThpScriptServer(this));
DEBUG_LOG(m_logger) << "Initialisation ThpTcpScriptServer successful.";
m_pdfServer.reset(new PdfServer(this, this));
if (!m_pdfServer->init())
{
ERROR_LOG(m_logger) << "Initialisation PdfServer failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation PdfServer successful.";
return true;
}
} // namespace FileManagement
+63
View File
@@ -0,0 +1,63 @@
/**
* @RDE_HEADER@
* MainHandler for FileManagement
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include <QObject>
#include "dds_handler.h"
#include "flm_db.h"
#include "logger.h"
#include "handler_file_type_info.h"
#include "WebSocketInterface/websocket_interface_handler.h"
#include <ngldb/db_service_handler.h>
namespace FileManagement
{
using DbHandler = NGLDB::DbServiceHandler<DatabaseInterface>;
class HandlerFileTypeInfo;
class HandlerFolder;
class HandlerFileContent;
class ThpScriptServer;
class PdfServer;
class MainHandler : public QObject
{
Q_OBJECT
public:
explicit MainHandler(QObject *parent = nullptr);
~MainHandler();
bool init(int domainId);
std::shared_ptr<DdsHandler> dds() const { return m_ddsHandler; }
std::shared_ptr<DatabaseInterface> db() const { return m_dbHandler->db(); }
std::shared_ptr<HandlerFileTypeInfo> getHandlerFileTypeInfo() const { return m_handlerFileTypeInfo; }
std::shared_ptr<HandlerFileContent> getHandlerFileContent() const { return m_handlerFileContent; }
std::shared_ptr<HandlerFolder> getHandlerFolder() const { return m_handlerFolder; }
int exerciseId() const;
private:
bool initFlmHandler();
private:
std::shared_ptr<DdsHandler> m_ddsHandler;
std::shared_ptr<DbHandler> m_dbHandler;
std::shared_ptr<HandlerFileTypeInfo> m_handlerFileTypeInfo;
std::shared_ptr<HandlerFolder> m_handlerFolder;
std::shared_ptr<HandlerFileContent> m_handlerFileContent;
std::shared_ptr<WebSocketInterface::WebSocketInterfaceHandler> m_handlerWebSocket;
std::unique_ptr<ThpScriptServer> m_thpScriptServer;
std::unique_ptr<PdfServer> m_pdfServer;
NGL::INGLLogger &m_logger;
};
} // namespace FileManagement
+251
View File
@@ -0,0 +1,251 @@
/**
* @RDE_HEADER@
* Object file content
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#include "object_file_content.h"
#include "flm_db_impl_custom.h"
namespace FileManagement
{
ObjectFileContent::ObjectFileContent(MainHandler *mainHandler)
: Base(mainHandler, getLogger("ObjectFileContent"))
{
}
ObjectFileContent::ObjectFileContent(const FileContent &data, MainHandler *mainHandler)
: Base(mainHandler, getLogger("ObjectFileContent"))
, m_data(data)
{
}
ObjectFileContent::~ObjectFileContent()
{
}
bool ObjectFileContent::isValid() const
{
return m_data.id() > 0;
}
bool ObjectFileContent::isUsed() const
{
return m_data.isUsed();
}
bool ObjectFileContent::isHidden() const
{
return m_data.isHidden();
}
static FileContent toFileContent(const FileContentModifyRequest &request)
{
FileContent data;
data.id(request.id());
data.name(request.name());
data.folderId(request.folderId());
data.fileCategory(request.fileCategory());
data.fileType(request.fileType());
data.fileStatus(request.fileStatus());
data.exerciseId(request.exerciseId());
data.phaseId(request.phaseId());
data.isTemplate(request.isTemplate());
data.isHidden(request.isHidden());
data.isUsedBy(request.isUsedBy());
data.usedBy(request.usedBy());
data.properties(request.properties());
data.exportFileName(request.exportFileName());
data.lastModified(request.lastModified());
data.operatorId(request.operatorId());
return data;
}
Core::FunctionReplyObject ObjectFileContent::createObject(const FileContentModifyRequest &request)
{
m_data = toFileContent(request);
m_data.id(0);
m_data.isUsed(false);
Database::FlmFileContent dbData(toDbData(m_data));
//m_content = request.content();
dbData.content = QByteArray::fromRawData(reinterpret_cast<const char *>(&request.content()[0]), request.content().size());
if (!db()->insert(dbData))
{
QString errText = db()->getLastError().databaseText();
ERROR_LOG(m_logger) << "Error inserting FileContent into database: " << errText;
if (db()->getLastError().nativeErrorCode().contains(QStringLiteral("23505")))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting FileContent into database: unique key violation (folder, name, type, status, operator) for file name '%1'")).arg(m_data.name());
else
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting FileContent with name %1 into database: %2")).arg(m_data.name()).arg(errText);
}
m_data.id(dbData.id);
DEBUG_LOG(m_logger) << "New FileContent Id: " << m_data.id();
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFileContent::updateObject(const FileContentModifyRequest &request)
{
if (!isValid())
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Object not valid/blocked"));
m_data = toFileContent(request);
Database::FlmFileContent dbData(toDbData(m_data));
//m_content = request.content();
DEBUG_LOG(m_logger) << "Content size: " << request.content().size();
dbData.content = QByteArray::fromRawData(reinterpret_cast<const char *>(&request.content()[0]), request.content().size());
if (!db()->update(dbData))
{
QString errText = db()->getLastError().databaseText();
ERROR_LOG(m_logger) << "Error updating FileContent into database: " << errText;
if (db()->getLastError().nativeErrorCode().contains(QStringLiteral("23505")))
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Error updating FileContent into database: unique key violation (folder, name, type, status, operator) for file name '%1'")).arg(m_data.name());
else
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Error updating FileContent with name %1 into database: %2")).arg(m_data.name()).arg(errText);
}
DEBUG_LOG(m_logger) << "Data changed for FileContent Id: " << m_data.id();
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFileContent::setUsed(bool isUsed)
{
if (!isValid())
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "Trying to update an already removed FileContent object"));
m_data.isUsed(isUsed);
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFileContent::changeStatus(const FileContentChangeStatusRequest &request)
{
if (!isValid())
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "Trying to update an already removed FileContent object"));
m_data.id(request.id());
m_data.fileStatus(request.fileStatus());
m_data.operatorId(request.operatorId());
m_data.lastModified(request.lastModified());
if (!db()->updateStatus(m_data.id(), m_data.fileStatus(), m_data.operatorId()))
{
QString errText = db()->getLastError().databaseText();
ERROR_LOG(m_logger) << "Error updating FileContent status into database: " << errText;
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Error updating FileContent status into database: %1")).arg(errText);
}
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFileContent::setUsedBy(const FileContentSetUsedRequest &request)
{
if (!isValid())
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "Trying to update an already removed FileContent object"));
m_data.id(request.id());
m_data.isUsedBy(request.isUsedBy());
m_data.usedBy(request.usedBy());
m_data.operatorId(request.operatorId());
m_data.lastModified(request.lastModified());
if (!db()->setUsedBy(m_data.id(), m_data.isUsedBy(), m_data.usedBy(), m_data.operatorId()))
{
QString errText = db()->getLastError().databaseText();
ERROR_LOG(m_logger) << "Error updating FileContent used status into database: " << errText;
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Error updating FileContent used status into database: %1")).arg(errText);
}
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFileContent::removeObject()
{
if (isUsed())
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "FileContent still in use"));
if (!db()->removeFlmFileContent(m_data.id()))
{
QString errText = db()->getLastError().databaseText();
ERROR_LOG(m_logger) << "FileContent with id " << m_data.id() << " can not be removed from database: " << errText;
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "FileContent with id %1 can not be removed from database: %2")).arg(m_data.id()).arg(errText);
}
if (!dts()->removeFileContentByKey(m_data.id()))
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "FileContent %1 can not be taken from DDS")).arg(m_data.id());
//m_content.clear();
return Core::FunctionReplyObject(m_data.id());
}
void ObjectFileContent::onPublishData()
{
INFO_LOG(m_logger) << "Publish FileContent-data to dds (" << m_data.id() << ") ...";
if (!dts()->publish(m_data))
ERROR_LOG(m_logger) << "Error publishing FileContent-data to dds";
}
// -------------------------------------------------------------------------------------------------------
// convert methods
// -------------------------------------------------------------------------------------------------------
// FileManagement::FileContent => Database::FileContent
Database::FlmFileContent ObjectFileContent::toDbData(const FileContent &ddsData)
{
Database::FlmFileContent dbData;
dbData.id = ddsData.id();
dbData.name = QString::fromStdString(ddsData.name());
dbData.isTemplate = ddsData.isTemplate();
dbData.isHidden = ddsData.isHidden();
dbData.fileCategoryId = ddsData.fileCategory();
dbData.folderId = ddsData.folderId();
dbData.fileTypeId = ddsData.fileType();
dbData.operatorId = ddsData.operatorId();
if (ddsData.exerciseId().is_set())
{
dbData.exerciseId = ddsData.exerciseId().get();
if (ddsData.phaseId().is_set())
dbData.phaseId = ddsData.phaseId().get();
}
dbData.fileStatusId = ddsData.fileStatus();
dbData.isUsedBy = ddsData.isUsedBy();
dbData.usedBy = ddsData.usedBy();
dbData.properties = QString::fromStdString(ddsData.properties());
dbData.lastModified = ddsData.lastModified();
return dbData;
}
// -------------------------------------------------------------------------------------------------------
} // Namespace FileManagement
+59
View File
@@ -0,0 +1,59 @@
/**
* @RDE_HEADER@
* Object file content
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include "base.h"
#include <DDS/Core/function_reply_object.h>
// Generated
#include <FileManagement/flm_db.h>
namespace FileManagement
{
class FileContent;
class ObjectFileContent : public Base
{
public:
explicit ObjectFileContent(MainHandler *mainHandler);
ObjectFileContent(const FileContent &data, MainHandler *mainHandler);
~ObjectFileContent();
Core::FunctionReplyObject createObject(const FileContentModifyRequest &request);
Core::FunctionReplyObject updateObject(const FileContentModifyRequest &request);
Core::FunctionReplyObject changeStatus(const FileContentChangeStatusRequest &request);
Core::FunctionReplyObject setUsedBy(const FileContentSetUsedRequest &request);
Core::FunctionReplyObject removeObject();
qint32 getId() const { return m_data.id(); }
qint32 getFolderId() const { return m_data.folderId(); }
const FileContent &getData() const { return m_data; }
QString getName() const { return QString::fromStdString(m_data.name()); }
// const std::vector<uint8_t> &getContent() const { return m_content; }
bool isValid() const;
bool isUsed() const;
bool isHidden() const;
Core::FunctionReplyObject setUsed(bool isUsed);
void setExportFileName(const std::string &fileName) { m_data.exportFileName().set(fileName); }
// void setContent(std::vector<uint8_t> &&content) { m_content = std::move(content); }
// convert methods
static Database::FlmFileContent toDbData(const FileContent &ddsData); // dds -> db
public Q_SLOTS:
void onPublishData();
private:
FileContent m_data;
// std::vector<uint8_t> m_content;
};
}
+128
View File
@@ -0,0 +1,128 @@
/**
* @RDE_HEADER@
* Object file type
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#include "object_file_type_info.h"
#include "convert_db_to_dds.h"
namespace FileManagement
{
ObjectFileTypeInfo::ObjectFileTypeInfo(MainHandler *mainHandler)
: Base(mainHandler, getLogger("ObjectFileTypeInfo"))
{
}
ObjectFileTypeInfo::~ObjectFileTypeInfo()
{
}
bool ObjectFileTypeInfo::isValid() const
{
return m_data.id() > 0;
}
bool ObjectFileTypeInfo::isUsed() const
{
return m_data.isUsed();
}
Core::FunctionReplyObject ObjectFileTypeInfo::createObject(const FileTypeInfo &data)
{
m_data = data;
if (m_data.id() <= 0)
{
m_data.isUsed(false);
Database::FlmFileTypeInfo dbData;
dbData = toDbData(data);
if (!db()->insert(dbData))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting FileTypeInfo-data into database"));
m_data.id(dbData.id);
DEBUG_LOG(m_logger) << "New FileTypeInfo Id: " << m_data.id();
}
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFileTypeInfo::updateObject(const FileTypeInfo &data)
{
if (!isValid())
return Core::FunctionReplyObject(data.id(), tr_lts("dds", "Object not valid/blocked"));
if (!db()->update(toDbData(data)))
return Core::FunctionReplyObject(data.id(), tr_lts("dds", "Error updating FileTypeInfo-data into database"));
m_data = data;
DEBUG_LOG(m_logger) << "Data changed for FileTypeInfo Id: " << m_data.id();
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFileTypeInfo::setUsed(bool isUsed)
{
if (!isValid())
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "Trying to update an already removed FileTypeInfo object"));
m_data.isUsed(isUsed);
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFileTypeInfo::removeObject()
{
if (isUsed())
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "FileTypeInfo still in use"));
if (!db()->removeFlmFileTypeInfo(m_data.id()))
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "FileTypeInfo %1 can not be removed")).arg(m_data.id());
if (!dts()->removeFileTypeInfoByKey(m_data.id()))
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "FileTypeInfo %1 can not be taken from DDS")).arg(m_data.id());
return Core::FunctionReplyObject(m_data.id());
}
void ObjectFileTypeInfo::onPublishData()
{
INFO_LOG(m_logger) << "Publish FileTypeInfo-data to dds (" << m_data.id() << ") ...";
if (!dts()->publish(m_data))
ERROR_LOG(m_logger) << "Error publishing FileTypeInfo-data to dds";
}
// -------------------------------------------------------------------------------------------------------
// convert methods
// -------------------------------------------------------------------------------------------------------
// FileManagement::FileTypeInfo => Database::FileTypeInfo
Database::FlmFileTypeInfo ObjectFileTypeInfo::toDbData(const FileTypeInfo &ddsData)
{
Database::FlmFileTypeInfo dbData;
dbData.id = ddsData.id();
dbData.description = QString::fromStdString(ddsData.description());
dbData.extension = QString::fromStdString(ddsData.extension());
return dbData;
}
// -------------------------------------------------------------------------------------------------------
} // Namespace FileManagement
+48
View File
@@ -0,0 +1,48 @@
/**
* @RDE_HEADER@
* Object file type
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include "base.h"
#include <DDS/Core/function_reply_object.h>
// Generated
#include <FileManagement/flm_db.h>
namespace FileManagement
{
class FileTypeInfo;
class ObjectFileTypeInfo : public Base
{
public:
explicit ObjectFileTypeInfo(MainHandler *mainHandler);
~ObjectFileTypeInfo();
Core::FunctionReplyObject createObject(const FileTypeInfo &data);
Core::FunctionReplyObject updateObject(const FileTypeInfo &data);
Core::FunctionReplyObject removeObject();
qint32 getId() const { return m_data.id(); }
QString getExtension() const { return QString::fromStdString(m_data.extension()); }
bool isValid() const;
bool isUsed() const;
Core::FunctionReplyObject setUsed(bool isUsed);
// convert methods
static Database::FlmFileTypeInfo toDbData(const FileTypeInfo &ddsData); // dds -> db
protected Q_SLOTS:
void onPublishData();
private:
FileTypeInfo m_data;
};
}
+153
View File
@@ -0,0 +1,153 @@
/**
* @RDE_HEADER@
* Object folder
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#include "object_folder.h"
#include "dds_handler.h"
#include "logger.h"
namespace FileManagement
{
ObjectFolder::ObjectFolder(MainHandler *mainHandler)
: Base(mainHandler, getLogger("ObjectFolder"))
{
}
ObjectFolder::~ObjectFolder()
{
}
bool ObjectFolder::isValid() const
{
return m_data.id() > 0;
}
bool ObjectFolder::isUsed() const
{
return m_data.isUsed();
}
Core::FunctionReplyObject ObjectFolder::createObject(const Folder &data)
{
m_data = data;
if (m_data.id() <= 0)
{
m_data.isUsed(false);
Database::FlmFolder dbData;
dbData = toDbData(data);
if (!db()->insert(dbData))
{
QString errText = db()->getLastError().databaseText();
ERROR_LOG(m_logger) << "Error inserting Folder into database: " << errText;
if (db()->getLastError().nativeErrorCode().contains(QStringLiteral("23505")))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting Folder into database: unique key violation inserting folder '%1'")).arg(m_data.name());
if (db()->getLastError().nativeErrorCode().contains(QStringLiteral("23503")))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting Folder into database: foreign key violation inserting folder '%1'")).arg(m_data.name());
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting Folder into database: %1")).arg(errText);
}
m_data.id(dbData.id);
DEBUG_LOG(m_logger) << "New Folder Id: " << m_data.id();
}
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFolder::updateObject(const Folder &data)
{
if (!isValid())
return Core::FunctionReplyObject(data.id(), tr_lts("dds", "Object not valid/blocked"));
Database::FlmFolder dbData(toDbData(data));
if (!db()->update(dbData))
{
QString errText = db()->getLastError().databaseText();
ERROR_LOG(m_logger) << "Error updating Folder into database: " << errText;
return Core::FunctionReplyObject(data.id(), tr_lts("dds", "Error updating Folder into database: %1")).arg(errText);
}
m_data = data;
DEBUG_LOG(m_logger) << "Data changed for Folder Id: " << m_data.id();
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFolder::setUsed(bool isUsed)
{
if (!isValid())
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "Trying to update an already removed Folder object"));
m_data.isUsed(isUsed);
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_data.id());
}
Core::FunctionReplyObject ObjectFolder::removeObject()
{
if (isUsed())
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "Folder still in use"));
if (!db()->removeFlmFolder(m_data.id()))
{
QString errText = db()->getLastError().databaseText();
ERROR_LOG(m_logger) << "Folder with id " << m_data.id() << " can not be removed from database: " << errText;
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "Folder with id %1 can not be removed from database: %2")).arg(m_data.id()).arg(errText);
}
if (!dts()->removeFolderByKey(m_data.id()))
return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "Folder with id %1 can not be taken from DDS")).arg(m_data.id());
return Core::FunctionReplyObject(m_data.id());
}
void ObjectFolder::onPublishData()
{
INFO_LOG(m_logger) << "Publish Folder-data to dds (" << m_data.id() << ") ...";
if (!dts()->publish(m_data))
ERROR_LOG(m_logger) << "Error publishing Folder-data to dds";
}
// -------------------------------------------------------------------------------------------------------
// convert methods
// -------------------------------------------------------------------------------------------------------
// FileManagement::Folder => Database::Folder
Database::FlmFolder ObjectFolder::toDbData(const Folder &ddsData)
{
Database::FlmFolder dbData;
dbData.id = ddsData.id();
dbData.name = QString::fromStdString(ddsData.name());
dbData.path = LtsUtils::IntArray(ddsData.path());
dbData.isEditable = ddsData.isEditable();
dbData.isHidden = ddsData.isHidden();
dbData.parentId = ddsData.parentId();
dbData.operatorId = ddsData.operatorId();
dbData.lastModified = ddsData.lastModified();
return dbData;
}
// -------------------------------------------------------------------------------------------------------
} // Namespace FileManagement
+62
View File
@@ -0,0 +1,62 @@
/**
* @RDE_HEADER@
* Object folder
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include "base.h"
#include <DDS/Core/function_reply_object.h>
// Generated
#include <FileManagement/flm_db.h>
namespace FileManagement
{
class Folder;
class ObjectFolder : public Base
{
public:
explicit ObjectFolder(MainHandler *mainHandler);
~ObjectFolder();
Core::FunctionReplyObject createObject(const Folder &data);
Core::FunctionReplyObject updateObject(const Folder &data);
Core::FunctionReplyObject removeObject();
qint32 getId() const { return m_data.id(); }
Folder getData() const { return m_data; }
QString getName() const { return QString::fromStdString(m_data.name()); }
std::vector<int32_t> getPath() const
{
return m_data.path();
}
qint32 getParentId() const
{
return m_data.path().size() > 1 ? m_data.path().at(m_data.path().size() - 2) : 0;
}
bool pathContains(const int32_t &val) const
{
for (auto i : m_data.path())
if (i == val) return true;
return false;
}
bool isValid() const;
bool isUsed() const;
Core::FunctionReplyObject setUsed(bool isUsed);
// convert methods
static Database::FlmFolder toDbData(const Folder &ddsData); // dds -> db
void onPublishData();
private:
Folder m_data;
};
}
+82
View File
@@ -0,0 +1,82 @@
/**
* @RDE_HEADER@
* Download a PDF file from the server
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 2019-04-29
*/
#include "pdf_download.h"
#include "main_handler.h"
#include <tcpserver/tcpserver.h>
namespace FileManagement
{
CBI_PdfDownload::CBI_PdfDownload(unsigned short port)
: CommandInterface(port, "PDF_DOWNLOAD")
, m_logger(getLogger("PdfDownload"))
{}
void CBI_PdfDownload::handleCommandInternal(const QVector<QByteArray> &args)
{
setAutoWriteEOL(false);
DEBUG_LOG(m_logger) << "Got command for PDF download";
if (args.count() != 1)
{
ERROR_LOG(m_logger) << "Invalid arg count";
return;
}
DEBUG_LOG(m_logger) << "Argument count ok";
bool bOk;
int documentId = args.at(0).toInt(&bOk);
if (!bOk)
{
const QString err(QStringLiteral("Invalid file id: '%1'").arg(QString::fromUtf8(args.at(0))));
writeError(err);
ERROR_LOG(m_logger) << err;
return;
}
DEBUG_LOG(m_logger) << "Argument ok";
MainHandler *mainHandler = static_cast<MainHandler *>(TcpServer::instance(port())->userData());
Database::FlmFileContent fileContent;
mainHandler->db()->selectFlmFileContent(documentId, fileContent);
if (fileContent.id < 1)
{
const QString err(QStringLiteral("File with ID '%1' does not exist").arg(QString::fromUtf8(args.at(0))));
writeError(err);
ERROR_LOG(m_logger) << err;
return;
}
DEBUG_LOG(m_logger) << "File ID valid";
if (fileContent.fileTypeId != FileManagement::FileType::Pdf)
{
const QString err(QStringLiteral("File with ID '%1' is not of type Pdf").arg(QString::fromUtf8(args.at(0))));
writeError(err);
ERROR_LOG(m_logger) << err;
return;
}
DEBUG_LOG(m_logger) << "FileType valid";
// success
DEBUG_LOG(m_logger) << "File ok, sending file \"" << fileContent.name << "\" with ID " << fileContent.id;
writeData(fileContent.content);
}
QString CBI_PdfDownload::help() const
{
return QLatin1String("PDF_DOWNLOAD <fileId> ");
}
} // namespace FileManagement
+34
View File
@@ -0,0 +1,34 @@
/**
* @RDE_HEADER@
* Download a PDF file from the server
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 2019-04-29
*/
#pragma once
#include <tcpserver/commandinterface.h>
#include "logger.h"
namespace FileManagement
{
class MainHandler;
class CBI_PdfDownload : public CommandInterface
{
Q_OBJECT
public:
explicit CBI_PdfDownload(unsigned short port);
QString help() const override;
protected:
void handleCommandInternal(const QVector<QByteArray> &args) override;
private:
NGL::INGLLogger &m_logger;
};
} // namespace FileManagement
+52
View File
@@ -0,0 +1,52 @@
/**
* @RDE_HEADER@
* TCP Server for downloading PDF files
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 2019-04-29
*/
#include "pdf_server.h"
#include "pdf_download.h"
#include <nglsettings/nglsettings_connections.h>
#include <tcpserver/cbi_help.h>
#include <tcpserver/cbi_quit.h>
namespace FileManagement
{
PdfServer::PdfServer(MainHandler *mainHandler, QObject *parent)
: QObject(parent)
, m_tcpServer(TcpServer::instance(NGL::Connections::port(NGL::Connections::eConnection::FLM_PDF_SERVER)))
, m_logger(getLogger("PdfServer"))
{
m_tcpServer->setUserData(mainHandler);
m_tcpServer->setUseWorkerThreads(false);
}
PdfServer::~PdfServer()
{
delete m_tcpServer;
}
bool PdfServer::init()
{
const quint16 port = m_tcpServer->getListenPort();
if (!m_tcpServer->listen(QHostAddress::Any))
{
FATAL_LOG(m_logger) << "Error listening on port: " << port
<< ", error: " << m_tcpServer->errorString();
return false;
}
TcpServer::registerCommand(port, CommandInterface::factory<CBI_Help>);
TcpServer::registerCommand(port, CommandInterface::factory<CBI_Quit>);
TcpServer::registerCommand(port, CommandInterface::factory<CBI_PdfDownload>);
TcpServer::registeredCommands(port);
return true;
}
} // namespace FileManagement
+33
View File
@@ -0,0 +1,33 @@
/**
* @RDE_HEADER@
* TCP Server for downloading PDF files
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 2019-04-29
*/
#pragma once
#include <QObject>
#include <tcpserver/tcpserver.h>
#include "logger.h"
namespace FileManagement
{
class MainHandler;
class PdfServer : public QObject
{
Q_OBJECT
public:
explicit PdfServer(MainHandler *mainHandler, QObject *parent = nullptr);
~PdfServer();
bool init();
private:
TcpServer *m_tcpServer;
NGL::INGLLogger &m_logger;
};
} // namespace FileManagement
+56
View File
@@ -0,0 +1,56 @@
/**
* @RDE_HEADER@
* Settings for FileManagement
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#include "settings.h"
#include <QtCore/QSettings>
#include <nglsettings/nglsettings_settings.h>
#include <ngltools/ngltools_filesystem.h>
#include "LtsUtilsCore/lts_portrange.h"
namespace FileManagement
{
class NGLSettingsClass : public NGL::Settings
{
public:
NGLSettingsClass()
: NGL::Settings(s_iniFile.isEmpty() ? NGL::findProjectConfigFile() : s_iniFile)
{}
static void setIniFile(const QString &fn)
{
s_iniFile = fn;
}
static QString s_iniFile;
};
QString NGLSettingsClass::s_iniFile;
Q_GLOBAL_STATIC(NGLSettingsClass, s)
//-----------------------------------------------------------------------------
NGL::Settings *Settings::settings()
{
return s();
}
//-----------------------------------------------------------------------------
void Settings::setIniFile(const QString &ini)
{
NGLSettingsClass::setIniFile(ini);
}
//-----------------------------------------------------------------------------
QPair<quint16, quint16> Settings::getWebSocketServerPortRange(int type)
{
return LtsUtils::fromQPoint(settings()->settings()->value(QString(QStringLiteral("FLM/webSocketServerPortRange/%1")).arg(type), QPoint()).toPoint());
}
} // namespace FileManagement
+28
View File
@@ -0,0 +1,28 @@
/**
* @RDE_HEADER@
* Settings for FileManagement
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-04-03
*/
#pragma once
#include <QString>
#include <QPair>
namespace NGL
{
class Settings;
}
namespace FileManagement
{
namespace Settings
{
NGL::Settings *settings();
void setIniFile(const QString &ini);
QPair<quint16, quint16> getWebSocketServerPortRange(int type);
}
} // namespace FileManagement
+753
View File
@@ -0,0 +1,753 @@
#include "thp_script_httq.h"
#include "logger.h"
#include <httq/HttpRequest.h>
#include <httq/DataStream.h>
#include <nglsettings/nglsettings_connections.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <Common2Core/tpm_tools.h>
#include <Common2Core/tpm_js_parser.h>
#include <QWebSocket>
#include <QWebSocketServer>
#include <QFile>
#include <QJsonParseError>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QTemporaryFile>
//#include <QSaveFile>
#include <QDateTime>
#include <QFileInfo>
#include <QDir>
#include <QUrlQuery>
#include <QDebug>
#define L QStringLiteral
using namespace TakeHomePackageManager;
namespace FileManagement
{
// LoggerFactory
LoggerFactory::LoggerFactory(QObject *parent)
: httq::LoggerFactory(parent)
{
}
Logger *LoggerFactory::createLogger(QObject *parent)
{
return new Logger(this, parent);
}
LoggerFactory *ThpScriptServer::createLoggerFactory()
{
return new LoggerFactory(this);
}
// Logger
Logger::Logger(LoggerFactory *loggerFactory, QObject *parent)
: httq::Logger(loggerFactory, parent)
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger(QString::fromUtf8(parent->metaObject()->className()).replace(QStringLiteral("::"), QStringLiteral(".")).toStdString())) // man man
{}
void Logger::debug(const QString &message)
{
/*DEBUG_LOG*/ERROR_LOG(m_logger) << message;
}
void Logger::warning(const QString &message)
{
WARNING_LOG(m_logger) << message;
}
void Logger::error(const QString &message)
{
ERROR_LOG(m_logger) << message;
}
// ThpScriptServer
ThpScriptServer::ThpScriptServer(QObject *parent)
: AbstractServer(parent)
, mWsSvr(new QWebSocketServer({}, QWebSocketServer::NonSecureMode, this))
, m_logger(getLogger("ThpScriptServer"))
{
if (!listen(NGL::Connections::port(NGL::Connections::eConnection::FLM_THP_SERVER)))
{
ERROR_LOG(m_logger) << "cannot listen on port " << NGL::Connections::port(NGL::Connections::eConnection::FLM_THP_SERVER);
Q_ASSERT(false);
}
QDir().mkpath(scriptsLocation(serverThpDir()));
connect(this, &ThpScriptServer::signalBroadcastNewContentFile,
this, [this]()
{
emit signalBroadcastMessage(readContentFile());
}, Qt::UniqueConnection);
connect(this, &ThpScriptServer::signalBroadcastNewScriptsJsFile,
this, [this]()
{
emit signalBroadcastMessage2(readScriptsJsFile());
}, Qt::UniqueConnection);
connect(mWsSvr, &QWebSocketServer::newConnection,
this, [this]()
{
while (mWsSvr->hasPendingConnections())
{
QWebSocket *cli = mWsSvr->nextPendingConnection();
if (cli == nullptr)
return;
bool failed = false;
switch (QStringList{{L("/thp"), L("/thp2")}}.indexOf(cli->requestUrl().path()))
{
case 0: // old
{
connect(this, &ThpScriptServer::signalBroadcastMessage,
cli, [cli](const QString &msg)
{
cli->sendTextMessage(msg);
});
cli->sendTextMessage(readContentFile());
break;
}
case 1: // THP2
{
connect(this, &ThpScriptServer::signalBroadcastMessage2,
cli, [cli](const QString &msg)
{
cli->sendTextMessage(msg);
});
cli->sendTextMessage(readScriptsJsFile());
break;
}
default:
{
ERROR_LOG(m_logger) << "ws unknown path: " << cli->requestUrl().path();
failed = true;
break;
}
}
if (failed)
{
cli->deleteLater();
continue;
}
connect(cli, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error),
this, [cli]()
{
cli->deleteLater();
//qWarning() << "ws error!!!";
});
connect(cli, &QWebSocket::disconnected,
this, [cli]()
{
cli->deleteLater();
//qWarning() << "ws disco!!!";
});
}
});
}
const QString ThpScriptServer::readScriptsJsFile() const
{
return QString::fromUtf8(QJsonDocument(ScriptsJsParser(serverThpDir(), false).get()).toJson());
}
const QString ThpScriptServer::readContentFile() const
{
QFile *f = new QFile(thpDirectory() + QStringLiteral("content.json"));
f->deleteLater();
if (!f->open(QIODevice::ReadOnly))
{
WARNING_LOG(m_logger) << "Error opening " << f->fileName() << " for reading: " << f->errorString();
return QStringLiteral("[]");
}
return QString::fromUtf8(f->readAll());
}
class DataStreamError : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
bool ThpScriptServer::newHttpConnection(httq::HttpRequest *request)
{
try
{
if (handleRequestSync(*request))
{
request->deleteLater();
}
else if (!handleRequest(request))
{
throw(L("unroutable"));
}
return true;
}
catch(const DataStreamError &err)
{
DEBUG_LOG(m_logger) << "handler threw DataStreamError: " << err.what();
// do not delete request as a failed datastream deletes it itself
return false;
}
catch(const std::runtime_error &err)
{
errorHandler(request, HttpException(QString::fromUtf8(err.what()), 400));
return false;
}
catch(const QString &error)
{
errorHandler(request, HttpException(error, 400));
return false;
}
catch(const HttpException &he)
{
errorHandler(request, he);
return false;
}
catch(...)
{
errorHandler(request, HttpException(L("<unknown exception!>"), 400));
return false;
}
}
QString ThpScriptServer::thpDirectory()
{
// TODO (what exactly?)
return QDir::tempPath() + QStringLiteral("/THP/");
}
QString ThpScriptServer::thpDirectory(int exerciseId)
{
return thpDirectory() + QStringLiteral("%1/").arg(exerciseId);
}
QString ThpScriptServer::thpFileName(int exerciseId, int scriptId)
{
return thpDirectory(exerciseId) + QString::number(scriptId) + QStringLiteral(".tar.bz2");
}
QJsonObject ThpScriptServer::toJson(const ThpServerInformation &tsi)
{
return QJsonObject({
{QStringLiteral("exerciseId"), tsi.exerciseId},
{QStringLiteral("exerciseName"), tsi.exerciseName},
{QStringLiteral("scriptId"), tsi.scriptId},
{QStringLiteral("uploadTime"), tsi.uploadTime},
{QStringLiteral("fileSize"), tsi.fileSize},
{QStringLiteral("name"), tsi.description}
//{QStringLiteral("md5sumHex"), tsi.md5sumHex}
});
}
ThpServerInformation ThpScriptServer::fromJson(const QJsonValue &val)
{
const QJsonObject obj = val.toObject();
ThpServerInformation tsi;
tsi.exerciseId = obj[QStringLiteral("exerciseId")].toInt();
tsi.exerciseName = obj[QStringLiteral("exerciseName")].toString();
tsi.scriptId = obj[QStringLiteral("scriptId")].toInt();
tsi.uploadTime = qRound64(obj[QStringLiteral("uploadTime")].toDouble());
tsi.fileSize = qRound64(obj[QStringLiteral("fileSize")].toDouble());
tsi.description = obj[QStringLiteral("name")].toString();
//tsi.md5sumHex = obj[QStringLiteral("md5sumHex")].toString();
return tsi;
}
void ThpScriptServer::errorHandler(httq::HttpRequest *request, const HttpException &e) const
{
DEBUG_LOG(m_logger) << "handler threw error: " << e.error << " (http status = " << e.status << ")";
QJsonObject root;
root[QStringLiteral("error")] = e.error;
#ifdef LTS_DEBUG
root[QStringLiteral("DEBUG")] = request->url().path();
#endif
request->write(e.status, root);
request->deleteLater();
}
void ThpScriptServer::changeList(const ThpServerInformation &tsi, httq::HttpRequest *request, bool remove)
{
try
{
QFile contentFile(thpDirectory() + QStringLiteral("content.json"), this);
if (!contentFile.open(QIODevice::ReadWrite))
{
ERROR_LOG(m_logger) << "Error opening file '" << contentFile.fileName() << "' for read/write: " << contentFile.errorString();
throw(HttpException(QStringLiteral("cannot open content file '%1': %2").arg(contentFile.fileName(), contentFile.errorString())));
}
if (contentFile.size() == 0) // file was just created by the open command - fill it with an valid, but empty json array
{
contentFile.write(QStringLiteral("[]").toUtf8());
contentFile.seek(0);
}
QJsonParseError err;
QJsonDocument doc(QJsonDocument::fromJson(contentFile.readAll(), &err));
if (err.error != QJsonParseError::NoError)
{
ERROR_LOG(m_logger) << "content file's json invalid at" << err.offset << ":" << err.errorString();
throw(HttpException(QStringLiteral("content file's json invalid at %1: %2").arg(err.offset).arg(err.errorString())));
}
QJsonArray arr(doc.array());
QVector<ThpServerInformation> tsiArray;
tsiArray.reserve(arr.size() + 1);
for (const QJsonValue &val : qAsConst(arr))
{
ThpServerInformation tsix(fromJson(val));
if (tsix.scriptId == tsi.scriptId && tsix.exerciseId == tsi.exerciseId)
continue;
tsiArray += std::move(tsix);
}
if (!remove)
tsiArray += tsi;
arr = {};
std::transform(tsiArray.constBegin(), tsiArray.constEnd(), std::back_inserter(arr),
[](const ThpServerInformation &tsix)
{
return toJson(tsix);
});
if (!contentFile.resize(0) || !contentFile.write(QJsonDocument(arr).toJson()))
{
ERROR_LOG(m_logger) << "Error writing content.json: " << contentFile.errorString();
throw(HttpException(QStringLiteral("error writing content file: %1").arg(contentFile.errorString())));
}
request->write(200, noError());
contentFile.flush(); // needed as signalBroadcastNewContentFile reads from the file, which has old data in it until it's flushed
emit signalBroadcastNewContentFile(); // content file has changed, as a new script was uploaded - tell all the clients
request->deleteLater();
}
catch (const HttpException &e)
{
errorHandler(request, e);
}
}
QJsonObject ThpScriptServer::noError()
{
static QJsonObject obj({{ QStringLiteral("error"), QString() }});
return obj;
}
QString ThpScriptServer::queryGetString(const QUrlQuery &q, const QString &key)
{
if (!q.hasQueryItem(key))
throw(HttpException(QStringLiteral("%1 missing").arg(key), 400));
return q.queryItemValue(key);
}
int ThpScriptServer::queryGetInt(const QUrlQuery &q, const QString &key)
{
const QString value(queryGetString(q, key));
bool k = false;
int num = value.toInt(&k);
if (!k)
throw(HttpException(QStringLiteral("%1 not an int").arg(key), 400));
return num;
}
bool ThpScriptServer::handleRequestSync(httq::HttpRequest &request) noexcept(false)
{
//qWarning() << "url" << request->url() << "method" << (request->method() == HTTP_GET ? "GET" : request->method() == HTTP_POST ? "POST" : "?");
const QUrl &url = request.url();
if (url.path() == L("/thp2"))
{
switch (request.method())
{
case HTTP_GET: // DOWNLOAD THP
{
const QUrlQuery &q(request.query());
const QString scriptId(queryGetString(q, L("scriptId")));
auto esi = ScriptsJsParser(serverThpDir()).getExportedScriptInformation(scriptId);
request.addHeader(L("x-thp-info"), QString::fromUtf8(QJsonDocument(esi.toJson().toObject()).toJson(QJsonDocument::JsonFormat::Compact)));
QFile f(scriptArchiveLocation(serverThpDir(), scriptId));
openFile(f, true, true);
httq::DataStream *ds = request.createDataStreamToClient(200, L("application/octet-stream"), &f, f.size());
try
{
awaitWithCancelationSignalx(ds, &httq::DataStream::signalDone, ds, &QObject::destroyed);
}
catch (const std::runtime_error &err)
{
throw DataStreamError("Writing DataStream failed! Client disconnect?");
}
return true;
break;
}
case HTTP_POST: // UPLOAD THP
{
const QString thpInfo(request.requestHeaders().value(L("x-thp-info")));
if (thpInfo.isEmpty())
{
qWarning() << "headers" << request.requestHeaders();
throw L("x-thp-info header missing");
}
auto esi = ExportedScriptInformation::fromJson(JsonObject::fromJson(thpInfo.toUtf8()).object());
const auto destDir(scriptLocation(serverThpDir(), esi.id()));
if (!QDir().mkpath(destDir)) // NOTE: we don't check if id is evil here
{
throw(L("Cannot create directory %1 - THP upload not possible").arg(destDir));
}
const auto destFile(scriptArchiveLocation(serverThpDir(), esi.id()));
QFileInfo fi(destFile);
if (fi.exists() && !QFile::remove(destFile))
{
throw L("Cannot remove old THP upload file %1 - THP upload not possible").arg(destDir);
}
auto saveFile = SaveFile::open(destFile);
qWarning() << "######### STEP 1" << request.contentLength();
httq::DataStream *ds = request.createDataStreamFromClient(saveFile.get(), request.contentLength()); // NOTE: auto-deletes itself
qWarning() << "######### STEP 2";
try
{
qWarning() << "######### STEP 3";
awaitWithCancelationSignalx(ds, &httq::DataStream::signalDone, ds, &QObject::destroyed); // destroyed before signalDone? => error
qWarning() << "######### STEP 4";
}
catch (const std::runtime_error &err)
{
throw DataStreamError("Reading DataStream failed! Client disconnect?");
}
qWarning() << "######### STEP 5";
auto parser = ScriptsJsParser(serverThpDir(), false);
parser.addExportedScriptInformation(esi);
parser.save();
qWarning() << "######### STEP 6";
request.write(201, QJsonObject());
qWarning() << "######### STEP 7";
emit signalBroadcastNewScriptsJsFile(); // scripts.js file has changed, as a new script was uploaded - tell all the clients
return true;
}
case HTTP_DELETE:
{
const QUrlQuery &q(request.query());
const QString scriptId(queryGetString(q, L("scriptId")));
auto parser = ScriptsJsParser(serverThpDir(), true);
parser.removeExportedScriptInformation(scriptId);
parser.save();
const auto scriptDir(scriptLocation(serverThpDir(), scriptId));
if (!QDir().rmdir(scriptDir)) // NOTE: we don't check if id is evil here
{
throw L("Failed to remove script dir '%1' - THP delete not possible").arg(scriptDir);
}
const auto scriptArchive(scriptArchiveLocation(serverThpDir(), scriptId));
if (!QFile::remove(scriptArchive)) // NOTE: we don't check if id is evil here
{
throw L("Failed to remove script archive '%1' - THP delete not possible").arg(scriptArchive);
}
request.write(200, QJsonObject());
emit signalBroadcastNewScriptsJsFile(); // scripts.js file has changed, as a new script was uploaded - tell all the clients
return true;
}
default:
{
WARNING_LOG(m_logger) << "unsupported method for /thp2";
throw HttpException(L("unsupported method for /thp2: %1").arg((int)request.method()), 405);
}
}
}
return false;
}
bool ThpScriptServer::handleRequest(httq::HttpRequest *request) noexcept(false)
{
//qWarning() << "url" << request->url() << "method" << (request->method() == HTTP_GET ? "GET" : request->method() == HTTP_POST ? "POST" : "?");
const QUrl &url = request->url();
switch (request->method())
{
case HTTP_GET:
{
if (url.path() == QStringLiteral("/list"))
{
QFile *f = new QFile(thpDirectory() + QStringLiteral("content.json"));
if (!f->open(QIODevice::ReadOnly))
{
f->deleteLater();
request->write(200, noError());
request->deleteLater();
return true;
}
httq::DataStream *ds = request->createDataStreamToClient(200, QStringLiteral("application/json"), f, f->size());
connect(ds, &httq::DataStream::signalDone,
this, [request, f]()
{
f->deleteLater();
request->deleteLater();
});
return true;
}
else if (url.path() == QStringLiteral("/thp"))
{
const QUrlQuery &q(request->query());
int exerciseId(queryGetInt(q, QStringLiteral("exerciseId")));
int scriptId(queryGetInt(q, QStringLiteral("scriptId")));
QFile *f = new QFile(thpFileName(exerciseId, scriptId));
if (!f->open(QIODevice::ReadOnly))
{
f->deleteLater();
throw(HttpException(QStringLiteral("thp for exercise %1, script %2 not found").arg(exerciseId).arg(scriptId), 404));
return true;
}
httq::DataStream *ds = request->createDataStreamToClient(200, QStringLiteral("application/octet-stream"), f, f->size());
connect(ds, &httq::DataStream::signalDone,
this, [request, f]()
{
f->deleteLater();
request->deleteLater();
});
return true;
}
break;
}
case HTTP_DELETE: // REMOVE THP
{
if (url.path() == QStringLiteral("/thp"))
{
const QUrlQuery &q(request->query());
ThpServerInformation tsi;
tsi.exerciseId = queryGetInt(q, QStringLiteral("exerciseId"));
tsi.scriptId = queryGetInt(q, QStringLiteral("scriptId"));
const QString destFile = thpFileName(tsi.exerciseId, tsi.scriptId);
if (!QFile::remove(destFile))
{
const QString err(QStringLiteral("Cannot remove old THP upload file %1 - removing THP not possible").arg(destFile));
ERROR_LOG(m_logger) << err;
throw(HttpException(err));
}
changeList(tsi, request, true);
request->write(200, noError());
return true;
}
break;
}
case HTTP_POST: // UPLOAD THP
{
if (url.path() == QStringLiteral("/thp"))
{
const QUrlQuery &q(request->query());
ThpServerInformation tsi;
tsi.exerciseId = queryGetInt(q, QStringLiteral("exerciseId"));
tsi.scriptId = queryGetInt(q, QStringLiteral("scriptId"));
tsi.exerciseName = queryGetString(q, QStringLiteral("exerciseName"));
tsi.description = q.queryItemValue(QStringLiteral("name"));
tsi.fileSize = request->contentLength();
tsi.uploadTime = QDateTime::currentMSecsSinceEpoch();
// qWarning() << "tsi.exerciseName=" << tsi.exerciseName
// << " tsi.scriptId=" << tsi.scriptId
// << " tsi.description (name)=" << tsi.description
// << " tsi.fileSize=" << tsi.fileSize
// //<< " tsi.md5sumHex=" << tsi.md5sumHex
// << " tsi.uploadTime=" << tsi.uploadTime;
const QString destDir = thpDirectory(tsi.exerciseId);
if (!QDir().mkpath(destDir))
{
const QString err(QStringLiteral("Cannot create directory %1 - THP upload not possible").arg(destDir));
ERROR_LOG(m_logger) << err;
throw(HttpException(err));
}
const QString destFile = thpFileName(tsi.exerciseId, tsi.scriptId);
QFileInfo fi(destFile);
if (fi.exists() && !QFile::remove(destFile))
{
const QString err(QStringLiteral("Cannot remove old THP upload file %1 - THP upload not possible").arg(destDir));
ERROR_LOG(m_logger) << err;
throw(HttpException(err));
}
// qWarning() << "New upload request - scriptId: " << tsi.scriptId
// << " exerciseId: " << tsi.exerciseId
// << " fileSize: " << tsi.fileSize
// //<< " md5sum: " << tsi.md5sumHex
// ;
QTemporaryFile *f = new QTemporaryFile(this);
if (!f->open())
{
f->deleteLater();
throw(HttpException(QStringLiteral("Error opening temp file '%1' for writing: %2").arg(f->fileName(), f->errorString())));
}
httq::DataStream *ds = request->createDataStreamFromClient(f, request->contentLength());
connect(ds, &httq::DataStream::signalDone, // step 2 =>
this, [this, f, request, tsi]()
{
try
{
const QString destDir = thpDirectory(tsi.exerciseId);
QDir d(destDir);
if (!d.exists() && !d.mkpath(destDir))
{
const QString errstr(QStringLiteral("Can create directory '%1' - THP upload not possible").arg(destDir));
ERROR_LOG(m_logger) << errstr;
throw(HttpException(errstr));
}
const QString destFile = thpFileName(tsi.exerciseId, tsi.scriptId);
QFileInfo fi(destFile);
if (fi.exists() && !QFile::remove(destFile))
{
const QString errstr(QStringLiteral("Can not remove old file '%1'").arg(destDir));
ERROR_LOG(m_logger) << errstr;
throw(HttpException(errstr));
}
// calling fileName() makes sure setAutoRemove(false) is honored on all systems
const QString tmpFilename = f->fileName();
if (!f->rename(destFile))
{
const QString errstr(QStringLiteral("Can not rename %1 to %2: %3").arg(tmpFilename, destFile, f->errorString()));
ERROR_LOG(m_logger) << errstr;
throw(HttpException(errstr));
}
f->setAutoRemove(false);
//qWarning() << QStringLiteral("Renamed %1 to %2").arg(tmpFilename, destFile);
// now update info.json
}
catch (const HttpException &e)
{
errorHandler(request, e);
}
changeList(tsi, request, false);
});
return true;
}
break;
}
default:
{
WARNING_LOG(m_logger) << "unsupported method";
throw(HttpException(QStringLiteral("unsupported method"), 405));
}
}
return false;
}
} // namespace FileManagement
+107
View File
@@ -0,0 +1,107 @@
#pragma once
#include <NGLLogger/INGLLogger.h>
#include <httq/AbstractServer.h>
#include <httq/Logger.h>
class QTemporaryFile;
class QUrlQuery;
namespace FileManagement
{
struct ThpServerInformation
{
int exerciseId { 0 };
int scriptId { 0 };
qint64 uploadTime { 0 }; // msecs / epoch
qint64 fileSize { 0 };
QString exerciseName;
QString description;
QString md5sumHex;
};
class HttpException
{
public:
HttpException(const QString &error, int status = 500)
: error(error)
, status(status)
{}
QString error;
int status { 500 };
};
class LoggerFactory;
class Logger : public httq::Logger
{
Q_OBJECT
public:
Logger(LoggerFactory *loggerFactory, QObject *parent);
void debug(const QString &message) override;
void warning(const QString &message) override;
void error(const QString &message) override;
private:
NGL::INGLLogger &m_logger;
};
class LoggerFactory : public httq::LoggerFactory
{
Q_OBJECT
public:
LoggerFactory(QObject *parent);
virtual Logger *createLogger(QObject *parent);
};
class ThpScriptServer : public httq::AbstractServer
{
Q_OBJECT
public :
ThpScriptServer(QObject *parent = nullptr);
private:
QWebSocketServer *mWsSvr;
NGL::INGLLogger &m_logger;
static QJsonObject noError();
bool newHttpConnection(httq::HttpRequest *request) override;
virtual QWebSocketServer *webSocketServer() const override { return mWsSvr; }
bool handleRequestSync(httq::HttpRequest &request) noexcept(false);
bool handleRequest(httq::HttpRequest *request) noexcept(false);
const QString readScriptsJsFile() const;
const QString readContentFile() const;
void changeList(const ThpServerInformation &tsi, httq::HttpRequest *request, bool remove);
void errorHandler(httq::HttpRequest *request, const HttpException &e) const;
int queryGetInt(const QUrlQuery &q, const QString &key);
QString queryGetString(const QUrlQuery &q, const QString &key);
LoggerFactory *createLoggerFactory() override;
static QString thpDirectory();
static QString thpDirectory(int exerciseId);
static QString thpFileName(int exerciseId, int scriptId);
static QJsonObject toJson(const ThpServerInformation &tsi);
static ThpServerInformation fromJson(const QJsonValue &val);
signals:
void signalBroadcastNewContentFile();
void signalBroadcastNewScriptsJsFile();
void signalBroadcastMessage(const QString &msg);
void signalBroadcastMessage2(const QString &msg);
};
} // namespace FileManagement