#include "project_service.h" #include #include #include #include #include #include namespace integrated_platform::services { namespace { // 使用高精度时间戳和随机值生成工程标识 std::string generateProjectId() { const auto timestamp = static_cast( std::chrono::high_resolution_clock::now().time_since_epoch().count()); std::random_device random_device; const auto random_value = static_cast(random_device()); std::ostringstream stream; stream << "project-" << std::hex << timestamp << '-' << random_value; return stream.str(); } } // namespace ProjectService::ProjectService(domain::ProjectStorage &storage) : storage_(storage), project_(makeNewProject("Untitled")) { } const domain::Project &ProjectService::project() const { return project_; } domain::Project &ProjectService::editProject() { modified_ = true; return project_; } const std::string &ProjectService::currentFilePath() const { return current_file_path_; } bool ProjectService::hasCurrentFile() const { return !current_file_path_.empty(); } bool ProjectService::isModified() const { return modified_; } ProjectOperationResult ProjectService::createNewProject(const std::string &name) { if (isBlank(name)) { return {false, ProjectServiceError::InvalidProjectName, domain::ProjectStorageError::None, "project name must not be empty"}; } // 新工程创建成功后清除原文件关联,并标记为待保存 project_ = makeNewProject(name); current_file_path_.clear(); modified_ = true; return {true, ProjectServiceError::None, domain::ProjectStorageError::None, {}}; } ProjectOperationResult ProjectService::save() { if (!hasCurrentFile()) { return {false, ProjectServiceError::FilePathRequired, domain::ProjectStorageError::None, "project file path is required"}; } return saveAs(current_file_path_); } ProjectOperationResult ProjectService::saveAs(const std::string &file_path) { if (isBlank(file_path)) { return {false, ProjectServiceError::FilePathRequired, domain::ProjectStorageError::None, "project file path is required"}; } std::string validation_error; if (!project_.validate(&validation_error)) { return {false, ProjectServiceError::InvalidProject, domain::ProjectStorageError::InvalidProject, validation_error}; } // 先完成领域校验,避免将非法工程交给存储层 const domain::ProjectSaveResult result = storage_.save(project_, file_path); if (!result.succeeded) { return storageFailure(result.error, result.message); } // 只有存储成功后才更新文件关联和未保存状态 current_file_path_ = file_path; modified_ = false; return {true, ProjectServiceError::None, domain::ProjectStorageError::None, {}}; } ProjectOperationResult ProjectService::load(const std::string &file_path) { if (isBlank(file_path)) { return {false, ProjectServiceError::FilePathRequired, domain::ProjectStorageError::None, "project file path is required"}; } domain::ProjectLoadResult result = storage_.load(file_path); if (!result.succeeded) { return storageFailure(result.error, result.message); } std::string validation_error; if (!result.project.validate(&validation_error)) { return {false, ProjectServiceError::InvalidProject, domain::ProjectStorageError::InvalidProject, validation_error}; } // 文件读取和领域校验均成功后,才替换当前工程状态 project_ = std::move(result.project); current_file_path_ = file_path; modified_ = false; return {true, ProjectServiceError::None, domain::ProjectStorageError::None, {}}; } domain::Project ProjectService::makeNewProject(const std::string &name) { domain::Project project; project.metadata.id = generateProjectId(); project.metadata.name = name; project.metadata.formatVersion = "1.0"; return project; } bool ProjectService::isBlank(const std::string &value) { return value.empty() || std::all_of( value.cbegin(), value.cend(), [](unsigned char character) { return std::isspace(character) != 0; }); } ProjectOperationResult ProjectService::storageFailure( domain::ProjectStorageError error, const std::string &message) { return {false, ProjectServiceError::StorageFailure, error, message}; } } // namespace integrated_platform::services