459 lines
13 KiB
Rust
459 lines
13 KiB
Rust
//! 宪法条款管理器模块
|
|
//!
|
|
//! 提供条款的添加、更新、删除和版本管理功能
|
|
|
|
use crate::{ConstitutionalClause, ClauseTier};
|
|
use crate::storage::{ClauseStorage, StorageError};
|
|
use crate::validator::{ClauseValidator, ValidationError};
|
|
use nac_udm::primitives::Hash;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
use std::path::Path;
|
|
|
|
/// 管理器错误类型
|
|
#[derive(Debug)]
|
|
pub enum ManagerError {
|
|
/// 验证错误
|
|
ValidationError(ValidationError),
|
|
/// 存储错误
|
|
StorageError(StorageError),
|
|
/// 条款已存在
|
|
ClauseExists(u64),
|
|
/// 条款不存在
|
|
ClauseNotFound(u64),
|
|
/// 版本冲突
|
|
VersionConflict(u64, u32),
|
|
}
|
|
|
|
impl From<ValidationError> for ManagerError {
|
|
fn from(err: ValidationError) -> Self {
|
|
ManagerError::ValidationError(err)
|
|
}
|
|
}
|
|
|
|
impl From<StorageError> for ManagerError {
|
|
fn from(err: StorageError) -> Self {
|
|
ManagerError::StorageError(err)
|
|
}
|
|
}
|
|
|
|
/// 条款版本信息
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ClauseVersion {
|
|
/// 版本号
|
|
pub version: u32,
|
|
/// 条款内容
|
|
pub clause: ConstitutionalClause,
|
|
/// 创建时间
|
|
pub created_at: u64,
|
|
/// 创建者
|
|
pub created_by: String,
|
|
/// 变更说明
|
|
pub change_note: String,
|
|
}
|
|
|
|
/// 宪法条款管理器
|
|
pub struct ConstitutionManager {
|
|
/// 存储层
|
|
storage: ClauseStorage,
|
|
/// 验证器
|
|
validator: ClauseValidator,
|
|
/// 版本历史 (clause_index -> versions)
|
|
version_history: HashMap<u64, Vec<ClauseVersion>>,
|
|
}
|
|
|
|
impl ConstitutionManager {
|
|
/// 创建新的管理器
|
|
pub fn new<P: AsRef<Path>>(storage_path: P) -> Result<Self, ManagerError> {
|
|
let storage = ClauseStorage::new(storage_path)?;
|
|
let validator = ClauseValidator::new();
|
|
|
|
Ok(Self {
|
|
storage,
|
|
validator,
|
|
version_history: HashMap::new(),
|
|
})
|
|
}
|
|
|
|
/// 从磁盘加载管理器
|
|
pub fn load_from_disk<P: AsRef<Path>>(storage_path: P) -> Result<Self, ManagerError> {
|
|
let storage = ClauseStorage::load_from_disk(storage_path)?;
|
|
let mut validator = ClauseValidator::new();
|
|
|
|
// 注册所有已存在的条款
|
|
for clause in storage.list_all_clauses() {
|
|
validator.register_clause(clause.clause_index, vec![]);
|
|
}
|
|
|
|
Ok(Self {
|
|
storage,
|
|
validator,
|
|
version_history: HashMap::new(),
|
|
})
|
|
}
|
|
|
|
/// 添加新条款
|
|
pub fn add_clause(
|
|
&mut self,
|
|
clause: ConstitutionalClause,
|
|
created_by: String,
|
|
change_note: String,
|
|
) -> Result<(), ManagerError> {
|
|
// 检查条款是否已存在
|
|
if self.storage.load_clause(clause.clause_index).is_ok() {
|
|
return Err(ManagerError::ClauseExists(clause.clause_index));
|
|
}
|
|
|
|
// 验证条款
|
|
self.validator.validate_clause(&clause)?;
|
|
|
|
// 保存到存储
|
|
self.storage.save_clause(clause.clone())?;
|
|
|
|
// 注册到验证器
|
|
self.validator.register_clause(clause.clause_index, vec![]);
|
|
|
|
// 记录版本历史
|
|
let version = ClauseVersion {
|
|
version: 1,
|
|
clause,
|
|
created_at: Self::current_timestamp(),
|
|
created_by,
|
|
change_note,
|
|
};
|
|
|
|
self.version_history
|
|
.entry(version.clause.clause_index)
|
|
.or_insert_with(Vec::new)
|
|
.push(version);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 更新条款
|
|
pub fn update_clause(
|
|
&mut self,
|
|
index: u64,
|
|
new_content: String,
|
|
updated_by: String,
|
|
change_note: String,
|
|
) -> Result<(), ManagerError> {
|
|
// 加载现有条款
|
|
let old_clause = self.storage.load_clause(index)?.clone();
|
|
|
|
// 创建新版本
|
|
let mut new_clause = old_clause.clone();
|
|
new_clause.content = new_content;
|
|
new_clause.clause_hash = ClauseValidator::compute_clause_hash(&new_clause);
|
|
|
|
// 验证新条款
|
|
self.validator.validate_clause(&new_clause)?;
|
|
|
|
// 保存到存储
|
|
self.storage.save_clause(new_clause.clone())?;
|
|
|
|
// 记录版本历史
|
|
let current_version = self.version_history
|
|
.get(&index)
|
|
.and_then(|versions| versions.last())
|
|
.map(|v| v.version)
|
|
.unwrap_or(0);
|
|
|
|
let version = ClauseVersion {
|
|
version: current_version + 1,
|
|
clause: new_clause,
|
|
created_at: Self::current_timestamp(),
|
|
created_by: updated_by,
|
|
change_note,
|
|
};
|
|
|
|
self.version_history
|
|
.entry(index)
|
|
.or_insert_with(Vec::new)
|
|
.push(version);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 删除条款
|
|
pub fn delete_clause(&mut self, index: u64) -> Result<(), ManagerError> {
|
|
// 删除存储中的条款
|
|
self.storage.delete_clause(index)?;
|
|
|
|
// 从验证器中移除
|
|
// 注意:这里简化处理,实际应该更新依赖关系
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 获取条款
|
|
pub fn get_clause(&self, index: u64) -> Result<&ConstitutionalClause, ManagerError> {
|
|
self.storage.load_clause(index)
|
|
.map_err(|e| ManagerError::from(e))
|
|
}
|
|
|
|
/// 获取所有条款
|
|
pub fn list_all_clauses(&self) -> Vec<&ConstitutionalClause> {
|
|
self.storage.list_all_clauses()
|
|
}
|
|
|
|
/// 按层级获取条款
|
|
pub fn list_clauses_by_tier(&self, tier: ClauseTier) -> Vec<&ConstitutionalClause> {
|
|
self.storage.list_clauses_by_tier(tier)
|
|
}
|
|
|
|
/// 获取条款版本历史
|
|
pub fn get_version_history(&self, index: u64) -> Option<&Vec<ClauseVersion>> {
|
|
self.version_history.get(&index)
|
|
}
|
|
|
|
/// 获取特定版本的条款
|
|
pub fn get_clause_version(&self, index: u64, version: u32) -> Result<&ClauseVersion, ManagerError> {
|
|
self.version_history
|
|
.get(&index)
|
|
.and_then(|versions| versions.iter().find(|v| v.version == version))
|
|
.ok_or(ManagerError::VersionConflict(index, version))
|
|
}
|
|
|
|
/// 回滚到特定版本
|
|
pub fn rollback_to_version(
|
|
&mut self,
|
|
index: u64,
|
|
version: u32,
|
|
rolled_back_by: String,
|
|
) -> Result<(), ManagerError> {
|
|
// 获取目标版本
|
|
let target_version = self.get_clause_version(index, version)?.clone();
|
|
|
|
// 创建新版本(基于目标版本的内容)
|
|
let mut new_clause = target_version.clause.clone();
|
|
new_clause.clause_hash = ClauseValidator::compute_clause_hash(&new_clause);
|
|
|
|
// 验证
|
|
self.validator.validate_clause(&new_clause)?;
|
|
|
|
// 保存
|
|
self.storage.save_clause(new_clause.clone())?;
|
|
|
|
// 记录版本历史
|
|
let current_version = self.version_history
|
|
.get(&index)
|
|
.and_then(|versions| versions.last())
|
|
.map(|v| v.version)
|
|
.unwrap_or(0);
|
|
|
|
let rollback_version = ClauseVersion {
|
|
version: current_version + 1,
|
|
clause: new_clause,
|
|
created_at: Self::current_timestamp(),
|
|
created_by: rolled_back_by,
|
|
change_note: format!("回滚到版本 {}", version),
|
|
};
|
|
|
|
self.version_history
|
|
.entry(index)
|
|
.or_insert_with(Vec::new)
|
|
.push(rollback_version);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 获取当前时间戳(简化实现)
|
|
fn current_timestamp() -> u64 {
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_secs()
|
|
}
|
|
|
|
/// 获取条款数量统计
|
|
pub fn get_statistics(&self) -> ClauseStatistics {
|
|
ClauseStatistics {
|
|
total: self.storage.count(),
|
|
eternal: self.storage.count_by_tier(ClauseTier::Eternal),
|
|
strategic: self.storage.count_by_tier(ClauseTier::Strategic),
|
|
tactical: self.storage.count_by_tier(ClauseTier::Tactical),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 条款统计信息
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ClauseStatistics {
|
|
/// 总数
|
|
pub total: usize,
|
|
/// 永恒级数量
|
|
pub eternal: usize,
|
|
/// 战略级数量
|
|
pub strategic: usize,
|
|
/// 战术级数量
|
|
pub tactical: usize,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use tempfile::tempdir;
|
|
|
|
fn create_test_clause(index: u64, tier: ClauseTier) -> ConstitutionalClause {
|
|
let clause = ConstitutionalClause {
|
|
clause_index: index,
|
|
title: format!("测试条款 {}", index),
|
|
content: format!("这是测试条款 {} 的内容", index),
|
|
clause_hash: Hash::zero(),
|
|
effective_from: 1000,
|
|
tier,
|
|
};
|
|
|
|
let hash = ClauseValidator::compute_clause_hash(&clause);
|
|
ConstitutionalClause {
|
|
clause_hash: hash,
|
|
..clause
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_add_clause() {
|
|
let dir = tempdir().unwrap();
|
|
let path = dir.path().join("clauses.json");
|
|
let mut manager = ConstitutionManager::new(&path).unwrap();
|
|
|
|
let clause = create_test_clause(1, ClauseTier::Eternal);
|
|
let result = manager.add_clause(
|
|
clause,
|
|
"测试用户".to_string(),
|
|
"初始版本".to_string(),
|
|
);
|
|
|
|
assert!(result.is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_update_clause() {
|
|
let dir = tempdir().unwrap();
|
|
let path = dir.path().join("clauses.json");
|
|
let mut manager = ConstitutionManager::new(&path).unwrap();
|
|
|
|
let clause = create_test_clause(1, ClauseTier::Eternal);
|
|
manager.add_clause(
|
|
clause,
|
|
"测试用户".to_string(),
|
|
"初始版本".to_string(),
|
|
).unwrap();
|
|
|
|
let result = manager.update_clause(
|
|
1,
|
|
"更新后的内容".to_string(),
|
|
"测试用户".to_string(),
|
|
"更新测试".to_string(),
|
|
);
|
|
|
|
assert!(result.is_ok());
|
|
|
|
let updated = manager.get_clause(1).unwrap();
|
|
assert_eq!(updated.content, "更新后的内容");
|
|
}
|
|
|
|
#[test]
|
|
fn test_version_history() {
|
|
let dir = tempdir().unwrap();
|
|
let path = dir.path().join("clauses.json");
|
|
let mut manager = ConstitutionManager::new(&path).unwrap();
|
|
|
|
let clause = create_test_clause(1, ClauseTier::Eternal);
|
|
manager.add_clause(
|
|
clause,
|
|
"测试用户".to_string(),
|
|
"初始版本".to_string(),
|
|
).unwrap();
|
|
|
|
manager.update_clause(
|
|
1,
|
|
"第二版内容".to_string(),
|
|
"测试用户".to_string(),
|
|
"第二版".to_string(),
|
|
).unwrap();
|
|
|
|
let history = manager.get_version_history(1).unwrap();
|
|
assert_eq!(history.len(), 2);
|
|
assert_eq!(history[0].version, 1);
|
|
assert_eq!(history[1].version, 2);
|
|
}
|
|
|
|
#[test]
|
|
fn test_rollback() {
|
|
let dir = tempdir().unwrap();
|
|
let path = dir.path().join("clauses.json");
|
|
let mut manager = ConstitutionManager::new(&path).unwrap();
|
|
|
|
let clause = create_test_clause(1, ClauseTier::Eternal);
|
|
manager.add_clause(
|
|
clause,
|
|
"测试用户".to_string(),
|
|
"初始版本".to_string(),
|
|
).unwrap();
|
|
|
|
manager.update_clause(
|
|
1,
|
|
"第二版内容".to_string(),
|
|
"测试用户".to_string(),
|
|
"第二版".to_string(),
|
|
).unwrap();
|
|
|
|
manager.rollback_to_version(
|
|
1,
|
|
1,
|
|
"测试用户".to_string(),
|
|
).unwrap();
|
|
|
|
let history = manager.get_version_history(1).unwrap();
|
|
assert_eq!(history.len(), 3);
|
|
assert_eq!(history[2].change_note, "回滚到版本 1");
|
|
}
|
|
|
|
#[test]
|
|
fn test_delete_clause() {
|
|
let dir = tempdir().unwrap();
|
|
let path = dir.path().join("clauses.json");
|
|
let mut manager = ConstitutionManager::new(&path).unwrap();
|
|
|
|
let clause = create_test_clause(1, ClauseTier::Eternal);
|
|
manager.add_clause(
|
|
clause,
|
|
"测试用户".to_string(),
|
|
"初始版本".to_string(),
|
|
).unwrap();
|
|
|
|
assert!(manager.get_clause(1).is_ok());
|
|
|
|
manager.delete_clause(1).unwrap();
|
|
assert!(manager.get_clause(1).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_statistics() {
|
|
let dir = tempdir().unwrap();
|
|
let path = dir.path().join("clauses.json");
|
|
let mut manager = ConstitutionManager::new(&path).unwrap();
|
|
|
|
manager.add_clause(
|
|
create_test_clause(1, ClauseTier::Eternal),
|
|
"测试用户".to_string(),
|
|
"条款1".to_string(),
|
|
).unwrap();
|
|
|
|
manager.add_clause(
|
|
create_test_clause(101, ClauseTier::Strategic),
|
|
"测试用户".to_string(),
|
|
"条款2".to_string(),
|
|
).unwrap();
|
|
|
|
let stats = manager.get_statistics();
|
|
assert_eq!(stats.total, 2);
|
|
assert_eq!(stats.eternal, 1);
|
|
assert_eq!(stats.strategic, 1);
|
|
assert_eq!(stats.tactical, 0);
|
|
}
|
|
}
|