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<String> = 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_node(&self.node_id) {
180 Some(_) => Some(Arc::new(MoveNodeStep::new(
181 self.target_parent_id.clone(),
182 self.source_parent_id.clone(),
183 self.node_id.clone(),
184 self.position,
185 ))),
186 None => None,
187 }
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194 use mf_model::{
195 node::Node,
196 node_type::{NodeEnum, NodeType, NodeSpec},
197 schema::{Schema, SchemaSpec, AttributeSpec},
198 tree::Tree,
199 attrs::Attrs,
200 mark::Mark,
201 };
202 use std::collections::HashMap;
203 use std::sync::Arc;
204
205 fn create_test_node(id: &str) -> Node {
206 Node::new(id, "test".to_string(), Attrs::default(), vec![], vec![])
207 }
208
209 fn create_test_schema() -> Arc<Schema> {
210 let mut nodes = HashMap::new();
211 nodes.insert(
212 "test".to_string(),
213 NodeSpec {
214 content: None,
215 marks: None,
216 group: None,
217 desc: Some("Test node".to_string()),
218 attrs: None,
219 },
220 );
221
222 let spec = SchemaSpec {
223 nodes,
224 marks: HashMap::new(),
225 top_node: Some("test".to_string()),
226 };
227
228 Arc::new(Schema::compile(spec).unwrap())
229 }
230
231 fn create_test_tree() -> Tree {
232 let root = create_test_node("root");
233 Tree::new(root)
234 }
235
236 #[test]
237 fn test_add_node_step() {
238 let mut tree = create_test_tree();
239 let schema = create_test_schema();
240
241 let node = create_test_node("root");
243 let test = create_test_node("test");
244 let node_enum = NodeEnum(node, vec![NodeEnum(test, vec![])]);
245 let step =
246 AddNodeStep::new("root".to_string(), vec![node_enum.clone()]);
247 let result = step.apply(&mut tree, schema.clone());
248 assert!(result.is_ok());
249
250 assert!(tree.get_node(&"test".to_string()).is_some());
252
253 let inverted = step.invert(&Arc::new(tree.clone()));
255 assert!(inverted.is_some());
256
257 if let Some(inverted_step) = inverted {
259 let result = inverted_step.apply(&mut tree, schema);
260 assert!(result.is_ok());
261 assert!(tree.get_node(&"test".to_string()).is_none());
263 }
264 }
265
266 #[test]
267 fn test_remove_node_step() {
268 let mut tree = create_test_tree();
269 let schema = create_test_schema();
270
271 let node = create_test_node("test");
273 tree.add_node(&"root".to_string(), &vec![node]).unwrap();
274
275 let step =
276 RemoveNodeStep::new("root".to_string(), vec!["test".to_string()]);
277 let result = step.apply(&mut tree, schema.clone());
278 assert!(result.is_ok());
279
280 assert!(tree.get_node(&"test".to_string()).is_none());
282
283 let inverted = step.invert(&Arc::new(tree.clone()));
285 assert!(inverted.is_some());
286 }
287
288 #[test]
289 fn test_move_node_step() {
290 let mut tree = create_test_tree();
291 let schema = create_test_schema();
292
293 let source = create_test_node("source");
295 let target = create_test_node("target");
296 let node = create_test_node("node");
297
298 tree.add_node(&"root".to_string(), &vec![source]).unwrap();
299 tree.add_node(&"root".to_string(), &vec![target]).unwrap();
300 tree.add_node(&"source".to_string(), &vec![node]).unwrap();
301
302 let step = MoveNodeStep::new(
303 "source".to_string(),
304 "target".to_string(),
305 "node".to_string(),
306 None,
307 );
308
309 let result = step.apply(&mut tree, schema.clone());
310 assert!(result.is_ok());
311
312 let target_node = tree.get_node(&"target".to_string()).unwrap();
314 assert!(target_node.content.contains(&"node".to_string()));
315
316 let inverted = step.invert(&Arc::new(tree.clone()));
318 assert!(inverted.is_some());
319 }
320}