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#[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 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 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#[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())), }
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 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>, }
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 let original_index = source_parent
183 .content
184 .iter()
185 .position(|id| id == &self.node_id);
186 let original_pos = original_index; 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 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 assert!(tree.get_node(&"test".into()).is_some());
258
259 let inverted = step.invert(&Arc::new(tree.clone()));
261 assert!(inverted.is_some());
262
263 if let Some(inverted_step) = inverted {
265 let result = inverted_step.apply(&mut tree, schema);
266 assert!(result.is_ok());
267 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 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 assert!(tree.get_node(&"test".into()).is_none());
287
288 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 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 let target_node = tree.get_node(&"target".into()).unwrap();
319 assert!(target_node.content.contains(&"node".into()));
320
321 let inverted = step.invert(&Arc::new(tree.clone()));
323 assert!(inverted.is_some());
324 }
325}