moduforge_collaboration/
mapping.rs

1use moduforge_transform::{node_step::AddNodeStep, step::Step};
2use moduforge_model::tree::Tree;
3use std::collections::HashMap;
4use crate::{StepResult, NodeData, MarkData, RoomSnapshot};
5use yrs::{Map, Transact, MapPrelim, ArrayPrelim, Array, TransactionMut, WriteTxn};
6
7/// Step转换器trait - 用于将Step直接应用到Yrs文档
8pub trait StepConverter {
9    /// 直接将Step应用到Yrs文档事务
10    fn apply_to_yrs_txn(&self, step: &dyn Step, txn: &mut yrs::TransactionMut, client_id: &str) -> Result<StepResult, Box<dyn std::error::Error>>;
11    
12    /// 获取转换器名称
13    fn name(&self) -> &'static str;
14    
15    /// 检查是否支持此Step类型
16    fn supports(&self, step: &dyn Step) -> bool;
17    
18    /// 获取Step的操作描述
19    fn get_description(&self, step: &dyn Step) -> String {
20        format!("执行操作: {} ({})", step.name(), self.name())
21    }
22}
23
24/// 默认Step转换器
25pub struct DefaultStepConverter;
26
27impl StepConverter for DefaultStepConverter {
28    fn apply_to_yrs_txn(&self, step: &dyn Step, _txn: &mut yrs::TransactionMut, client_id: &str) -> Result<StepResult, Box<dyn std::error::Error>> {
29       
30        
31        Ok(StepResult {
32            step_id: uuid::Uuid::new_v4().to_string(),
33            step_name: step.name().to_string(),
34            description: format!("默认处理器处理了未知步骤: {}", step.name()),
35            timestamp: std::time::SystemTime::now()
36                .duration_since(std::time::UNIX_EPOCH)
37                .unwrap()
38                .as_millis() as u64,
39            client_id: client_id.to_string(),
40        })
41    }
42    
43    fn name(&self) -> &'static str {
44        "DefaultStepConverter"
45    }
46    
47    fn supports(&self, _step: &dyn Step) -> bool {
48        true // 默认转换器支持所有类型
49    }
50}
51
52/// 节点操作Step转换器
53pub struct NodeStepConverter;
54
55impl StepConverter for NodeStepConverter {
56    fn apply_to_yrs_txn(&self, step: &dyn Step, txn: &mut yrs::TransactionMut, client_id: &str) -> Result<StepResult, Box<dyn std::error::Error>> {
57        if let Some(add_step) = step.downcast_ref::<AddNodeStep>() {
58            let nodes_map = txn.get_or_insert_map("nodes");
59
60            for node_enum in &add_step.nodes {
61                let node = &node_enum.0; 
62                
63                // 1. Insert a new Map for the node and get a handle to it.
64                let node_data_map = nodes_map.insert(txn, node.id.clone(), MapPrelim::default());
65
66                // 2. Populate basic info
67                node_data_map.insert(txn, "type", node.r#type.clone());
68
69                // 3. Create and populate a nested Map for attributes
70                let attrs_map = node_data_map.insert(txn, "attrs", MapPrelim::default());
71                for (key, value) in node.attrs.iter() {
72                    attrs_map.insert(txn, key.clone(), value.to_string());
73                }
74
75                // 4. Create and populate a nested Array for content
76                let content_array = node_data_map.insert(txn, "content", ArrayPrelim::default());
77                for child_id in &node.content {
78                    content_array.push_back(txn, child_id.clone());
79                }
80            }
81
82            return Ok(StepResult {
83                step_id: uuid::Uuid::new_v4().to_string(),
84                step_name: step.name().to_string(),
85                description: format!("添加了 {} 个节点", add_step.nodes.len()),
86                timestamp: std::time::SystemTime::now()
87                    .duration_since(std::time::UNIX_EPOCH)
88                    .unwrap()
89                    .as_millis() as u64,
90                client_id: client_id.to_string(),
91            });
92
93        } else if step.name().contains("RemoveNode") {
94            let _nodes_map = txn.get_or_insert_map("nodes");
95            // 假设 RemoveNode step 有一个 `node_id` 字段
96            // let node_id_to_remove = step.get_node_id(); 
97            // nodes_map.remove(txn, node_id_to_remove);
98            // 此处为简化后的占位逻辑
99            return Ok(StepResult {
100                step_id: uuid::Uuid::new_v4().to_string(),
101                step_name: step.name().to_string(),
102                description: "模拟删除了节点".to_string(),
103                timestamp: std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis() as u64,
104                client_id: client_id.to_string(),
105            });
106        }
107        
108        Err("不支持的节点操作".into())
109    }
110    
111    fn name(&self) -> &'static str {
112        "NodeStepConverter"
113    }
114    
115    fn supports(&self, step: &dyn Step) -> bool {
116       step.name().contains("add_node_step") || step.name().contains("RemoveNode")
117    }
118}
119
120/// 属性操作Step转换器
121pub struct AttrStepConverter;
122
123impl StepConverter for AttrStepConverter {
124    fn apply_to_yrs_txn(&self, step: &dyn Step, _txn: &mut yrs::TransactionMut, client_id: &str) -> Result<StepResult, Box<dyn std::error::Error>> {
125        let step_name = step.name();
126        
127        if step_name.contains("Attr") {
128          
129            Ok(StepResult {
130                step_id: uuid::Uuid::new_v4().to_string(),
131                step_name: step.name().to_string(),
132                description: format!("更新了节点属性"),
133                timestamp: std::time::SystemTime::now()
134                    .duration_since(std::time::UNIX_EPOCH)
135                    .unwrap()
136                    .as_millis() as u64,
137                client_id: client_id.to_string(),
138            })
139        } else {
140            Err("不支持的属性操作".into())
141        }
142    }
143    
144    fn name(&self) -> &'static str {
145        "AttrStepConverter"
146    }
147    
148    fn supports(&self, step: &dyn Step) -> bool {
149        let step_name = step.name();
150        step_name.contains("Attr")
151    }
152}
153
154/// 标记操作Step转换器
155pub struct MarkStepConverter;
156
157impl StepConverter for MarkStepConverter {
158    fn apply_to_yrs_txn(&self, _step: &dyn Step, _txn: &mut yrs::TransactionMut, _client_id: &str) -> Result<StepResult, Box<dyn std::error::Error>> {
159
160        Err("不支持的标记操作".into())
161    }
162    
163    fn name(&self) -> &'static str {
164        "MarkStepConverter"
165    }
166    
167    fn supports(&self, step: &dyn Step) -> bool {
168        let step_name = step.name();
169        step_name.contains("Mark")
170    }
171}
172
173/// Step转换器注册表
174pub struct StepConverterRegistry {
175    converters: Vec<Box<dyn StepConverter + Send + Sync>>,
176}
177
178impl StepConverterRegistry {
179    /// 创建新的转换器注册表
180    pub fn new() -> Self {
181        let mut registry = Self {
182            converters: Vec::new(),
183        };
184        
185        // 注册默认转换器(必须最后注册,作为fallback)
186        registry.register(Box::new(NodeStepConverter));
187        registry.register(Box::new(AttrStepConverter));
188        registry.register(Box::new(MarkStepConverter));
189        registry.register(Box::new(DefaultStepConverter)); // fallback
190        
191        registry
192    }
193    
194    /// 注册转换器
195    pub fn register(&mut self, converter: Box<dyn StepConverter + Send + Sync>) {
196        tracing::info!("注册Step转换器: {}", converter.name());
197        self.converters.push(converter);
198    }
199    
200    /// 查找支持指定Step的转换器
201    pub fn find_converter(&self, step: &dyn Step) -> Option<&(dyn StepConverter + Send + Sync)> {
202        for converter in &self.converters {
203            if converter.supports(step) {
204                return Some(converter.as_ref());
205            }
206        }
207        None
208    }
209    
210    /// 列出所有转换器
211    pub fn list_converters(&self) -> Vec<&str> {
212        self.converters.iter().map(|c| c.name()).collect()
213    }
214}
215
216impl Default for StepConverterRegistry {
217    fn default() -> Self {
218        Self::new()
219    }
220}
221
222/// 全局映射器
223pub struct Mapper;
224
225impl Mapper {
226    /// 获取全局转换器注册表
227    pub fn global_registry() -> &'static StepConverterRegistry {
228        use std::sync::OnceLock;
229        static REGISTRY: OnceLock<StepConverterRegistry> = OnceLock::new();
230        REGISTRY.get_or_init(|| StepConverterRegistry::new())
231    }
232    
233    /// 将 ModuForge 的 Tree 转换为 RoomSnapshot
234    pub fn tree_to_snapshot(tree: &Tree, room_id: String) -> RoomSnapshot {
235        let mut nodes = HashMap::new();
236        
237        // 递归遍历所有节点并转换
238        fn collect_nodes(tree: &Tree, node_id: &str, nodes: &mut HashMap<String, NodeData>) {
239            if let Some(node) = tree.get_node(&node_id.to_string()) {
240                let node_data = NodeData {
241                    id: node.id.clone(),
242                    node_type: node.r#type.clone(),
243                    attrs: node.attrs.iter().map(|(k, v)| (k.clone(), v.clone())).collect(),
244                    content: node.content.iter().cloned().collect(),
245                    marks: node.marks.iter().map(|mark| MarkData {
246                        mark_type: mark.r#type.clone(),
247                        attrs: mark.attrs.iter().map(|(k, v)| (k.clone(), v.clone())).collect(),
248                    }).collect(),
249                };
250                
251                nodes.insert(node_id.to_string(), node_data);
252                
253                // 递归处理子节点
254                for child_id in &node.content {
255                    collect_nodes(tree, child_id, nodes);
256                }
257            }
258        }
259        
260        collect_nodes(tree, &tree.root_id, &mut nodes);
261        
262        RoomSnapshot {
263            room_id,
264            root_id: tree.root_id.clone(),
265            nodes,
266            version: 0, // Version is now managed by YrsManager, snapshot is always at a point in time.
267        }
268    }
269
270    /// 将 ModuForge 的 Tree 转换为一个临时的 yrs::Doc (用于同步)
271    pub fn tree_to_yrs_doc(tree: &Tree) -> yrs::Doc {
272        let doc = yrs::Doc::new();
273        {
274            // Scope the transaction so it's dropped before we return the doc
275            let mut txn = doc.transact_mut();
276            let nodes_map = txn.get_or_insert_map("nodes");
277
278            // Use an iterative approach to avoid recursion issues and stack overflows
279            let mut queue = std::collections::VecDeque::new();
280            if !tree.root_id.is_empty() {
281                queue.push_back(tree.root_id.clone());
282            }
283
284            let mut visited = std::collections::HashSet::new();
285            if !tree.root_id.is_empty() {
286                visited.insert(tree.root_id.clone());
287            }
288
289            while let Some(node_id) = queue.pop_front() {
290                if let Some(node) = tree.get_node(&node_id) {
291                    let node_data_map = nodes_map.insert(&mut txn, node.id.clone(), MapPrelim::default());
292
293                    node_data_map.insert(&mut txn, "type", node.r#type.clone());
294
295                    let attrs_map = node_data_map.insert(&mut txn, "attrs", MapPrelim::default());
296                    for (key, value) in node.attrs.iter() {
297                        attrs_map.insert(&mut txn, key.clone(), value.to_string());
298                    }
299
300                    let content_array = node_data_map.insert(&mut txn, "content", ArrayPrelim::default());
301                    for child_id in &node.content {
302                        content_array.push_back(&mut txn, child_id.clone());
303                        if visited.insert(child_id.clone()) {
304                            queue.push_back(child_id.clone());
305                        }
306                    }
307                }
308            }
309        }
310        doc
311    }
312}