Add endpoint for deleting templates

Issue-ID: CCSDK-3735
Signed-off-by: Jozsef Csongvai <jozsef.csongvai@bell.ca>
Signed-off-by: kuldipr <kuldip.rai@amdocs.com>
Change-Id: I80d0da87651933da103e79d878902da743bb134e
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionRepository.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionRepository.kt
index 0d8946e..1ee9f79 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionRepository.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionRepository.kt
@@ -16,6 +16,7 @@
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db
 
 import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.data.jpa.repository.Modifying
 import org.springframework.data.jpa.repository.Query
 import org.springframework.data.repository.query.Param
 import org.springframework.stereotype.Repository
@@ -162,4 +163,69 @@
         artifactName: String,
         occurrence: Int
     )
+
+    @Transactional
+    fun deleteByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactName(
+        resourceId: String,
+        resourceType: String,
+        blueprintName: String,
+        blueprintVersion: String,
+        artifactName: String
+    ): Int
+
+    @Transactional
+    fun deleteByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+        key: String,
+        blueprintName: String,
+        blueprintVersion: String,
+        artifactName: String
+    ): Int
+
+    @Transactional
+    @Modifying
+    @Query(
+        value = """
+        DELETE FROM TEMPLATE_RESOLUTION WHERE resolution_key = :resolutionKey
+            AND blueprint_name = :blueprintName AND blueprint_version = :blueprintVersion
+            AND artifact_name = :artifactName
+            AND occurrence > (
+                SELECT MAX(occurrence) - :lastN FROM TEMPLATE_RESOLUTION
+                WHERE resolution_key = :resolutionKey AND blueprint_name = :blueprintName
+                    AND blueprint_version = :blueprintVersion AND artifact_name = :artifactName
+                )
+    """,
+        nativeQuery = true
+    )
+    fun deleteTemplates(
+        blueprintName: String,
+        blueprintVersion: String,
+        artifactName: String,
+        resolutionKey: String,
+        lastN: Int
+    ): Int
+
+    @Transactional
+    @Modifying
+    @Query(
+        value = """
+        DELETE FROM TEMPLATE_RESOLUTION WHERE resource_type = :resourceType
+            AND resource_id = :resourceId AND artifact_name = :artifactName
+            AND blueprint_name = :blueprintName AND blueprint_version = :blueprintVersion
+            AND occurrence > (
+                SELECT MAX(occurrence) - :lastN FROM TEMPLATE_RESOLUTION
+                WHERE resource_type = :resourceType
+                    AND resource_id = :resourceId AND blueprint_name = :blueprintName
+                    AND blueprint_version = :blueprintVersion AND artifact_name = :artifactName
+            )
+    """,
+        nativeQuery = true
+    )
+    fun deleteTemplates(
+        blueprintName: String,
+        blueprintVersion: String,
+        artifactName: String,
+        resourceType: String,
+        resourceId: String,
+        lastN: Int
+    ): Int
 }
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionService.kt
index 906aedf..af6d1ab 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionService.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionService.kt
@@ -25,6 +25,7 @@
 import org.springframework.dao.DataIntegrityViolationException
 import org.springframework.dao.EmptyResultDataAccessException
 import org.springframework.stereotype.Service
+import java.lang.IllegalArgumentException
 import java.util.UUID
 
 @Service
@@ -336,4 +337,55 @@
             artifactPrefix
         )
     }
+
+    suspend fun deleteTemplates(
+        blueprintName: String,
+        blueprintVersion: String,
+        artifactPrefix: String,
+        resolutionKey: String,
+        lastNOccurrences: Int?
+    ): Int = lastNOccurrences?.let {
+        if (lastNOccurrences < 0) {
+            throw IllegalArgumentException("last N occurrences must be a positive integer")
+        }
+        templateResolutionRepository.deleteTemplates(
+            blueprintName,
+            blueprintVersion,
+            artifactPrefix,
+            resolutionKey,
+            it
+        )
+    } ?: templateResolutionRepository.deleteByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+        resolutionKey,
+        blueprintName,
+        blueprintVersion,
+        artifactPrefix
+    )
+
+    suspend fun deleteTemplates(
+        blueprintName: String,
+        blueprintVersion: String,
+        artifactPrefix: String,
+        resourceType: String,
+        resourceId: String,
+        lastNOccurrences: Int?
+    ): Int = lastNOccurrences?.let {
+        if (lastNOccurrences < 0) {
+            throw IllegalArgumentException("last N occurrences must be a positive integer")
+        }
+        templateResolutionRepository.deleteTemplates(
+            blueprintName,
+            blueprintVersion,
+            artifactPrefix,
+            resourceType,
+            resourceId,
+            it
+        )
+    } ?: templateResolutionRepository.deleteByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactName(
+        resourceId,
+        resourceType,
+        blueprintName,
+        blueprintVersion,
+        artifactPrefix
+    )
 }
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionServiceTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionServiceTest.kt
index a2550ed..65304b2 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionServiceTest.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionServiceTest.kt
@@ -220,4 +220,48 @@
             assertEquals(tr, res)
         }
     }
