grid_revision_pad.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. use crate::entities::revision::{md5, RepeatedRevision, Revision};
  2. use crate::errors::{internal_error, CollaborateError, CollaborateResult};
  3. use crate::util::{cal_diff, make_text_delta_from_revisions};
  4. use bytes::Bytes;
  5. use flowy_grid_data_model::revision::{
  6. gen_block_id, gen_grid_id, FieldRevision, FieldTypeRevision, GridBlockMetaRevision, GridBlockMetaRevisionChangeset,
  7. GridRevision,
  8. };
  9. use lib_infra::util::move_vec_element;
  10. use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta, TextDeltaBuilder};
  11. use std::collections::HashMap;
  12. use std::sync::Arc;
  13. pub type GridRevisionDelta = TextDelta;
  14. pub type GridRevisionDeltaBuilder = TextDeltaBuilder;
  15. pub struct GridRevisionPad {
  16. grid_rev: Arc<GridRevision>,
  17. delta: GridRevisionDelta,
  18. }
  19. pub trait JsonDeserializer {
  20. fn deserialize(&self, type_option_data: Vec<u8>) -> CollaborateResult<String>;
  21. }
  22. impl GridRevisionPad {
  23. pub fn grid_id(&self) -> String {
  24. self.grid_rev.grid_id.clone()
  25. }
  26. pub async fn duplicate_grid_block_meta(&self) -> (Vec<FieldRevision>, Vec<GridBlockMetaRevision>) {
  27. let fields = self
  28. .grid_rev
  29. .fields
  30. .iter()
  31. .map(|field_rev| field_rev.as_ref().clone())
  32. .collect();
  33. let blocks = self
  34. .grid_rev
  35. .blocks
  36. .iter()
  37. .map(|block| {
  38. let mut duplicated_block = (&**block).clone();
  39. duplicated_block.block_id = gen_block_id();
  40. duplicated_block
  41. })
  42. .collect::<Vec<GridBlockMetaRevision>>();
  43. (fields, blocks)
  44. }
  45. pub fn from_delta(delta: GridRevisionDelta) -> CollaborateResult<Self> {
  46. let content = delta.content()?;
  47. let grid: GridRevision = serde_json::from_str(&content).map_err(|e| {
  48. let msg = format!("Deserialize delta to grid failed: {}", e);
  49. tracing::error!("{}", msg);
  50. CollaborateError::internal().context(msg)
  51. })?;
  52. Ok(Self {
  53. grid_rev: Arc::new(grid),
  54. delta,
  55. })
  56. }
  57. pub fn from_revisions(revisions: Vec<Revision>) -> CollaborateResult<Self> {
  58. let grid_delta: GridRevisionDelta = make_text_delta_from_revisions(revisions)?;
  59. Self::from_delta(grid_delta)
  60. }
  61. #[tracing::instrument(level = "debug", skip_all, err)]
  62. pub fn create_field_rev(
  63. &mut self,
  64. new_field_rev: FieldRevision,
  65. start_field_id: Option<String>,
  66. ) -> CollaborateResult<Option<GridRevisionChangeset>> {
  67. self.modify_grid(|grid_meta| {
  68. // Check if the field exists or not
  69. if grid_meta
  70. .fields
  71. .iter()
  72. .any(|field_rev| field_rev.id == new_field_rev.id)
  73. {
  74. tracing::error!("Duplicate grid field");
  75. return Ok(None);
  76. }
  77. let insert_index = match start_field_id {
  78. None => None,
  79. Some(start_field_id) => grid_meta.fields.iter().position(|field| field.id == start_field_id),
  80. };
  81. let new_field_rev = Arc::new(new_field_rev);
  82. match insert_index {
  83. None => grid_meta.fields.push(new_field_rev),
  84. Some(index) => grid_meta.fields.insert(index, new_field_rev),
  85. }
  86. Ok(Some(()))
  87. })
  88. }
  89. pub fn delete_field_rev(&mut self, field_id: &str) -> CollaborateResult<Option<GridRevisionChangeset>> {
  90. self.modify_grid(
  91. |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
  92. None => Ok(None),
  93. Some(index) => {
  94. grid_meta.fields.remove(index);
  95. Ok(Some(()))
  96. }
  97. },
  98. )
  99. }
  100. pub fn duplicate_field_rev(
  101. &mut self,
  102. field_id: &str,
  103. duplicated_field_id: &str,
  104. ) -> CollaborateResult<Option<GridRevisionChangeset>> {
  105. self.modify_grid(
  106. |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
  107. None => Ok(None),
  108. Some(index) => {
  109. let mut duplicate_field_rev = grid_meta.fields[index].as_ref().clone();
  110. duplicate_field_rev.id = duplicated_field_id.to_string();
  111. duplicate_field_rev.name = format!("{} (copy)", duplicate_field_rev.name);
  112. grid_meta.fields.insert(index + 1, Arc::new(duplicate_field_rev));
  113. Ok(Some(()))
  114. }
  115. },
  116. )
  117. }
  118. pub fn switch_to_field<B, T>(
  119. &mut self,
  120. field_id: &str,
  121. field_type: T,
  122. type_option_json_builder: B,
  123. ) -> CollaborateResult<Option<GridRevisionChangeset>>
  124. where
  125. B: FnOnce(&FieldTypeRevision) -> String,
  126. T: Into<FieldTypeRevision>,
  127. {
  128. let field_type = field_type.into();
  129. self.modify_grid(|grid_meta| {
  130. //
  131. match grid_meta.fields.iter_mut().find(|field_rev| field_rev.id == field_id) {
  132. None => {
  133. tracing::warn!("Can not find the field with id: {}", field_id);
  134. Ok(None)
  135. }
  136. Some(field_rev) => {
  137. let mut_field_rev = Arc::make_mut(field_rev);
  138. if mut_field_rev.get_type_option_str(field_type).is_none() {
  139. let type_option_json = type_option_json_builder(&field_type);
  140. mut_field_rev.insert_type_option_str(&field_type, type_option_json);
  141. }
  142. mut_field_rev.ty = field_type;
  143. Ok(Some(()))
  144. }
  145. }
  146. })
  147. }
  148. pub fn get_field_rev(&self, field_id: &str) -> Option<(usize, &Arc<FieldRevision>)> {
  149. self.grid_rev
  150. .fields
  151. .iter()
  152. .enumerate()
  153. .find(|(_, field)| field.id == field_id)
  154. }
  155. pub fn replace_field_rev(
  156. &mut self,
  157. field_rev: Arc<FieldRevision>,
  158. ) -> CollaborateResult<Option<GridRevisionChangeset>> {
  159. self.modify_grid(
  160. |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_rev.id) {
  161. None => Ok(None),
  162. Some(index) => {
  163. grid_meta.fields.remove(index);
  164. grid_meta.fields.insert(index, field_rev);
  165. Ok(Some(()))
  166. }
  167. },
  168. )
  169. }
  170. pub fn move_field(
  171. &mut self,
  172. field_id: &str,
  173. from_index: usize,
  174. to_index: usize,
  175. ) -> CollaborateResult<Option<GridRevisionChangeset>> {
  176. self.modify_grid(|grid_meta| {
  177. match move_vec_element(
  178. &mut grid_meta.fields,
  179. |field| field.id == field_id,
  180. from_index,
  181. to_index,
  182. )
  183. .map_err(internal_error)?
  184. {
  185. true => Ok(Some(())),
  186. false => Ok(None),
  187. }
  188. })
  189. }
  190. pub fn contain_field(&self, field_id: &str) -> bool {
  191. self.grid_rev.fields.iter().any(|field| field.id == field_id)
  192. }
  193. pub fn get_field_revs(&self, field_ids: Option<Vec<String>>) -> CollaborateResult<Vec<Arc<FieldRevision>>> {
  194. match field_ids {
  195. None => Ok(self.grid_rev.fields.clone()),
  196. Some(field_ids) => {
  197. let field_by_field_id = self
  198. .grid_rev
  199. .fields
  200. .iter()
  201. .map(|field| (&field.id, field))
  202. .collect::<HashMap<&String, &Arc<FieldRevision>>>();
  203. let fields = field_ids
  204. .iter()
  205. .flat_map(|field_id| match field_by_field_id.get(&field_id) {
  206. None => {
  207. tracing::error!("Can't find the field with id: {}", field_id);
  208. None
  209. }
  210. Some(field) => Some((*field).clone()),
  211. })
  212. .collect::<Vec<Arc<FieldRevision>>>();
  213. Ok(fields)
  214. }
  215. }
  216. }
  217. pub fn create_block_meta_rev(
  218. &mut self,
  219. block: GridBlockMetaRevision,
  220. ) -> CollaborateResult<Option<GridRevisionChangeset>> {
  221. self.modify_grid(|grid_meta| {
  222. if grid_meta.blocks.iter().any(|b| b.block_id == block.block_id) {
  223. tracing::warn!("Duplicate grid block");
  224. Ok(None)
  225. } else {
  226. match grid_meta.blocks.last() {
  227. None => grid_meta.blocks.push(Arc::new(block)),
  228. Some(last_block) => {
  229. if last_block.start_row_index > block.start_row_index
  230. && last_block.len() > block.start_row_index
  231. {
  232. let msg = "GridBlock's start_row_index should be greater than the last_block's start_row_index and its len".to_string();
  233. return Err(CollaborateError::internal().context(msg))
  234. }
  235. grid_meta.blocks.push(Arc::new(block));
  236. }
  237. }
  238. Ok(Some(()))
  239. }
  240. })
  241. }
  242. pub fn get_block_meta_revs(&self) -> Vec<Arc<GridBlockMetaRevision>> {
  243. self.grid_rev.blocks.clone()
  244. }
  245. pub fn update_block_rev(
  246. &mut self,
  247. changeset: GridBlockMetaRevisionChangeset,
  248. ) -> CollaborateResult<Option<GridRevisionChangeset>> {
  249. let block_id = changeset.block_id.clone();
  250. self.modify_block(&block_id, |block| {
  251. let mut is_changed = None;
  252. if let Some(row_count) = changeset.row_count {
  253. block.row_count = row_count;
  254. is_changed = Some(());
  255. }
  256. if let Some(start_row_index) = changeset.start_row_index {
  257. block.start_row_index = start_row_index;
  258. is_changed = Some(());
  259. }
  260. Ok(is_changed)
  261. })
  262. }
  263. pub fn md5(&self) -> String {
  264. md5(&self.delta.json_bytes())
  265. }
  266. pub fn delta_str(&self) -> String {
  267. self.delta.json_str()
  268. }
  269. pub fn delta_bytes(&self) -> Bytes {
  270. self.delta.json_bytes()
  271. }
  272. pub fn fields(&self) -> &[Arc<FieldRevision>] {
  273. &self.grid_rev.fields
  274. }
  275. fn modify_grid<F>(&mut self, f: F) -> CollaborateResult<Option<GridRevisionChangeset>>
  276. where
  277. F: FnOnce(&mut GridRevision) -> CollaborateResult<Option<()>>,
  278. {
  279. let cloned_grid = self.grid_rev.clone();
  280. match f(Arc::make_mut(&mut self.grid_rev))? {
  281. None => Ok(None),
  282. Some(_) => {
  283. let old = make_grid_rev_json_str(&cloned_grid)?;
  284. let new = self.json_str()?;
  285. match cal_diff::<PhantomAttributes>(old, new) {
  286. None => Ok(None),
  287. Some(delta) => {
  288. self.delta = self.delta.compose(&delta)?;
  289. Ok(Some(GridRevisionChangeset { delta, md5: self.md5() }))
  290. }
  291. }
  292. }
  293. }
  294. }
  295. fn modify_block<F>(&mut self, block_id: &str, f: F) -> CollaborateResult<Option<GridRevisionChangeset>>
  296. where
  297. F: FnOnce(&mut GridBlockMetaRevision) -> CollaborateResult<Option<()>>,
  298. {
  299. self.modify_grid(
  300. |grid_rev| match grid_rev.blocks.iter().position(|block| block.block_id == block_id) {
  301. None => {
  302. tracing::warn!("[GridMetaPad]: Can't find any block with id: {}", block_id);
  303. Ok(None)
  304. }
  305. Some(index) => {
  306. let block_rev = Arc::make_mut(&mut grid_rev.blocks[index]);
  307. f(block_rev)
  308. }
  309. },
  310. )
  311. }
  312. pub fn modify_field<F>(&mut self, field_id: &str, f: F) -> CollaborateResult<Option<GridRevisionChangeset>>
  313. where
  314. F: FnOnce(&mut FieldRevision) -> CollaborateResult<Option<()>>,
  315. {
  316. self.modify_grid(
  317. |grid_rev| match grid_rev.fields.iter().position(|field| field.id == field_id) {
  318. None => {
  319. tracing::warn!("[GridMetaPad]: Can't find any field with id: {}", field_id);
  320. Ok(None)
  321. }
  322. Some(index) => {
  323. let mut_field_rev = Arc::make_mut(&mut grid_rev.fields[index]);
  324. f(mut_field_rev)
  325. }
  326. },
  327. )
  328. }
  329. pub fn json_str(&self) -> CollaborateResult<String> {
  330. make_grid_rev_json_str(&self.grid_rev)
  331. }
  332. }
  333. pub fn make_grid_rev_json_str(grid_revision: &GridRevision) -> CollaborateResult<String> {
  334. let json = serde_json::to_string(grid_revision)
  335. .map_err(|err| internal_error(format!("Serialize grid to json str failed. {:?}", err)))?;
  336. Ok(json)
  337. }
  338. pub struct GridRevisionChangeset {
  339. pub delta: GridRevisionDelta,
  340. /// md5: the md5 of the grid after applying the change.
  341. pub md5: String,
  342. }
  343. pub fn make_grid_delta(grid_rev: &GridRevision) -> GridRevisionDelta {
  344. let json = serde_json::to_string(&grid_rev).unwrap();
  345. TextDeltaBuilder::new().insert(&json).build()
  346. }
  347. pub fn make_grid_revisions(user_id: &str, grid_rev: &GridRevision) -> RepeatedRevision {
  348. let delta = make_grid_delta(grid_rev);
  349. let bytes = delta.json_bytes();
  350. let revision = Revision::initial_revision(user_id, &grid_rev.grid_id, bytes);
  351. revision.into()
  352. }
  353. impl std::default::Default for GridRevisionPad {
  354. fn default() -> Self {
  355. let grid = GridRevision::new(&gen_grid_id());
  356. let delta = make_grid_delta(&grid);
  357. GridRevisionPad {
  358. grid_rev: Arc::new(grid),
  359. delta,
  360. }
  361. }
  362. }