""" 映射管理服务 提供映射模型管理的业务逻辑 """ from typing import List, Optional, Tuple from database.repositories.mapping_repository import MappingRepository from models.mapping import OperatorMapping, CodeMapping, CompositeMapping, Mapping, MappingType from models.mapping_graph import MappingGraph, GraphNode, GraphEdge from utils.validator import Validator from utils.logger import get_logger logger = get_logger(__name__) class MappingService: """映射管理服务类""" def __init__(self): self.repository = MappingRepository() self.validator = Validator() def create_operator_mapping(self, mapping: OperatorMapping) -> tuple[bool, str, Optional[int]]: """ 创建操作符映射 Args: mapping: 操作符映射对象 Returns: (是否成功, 消息, 映射ID) """ # 验证映射数据 is_valid, error_msg = mapping.validate() if not is_valid: logger.warning(f"Operator mapping validation failed: {error_msg}") return False, error_msg, None try: mapping_id = self.repository.create_operator_mapping(mapping) logger.info(f"Operator mapping created successfully: ID {mapping_id}") return True, "操作符映射创建成功", mapping_id except Exception as e: logger.error(f"Failed to create operator mapping: {e}") return False, f"创建操作符映射失败: {str(e)}", None def create_code_mapping(self, mapping: CodeMapping) -> tuple[bool, str, Optional[int]]: """ 创建代码映射 Args: mapping: 代码映射对象 Returns: (是否成功, 消息, 映射ID) """ # 验证映射数据 is_valid, error_msg = mapping.validate() if not is_valid: logger.warning(f"Code mapping validation failed: {error_msg}") return False, error_msg, None # 验证代码语法 is_valid, error_msg = self.validator.validate_code( mapping.code, mapping.language.value ) if not is_valid: return False, error_msg, None try: mapping_id = self.repository.create_code_mapping(mapping) logger.info(f"Code mapping created successfully: ID {mapping_id}") return True, "代码映射创建成功", mapping_id except Exception as e: logger.error(f"Failed to create code mapping: {e}") return False, f"创建代码映射失败: {str(e)}", None def create_composite_mapping(self, mapping: CompositeMapping) -> tuple[bool, str, Optional[int]]: """ 创建复合映射 Args: mapping: 复合映射对象 Returns: (是否成功, 消息, 映射ID) """ # 验证映射数据 is_valid, error_msg = mapping.validate() if not is_valid: logger.warning(f"Composite mapping validation failed: {error_msg}") return False, error_msg, None try: mapping_id = self.repository.create_composite_mapping(mapping) logger.info(f"Composite mapping created successfully: ID {mapping_id}") return True, "复合映射创建成功", mapping_id except Exception as e: logger.error(f"Failed to create composite mapping: {e}") return False, f"创建复合映射失败: {str(e)}", None def update_operator_mapping(self, mapping: OperatorMapping) -> tuple[bool, str]: """ 更新操作符映射 Args: mapping: 操作符映射对象 Returns: (是否成功, 消息) """ if not mapping.id: return False, "映射ID不能为空" # 验证映射数据 is_valid, error_msg = mapping.validate() if not is_valid: return False, error_msg try: success = self.repository.update_operator_mapping(mapping) if success: logger.info(f"Operator mapping updated successfully: ID {mapping.id}") return True, "操作符映射更新成功" else: return False, "映射不存在" except Exception as e: logger.error(f"Failed to update operator mapping: {e}") return False, f"更新操作符映射失败: {str(e)}" def delete_mapping(self, mapping_id: int) -> tuple[bool, str]: """ 删除映射 Args: mapping_id: 映射ID Returns: (是否成功, 消息) """ try: success = self.repository.delete(mapping_id) if success: logger.info(f"Mapping deleted successfully: ID {mapping_id}") return True, "映射删除成功" else: return False, "映射不存在" except Exception as e: logger.error(f"Failed to delete mapping: {e}") return False, f"删除映射失败: {str(e)}" def get_mapping_by_id(self, mapping_id: int) -> Optional[Mapping]: """ 根据ID获取映射 Args: mapping_id: 映射ID Returns: 映射对象或None """ try: return self.repository.get_by_id(mapping_id) except Exception as e: logger.error(f"Failed to get mapping by id: {e}") return None def search_mappings(self, mapping_type: Optional[MappingType] = None, target_field_id: Optional[int] = None, page: int = 1, page_size: int = 50) -> tuple[List[Mapping], int]: """ 搜索映射 Args: mapping_type: 映射类型 target_field_id: 目标字段ID page: 页码 page_size: 每页数量 Returns: (映射列表, 总数量) """ try: offset = (page - 1) * page_size mappings = self.repository.search(mapping_type, target_field_id, page_size, offset) # 简化的总数统计 total = len(mappings) return mappings, total except Exception as e: logger.error(f"Failed to search mappings: {e}") return [], 0 # 映射图相关方法 def add_node_to_graph(self, node: GraphNode) -> tuple[bool, str]: """ 向映射图添加节点 Args: node: 图节点 Returns: (是否成功, 消息) """ try: success = self.repository.add_graph_node(node) if success: logger.info(f"Node added to graph: field ID {node.field.id}") return True, "节点添加成功" else: return False, "添加节点失败" except Exception as e: logger.error(f"Failed to add node to graph: {e}") return False, f"添加节点失败: {str(e)}" def remove_node_from_graph(self, field_id: int) -> tuple[bool, str]: """ 从映射图移除节点 Args: field_id: 字段ID Returns: (是否成功, 消息) """ try: success = self.repository.remove_graph_node(field_id) if success: logger.info(f"Node removed from graph: field ID {field_id}") return True, "节点移除成功" else: return False, "节点不存在" except Exception as e: logger.error(f"Failed to remove node from graph: {e}") return False, f"移除节点失败: {str(e)}" def add_edge_to_graph(self, edge: GraphEdge) -> tuple[bool, str, Optional[int]]: """ 向映射图添加边 Args: edge: 图边 Returns: (是否成功, 消息, 边ID) """ try: edge_id = self.repository.add_graph_edge(edge) logger.info(f"Edge added to graph: ID {edge_id}") return True, "边添加成功", edge_id except Exception as e: logger.error(f"Failed to add edge to graph: {e}") return False, f"添加边失败: {str(e)}", None def remove_edge_from_graph(self, edge_id: int) -> tuple[bool, str]: """ 从映射图移除边 Args: edge_id: 边ID Returns: (是否成功, 消息) """ try: success = self.repository.remove_graph_edge(edge_id) if success: logger.info(f"Edge removed from graph: ID {edge_id}") return True, "边移除成功" else: return False, "边不存在" except Exception as e: logger.error(f"Failed to remove edge from graph: {e}") return False, f"移除边失败: {str(e)}" def get_mapping_graph(self) -> Optional[MappingGraph]: """ 获取映射图 Returns: 映射图对象或None """ try: return self.repository.get_mapping_graph() except Exception as e: logger.error(f"Failed to get mapping graph: {e}") return None