+
+    @Test
+    fun deleteTemplatesResolutionKeyAll() {
+        every {
+            templateResolutionRepository.deleteByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(resolutionKey, blueprintName, blueprintVersion, artifactPrefix)
+        }.returns(1)
+        runBlocking {
+            val result = templateResolutionService.deleteTemplates(blueprintName, blueprintVersion, artifactPrefix, resolutionKey, null)
+            assertEquals(1, result)
+        }
+    }
+
+    @Test
+    fun deleteTemplatesResolutionKeyLastN() {
+        every {
+            templateResolutionRepository.deleteTemplates(blueprintName, blueprintVersion, artifactPrefix, resolutionKey, 1)
+        }.returns(1)
+        runBlocking {
+            val result = templateResolutionService.deleteTemplates(blueprintName, blueprintVersion, artifactPrefix, resolutionKey, 1)
+            assertEquals(1, result)
+        }
+    }
+
+    @Test
+    fun deleteTemplatesResourceIdAndTypeAll() {
+        every {
+            templateResolutionRepository.deleteByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactName(resourceId, resourceType, blueprintName, blueprintVersion, artifactPrefix)
+        }.returns(1)
+        runBlocking {
+            val result = templateResolutionService.deleteTemplates(blueprintName, blueprintVersion, artifactPrefix, resourceType, resourceId, null)
+            assertEquals(1, result)
+        }
+    }
+
+    @Test
+    fun deleteTemplatesResourceIdAndTypeLastN() {
+        every {
+            templateResolutionRepository.deleteTemplates(blueprintName, blueprintVersion, artifactPrefix, resourceType, resourceType, 1)
+        }.returns(1)
+        runBlocking {
+            val result = templateResolutionService.deleteTemplates(blueprintName, blueprintVersion, artifactPrefix, resourceType, resourceType, 1)
+            assertEquals(1, result)
+        }
+    }
 }
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt
index 03ba347..49e0313 100644
--- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt
@@ -255,4 +255,41 @@
 
         ResponseEntity.ok().body(resultStored)
     }
+
+    @RequestMapping(
+        path = [""],
+        method = [RequestMethod.DELETE], produces = [MediaType.APPLICATION_JSON_VALUE]
+    )
+    @PreAuthorize("hasRole('USER')")
+    fun deleteTemplates(
+        @ApiParam(value = "Name of the CBA", required = true)
+        @RequestParam(value = "bpName", required = true) bpName: String,
+        @ApiParam(value = "Version of the CBA", required = true)
+        @RequestParam(value = "bpVersion", required = true) bpVersion: String,
+        @ApiParam(value = "Artifact name", required = true)
+        @RequestParam(value = "artifactName", required = true, defaultValue = "") artifactName: String,
+        @ApiParam(value = "Resolution Key associated with the template", required = false)
+        @RequestParam(value = "resolutionKey", required = false) resolutionKey: String?,
+        @ApiParam(value = "resourceType associated with the template, must be used with resourceId", required = false)
+        @RequestParam(value = "resourceType", required = false) resourceType: String?,
+        @ApiParam(value = "Resolution Key associated with the template, must be used with resourceType", required = false)
+        @RequestParam(value = "resourceId", required = false) resourceId: String?,
+        @ApiParam(value = "Only delete last N occurrences", required = false)
+        @RequestParam(value = "lastN", required = false) lastN: Int?
+    ) = runBlocking {
+        when {
+            resolutionKey?.isNotBlank() == true -> templateResolutionService.deleteTemplates(
+                bpName, bpVersion, artifactName, resolutionKey, lastN
+            )
+            resourceType?.isNotBlank() == true && resourceId?.isNotBlank() == true ->
+                templateResolutionService.deleteTemplates(
+                    bpName, bpVersion, artifactName, resourceType, resourceId, lastN
+                )
+            else -> throw httpProcessorException(
+                ErrorCatalogCodes.REQUEST_NOT_FOUND,
+                ResourceApiDomains.RESOURCE_API,
+                "Either use resolutionKey or resourceType + resourceId. Values cannot be blank"
+            )
+        }.let { ResponseEntity.ok().body(DeleteResponse(it)) }
+    }
 }