* Copyright (c), Huawei Technologies Co., Ltd. 2025-2025.All rights reserved.
*/
#include "ScalarVisuallyFileMergeHandler.h"
#include <random>
#include "Logger.h"
#include "ScalarVisuallyServer.h"
#include "FileManager/VirtualFile.h"
using namespace Dic::Core;
using namespace Insight::Scalar::Protocol;
using namespace Insight::Scalar::FileInfo;
bool ScalarVisuallyFileMergeHandler::run(std::string_view data, std::string& result)
{
result = ::Protocol::GetBasicResponse();
std::string errMsg;
FileMergeRequest request;
if (auto errCode = ParseRequestFromJson(data, request, errMsg); errCode != ErrCode::OK) {
LOG(Insight::LogRank::Error) << errMsg;
SetResponseError(errCode, errMsg, result);
return false;
}
auto InValidFile = [&request](const std::string& file) {
auto fileInfo = ScalarVisuallyServer::Instance().GetFileInfo(file);
if (fileInfo == nullptr) {
return true;
}
if (fileInfo->Type() == FileInfo::FileType::VISUAL) {
return true;
}
return false;
};
if (std::any_of(request.files_.begin(), request.files_.end(), InValidFile)) {
SetResponseError(ErrCode::REQUEST_INVALID_PARAM, "Invalid File", result);
return false;
}
FileMergeResponse response;
response.action_ = request.isMerge_ ? "merge" : "unset";
response.name_ = request.name_;
if (request.isMerge_) {
auto fileInfo = FileMerge(std::move(request.files_), request.name_);
if (fileInfo == nullptr) {
SetResponseError(ErrCode::REQUEST_INVALID_PARAM, "Merge failed", result);
return true;
}
response.tag_ = fileInfo->GetContainsTag();
response.file_ = fileInfo->FilePath();
response.subFiles_ = reinterpret_cast<VirtualFile*>(fileInfo.get())->GetSubFiles();
} else {
auto fileInfo = ScalarVisuallyServer::Instance().GetFileInfo(request.name_);
if (fileInfo == nullptr || fileInfo->Type() != FileType::VISUAL) {
SetResponseError(ErrCode::REQUEST_INVALID_PARAM, "Unmerge failed", result);
return true;
}
response.tag_ = fileInfo->GetContainsTag();
response.file_ = fileInfo->FilePath();
response.subFiles_ = {};
FileUnMerge(request.name_);
}
SetResponse(std::move(response), result);
return true;
}
ErrCode ScalarVisuallyFileMergeHandler::ParseRequestFromJson(std::string_view data, FileMergeRequest& request,
std::string& errMsg)
{
std::string parseErr;
std::optional<document_t> document = ParseJsonToStr(data);
if (!document.has_value()) {
errMsg = "Invalid request json," + parseErr;
return ErrCode::INVALID_REQUEST_JSON;
}
if (!CheckParamValid(document.value())) {
errMsg = "Invalid request param";
return ErrCode::REQUEST_INVALID_PARAM;
}
auto& param = document.value();
std::string action = param["action"].GetString();
request.isMerge_ = (action == "merge");
request.name_ = param["name"].GetString();
std::transform(param["fileList"].Begin(), param["fileList"].End(), std::back_inserter(request.files_),
[](const auto& item) {
return item.GetString();
});
return ErrCode::OK;
}
bool ScalarVisuallyFileMergeHandler::CheckParamValid(document_t& request)
{
if (!request.HasMember("action") || !request["action"].IsString()) {
return false;
}
if (!request.HasMember("name") || !request["name"].IsString()) {
return false;
}
if (!request.HasMember("fileList") || !request["fileList"].IsArray()) {
return false;
}
return std::all_of(request["fileList"].Begin(), request["fileList"].End(), [](const auto& item) {
return item.IsString();
});
}
void ScalarVisuallyFileMergeHandler::SetResponse(FileMergeResponse&& response, std::string& resultStr)
{
document_t documet = ParseJsonToStr(resultStr);
auto& allocator = documet.GetAllocator();
json_t data(rapidjson::kObjectType);
AddJsonMember(data, "file", response.file_, allocator);
AddJsonMember(data, "tags", response.tag_, allocator);
AddJsonMember(data, "fileList", response.subFiles_, allocator);
AddJsonMember(data, "action", response.action_, allocator);
AddJsonMember(documet["body"], "data", data, allocator);
resultStr = DumpJsonToStr(documet);
}
std::shared_ptr<FileInfo::File> ScalarVisuallyFileMergeHandler::FileMerge(
std::vector<std::string>&& subFiles, const std::string& name)
{
auto fileInfo = std::make_shared<VirtualFile>(name);
fileInfo->AddSubFiles(subFiles);
ScalarVisuallyServer::Instance().AddVirtualFile(fileInfo);
return fileInfo;
}
std::string ScalarVisuallyFileMergeHandler::GeneratorFileName()
{
static const std::string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static std::mt19937 rng(std::random_device{}());
static std::uniform_int_distribution<size_t> dist(0, charset.size() - 1);
constexpr int randomStrLen = 8;
std::string result;
for (size_t i = 0; i < randomStrLen; ++i) {
result += charset[dist(rng)];
}
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
std::stringstream ss;
ss << now_ms.count();
return result + "_" + ss.str();
}
void ScalarVisuallyFileMergeHandler::FileUnMerge(const std::string& file)
{
if (file.empty()) {
return;
}
auto fileInfo = ScalarVisuallyServer::Instance().GetFileInfo(file);
if (fileInfo == nullptr) {
return;
}
if (fileInfo->Type() != FileType::VISUAL) {
return;
}
ScalarVisuallyServer::Instance().DelVirtualFile(fileInfo);
}