mf_transform/
node_step.rs

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