@@ -6,29 +6,31 @@ import com.sakethh.linkora.domain.Result
66import com.sakethh.linkora.domain.Route
77import com.sakethh.linkora.domain.dto.*
88import com.sakethh.linkora.domain.dto.folder.MarkItemsRegularDTO
9+ import com.sakethh.linkora.domain.model.Folder
910import com.sakethh.linkora.domain.model.WebSocketEvent
1011import com.sakethh.linkora.domain.repository.FoldersRepo
1112import com.sakethh.linkora.domain.repository.MultiActionRepo
1213import com.sakethh.linkora.domain.tables.FoldersTable
14+ import com.sakethh.linkora.domain.tables.FoldersTable.folderName
15+ import com.sakethh.linkora.domain.tables.FoldersTable.isFolderArchived
16+ import com.sakethh.linkora.domain.tables.FoldersTable.lastModified
17+ import com.sakethh.linkora.domain.tables.FoldersTable.note
18+ import com.sakethh.linkora.domain.tables.FoldersTable.parentFolderID
1319import com.sakethh.linkora.domain.tables.LinkTagTable
1420import com.sakethh.linkora.domain.tables.LinksTable
1521import com.sakethh.linkora.domain.tables.helper.TombStoneHelper
1622import com.sakethh.linkora.utils.checkForLWWConflictAndThrow
17- import com.sakethh.linkora.utils.insertNewLinks
18- import com.sakethh.linkora.utils.insertNewFolders
1923import com.sakethh.linkora.utils.getSystemEpochSeconds
24+ import com.sakethh.linkora.utils.insertNewLinks
2025import kotlinx.coroutines.async
2126import kotlinx.coroutines.awaitAll
2227import kotlinx.coroutines.coroutineScope
2328import kotlinx.serialization.encodeToString
2429import kotlinx.serialization.json.Json
2530import kotlinx.serialization.json.encodeToJsonElement
2631import org.jetbrains.exposed.v1.core.SqlExpressionBuilder.inList
27- import org.jetbrains.exposed.v1.jdbc.batchInsert
28- import org.jetbrains.exposed.v1.jdbc.deleteWhere
29- import org.jetbrains.exposed.v1.jdbc.selectAll
32+ import org.jetbrains.exposed.v1.jdbc.*
3033import org.jetbrains.exposed.v1.jdbc.transactions.transaction
31- import org.jetbrains.exposed.v1.jdbc.update
3234
3335class MultiActionRepoImpl (
3436 private val foldersRepo : FoldersRepo
@@ -46,7 +48,7 @@ class MultiActionRepoImpl(
4648 FoldersTable .checkForLWWConflictAndThrow(
4749 id = archiveMultipleItemsDTO.folderIds.last(),
4850 timeStamp = archiveMultipleItemsDTO.eventTimestamp,
49- lastModifiedColumn = FoldersTable . lastModified
51+ lastModifiedColumn = lastModified
5052 )
5153 }
5254 val eventTimestamp = getSystemEpochSeconds()
@@ -127,7 +129,7 @@ class MultiActionRepoImpl(
127129 FoldersTable .checkForLWWConflictAndThrow(
128130 id = moveItemsDTO.folderIds.last(),
129131 timeStamp = moveItemsDTO.eventTimestamp,
130- lastModifiedColumn = FoldersTable . lastModified
132+ lastModifiedColumn = lastModified
131133 )
132134 }
133135 if (moveItemsDTO.linkIds.isNotEmpty()) {
@@ -175,6 +177,8 @@ class MultiActionRepoImpl(
175177 lateinit var globalLinksOldToNewIdsMap: Map <Long , Long >
176178 val copiedFolderResponse = mutableListOf<CopiedFolderResponse >()
177179 transaction {
180+
181+ // 1. Copy the root links that aren't connected to anything
178182 val sourceGlobalSelectedLinks = LinksTable .selectAll().where {
179183 LinksTable .id inList copyItemsDTO.linkIds.values
180184 }.toList()
@@ -188,126 +192,98 @@ class MultiActionRepoImpl(
188192
189193 insertNewLinkTags(oldToNewLinkIdsMap = globalLinksOldToNewIdsMap)
190194
191- // initially, we'll insert the root folders
192- val sourceRootFolders = FoldersTable .selectAll().where {
193- FoldersTable .id.inList(copyItemsDTO.folders.map { it.currentFolder.remoteId })
194- }.toList()
195+ val localToNewFolderCreationMap = mutableMapOf<Long , Long >() // local to remote
195196
196- val copiedRootFolderOldToNewIdsMap = FoldersTable .insertNewFolders(
197- source = sourceRootFolders,
198- eventTimestamp = eventTimestamp,
199- parentFolderId = copyItemsDTO.newParentFolderId
200- )
197+ copyItemsDTO.folders.forEach { (currentFolder, links) ->
201198
202- copyItemsDTO.folders.forEach { (currentFolder, _, _) ->
203- copiedFolderResponse.add(
204- CopiedFolderResponse (
205- currentFolder = CurrentFolder (
206- localId = currentFolder.localId,
207- remoteId = copiedRootFolderOldToNewIdsMap.getValue(currentFolder.remoteId)
208- ), links = emptyList()
199+ val sourceFolder = FoldersTable .selectAll().where {
200+ FoldersTable .id.eq(currentFolder.sourceRemoteId)
201+ }.limit(1 ).map {
202+ Folder (
203+ id = it[FoldersTable .id].value,
204+ name = it[folderName],
205+ note = it[note],
206+ parentFolderId = it[parentFolderID],
207+ isArchived = it[isFolderArchived],
208+ eventTimestamp = it[lastModified]
209209 )
210- )
211- }
212-
213- // insert links of root folders
214- copyItemsDTO.folders.forEachIndexed { folderIndex, folder ->
215- val sourceLinksOfRootFolder = LinksTable .selectAll().where {
216- LinksTable .id.inList(folder.links.map { it.remoteId })
217- }.toList()
218-
219- val newRootFolderLinkIds = LinksTable .insertNewLinks(
220- source = sourceLinksOfRootFolder,
221- eventTimestamp = eventTimestamp,
222- parentFolderId = copiedRootFolderOldToNewIdsMap[folder.currentFolder.remoteId]
223- )
224-
225- insertNewLinkTags(oldToNewLinkIdsMap = newRootFolderLinkIds)
210+ }.first()
226211
227- val folderLinks = folder.links.mapNotNull {
228- val newRemoteId = newRootFolderLinkIds[it.remoteId]
229- if (newRemoteId != null ) {
230- FolderLink (localId = it.localId, remoteId = newRemoteId)
231- } else {
232- println (" folder.links.mapNotNull hit null" )
233- null
234- }
212+ val parentFolderOfCopiedFolder = if (currentFolder.isRootFolderForTheDestination) {
213+ copyItemsDTO.newParentFolderId
214+ } else {
215+ localToNewFolderCreationMap.getOrElse(
216+ key = currentFolder.parentOfNewlyCopiedLocalId, defaultValue = {
217+ null
218+ })
235219 }
236- copiedFolderResponse[folderIndex] = copiedFolderResponse[folderIndex].copy(
237- links = folderLinks
238- )
239- }
240-
241- fun insertChildFolders (
242- parentFolderId : Long ,
243- childFolders : List <CopyFolderDTO >,
244- ) {
245- val sourceFolders = FoldersTable .selectAll().where {
246- FoldersTable .id.inList(childFolders.map { it.currentFolder.remoteId })
247- }.toList()
248220
249- val oldToNewChildFolderMap =
250- FoldersTable .insertNewFolders(source = sourceFolders, eventTimestamp, parentFolderId)
221+ val copiedFolderId = FoldersTable .insertAndGetId { folder ->
222+ folder[lastModified] = eventTimestamp
223+ folder[folderName] = sourceFolder.name
224+ folder[note] = sourceFolder.note
225+ folder[parentFolderID] = parentFolderOfCopiedFolder
226+ folder[isFolderArchived] = sourceFolder.isArchived
227+ }.value
251228
252- childFolders.forEach { childFolder ->
253- val oldFolderId = childFolder.currentFolder.remoteId
254- val newFolderId = oldToNewChildFolderMap.getValue(oldFolderId)
229+ localToNewFolderCreationMap[currentFolder.newlyCopiedLocalId] = copiedFolderId
255230
256- val sourceCurrentFolderLinks = LinksTable .selectAll().where {
257- LinksTable .id.inList(childFolder.links.map { it.remoteId })
258- }
259- val newChildFolderLinksMap = LinksTable .insertNewLinks(
260- source = sourceCurrentFolderLinks.toList(),
261- eventTimestamp = eventTimestamp,
262- parentFolderId = newFolderId
263- )
231+ val sourceLinks = LinksTable .selectAll().where {
232+ LinksTable .id.inList(links.map {
233+ it.sourceRemoteId
234+ })
235+ }.toList()
264236
265- insertNewLinkTags(oldToNewLinkIdsMap = newChildFolderLinksMap)
237+ val oldToNewLinkIdsMap = LinksTable .insertNewLinks(
238+ source = sourceLinks,
239+ eventTimestamp = eventTimestamp,
240+ parentFolderId = copiedFolderId,
241+ newLinkType = LinkType .FOLDER_LINK
242+ )
266243
267- val folderLinks = childFolder.links.mapNotNull { link ->
268- val newRemoteId = newChildFolderLinksMap[link.remoteId]
269- if (newRemoteId != null ) {
270- FolderLink (localId = link.localId, remoteId = newRemoteId)
271- } else {
272- println (" childFolder.links.mapNotNull hit null" )
273- null
274- }
275- }
244+ insertNewLinkTags(oldToNewLinkIdsMap)
276245
277- copiedFolderResponse.add(
278- CopiedFolderResponse (
279- currentFolder = CurrentFolder (
280- localId = childFolder.currentFolder.localId, remoteId = newFolderId
281- ), links = folderLinks
282- )
283- )
284- insertChildFolders(
285- parentFolderId = newFolderId, childFolder.childFolders
286- )
287- }
288- }
246+ copiedFolderResponse.add(
247+ CopiedFolderResponse (
248+ currentFolder = CurrentFolder (
249+ newlyCopiedLocalId = currentFolder.newlyCopiedLocalId,
250+ sourceRemoteId = copiedFolderId,
251+ sourceRemoteParentId = - 45454 , // the client doesn't give a damn about this value
252+ isRootFolderForTheDestination = false , // the client doesn't give a damn about this value
253+ parentOfNewlyCopiedLocalId = - 45454 , // the client doesn't give a damn about this value
254+ ), links = links.mapNotNull { link ->
255+ val newRemoteId =
256+ oldToNewLinkIdsMap[link.sourceRemoteId] ? : return @mapNotNull null
289257
290- // insert child folders
291- copyItemsDTO.folders.forEach { parentFolder ->
292- insertChildFolders(
293- parentFolderId = copiedRootFolderOldToNewIdsMap.getValue(parentFolder.currentFolder.remoteId),
294- childFolders = parentFolder.childFolders
258+ FolderLink (
259+ newlyCopiedLocalId = link.newlyCopiedLocalId,
260+ sourceRemoteId = newRemoteId,
261+ sourceRemoteParentId = - 454545 , // the client doesn't give a damn about this value
262+ isRootFolderForTheDestination = false , // the client doesn't give a damn about this value
263+ parentOfNewlyCopiedLocalId = - 45454 , // the client doesn't give a damn about this value
264+ )
265+ })
295266 )
296267 }
297268 }
298269 Result .Success (
299270 response = CopyItemsHTTPResponseDTO (
300271 folders = copiedFolderResponse.toList(),
301- linkIds = globalLinksOldToNewIdsMap,
272+ linkIds = copyItemsDTO.linkIds.mapNotNull { (localId, oldRemoteId) ->
273+ globalLinksOldToNewIdsMap[oldRemoteId]?.let { newRemoteId ->
274+ localId to newRemoteId
275+ }
276+ }.toMap(),
302277 correlation = copyItemsDTO.correlation,
303278 eventTimestamp = eventTimestamp
304- ), webSocketEvent = WebSocketEvent (
279+ ),
280+ webSocketEvent = WebSocketEvent (
305281 operation = Route .COPY_EXISTING_ITEMS .name, payload = Json .encodeToJsonElement(
306282 CopyItemsSocketResponseDTO (
307283 eventTimestamp = eventTimestamp, correlation = copyItemsDTO.correlation
308284 )
309285 )
310- )
286+ ),
311287 )
312288 } catch (e: Exception ) {
313289 Result .Failure (e)
@@ -345,7 +321,7 @@ class MultiActionRepoImpl(
345321 FoldersTable .checkForLWWConflictAndThrow(
346322 id = markItemsRegularDTO.foldersIds.random(),
347323 timeStamp = markItemsRegularDTO.eventTimestamp,
348- lastModifiedColumn = FoldersTable . lastModified
324+ lastModifiedColumn = lastModified
349325 )
350326 }
351327 if (markItemsRegularDTO.linkIds.isNotEmpty()) {
0 commit comments