@@ -10,6 +10,7 @@ import com.sakethh.linkora.domain.model.WebSocketEvent
1010import com.sakethh.linkora.domain.repository.FoldersRepo
1111import com.sakethh.linkora.domain.repository.MultiActionRepo
1212import com.sakethh.linkora.domain.tables.FoldersTable
13+ import com.sakethh.linkora.domain.tables.LinkTagTable
1314import com.sakethh.linkora.domain.tables.LinksTable
1415import com.sakethh.linkora.domain.tables.helper.TombStoneHelper
1516import com.sakethh.linkora.utils.checkForLWWConflictAndThrow
@@ -22,13 +23,11 @@ import kotlinx.serialization.encodeToString
2223import kotlinx.serialization.json.Json
2324import kotlinx.serialization.json.encodeToJsonElement
2425import org.jetbrains.exposed.v1.core.SqlExpressionBuilder.inList
25- import org.jetbrains.exposed.v1.core.and
26+ import org.jetbrains.exposed.v1.jdbc.batchInsert
2627import org.jetbrains.exposed.v1.jdbc.deleteWhere
27- import org.jetbrains.exposed.v1.jdbc.select
2828import org.jetbrains.exposed.v1.jdbc.selectAll
2929import org.jetbrains.exposed.v1.jdbc.transactions.transaction
3030import org.jetbrains.exposed.v1.jdbc.update
31- import java.time.Instant
3231
3332class MultiActionRepoImpl (
3433 private val foldersRepo : FoldersRepo
@@ -172,26 +171,33 @@ class MultiActionRepoImpl(
172171 override suspend fun copyMultipleItems (copyItemsDTO : CopyItemsDTO ): Result <CopyItemsHTTPResponseDTO > {
173172 return try {
174173 val eventTimestamp = getSystemEpochSeconds()
175- lateinit var linkIds : List <Long >
174+ lateinit var newGlobalSelectedLinkIds : List <Long >
176175 println (" Remote Links : ${copyItemsDTO.linkIds.values} " )
177176 // copy the links based on `copyItemsDTO.linkIds`
178177 val copiedFolderResponse = mutableListOf<CopiedFolderResponse >()
179178 transaction {
180- this .exec(
181- """
182- INSERT INTO links_table (last_modified,link_type,link_title,url,base_url,img_url,note,id_of_linked_folder,user_agent,media_type,marked_as_important)
183- SELECT $eventTimestamp AS last_modified,'${copyItemsDTO.linkType.name} ' AS link_type,link_title,url,base_url,img_url,note,${copyItemsDTO.newParentFolderId} AS id_of_linked_folder,user_agent,media_type,marked_as_important FROM links_table
184- WHERE id IN (${copyItemsDTO.linkIds.values.joinToString(separator = " ," )} );
185- """ .trimIndent()
186- )
187- linkIds = LinksTable .select(LinksTable .id).where {
188- LinksTable .lastModified.eq(eventTimestamp) and LinksTable .linkType.eq(copyItemsDTO.linkType.name) and LinksTable .idOfLinkedFolder.eq(
189- copyItemsDTO.newParentFolderId
190- )
191- }.map { resultRow ->
192- resultRow[LinksTable .id].value
179+ val sourceGlobalSelectedLinks = LinksTable .selectAll().where {
180+ LinksTable .id inList copyItemsDTO.linkIds.values
193181 }.toList()
194182
183+ newGlobalSelectedLinkIds = LinksTable .copy(
184+ source = sourceGlobalSelectedLinks,
185+ eventTimestamp = eventTimestamp,
186+ parentFolderId = copyItemsDTO.newParentFolderId,
187+ newLinkType = copyItemsDTO.linkType
188+ ).map {
189+ it[LinksTable .id].value
190+ }
191+
192+ val sourceGlobalSelectedLinksIds = sourceGlobalSelectedLinks.map {
193+ it[LinksTable .id].value
194+ }
195+
196+ val globalOldToNewLinkIdsMap = sourceGlobalSelectedLinksIds.zip(newGlobalSelectedLinkIds).toMap()
197+
198+ insertNewLinkTags(
199+ oldToNewLinkIdsMap = globalOldToNewLinkIdsMap
200+ )
195201
196202 // initially, we'll insert the root folders
197203 lateinit var copiedRootFolderIds: List <Long >
@@ -222,12 +228,23 @@ class MultiActionRepoImpl(
222228 val sourceLinksOfRootFolder = LinksTable .selectAll().where {
223229 LinksTable .idOfLinkedFolder.eq(folderId)
224230 }.toList()
231+ val sourceLinksIdsOfRootFolder = sourceLinksOfRootFolder.map {
232+ it[LinksTable .id].value
233+ }
225234 val eventTimestamp = getSystemEpochSeconds()
226- LinksTable .copy(
235+ val newRootFolderLinkIds = LinksTable .copy(
227236 source = sourceLinksOfRootFolder,
228237 eventTimestamp = eventTimestamp,
229238 parentFolderId = copiedRootFolderIds[folderIndex]
230- ).mapIndexed { linkResultRowIndex, resultRow ->
239+ )
240+
241+ insertNewLinkTags(
242+ oldToNewLinkIdsMap = sourceLinksIdsOfRootFolder.zip(newRootFolderLinkIds.map {
243+ it[LinksTable .id].value
244+ }).toMap()
245+ )
246+
247+ newRootFolderLinkIds.mapIndexed { linkResultRowIndex, resultRow ->
231248 FolderLink (
232249 localId = copyItemsDTO.folders[folderIndex].links[linkResultRowIndex].localId,
233250 remoteId = resultRow[LinksTable .id].value
@@ -251,29 +268,38 @@ class MultiActionRepoImpl(
251268 .forEachIndexed { insertedFolderRowIndex, insertedFolderRow ->
252269 val newParentFolderId = insertedFolderRow[FoldersTable .id].value
253270 val sourceParentFolderId = sourceFolders[insertedFolderRowIndex][FoldersTable .id].value
254-
255- LinksTable .selectAll().where {
271+ val sourceCurrentFolderLinks = LinksTable .selectAll().where {
256272 LinksTable .idOfLinkedFolder.eq(sourceParentFolderId)
273+ }
274+ val sourceCurrentFolderLinkIds = sourceCurrentFolderLinks.map {
275+ it[LinksTable .id].value
276+ }
277+ val newChildFolderLinks = LinksTable .copy(
278+ source = sourceCurrentFolderLinks.toList(),
279+ eventTimestamp = eventTimestamp,
280+ parentFolderId = newParentFolderId
281+ )
282+
283+ insertNewLinkTags(
284+ oldToNewLinkIdsMap = sourceCurrentFolderLinkIds.zip(newChildFolderLinks.map {
285+ it[LinksTable .id].value
286+ }).toMap()
287+ )
288+
289+ newChildFolderLinks.mapIndexed { insertedLinkRowIndex, insertedLinkRow ->
290+ FolderLink (
291+ localId = childFolders[insertedFolderRowIndex].links[insertedLinkRowIndex].localId,
292+ remoteId = insertedLinkRow[LinksTable .id].value
293+ )
257294 }.let {
258- LinksTable .copy(
259- source = it.toList(),
260- eventTimestamp = eventTimestamp,
261- parentFolderId = newParentFolderId
262- ).mapIndexed { insertedLinkRowIndex, insertedLinkRow ->
263- FolderLink (
264- localId = childFolders[insertedFolderRowIndex].links[insertedLinkRowIndex].localId,
265- remoteId = insertedLinkRow[LinksTable .id].value
266- )
267- }.let {
268- copiedFolderResponse.add(
269- CopiedFolderResponse (
270- currentFolder = CurrentFolder (
271- localId = childFolders[insertedFolderRowIndex].currentFolder.localId,
272- remoteId = newParentFolderId
273- ), links = it
274- )
295+ copiedFolderResponse.add(
296+ CopiedFolderResponse (
297+ currentFolder = CurrentFolder (
298+ localId = childFolders[insertedFolderRowIndex].currentFolder.localId,
299+ remoteId = newParentFolderId
300+ ), links = it
275301 )
276- }
302+ )
277303 }
278304 insertChildFolders(
279305 newParentFolderId, childFolders[insertedFolderRowIndex].childFolders
@@ -284,7 +310,7 @@ class MultiActionRepoImpl(
284310 // insert child folders
285311 copyItemsDTO.folders.forEachIndexed { index, parentFolder ->
286312 insertChildFolders(
287- copiedRootFolderIds[index], parentFolder.childFolders
313+ parentFolderId = copiedRootFolderIds[index], childFolders = parentFolder.childFolders
288314 )
289315 }
290316
@@ -293,7 +319,7 @@ class MultiActionRepoImpl(
293319 response = CopyItemsHTTPResponseDTO (
294320 folders = copiedFolderResponse.toList(), linkIds = copyItemsDTO.linkIds.run {
295321 this .toList().mapIndexed { index, pair ->
296- pair.first to linkIds [index]
322+ pair.first to newGlobalSelectedLinkIds [index]
297323 }.toMap()
298324 }, correlation = copyItemsDTO.correlation, eventTimestamp = eventTimestamp
299325 ), webSocketEvent = WebSocketEvent (
@@ -310,6 +336,30 @@ class MultiActionRepoImpl(
310336 }
311337 }
312338
339+ private fun insertNewLinkTags (oldToNewLinkIdsMap : Map <Long , Long >) {
340+ val eventTimestamp = getSystemEpochSeconds()
341+ val previousAssignedTags = LinkTagTable .selectAll().where {
342+ LinkTagTable .linkId inList oldToNewLinkIdsMap.keys
343+ }.groupBy {
344+ it[LinkTagTable .linkId]
345+ }.mapValues {
346+ it.value.map {
347+ it[LinkTagTable .tagId]
348+ }
349+ }
350+
351+ previousAssignedTags.forEach { (linkId, tagsIds) ->
352+ val newLinkId = oldToNewLinkIdsMap[linkId]
353+ if (newLinkId != null ) {
354+ LinkTagTable .batchInsert(tagsIds) {
355+ this [LinkTagTable .tagId] = it
356+ this [LinkTagTable .linkId] = newLinkId
357+ this [LinkTagTable .lastModified] = eventTimestamp
358+ }
359+ }
360+ }
361+ }
362+
313363 override suspend fun markItemsAsRegular (markItemsRegularDTO : MarkItemsRegularDTO ): Result <TimeStampBasedResponse > {
314364 return try {
315365 val eventTimestamp = getSystemEpochSeconds()
0 commit comments