mf_transform/
node_step.rs

1use std::sync::Arc;
2
3use mf_model::{node_type::NodeEnum, schema::Schema, tree::Tree, types::NodeId};
4
5use crate::transform_error;
6
7use super::{
8    step::{Step, StepResult},
9    TransformResult,
10};
11use serde::{Deserialize, Serialize};
12/// 添加节点的步骤
13#[derive(Debug, Serialize, Deserialize, Clone)]
14pub struct AddNodeStep {
15    pub parent_id: NodeId,
16    pub nodes: Vec<NodeEnum>,
17}
18impl AddNodeStep {
19    pub fn new(
20        parent_id: NodeId,
21        nodes: Vec<NodeEnum>,
22    ) -> Self {
23        AddNodeStep { parent_id, nodes }
24    }
25    // 递归收集单个节点枚举的所有子节点 id
26    pub fn collect_node_ids(node_enum: &NodeEnum) -> Vec<NodeId> {
27        let mut ids: Vec<NodeId> = vec![node_enum.0.id.clone()];
28        for child in &node_enum.1 {
29            ids.extend(Self::collect_node_ids(child));
30        }
31        ids
32    }
33}
34impl Step for AddNodeStep {
35    fn name(&self) -> String {
36        "add_node_step".to_string()
37    }
38    fn apply(
39        &self,
40        dart: &mut Tree,
41        schema: Arc<Schema>,
42    ) -> TransformResult<StepResult> {
43        let _ = schema;
44        let result = dart.add(&self.parent_id, self.nodes.clone());
45        match result {
46            Ok(_) => Ok(StepResult::ok()),
47            Err(e) => Err(transform_error(e.to_string())),
48        }
49    }
50    fn serialize(&self) -> Option<Vec<u8>> {
51        serde_json::to_vec(self).ok()
52    }
53
54    fn invert(
55        &self,
56        _: &Arc<Tree>,
57    ) -> Option<Arc<dyn Step>> {
58        // 收集所有节点的 id(包括顶级节点和所有子节点)
59        let mut all_node_ids = Vec::new();
60        for node_enum in &self.nodes {
61            all_node_ids.extend(Self::collect_node_ids(node_enum));
62        }
63
64        if !all_node_ids.is_empty() {
65            return Some(Arc::new(RemoveNodeStep::new(
66                self.parent_id.clone(),
67                all_node_ids,
68            )));
69        }
70        None
71    }
72}
73/// 删除节点的步骤
74#[derive(Debug, Serialize, Deserialize, Clone)]
75pub struct RemoveNodeStep {
76    pub parent_id: NodeId,
77    pub node_ids: Vec<NodeId>,
78}
79impl RemoveNodeStep {
80    pub fn new(
81        parent_id: NodeId,
82        node_ids: Vec<NodeId>,
83    ) -> Self {
84        RemoveNodeStep { parent_id, node_ids }
85    }
86}
87impl Step for RemoveNodeStep {
88    fn name(&self) -> String {
89        "remove_node_step".to_string()
90    }
91    fn apply(
92        &self,
93        dart: &mut Tree,
94        schema: Arc<Schema>,
95    ) -> TransformResult<StepResult> {
96        let _ = schema;
97        let result = dart.remove_node(&self.parent_id, self.node_ids.clone());
98        match result {
99            Ok(_) => Ok(StepResult::ok()),
100            Err(e) => Err(transform_error(e.to_string())), // 修复:失败时返回Err保持一致性
101        }
102    }
103    fn serialize(&self) -> Option<Vec<u8>> {
104        serde_json::to_vec(self).ok()
105    }
106
107    fn invert(
108        &self,
109        dart: &Arc<Tree>,
110    ) -> Option<Arc<dyn Step>> {
111        // 收集所有要删除的节点及其子树
112        let mut nodes_to_restore = Vec::new();
113
114        for node_id in &self.node_ids {
115            if let Some(node_enum) = dart.all_children(node_id, None) {
116                nodes_to_restore.push(node_enum);
117            }
118        }
119
120        if !nodes_to_restore.is_empty() {
121            Some(Arc::new(AddNodeStep::new(
122                self.parent_id.clone(),
123                nodes_to_restore,
124            )))
125        } else {
126            None
127        }
128    }
129}
130
131#[derive(Debug, Serialize, Deserialize, Clone)]
132pub struct MoveNodeStep {
133    source_parent_id: NodeId,
134    target_parent_id: NodeId,
135    node_id: NodeId,
136    position: Option<usize>, // 目标位置,None 表示追加到末尾
137}
138
139impl MoveNodeStep {
140    pub fn new(
141        source_parent_id: NodeId,
142        target_parent_id: NodeId,
143        node_id: NodeId,
144        position: Option<usize>,
145    ) -> Self {
146        MoveNodeStep { source_parent_id, target_parent_id, node_id, position }
147    }
148}
149
150impl Step for MoveNodeStep {
151    fn name(&self) -> String {
152        "move_node_step".to_string()
153    }
154    fn apply(
155        &self,
156        dart: &mut Tree,
157        schema: Arc<Schema>,
158    ) -> TransformResult<StepResult> {
159        let _ = schema;
160
161        match dart.move_node(
162            &self.source_parent_id,
163            &self.target_parent_id,
164            &self.node_id,
165            self.position,
166        ) {
167            Ok(()) => Ok(StepResult::ok()),
168            Err(err) => Err(transform_error(err.to_string())),
169        }
170    }
171    fn serialize(&self) -> Option<Vec<u8>> {
172        serde_json::to_vec(self).ok()
173    }
174
175    fn invert(
176        &self,
177        dart: &Arc<Tree>,
178    ) -> Option<Arc<dyn Step>> {
179        match dart.get_parent_node(&self.node_id) {
180            Some(source_parent) => {
181                // 反向时需要把节点放回原父节点的原索引
182                let original_index = source_parent
183                    .content
184                    .iter()
185                    .position(|id| id == &self.node_id);
186                let original_pos = original_index; // Option<usize>
187                Some(Arc::new(MoveNodeStep::new(
188                    self.target_parent_id.clone(),
189                    self.source_parent_id.clone(),
190                    self.node_id.clone(),
191                    original_pos,
192                )))
193            },
194            None => None,
195        }
196    }
197}
198
199#[cfg(test)]
200mod tests {
201    use super::*;
202    use mf_model::{
203        node::Node,
204        node_type::{NodeEnum, NodeSpec},
205        schema::{Schema, SchemaSpec},
206        tree::Tree,
207        attrs::Attrs,
208    };
209    use std::collections::HashMap;
210    use std::sync::Arc;
211
212    fn create_test_node(id: &str) -> Node {
213        Node::new(id, "test".to_string(), Attrs::default(), vec![], vec![])
214    }
215
216    fn create_test_schema() -> Arc<Schema> {
217        let mut nodes = HashMap::new();
218        nodes.insert(
219            "test".to_string(),
220            NodeSpec {
221                content: None,
222                marks: None,
223                group: None,
224                desc: Some("Test node".to_string()),
225                attrs: None,
226            },
227        );
228
229        let spec = SchemaSpec {
230            nodes,
231            marks: HashMap::new(),
232            top_node: Some("test".to_string()),
233        };
234
235        Arc::new(Schema::compile(spec).unwrap())
236    }
237
238    fn create_test_tree() -> Tree {
239        let root = create_test_node("root");
240        Tree::new(root)
241    }
242
243    #[test]
244    fn test_add_node_step() {
245        let mut tree = create_test_tree();
246        let schema = create_test_schema();
247
248        // Create a test node to add
249        let node = create_test_node("root");
250        let test = create_test_node("test");
251        let node_enum = NodeEnum(node, vec![NodeEnum(test, vec![])]);
252        let step = AddNodeStep::new("root".into(), vec![node_enum.clone()]);
253        let result = step.apply(&mut tree, schema.clone());
254        assert!(result.is_ok());
255
256        // Verify node was added
257        assert!(tree.get_node(&"test".into()).is_some());
258
259        // Test invert
260        let inverted = step.invert(&Arc::new(tree.clone()));
261        assert!(inverted.is_some());
262
263        // Apply inverted step
264        if let Some(inverted_step) = inverted {
265            let result = inverted_step.apply(&mut tree, schema);
266            assert!(result.is_ok());
267            // Verify node was removed
268            assert!(tree.get_node(&"test".into()).is_none());
269        }
270    }
271
272    #[test]
273    fn test_remove_node_step() {
274        let mut tree = create_test_tree();
275        let schema = create_test_schema();
276
277        // Add a node first
278        let node = create_test_node("test");
279        tree.add_node(&"root".into(), &vec![node]).unwrap();
280
281        let step = RemoveNodeStep::new("root".into(), vec!["test".into()]);
282        let result = step.apply(&mut tree, schema.clone());
283        assert!(result.is_ok());
284
285        // Verify node was removed
286        assert!(tree.get_node(&"test".into()).is_none());
287
288        // Test invert
289        let inverted = step.invert(&Arc::new(tree.clone()));
290        assert!(inverted.is_some());
291    }
292
293    #[test]
294    fn test_move_node_step() {
295        let mut tree = create_test_tree();
296        let schema = create_test_schema();
297
298        // Add source and target nodes
299        let source = create_test_node("source");
300        let target = create_test_node("target");
301        let node = create_test_node("node");
302
303        tree.add_node(&"root".into(), &vec![source]).unwrap();
304        tree.add_node(&"root".into(), &vec![target]).unwrap();
305        tree.add_node(&"source".into(), &vec![node]).unwrap();
306
307        let step = MoveNodeStep::new(
308            "source".into(),
309            "target".into(),
310            "node".into(),
311            None,
312        );
313
314        let result = step.apply(&mut tree, schema.clone());
315        assert!(result.is_ok());
316
317        // Verify node was moved
318        let target_node = tree.get_node(&"target".into()).unwrap();
319        assert!(target_node.content.contains(&"node".into()));
320
321        // Test invert
322        let inverted = step.invert(&Arc::new(tree.clone()));
323        assert!(inverted.is_some());
324    }
325}