SIT/models/message.py

191 lines
6.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
消息业务模型
定义消息的数据结构和业务逻辑
"""
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional, List
from config import ProtocolType, SerializationType
from models.field import Field
@dataclass
class Message:
"""
消息模型类
Attributes:
id: 消息ID
full_name: 完整名称(如 Radar.Receiver.v3
system_name: 系统名(如 Radar
message_type: 消息类型(如 Receiver
version: 版本号(如 v3
fields: 关联的字段列表
description: 描述信息
protocol: 传输协议
serialization: 序列化格式
created_time: 创建时间
updated_time: 更新时间
"""
full_name: str
system_name: str
message_type: str
version: str
protocol: ProtocolType
serialization: SerializationType
id: Optional[int] = None
fields: List[Field] = field(default_factory=list)
description: Optional[str] = None
created_time: Optional[datetime] = None
updated_time: Optional[datetime] = None
def __post_init__(self):
"""初始化后处理"""
# 确保protocol和serialization是枚举类型
if isinstance(self.protocol, str):
self.protocol = ProtocolType(self.protocol)
if isinstance(self.serialization, str):
self.serialization = SerializationType(self.serialization)
# 从full_name解析system_name、message_type和version
if self.full_name and not self.system_name:
self._parse_full_name()
def _parse_full_name(self):
"""从完整名称解析系统名、消息类型和版本"""
parts = self.full_name.split('.')
if len(parts) >= 3:
self.system_name = parts[0]
self.message_type = parts[1]
self.version = parts[2]
elif len(parts) == 2:
self.system_name = parts[0]
self.message_type = parts[1]
self.version = "v1"
@staticmethod
def build_full_name(system_name: str, message_type: str, version: str) -> str:
"""
构建完整消息名
Args:
system_name: 系统名
message_type: 消息类型
version: 版本号
Returns:
完整消息名
"""
return f"{system_name}.{message_type}.{version}"
def add_field(self, field_obj: Field):
"""添加字段"""
if field_obj not in self.fields:
self.fields.append(field_obj)
def remove_field(self, field_obj: Field):
"""移除字段"""
if field_obj in self.fields:
self.fields.remove(field_obj)
def get_field_by_name(self, full_name: str) -> Optional[Field]:
"""根据完整名称获取字段"""
for f in self.fields:
if f.full_name == full_name:
return f
return None
def validate(self) -> tuple[bool, str]:
"""
验证消息数据的有效性
Returns:
(是否有效, 错误信息)
"""
if not self.full_name:
return False, "消息完整名称不能为空"
if not self.system_name:
return False, "系统名不能为空"
if not self.message_type:
return False, "消息类型不能为空"
if not self.version:
return False, "版本号不能为空"
if not self.fields or len(self.fields) == 0:
return False, "消息至少需要包含一个字段"
if not self.protocol:
return False, "传输协议不能为空"
if not self.serialization:
return False, "序列化格式不能为空"
return True, ""
def to_dict(self) -> dict:
"""转换为字典"""
return {
'id': self.id,
'full_name': self.full_name,
'system_name': self.system_name,
'message_type': self.message_type,
'version': self.version,
'description': self.description,
'protocol': self.protocol.value if isinstance(self.protocol, ProtocolType) else self.protocol,
'serialization': self.serialization.value if isinstance(self.serialization,
SerializationType) else self.serialization,
'fields': [f.to_dict() for f in self.fields],
'created_time': self.created_time.isoformat() if self.created_time else None,
'updated_time': self.updated_time.isoformat() if self.updated_time else None,
}
@classmethod
def from_dict(cls, data: dict) -> 'Message':
"""从字典创建对象"""
# 解析字段列表
fields = []
if 'fields' in data:
fields = [Field.from_dict(f) if isinstance(f, dict) else f for f in data['fields']]
# 解析时间
created_time = None
if data.get('created_time'):
if isinstance(data['created_time'], str):
created_time = datetime.fromisoformat(data['created_time'])
else:
created_time = data['created_time']
updated_time = None
if data.get('updated_time'):
if isinstance(data['updated_time'], str):
updated_time = datetime.fromisoformat(data['updated_time'])
else:
updated_time = data['updated_time']
return cls(
id=data.get('id'),
full_name=data['full_name'],
system_name=data['system_name'],
message_type=data['message_type'],
version=data['version'],
protocol=data['protocol'],
serialization=data['serialization'],
fields=fields,
description=data.get('description'),
created_time=created_time,
updated_time=updated_time,
)
def __str__(self) -> str:
"""字符串表示"""
return f"Message(id={self.id}, full_name={self.full_name}, fields={len(self.fields)})"
def __repr__(self) -> str:
"""详细字符串表示"""
return self.__str__()