#include "pch.h" #include "BatchOperationManager.h" #include "CreoManager.h" #include "PathDeleteManager.h" #include "ShrinkwrapManager.h" #include #include #include // Helper: Get current time as string std::string BatchOperationManager::GetCurrentTimeString() { auto now = std::chrono::system_clock::now(); auto now_time = std::chrono::system_clock::to_time_t(now); std::tm local_time; localtime_s(&local_time, &now_time); std::ostringstream oss; oss << std::put_time(&local_time, "%Y-%m-%d %H:%M:%S"); return oss.str(); } // Helper: Escape JSON string std::string BatchOperationManager::EscapeJsonString(const std::string& str) { std::string escaped = str; // Replace backslashes size_t pos = 0; while ((pos = escaped.find("\\", pos)) != std::string::npos) { escaped.replace(pos, 1, "\\\\"); pos += 2; } // Replace double quotes pos = 0; while ((pos = escaped.find("\"", pos)) != std::string::npos) { escaped.replace(pos, 1, "\\\""); pos += 2; } // Replace newlines pos = 0; while ((pos = escaped.find("\n", pos)) != std::string::npos) { escaped.replace(pos, 1, "\\n"); pos += 2; } // Replace tabs pos = 0; while ((pos = escaped.find("\t", pos)) != std::string::npos) { escaped.replace(pos, 1, "\\t"); pos += 2; } return escaped; } // Build JSON result for SaveModel std::string BatchOperationManager::BuildSaveResultJson(const SaveResult& result) { std::ostringstream json; json << "{" << "\"file_size\":\"" << EscapeJsonString(result.file_size) << "\"," << "\"save_time\":\"" << EscapeJsonString(result.save_time) << "\"," << "\"software\":\"" << EscapeJsonString(result.software) << "\"," << "\"original_file\":\"" << EscapeJsonString(result.original_file) << "\"" << "}"; return json.str(); } // Build JSON result for ExportModel std::string BatchOperationManager::BuildExportResultJson(const ExportResult& result) { std::ostringstream json; json << "{" << "\"export_path\":\"" << EscapeJsonString(result.export_path) << "\"," << "\"file_size\":\"" << EscapeJsonString(result.file_size) << "\"," << "\"format\":\"" << EscapeJsonString(result.format) << "\"," << "\"export_time\":\"" << EscapeJsonString(result.export_time) << "\"," << "\"software\":\"" << EscapeJsonString(result.software) << "\"," << "\"original_file\":\"" << EscapeJsonString(result.original_file) << "\"," << "\"dirname\":\"" << EscapeJsonString(result.dirname) << "\"," << "\"filename\":\"" << EscapeJsonString(result.filename) << "\"" << "}"; return json.str(); } // Build JSON result for DeleteByPath std::string BatchOperationManager::BuildDeleteByPathResultJson(const PathDeleteManager::PathDeleteResult& result) { std::ostringstream json; json << "{" << "\"successfully_deleted\":["; for (size_t i = 0; i < result.successfully_deleted.size(); i++) { if (i > 0) json << ","; json << "\"" << EscapeJsonString(result.successfully_deleted[i]) << "\""; } json << "],\"failed_to_delete\":["; for (size_t i = 0; i < result.failed_to_delete.size(); i++) { if (i > 0) json << ","; json << "\"" << EscapeJsonString(result.failed_to_delete[i]) << "\""; } json << "],\"total_requested\":" << result.total_requested << ",\"successful\":" << result.successful << ",\"failed\":" << result.failed << "}"; return json.str(); } // Build JSON result for HierarchyDelete std::string BatchOperationManager::BuildHierarchyDeleteResultJson(const CreoManager::HierarchyDeleteResult& result) { std::ostringstream json; json << "{" << "\"message\":\"" << EscapeJsonString(result.message) << "\"," << "\"original_levels\":" << result.original_levels << "," << "\"target_level\":" << result.target_level << "," << "\"final_levels\":" << result.final_levels << "," << "\"total_deleted\":" << result.total_deleted << "," << "\"successful\":" << result.successful << "," << "\"failed\":" << result.failed << "}"; return json.str(); } // Build JSON result for Shrinkwrap std::string BatchOperationManager::BuildShrinkwrapResultJson(const ShrinkwrapShellResult& result) { std::ostringstream json; json << "{" << "\"message\":\"" << EscapeJsonString(result.message) << "\"," << "\"output_file_path\":\"" << EscapeJsonString(result.parameters.output_file_path) << "\"," << "\"output_file_size\":\"" << EscapeJsonString(result.parameters.output_file_size) << "\"," << "\"shrinkwrap_time\":\"" << EscapeJsonString(result.parameters.shrinkwrap_time) << "\"," << "\"quality\":" << result.parameters.quality << "," << "\"chord_height\":" << result.parameters.chord_height << "}"; return json.str(); } // Build JSON result for CloseModel std::string BatchOperationManager::BuildCloseResultJson(const CloseResult& result) { std::ostringstream json; json << "{" << "\"model_name\":\"" << EscapeJsonString(result.model_name) << "\"," << "\"was_modified\":" << (result.was_modified ? "true" : "false") << "," << "\"close_time\":\"" << EscapeJsonString(result.close_time) << "\"" << "}"; return json.str(); } // Build JSON result for OpenModel std::string BatchOperationManager::BuildOpenResultJson(const OpenResult& result) { std::ostringstream json; json << "{" << "\"model_name\":\"" << EscapeJsonString(result.model_name) << "\"," << "\"model_type\":\"" << EscapeJsonString(result.model_type) << "\"," << "\"file_path\":\"" << EscapeJsonString(result.file_path) << "\"," << "\"file_size\":\"" << EscapeJsonString(result.file_size) << "\"," << "\"open_time\":\"" << EscapeJsonString(result.open_time) << "\"," << "\"is_assembly\":" << (result.is_assembly ? "true" : "false") << "," << "\"total_parts\":" << result.total_parts << "}"; return json.str(); } // Build JSON for workflow step std::string BatchOperationManager::BuildWorkflowStepJson(const std::string& step_name, bool success, const std::string& time, const std::string& error) { std::ostringstream json; json << "{" << "\"step\":\"" << EscapeJsonString(step_name) << "\"," << "\"success\":" << (success ? "true" : "false") << "," << "\"time\":\"" << EscapeJsonString(time) << "\""; if (!error.empty()) { json << ",\"error\":\"" << EscapeJsonString(error) << "\""; } json << "}"; return json.str(); } // Execute save_model operation BatchOperationResult BatchOperationManager::ExecuteSaveModel(int index, const BatchOperation& operation) { BatchOperationResult result; result.operation_index = index; result.operation_type = "save_model"; auto start = std::chrono::high_resolution_clock::now(); try { SaveResult save_result = CreoManager::Instance().SaveModel(); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); result.execution_time = std::to_string(duration.count()) + "ms"; result.success = save_result.success; if (save_result.success) { result.result_json = BuildSaveResultJson(save_result); } else { result.error_message = save_result.error_message; } } catch (const std::exception& e) { result.success = false; result.error_message = "Exception: " + std::string(e.what()); } catch (...) { result.success = false; result.error_message = "Unknown error during save operation"; } return result; } // Execute export_model operation BatchOperationResult BatchOperationManager::ExecuteExportModel(int index, const BatchOperation& operation) { BatchOperationResult result; result.operation_index = index; result.operation_type = "export_model"; auto start = std::chrono::high_resolution_clock::now(); try { // Extract parameters std::string export_path; std::string geom_flags = "solids"; auto it = operation.parameters.find("export_path"); if (it != operation.parameters.end()) { export_path = it->second; } it = operation.parameters.find("geom_flags"); if (it != operation.parameters.end()) { geom_flags = it->second; } if (export_path.empty()) { result.success = false; result.error_message = "Missing required parameter: export_path"; return result; } ExportResult export_result = CreoManager::Instance().ExportModelToSTEP(export_path, geom_flags); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); result.execution_time = std::to_string(duration.count()) + "ms"; result.success = export_result.success; if (export_result.success) { result.result_json = BuildExportResultJson(export_result); } else { result.error_message = export_result.error_message; } } catch (const std::exception& e) { result.success = false; result.error_message = "Exception: " + std::string(e.what()); } catch (...) { result.success = false; result.error_message = "Unknown error during export operation"; } return result; } // Execute delete_by_path operation BatchOperationResult BatchOperationManager::ExecuteDeleteByPath(int index, const BatchOperation& operation) { BatchOperationResult result; result.operation_index = index; result.operation_type = "delete_by_path"; auto start = std::chrono::high_resolution_clock::now(); try { PathDeleteManager::PathDeleteRequest delete_request; delete_request.software_type = "creo"; delete_request.component_paths = operation.array_parameters; auto it = operation.parameters.find("force_delete"); if (it != operation.parameters.end()) { delete_request.force_delete = (it->second == "true"); } if (delete_request.component_paths.empty()) { result.success = false; result.error_message = "Missing required parameter: component_paths"; return result; } PathDeleteManager::PathDeleteResult delete_result = PathDeleteManager::Instance().DeleteComponentsByPaths(delete_request); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); result.execution_time = std::to_string(duration.count()) + "ms"; result.success = delete_result.success; if (delete_result.success) { result.result_json = BuildDeleteByPathResultJson(delete_result); } else { result.error_message = delete_result.error_message; } } catch (const std::exception& e) { result.success = false; result.error_message = "Exception: " + std::string(e.what()); } catch (...) { result.success = false; result.error_message = "Unknown error during delete by path operation"; } return result; } // Execute hierarchy_delete operation BatchOperationResult BatchOperationManager::ExecuteHierarchyDelete(int index, const BatchOperation& operation) { BatchOperationResult result; result.operation_index = index; result.operation_type = "hierarchy_delete"; auto start = std::chrono::high_resolution_clock::now(); try { std::string project_name; int target_level = 0; auto it = operation.parameters.find("project_name"); if (it != operation.parameters.end()) { project_name = it->second; } it = operation.parameters.find("target_level"); if (it != operation.parameters.end()) { try { target_level = std::stoi(it->second); } catch (...) { result.success = false; result.error_message = "Invalid target_level parameter"; return result; } } if (project_name.empty()) { result.success = false; result.error_message = "Missing required parameter: project_name"; return result; } CreoManager::HierarchyDeleteResult delete_result = CreoManager::Instance().DeleteHierarchyComponents(project_name, target_level); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); result.execution_time = std::to_string(duration.count()) + "ms"; result.success = delete_result.success; if (delete_result.success) { result.result_json = BuildHierarchyDeleteResultJson(delete_result); } else { result.error_message = delete_result.error_message; } } catch (const std::exception& e) { result.success = false; result.error_message = "Exception: " + std::string(e.what()); } catch (...) { result.success = false; result.error_message = "Unknown error during hierarchy delete operation"; } return result; } // Execute shrinkwrap_shell operation BatchOperationResult BatchOperationManager::ExecuteShrinkwrapShell(int index, const BatchOperation& operation) { BatchOperationResult result; result.operation_index = index; result.operation_type = "shrinkwrap_shell"; auto start = std::chrono::high_resolution_clock::now(); try { ShrinkwrapShellRequest shrink_request; // Extract parameters auto it = operation.parameters.find("output_file_path"); if (it != operation.parameters.end()) { shrink_request.output_file_path = it->second; } it = operation.parameters.find("quality"); if (it != operation.parameters.end()) { try { shrink_request.quality = std::stoi(it->second); } catch (...) {} } it = operation.parameters.find("chord_height"); if (it != operation.parameters.end()) { try { shrink_request.chord_height = std::stod(it->second); } catch (...) {} } if (shrink_request.output_file_path.empty()) { result.success = false; result.error_message = "Missing required parameter: output_file_path"; return result; } ShrinkwrapShellResult shrink_result = ShrinkwrapManager::Instance().ExecuteShrinkwrapShell(shrink_request); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); result.execution_time = std::to_string(duration.count()) + "ms"; result.success = shrink_result.success; if (shrink_result.success) { result.result_json = BuildShrinkwrapResultJson(shrink_result); } else { result.error_message = shrink_result.error_message; } } catch (const std::exception& e) { result.success = false; result.error_message = "Exception: " + std::string(e.what()); } catch (...) { result.success = false; result.error_message = "Unknown error during shrinkwrap operation"; } return result; } // Execute close_model operation BatchOperationResult BatchOperationManager::ExecuteCloseModel(int index, const BatchOperation& operation) { BatchOperationResult result; result.operation_index = index; result.operation_type = "close_model"; auto start = std::chrono::high_resolution_clock::now(); try { bool force_close = false; auto it = operation.parameters.find("force_close"); if (it != operation.parameters.end()) { force_close = (it->second == "true"); } CloseResult close_result = CreoManager::Instance().CloseModel(force_close); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); result.execution_time = std::to_string(duration.count()) + "ms"; result.success = close_result.success; if (close_result.success) { result.result_json = BuildCloseResultJson(close_result); } else { result.error_message = close_result.error_message; } } catch (const std::exception& e) { result.success = false; result.error_message = "Exception: " + std::string(e.what()); } catch (...) { result.success = false; result.error_message = "Unknown error during close operation"; } return result; } // Execute open_model operation BatchOperationResult BatchOperationManager::ExecuteOpenModel(int index, const BatchOperation& operation) { BatchOperationResult result; result.operation_index = index; result.operation_type = "open_model"; auto start = std::chrono::high_resolution_clock::now(); try { std::string file_path; std::string open_mode = "active"; auto it = operation.parameters.find("file_path"); if (it != operation.parameters.end()) { file_path = it->second; } it = operation.parameters.find("open_mode"); if (it != operation.parameters.end()) { open_mode = it->second; } if (file_path.empty()) { result.success = false; result.error_message = "Missing required parameter: file_path"; return result; } OpenResult open_result = CreoManager::Instance().OpenModel(file_path, open_mode); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); result.execution_time = std::to_string(duration.count()) + "ms"; result.success = open_result.success; if (open_result.success) { result.result_json = BuildOpenResultJson(open_result); } else { result.error_message = open_result.error_message; } } catch (const std::exception& e) { result.success = false; result.error_message = "Exception: " + std::string(e.what()); } catch (...) { result.success = false; result.error_message = "Unknown error during open operation"; } return result; } // Execute workflow_hierarchy_delete operation BatchOperationResult BatchOperationManager::ExecuteHierarchyDeleteWorkflow(int index, const BatchOperation& operation) { BatchOperationResult result; result.operation_index = index; result.operation_type = "workflow_hierarchy_delete"; auto workflow_start = std::chrono::high_resolution_clock::now(); std::vector steps_json; try { // Extract parameters std::string working_directory; std::string input_file_path; std::string open_mode = "active"; std::string project_name; std::string target_level_str; std::string export_path; std::string geom_flags = "solids"; auto it = operation.parameters.find("working_directory"); if (it != operation.parameters.end()) { working_directory = it->second; } it = operation.parameters.find("input_file_path"); if (it != operation.parameters.end()) { input_file_path = it->second; } it = operation.parameters.find("open_mode"); if (it != operation.parameters.end()) { open_mode = it->second; } it = operation.parameters.find("project_name"); if (it != operation.parameters.end()) { project_name = it->second; } it = operation.parameters.find("target_level"); if (it != operation.parameters.end()) { target_level_str = it->second; } it = operation.parameters.find("export_path"); if (it != operation.parameters.end()) { export_path = it->second; } it = operation.parameters.find("geom_flags"); if (it != operation.parameters.end()) { geom_flags = it->second; } // Validate required parameters if (input_file_path.empty()) { result.success = false; result.error_message = "Missing required parameter: input_file_path"; return result; } if (project_name.empty()) { result.success = false; result.error_message = "Missing required parameter: project_name"; return result; } if (target_level_str.empty()) { result.success = false; result.error_message = "Missing required parameter: target_level"; return result; } if (export_path.empty()) { result.success = false; result.error_message = "Missing required parameter: export_path"; return result; } int target_level = 0; try { target_level = std::stoi(target_level_str); } catch (...) { result.success = false; result.error_message = "Invalid target_level value"; return result; } // Step 1: Set working directory (if provided) if (!working_directory.empty()) { auto step_start = std::chrono::high_resolution_clock::now(); ChangeDirectoryResult dir_result = CreoUtilities::SetWorkingDirectory(working_directory); auto step_end = std::chrono::high_resolution_clock::now(); auto step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("set_directory", dir_result.success, std::to_string(step_duration.count()) + "ms", dir_result.success ? "" : dir_result.error_message)); if (!dir_result.success) { result.success = false; result.error_message = "Failed to set working directory: " + dir_result.error_message; result.result_json = "{\"steps\":[" + steps_json[0] + "]}"; return result; } } // Step 2: Open model auto step_start = std::chrono::high_resolution_clock::now(); OpenResult open_result = CreoManager::Instance().OpenModel(input_file_path, open_mode); auto step_end = std::chrono::high_resolution_clock::now(); auto step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("open_model", open_result.success, std::to_string(step_duration.count()) + "ms", open_result.success ? "" : open_result.error_message)); if (!open_result.success) { result.success = false; result.error_message = "Failed to open model: " + open_result.error_message; std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); return result; } // Step 3: Hierarchy delete step_start = std::chrono::high_resolution_clock::now(); CreoManager::HierarchyDeleteResult delete_result = CreoManager::Instance().DeleteHierarchyComponents(project_name, target_level); step_end = std::chrono::high_resolution_clock::now(); step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("hierarchy_delete", delete_result.success, std::to_string(step_duration.count()) + "ms", delete_result.success ? "" : delete_result.error_message)); if (!delete_result.success) { // Try to close model before returning error try { CreoManager::Instance().CloseModel(true); } catch (...) {} result.success = false; result.error_message = "Failed to delete hierarchy: " + delete_result.error_message; std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); return result; } // Step 4: Export STEP step_start = std::chrono::high_resolution_clock::now(); ExportResult export_result = CreoManager::Instance().ExportModelToSTEP(export_path, geom_flags); step_end = std::chrono::high_resolution_clock::now(); step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("export_step", export_result.success, std::to_string(step_duration.count()) + "ms", export_result.success ? "" : export_result.error_message)); if (!export_result.success) { // Try to close model before returning error try { CreoManager::Instance().CloseModel(true); } catch (...) {} result.success = false; result.error_message = "Failed to export STEP: " + export_result.error_message; std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); return result; } // Step 5: Close model step_start = std::chrono::high_resolution_clock::now(); CloseResult close_result = CreoManager::Instance().CloseModel(false); step_end = std::chrono::high_resolution_clock::now(); step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("close_model", close_result.success, std::to_string(step_duration.count()) + "ms", close_result.success ? "" : close_result.error_message)); // Build final result auto workflow_end = std::chrono::high_resolution_clock::now(); auto workflow_duration = std::chrono::duration_cast(workflow_end - workflow_start); result.execution_time = std::to_string(workflow_duration.count()) + "ms"; std::ostringstream final_json; final_json << "{" << "\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) final_json << ","; final_json << steps_json[i]; } final_json << "]," << "\"final_output\":\"" << EscapeJsonString(export_path) << "\"," << "\"final_size\":\"" << EscapeJsonString(export_result.file_size) << "\"" << "}"; result.success = true; result.result_json = final_json.str(); } catch (const std::exception& e) { // Try to close model on exception try { CreoManager::Instance().CloseModel(true); } catch (...) {} result.success = false; result.error_message = "Exception in workflow: " + std::string(e.what()); if (!steps_json.empty()) { std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); } } catch (...) { // Try to close model on exception try { CreoManager::Instance().CloseModel(true); } catch (...) {} result.success = false; result.error_message = "Unknown error in workflow"; if (!steps_json.empty()) { std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); } } return result; } // Execute workflow_shrinkwrap operation BatchOperationResult BatchOperationManager::ExecuteShrinkwrapWorkflow(int index, const BatchOperation& operation) { BatchOperationResult result; result.operation_index = index; result.operation_type = "workflow_shrinkwrap"; auto workflow_start = std::chrono::high_resolution_clock::now(); std::vector steps_json; try { // Extract parameters std::string working_directory; std::string input_file_path; std::string shrinkwrap_output_path; std::string quality_str = "5"; std::string chord_height_str = "0.5"; std::string step_export_path; std::string geom_flags = "solids"; auto it = operation.parameters.find("working_directory"); if (it != operation.parameters.end()) { working_directory = it->second; } it = operation.parameters.find("input_file_path"); if (it != operation.parameters.end()) { input_file_path = it->second; } it = operation.parameters.find("shrinkwrap_output_path"); if (it != operation.parameters.end()) { shrinkwrap_output_path = it->second; } it = operation.parameters.find("quality"); if (it != operation.parameters.end() && !it->second.empty()) { quality_str = it->second; } it = operation.parameters.find("chord_height"); if (it != operation.parameters.end() && !it->second.empty()) { chord_height_str = it->second; } it = operation.parameters.find("step_export_path"); if (it != operation.parameters.end()) { step_export_path = it->second; } it = operation.parameters.find("geom_flags"); if (it != operation.parameters.end()) { geom_flags = it->second; } // Validate required parameters if (input_file_path.empty()) { result.success = false; result.error_message = "Missing required parameter: input_file_path"; return result; } if (shrinkwrap_output_path.empty()) { result.success = false; result.error_message = "Missing required parameter: shrinkwrap_output_path"; return result; } if (step_export_path.empty()) { result.success = false; result.error_message = "Missing required parameter: step_export_path"; return result; } int quality = 5; double chord_height = 0.5; try { quality = std::stoi(quality_str); } catch (...) { result.success = false; result.error_message = "Invalid quality value"; return result; } try { chord_height = std::stod(chord_height_str); } catch (...) { result.success = false; result.error_message = "Invalid chord_height value"; return result; } // Step 1: Set working directory (if provided) if (!working_directory.empty()) { auto step_start = std::chrono::high_resolution_clock::now(); ChangeDirectoryResult dir_result = CreoUtilities::SetWorkingDirectory(working_directory); auto step_end = std::chrono::high_resolution_clock::now(); auto step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("set_directory", dir_result.success, std::to_string(step_duration.count()) + "ms", dir_result.success ? "" : dir_result.error_message)); if (!dir_result.success) { result.success = false; result.error_message = "Failed to set working directory: " + dir_result.error_message; result.result_json = "{\"steps\":[" + steps_json[0] + "]}"; return result; } } // Step 2: Open original model auto step_start = std::chrono::high_resolution_clock::now(); OpenResult open_result = CreoManager::Instance().OpenModel(input_file_path, "active"); auto step_end = std::chrono::high_resolution_clock::now(); auto step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("open_model", open_result.success, std::to_string(step_duration.count()) + "ms", open_result.success ? "" : open_result.error_message)); if (!open_result.success) { result.success = false; result.error_message = "Failed to open model: " + open_result.error_message; std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); return result; } // Step 3: Execute Shrinkwrap step_start = std::chrono::high_resolution_clock::now(); ShrinkwrapShellRequest shrink_request; shrink_request.output_file_path = shrinkwrap_output_path; shrink_request.quality = quality; shrink_request.chord_height = chord_height; ShrinkwrapShellResult shrink_result = ShrinkwrapManager::Instance().ExecuteShrinkwrapShell(shrink_request); step_end = std::chrono::high_resolution_clock::now(); step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("shrinkwrap", shrink_result.success, std::to_string(step_duration.count()) + "ms", shrink_result.success ? "" : shrink_result.error_message)); if (!shrink_result.success) { // Try to close model before returning error try { CreoManager::Instance().CloseModel(true); } catch (...) {} result.success = false; result.error_message = "Failed to execute shrinkwrap: " + shrink_result.error_message; std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); return result; } // Step 4: Close original model step_start = std::chrono::high_resolution_clock::now(); CloseResult close_original = CreoManager::Instance().CloseModel(true); step_end = std::chrono::high_resolution_clock::now(); step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("close_original", close_original.success, std::to_string(step_duration.count()) + "ms", close_original.success ? "" : close_original.error_message)); // Step 5: Open Shrinkwrap model step_start = std::chrono::high_resolution_clock::now(); OpenResult open_shrink = CreoManager::Instance().OpenModel(shrinkwrap_output_path, "active"); step_end = std::chrono::high_resolution_clock::now(); step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("open_shrinkwrap_model", open_shrink.success, std::to_string(step_duration.count()) + "ms", open_shrink.success ? "" : open_shrink.error_message)); if (!open_shrink.success) { result.success = false; result.error_message = "Failed to open shrinkwrap model: " + open_shrink.error_message; std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); return result; } // Step 6: Export STEP step_start = std::chrono::high_resolution_clock::now(); ExportResult export_result = CreoManager::Instance().ExportModelToSTEP(step_export_path, geom_flags); step_end = std::chrono::high_resolution_clock::now(); step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("export_step", export_result.success, std::to_string(step_duration.count()) + "ms", export_result.success ? "" : export_result.error_message)); if (!export_result.success) { // Try to close model before returning error try { CreoManager::Instance().CloseModel(true); } catch (...) {} result.success = false; result.error_message = "Failed to export STEP: " + export_result.error_message; std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); return result; } // Step 7: Close shrinkwrap model step_start = std::chrono::high_resolution_clock::now(); CloseResult close_shrink = CreoManager::Instance().CloseModel(true); step_end = std::chrono::high_resolution_clock::now(); step_duration = std::chrono::duration_cast(step_end - step_start); steps_json.push_back(BuildWorkflowStepJson("close_shrinkwrap", close_shrink.success, std::to_string(step_duration.count()) + "ms", close_shrink.success ? "" : close_shrink.error_message)); // Build final result auto workflow_end = std::chrono::high_resolution_clock::now(); auto workflow_duration = std::chrono::duration_cast(workflow_end - workflow_start); result.execution_time = std::to_string(workflow_duration.count()) + "ms"; std::ostringstream final_json; final_json << "{" << "\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) final_json << ","; final_json << steps_json[i]; } final_json << "]," << "\"final_output\":\"" << EscapeJsonString(step_export_path) << "\"," << "\"final_size\":\"" << EscapeJsonString(export_result.file_size) << "\"" << "}"; result.success = true; result.result_json = final_json.str(); } catch (const std::exception& e) { // Try to close model on exception try { CreoManager::Instance().CloseModel(true); } catch (...) {} result.success = false; result.error_message = "Exception in workflow: " + std::string(e.what()); if (!steps_json.empty()) { std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); } } catch (...) { // Try to close model on exception try { CreoManager::Instance().CloseModel(true); } catch (...) {} result.success = false; result.error_message = "Unknown error in workflow"; if (!steps_json.empty()) { std::ostringstream steps_array; steps_array << "{\"steps\":["; for (size_t i = 0; i < steps_json.size(); i++) { if (i > 0) steps_array << ","; steps_array << steps_json[i]; } steps_array << "]}"; result.result_json = steps_array.str(); } } return result; } // Main entry point: Execute batch operations BatchOperationsResponse BatchOperationManager::ExecuteBatchOperations(const BatchOperationsRequest& request) { BatchOperationsResponse response; response.total_operations = static_cast(request.operations.size()); auto start = std::chrono::high_resolution_clock::now(); try { // Validate request if (request.software_type != "creo") { response.success = false; response.error_message = "Invalid software_type, must be 'creo'"; return response; } if (request.operations.empty()) { response.success = false; response.error_message = "No operations specified"; return response; } // Execute each operation sequentially for (size_t i = 0; i < request.operations.size(); i++) { const BatchOperation& operation = request.operations[i]; BatchOperationResult op_result; if (operation.operation_type == "save_model") { op_result = ExecuteSaveModel(static_cast(i), operation); } else if (operation.operation_type == "export_model") { op_result = ExecuteExportModel(static_cast(i), operation); } else if (operation.operation_type == "delete_by_path") { op_result = ExecuteDeleteByPath(static_cast(i), operation); } else if (operation.operation_type == "hierarchy_delete") { op_result = ExecuteHierarchyDelete(static_cast(i), operation); } else if (operation.operation_type == "shrinkwrap_shell") { op_result = ExecuteShrinkwrapShell(static_cast(i), operation); } else if (operation.operation_type == "close_model") { op_result = ExecuteCloseModel(static_cast(i), operation); } else if (operation.operation_type == "open_model") { op_result = ExecuteOpenModel(static_cast(i), operation); } else if (operation.operation_type == "workflow_hierarchy_delete") { op_result = ExecuteHierarchyDeleteWorkflow(static_cast(i), operation); } else if (operation.operation_type == "workflow_shrinkwrap") { op_result = ExecuteShrinkwrapWorkflow(static_cast(i), operation); } else { // Unknown operation type op_result.operation_index = static_cast(i); op_result.operation_type = operation.operation_type; op_result.success = false; op_result.error_message = "Unknown operation type: " + operation.operation_type; } response.results.push_back(op_result); if (op_result.success) { response.successful_operations++; } else { response.failed_operations++; } } auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); response.execution_time = std::to_string(duration.count()) + "ms"; // Overall success if at least one operation succeeded response.success = (response.successful_operations > 0); if (response.success) { response.message = "Batch operations completed"; } else { response.message = "All batch operations failed"; response.error_message = "All operations failed to execute"; } } catch (const std::exception& e) { response.success = false; response.error_message = "Exception during batch operations: " + std::string(e.what()); } catch (...) { response.success = false; response.error_message = "Unknown error during batch operations"; } return response; }