transaction.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. use crate::core::document::position::Path;
  2. use crate::core::{DocumentOperation, DocumentTree, NodeAttributes, NodeSubTree};
  3. use indextree::NodeId;
  4. use std::collections::HashMap;
  5. pub struct Transaction {
  6. pub operations: Vec<DocumentOperation>,
  7. }
  8. impl Transaction {
  9. fn new(operations: Vec<DocumentOperation>) -> Transaction {
  10. Transaction { operations }
  11. }
  12. }
  13. pub struct TransactionBuilder<'a> {
  14. document: &'a DocumentTree,
  15. operations: Vec<DocumentOperation>,
  16. }
  17. impl<'a> TransactionBuilder<'a> {
  18. pub fn new(document: &'a DocumentTree) -> TransactionBuilder {
  19. TransactionBuilder {
  20. document,
  21. operations: Vec::new(),
  22. }
  23. }
  24. ///
  25. ///
  26. /// # Arguments
  27. ///
  28. /// * `path`: the path that is used to save the nodes
  29. /// * `nodes`: the nodes you will be save in the path
  30. ///
  31. /// # Examples
  32. ///
  33. /// ```
  34. /// // -- 0 (root)
  35. /// // 0 -- text_1
  36. /// // 1 -- text_2
  37. /// use lib_ot::core::{DocumentTree, NodeSubTree, TransactionBuilder};
  38. /// let mut document = DocumentTree::new();
  39. /// let transaction = {
  40. /// let mut tb = TransactionBuilder::new(&document);
  41. /// tb.insert_nodes_at_path(0,vec![ NodeSubTree::new("text_1"), NodeSubTree::new("text_2")]);
  42. /// tb.finalize()
  43. /// };
  44. /// document.apply(transaction).unwrap();
  45. ///
  46. /// document.node_at_path(vec![0, 0]);
  47. /// ```
  48. ///
  49. pub fn insert_nodes_at_path<T: Into<Path>>(&mut self, path: T, nodes: Vec<NodeSubTree>) {
  50. self.push(DocumentOperation::Insert {
  51. path: path.into(),
  52. nodes,
  53. });
  54. }
  55. ///
  56. ///
  57. /// # Arguments
  58. ///
  59. /// * `path`: the path that is used to save the nodes
  60. /// * `node`: the node data will be saved in the path
  61. ///
  62. /// # Examples
  63. ///
  64. /// ```
  65. /// // 0
  66. /// // -- 0
  67. /// // |-- text
  68. /// use lib_ot::core::{DocumentTree, NodeSubTree, TransactionBuilder};
  69. /// let mut document = DocumentTree::new();
  70. /// let transaction = {
  71. /// let mut tb = TransactionBuilder::new(&document);
  72. /// tb.insert_node_at_path(0, NodeSubTree::new("text"));
  73. /// tb.finalize()
  74. /// };
  75. /// document.apply(transaction).unwrap();
  76. /// ```
  77. ///
  78. pub fn insert_node_at_path<T: Into<Path>>(&mut self, path: T, node: NodeSubTree) {
  79. self.insert_nodes_at_path(path, vec![node]);
  80. }
  81. pub fn update_attributes_at_path(&mut self, path: &Path, attributes: HashMap<String, Option<String>>) {
  82. let mut old_attributes: HashMap<String, Option<String>> = HashMap::new();
  83. let node = self.document.node_at_path(path).unwrap();
  84. let node_data = self.document.get_node_data(node).unwrap();
  85. for key in attributes.keys() {
  86. let old_attrs = &node_data.attributes;
  87. let old_value = match old_attrs.0.get(key.as_str()) {
  88. Some(value) => value.clone(),
  89. None => None,
  90. };
  91. old_attributes.insert(key.clone(), old_value);
  92. }
  93. self.push(DocumentOperation::Update {
  94. path: path.clone(),
  95. attributes: NodeAttributes(attributes),
  96. old_attributes: NodeAttributes(old_attributes),
  97. })
  98. }
  99. pub fn delete_node_at_path(&mut self, path: &Path) {
  100. self.delete_nodes_at_path(path, 1);
  101. }
  102. pub fn delete_nodes_at_path(&mut self, path: &Path, length: usize) {
  103. let mut node = self.document.node_at_path(path).unwrap();
  104. let mut deleted_nodes = vec![];
  105. for _ in 0..length {
  106. deleted_nodes.push(self.get_deleted_nodes(node));
  107. node = self.document.following_siblings(node).next().unwrap();
  108. }
  109. self.operations.push(DocumentOperation::Delete {
  110. path: path.clone(),
  111. nodes: deleted_nodes,
  112. })
  113. }
  114. fn get_deleted_nodes(&self, node_id: NodeId) -> NodeSubTree {
  115. let node_data = self.document.get_node_data(node_id).unwrap();
  116. let mut children = vec![];
  117. self.document.children_from_node(node_id).for_each(|child_id| {
  118. children.push(self.get_deleted_nodes(child_id));
  119. });
  120. NodeSubTree {
  121. node_type: node_data.node_type.clone(),
  122. attributes: node_data.attributes.clone(),
  123. delta: node_data.delta.clone(),
  124. children,
  125. }
  126. }
  127. pub fn push(&mut self, op: DocumentOperation) {
  128. self.operations.push(op);
  129. }
  130. pub fn finalize(self) -> Transaction {
  131. Transaction::new(self.operations)
  132. }
  133. }