Merge "CCSDK-3684 ComponentRemotePYthonExecutor eliminate recursive call"
[ccsdk/cds.git] / ms / blueprintsprocessor / functions / resource-resolution / src / main / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / functions / resource / resolution / db / ResourceResolutionDBService.kt
1 /*
2  * Copyright (C) 2019 Bell Canada.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db
17
18 import kotlinx.coroutines.Dispatchers
19 import kotlinx.coroutines.withContext
20 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
21 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
22 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
23 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
24 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
25 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
26 import org.slf4j.LoggerFactory
27 import org.springframework.dao.EmptyResultDataAccessException
28 import org.springframework.stereotype.Service
29 import java.util.UUID
30
31 @Service
32 class ResourceResolutionDBService(private val resourceResolutionRepository: ResourceResolutionRepository) {
33
34     private val log = LoggerFactory.getLogger(ResourceResolutionDBService::class.toString())
35
36     suspend fun findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
37         bluePrintRuntimeService: BluePrintRuntimeService<*>,
38         key: String,
39         occurrence: Int,
40         artifactPrefix: String
41     ): List<ResourceResolution> {
42         return try {
43             val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
44
45             val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
46             val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
47
48             resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
49                 blueprintName,
50                 blueprintVersion,
51                 artifactPrefix,
52                 key,
53                 occurrence
54             )
55         } catch (e: EmptyResultDataAccessException) {
56             emptyList()
57         }
58     }
59
60     suspend fun findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
61         bluePrintRuntimeService: BluePrintRuntimeService<*>,
62         resourceId: String,
63         resourceType: String,
64         occurrence: Int,
65         artifactPrefix: String
66     ): List<ResourceResolution> {
67         return try {
68
69             val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
70
71             val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
72             val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
73
74             resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
75                 blueprintName,
76                 blueprintVersion,
77                 artifactPrefix,
78                 resourceId,
79                 resourceType,
80                 occurrence
81             )
82         } catch (e: EmptyResultDataAccessException) {
83             emptyList()
84         }
85     }
86
87     suspend fun readValue(
88         blueprintName: String,
89         blueprintVersion: String,
90         artifactPrefix: String,
91         resolutionKey: String,
92         name: String
93     ): ResourceResolution? = withContext(Dispatchers.IO) {
94
95         resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndName(
96             resolutionKey,
97             blueprintName,
98             blueprintVersion,
99             artifactPrefix,
100             name
101         )
102     }
103
104     suspend fun readWithResolutionKey(
105         blueprintName: String,
106         blueprintVersion: String,
107         artifactPrefix: String,
108         resolutionKey: String
109     ): List<ResourceResolution> = withContext(Dispatchers.IO) {
110
111         resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
112             resolutionKey,
113             blueprintName,
114             blueprintVersion,
115             artifactPrefix
116         )
117     }
118
119     /**
120      * This returns the resolutions of first N 'occurrences'.
121      *
122      * @param blueprintName
123      * @param blueprintVersion
124      * @param artifactPrefix
125      * @param resolutionKey
126      * @param firstN
127      */
128     suspend fun findFirstNOccurrences(
129         blueprintName: String,
130         blueprintVersion: String,
131         artifactPrefix: String,
132         resolutionKey: String,
133         firstN: Int
134     ): Map<Int, List<ResourceResolution>> = withContext(Dispatchers.IO) {
135
136         resourceResolutionRepository.findFirstNOccurrences(
137             resolutionKey,
138             blueprintName,
139             blueprintVersion,
140             artifactPrefix,
141             firstN
142         ).groupBy(ResourceResolution::occurrence).toSortedMap(reverseOrder())
143     }
144
145     /**
146      * This returns the resolutions of last N 'occurrences'.
147      *
148      * @param blueprintName
149      * @param blueprintVersion
150      * @param artifactPrefix
151      * @param resolutionKey
152      * @param lastN
153      */
154     suspend fun findLastNOccurrences(
155         blueprintName: String,
156         blueprintVersion: String,
157         artifactPrefix: String,
158         resolutionKey: String,
159         lastN: Int
160     ): Map<Int, List<ResourceResolution>> = withContext(Dispatchers.IO) {
161
162         resourceResolutionRepository.findLastNOccurrences(
163             resolutionKey,
164             blueprintName,
165             blueprintVersion,
166             artifactPrefix,
167             lastN
168         ).groupBy(ResourceResolution::occurrence).toSortedMap(reverseOrder())
169     }
170
171     /**
172      * This returns the resolutions with 'occurrence' value between begin and end.
173      *
174      * @param blueprintName
175      * @param blueprintVersion
176      * @param artifactPrefix
177      * @param resolutionKey
178      * @param begin
179      * @param end
180      */
181     suspend fun findOccurrencesWithinRange(
182         blueprintName: String,
183         blueprintVersion: String,
184         artifactPrefix: String,
185         resolutionKey: String,
186         begin: Int,
187         end: Int
188     ): Map<Int, List<ResourceResolution>> = withContext(Dispatchers.IO) {
189
190         resourceResolutionRepository.findOccurrencesWithinRange(
191             resolutionKey,
192             blueprintName,
193             blueprintVersion,
194             artifactPrefix,
195             begin,
196             end
197         ).groupBy(ResourceResolution::occurrence).toSortedMap(reverseOrder())
198     }
199
200     suspend fun readWithResourceIdAndResourceType(
201         blueprintName: String,
202         blueprintVersion: String,
203         resourceId: String,
204         resourceType: String
205     ): List<ResourceResolution> =
206         withContext(Dispatchers.IO) {
207
208             resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(
209                 blueprintName,
210                 blueprintVersion,
211                 resourceId,
212                 resourceType
213             )
214         }
215
216     suspend fun write(
217         properties: Map<String, Any>,
218         bluePrintRuntimeService: BluePrintRuntimeService<*>,
219         artifactPrefix: String,
220         resourceAssignment: ResourceAssignment
221     ): ResourceResolution = withContext(Dispatchers.IO) {
222
223         val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
224
225         val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
226         val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
227
228         val resolutionKey = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] as String
229         val resourceId = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] as String
230         val resourceType = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] as String
231         val occurrence = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] as Int
232
233         write(
234             blueprintName,
235             blueprintVersion,
236             resolutionKey,
237             resourceId,
238             resourceType,
239             artifactPrefix,
240             resourceAssignment,
241             occurrence
242         )
243     }
244
245     suspend fun write(
246         blueprintName: String,
247         blueprintVersion: String,
248         resolutionKey: String,
249         resourceId: String,
250         resourceType: String,
251         artifactPrefix: String,
252         resourceAssignment: ResourceAssignment,
253         occurrence: Int = 0
254     ): ResourceResolution = withContext(Dispatchers.IO) {
255
256         val resourceResolution = ResourceResolution()
257         resourceResolution.id = UUID.randomUUID().toString()
258         resourceResolution.artifactName = artifactPrefix
259         resourceResolution.occurrence = occurrence
260         resourceResolution.blueprintVersion = blueprintVersion
261         resourceResolution.blueprintName = blueprintName
262         resourceResolution.resolutionKey = resolutionKey
263         resourceResolution.resourceType = resourceType
264         resourceResolution.resourceId = resourceId
265         resourceResolution.value = resourceAssignment.property?.value?.let {
266             if (BluePrintConstants.STATUS_SUCCESS == resourceAssignment.status)
267                 JacksonUtils.getValue(it).toString()
268             else ""
269         } ?: ""
270         resourceResolution.name = resourceAssignment.name
271         resourceResolution.dictionaryName = resourceAssignment.dictionaryName
272         resourceResolution.dictionaryVersion = resourceAssignment.version
273         resourceResolution.dictionarySource = resourceAssignment.dictionarySource
274         resourceResolution.status = resourceAssignment.status ?: BluePrintConstants.STATUS_FAILURE
275
276         try {
277             resourceResolutionRepository.saveAndFlush(resourceResolution)
278         } catch (ex: Exception) {
279             throw BluePrintException("Failed to store resource resolution result.", ex)
280         }
281     }
282
283     /**
284      * This is a deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey method to delete resources
285      * associated to a specific resolution-key
286      *
287      * @param blueprintName name of the CBA
288      * @param blueprintVersion version of the CBA
289      * @param artifactName name of the artifact
290      * @param resolutionKey value of the resolution-key
291      */
292     suspend fun deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(
293         blueprintName: String,
294         blueprintVersion: String,
295         artifactName: String,
296         resolutionKey: String
297     ) {
298         resourceResolutionRepository.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(
299             blueprintName,
300             blueprintVersion,
301             artifactName,
302             resolutionKey
303         )
304     }
305
306     suspend fun deleteResourceResolutionList(listResourceResolution: List<ResourceResolution>) = withContext(Dispatchers.IO) {
307         try {
308             resourceResolutionRepository.deleteInBatch(listResourceResolution)
309         } catch (ex: Exception) {
310             throw BluePrintException("Failed to batch delete resource resolution", ex)
311         }
312     }
313
314     /**
315      * This method returns the (highest occurrence + 1) of resource resolutions if present in DB, returns 1 otherwise.
316      * The 'occurrence' is used to persist new resource resolution in the DB.
317      *
318      * @param resolutionKey
319      * @param blueprintName
320      * @param blueprintVersion
321      * @param artifactPrefix
322      */
323     suspend fun findNextOccurrenceByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
324         resolutionKey: String,
325         blueprintName: String,
326         blueprintVersion: String,
327         artifactPrefix: String
328     ) = withContext(Dispatchers.IO) {
329         val maxOccurrence = resourceResolutionRepository.findMaxOccurrenceByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
330             resolutionKey,
331             blueprintName,
332             blueprintVersion,
333             artifactPrefix
334         )
335         maxOccurrence?.inc() ?: 1
336     }
337
338     /**
339      * This method returns the (highest occurrence + 1) of resource resolutions if present in DB, returns 1 otherwise.
340      * The 'occurrence' is used to persist new resource resolution in the DB.
341      *
342      * @param blueprintName
343      * @param blueprintVersion
344      * @param resourceId
345      * @param resourceType
346      */
347     suspend fun findNextOccurrenceByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(
348         blueprintName: String,
349         blueprintVersion: String,
350         resourceId: String,
351         resourceType: String
352     ) = withContext(Dispatchers.IO) {
353         val maxOccurrence = resourceResolutionRepository.findMaxOccurrenceByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(
354             blueprintName,
355             blueprintVersion,
356             resourceId,
357             resourceType
358         )
359         maxOccurrence?.inc() ?: 1
360     }
361 }