Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+200
@@ -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
@@ -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
@@ -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
@@ -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 |
+103
@@ -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 ¤t)
|
||||
{
|
||||
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
|
||||
@@ -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
|
||||
+70
@@ -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
|
||||
+70
@@ -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
|
||||
Executable
+44
@@ -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
|
||||
Executable
+37
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Executable
+55
@@ -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
|
||||
Executable
+53
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Executable
+54
@@ -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
|
||||
Executable
+393
@@ -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 &"/>
|
||||
<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 &"/>
|
||||
<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<octet>"/>
|
||||
<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<long>"/>
|
||||
<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<long>"/>
|
||||
<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<string>"/>
|
||||
<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<octet>"/>
|
||||
</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<FileContent > &"/>
|
||||
</function>
|
||||
<function name="getAllFiles" returns="bool">
|
||||
<parameter pos="1" name="fileType" type="const FileType &"/>
|
||||
<parameter pos="2" name="folderId" type="int"/>
|
||||
<parameter pos="3" name="allFiles" type="QStringList &"/>
|
||||
<parameter pos="4" name="showHidden" type="bool" default="false"/>
|
||||
</function>
|
||||
<function name="getFilesOperator" returns="bool">
|
||||
<parameter pos="1" name="fileType" type="const FileType &"/>
|
||||
<parameter pos="2" name="folderId" type="int"/>
|
||||
<parameter pos="3" name="operatorId" type="int"/>
|
||||
<parameter pos="4" name="allFiles" type="QStringList &"/>
|
||||
</function>
|
||||
<function name="getFile" returns="bool">
|
||||
<parameter pos="1" name="fileType" type="const FileType &"/>
|
||||
<parameter pos="2" name="folderId" type="int"/>
|
||||
<parameter pos="3" name="fileName" type="const QString &"/>
|
||||
<parameter pos="4" name="fileMetadata" type="FileContent &"/>
|
||||
</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 &"/>
|
||||
<parameter pos="2" name="fileName" type="const QString &"/>
|
||||
<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 &"/>
|
||||
</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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Executable
+56
@@ -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
@@ -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:
|
||||
Executable
+38
@@ -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
|
||||
Executable
+24
@@ -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
|
||||
Executable
+43
@@ -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;
|
||||
}
|
||||
Executable
+161
@@ -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
|
||||
Executable
+63
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Executable
+62
@@ -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;
|
||||
};
|
||||
}
|
||||
Executable
+82
@@ -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
|
||||
Executable
+34
@@ -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
|
||||
Executable
+52
@@ -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
|
||||
Executable
+33
@@ -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
|
||||
Executable
+56
@@ -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
|
||||
Executable
+28
@@ -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
@@ -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
@@ -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
|
||||
Reference in new issue
Block a user