906aedf09492a02ce75ee04ea84104e6d4575173
[ccsdk/cds.git] /
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.slf4j.LoggerFactory
25 import org.springframework.dao.DataIntegrityViolationException
26 import org.springframework.dao.EmptyResultDataAccessException
27 import org.springframework.stereotype.Service
28 import java.util.UUID
29
30 @Service
31 class TemplateResolutionService(private val templateResolutionRepository: TemplateResolutionRepository) {
32
33     private val log = LoggerFactory.getLogger(TemplateResolutionService::class.toString())
34
35     suspend fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
36         bluePrintRuntimeService: BluePrintRuntimeService<*>,
37         artifactPrefix: String,
38         resolutionKey: String
39     ): String =
40         withContext(Dispatchers.IO) {
41
42             val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
43
44             val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
45             val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
46
47             findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
48                 blueprintName,
49                 blueprintVersion,
50                 artifactPrefix,
51                 resolutionKey
52             )
53         }
54
55     suspend fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
56         blueprintName: String,
57         blueprintVersion: String,
58         artifactPrefix: String,
59         resolutionKey: String,
60         occurrence: Int = 1
61     ): String =
62         withContext(Dispatchers.IO) {
63
64             templateResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
65                 resolutionKey,
66                 blueprintName,
67                 blueprintVersion,
68                 artifactPrefix,
69                 occurrence
70             )?.result ?: throw EmptyResultDataAccessException(1)
71         }
72
73     suspend fun findResolutionKeysByBlueprintNameAndBlueprintVersionAndArtifactName(
74         bluePrintRuntimeService: BluePrintRuntimeService<*>,
75         artifactPrefix: String,
76         occurrence: Int = 1
77     ): List<String> =
78         withContext(Dispatchers.IO) {
79
80             val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
81
82             val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
83             val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
84
85             templateResolutionRepository.findResolutionKeysByBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
86                 blueprintName,
87                 blueprintVersion,
88                 artifactPrefix,
89                 occurrence
90             ) ?: throw EmptyResultDataAccessException(1)
91         }
92
93     suspend fun findArtifactNamesAndResolutionKeysByBlueprintNameAndBlueprintVersion(
94         bluePrintRuntimeService: BluePrintRuntimeService<*>,
95         occurrence: Int = 1
96     ): Map<String, List<String>> =
97         withContext(Dispatchers.IO) {
98
99             val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
100
101             val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
102             val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
103
104             val resultList = templateResolutionRepository.findArtifactNamesAndResolutionKeysByBlueprintNameAndBlueprintVersionAndOccurrence(
105                 blueprintName,
106                 blueprintVersion,
107                 occurrence
108             ) ?: throw EmptyResultDataAccessException(1)
109
110             var resultMap: MutableMap<String, MutableList<String>> = mutableMapOf()
111
112             resultList.forEach { it ->
113                 if (!resultMap.containsKey(it.getArtifactName())) {
114                     resultMap[it.getArtifactName()] = mutableListOf(it.getResolutionKey())
115                 } else {
116                     resultMap[it.getArtifactName()]!!.add(it.getResolutionKey())
117                 }
118             }
119             resultMap
120                 .mapValues { it.value.toList() }
121                 .toMap()
122         }
123
124     suspend fun findByResoureIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactName(
125         blueprintName: String,
126         blueprintVersion: String,
127         artifactPrefix: String,
128         resourceId: String,
129         resourceType: String,
130         occurrence: Int = 1
131     ): String =
132         withContext(Dispatchers.IO) {
133
134             templateResolutionRepository.findByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
135                 resourceId,
136                 resourceType,
137                 blueprintName,
138                 blueprintVersion,
139                 artifactPrefix,
140                 occurrence
141             )?.result!!
142         }
143
144     suspend fun write(
145         properties: Map<String, Any>,
146         result: String,
147         bluePrintRuntimeService: BluePrintRuntimeService<*>,
148         artifactPrefix: String
149     ): TemplateResolution = withContext(Dispatchers.IO) {
150
151         val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
152
153         val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
154         val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
155         val resolutionKey = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] as String
156         val resourceId = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] as String
157         val resourceType = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] as String
158         val occurrence = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] as Int
159         write(
160             blueprintName,
161             blueprintVersion,
162             artifactPrefix,
163             result,
164             occurrence,
165             resolutionKey,
166             resourceId,
167             resourceType
168         )
169     }
170
171     suspend fun write(
172         blueprintName: String,
173         blueprintVersion: String,
174         artifactPrefix: String,
175         template: String,
176         occurrence: Int = 1,
177         resolutionKey: String = "",
178         resourceId: String = "",
179         resourceType: String = ""
180     ): TemplateResolution =
181         withContext(Dispatchers.IO) {
182
183             val resourceResolutionResult = TemplateResolution()
184             resourceResolutionResult.id = UUID.randomUUID().toString()
185             resourceResolutionResult.artifactName = artifactPrefix
186             resourceResolutionResult.blueprintVersion = blueprintVersion
187             resourceResolutionResult.blueprintName = blueprintName
188             resourceResolutionResult.resolutionKey = resolutionKey
189             resourceResolutionResult.resourceId = resourceId
190             resourceResolutionResult.resourceType = resourceType
191             resourceResolutionResult.result = template
192             resourceResolutionResult.occurrence = occurrence
193
194             // Overwrite template resolution-key of resourceId/resourceType already existant
195             if (resolutionKey.isNotEmpty()) {
196                 templateResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
197                     resolutionKey, blueprintName, blueprintVersion, artifactPrefix, occurrence
198                 )?.let {
199                     log.info(
200                         "Overwriting template resolution for blueprintName=($blueprintVersion), blueprintVersion=($blueprintName), " +
201                             "artifactName=($artifactPrefix) and resolutionKey=($resolutionKey)"
202                     )
203                     templateResolutionRepository.deleteByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
204                         resolutionKey,
205                         blueprintName,
206                         blueprintVersion,
207                         artifactPrefix,
208                         occurrence
209                     )
210                 }
211             } else if (resourceId.isNotEmpty() && resourceType.isNotEmpty()) {
212                 templateResolutionRepository.findByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
213                     resourceId, resourceType, blueprintName, blueprintVersion, artifactPrefix, occurrence
214                 )?.let {
215                     log.info(
216                         "Overwriting template resolution for blueprintName=($blueprintVersion), blueprintVersion=($blueprintName), " +
217                             "artifactName=($artifactPrefix), resourceId=($resourceId) and resourceType=($resourceType)"
218                     )
219                     templateResolutionRepository.deleteByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
220                         resourceId,
221                         resourceType,
222                         blueprintName,
223                         blueprintVersion,
224                         artifactPrefix,
225                         occurrence
226                     )
227                 }
228             }
229             try {
230                 log.info(
231                     "Writing out template_resolution result: bpName: $blueprintName bpVer $blueprintVersion resKey:$resolutionKey" +
232                         " (resourceId: $resourceId resourceType: $resourceType) occurrence:$occurrence"
233                 )
234                 templateResolutionRepository.saveAndFlush(resourceResolutionResult)
235             } catch (ex: DataIntegrityViolationException) {
236                 log.error(
237                     "Error writing out template_resolution result: bpName: $blueprintName bpVer $blueprintVersion resKey:$resolutionKey" +
238                         " (resourceId: $resourceId resourceType: $resourceType) occurrence:$occurrence error: {}",
239                     ex.message
240                 )
241                 throw BluePrintException("Failed to store resource api result.", ex)
242             }
243         }
244     /**
245      * This returns the templates of first N 'occurrences'.
246      *
247      * @param blueprintName
248      * @param blueprintVersion
249      * @param artifactPrefix
250      * @param resolutionKey
251      * @param firstN
252      */
253     suspend fun findFirstNOccurrences(
254         blueprintName: String,
255         blueprintVersion: String,
256         artifactPrefix: String,
257         resolutionKey: String,
258         firstN: Int
259     ): Map<Int, List<TemplateResolution>> = withContext(Dispatchers.IO) {
260
261         templateResolutionRepository.findFirstNOccurrences(
262             resolutionKey,
263             blueprintName,
264             blueprintVersion,
265             artifactPrefix,
266             firstN
267         ).groupBy(TemplateResolution::occurrence).toSortedMap(reverseOrder())
268     }
269
270     /**
271      * This returns the templates of last N 'occurrences'.
272      *
273      * @param blueprintName
274      * @param blueprintVersion
275      * @param artifactPrefix
276      * @param resolutionKey
277      * @param lastN
278      */
279     suspend fun findLastNOccurrences(
280         blueprintName: String,
281         blueprintVersion: String,
282         artifactPrefix: String,
283         resolutionKey: String,
284         lastN: Int
285     ): Map<Int, List<TemplateResolution>> = withContext(Dispatchers.IO) {
286
287         templateResolutionRepository.findLastNOccurrences(
288             resolutionKey,
289             blueprintName,
290             blueprintVersion,
291             artifactPrefix,
292             lastN
293         ).groupBy(TemplateResolution::occurrence).toSortedMap(reverseOrder())
294     }
295
296     /**
297      * This returns the templates with 'occurrence' value between begin and end.
298      *
299      * @param blueprintName
300      * @param blueprintVersion
301      * @param artifactPrefix
302      * @param resolutionKey
303      * @param begin
304      * @param end
305      */
306     suspend fun findOccurrencesWithinRange(
307         blueprintName: String,
308         blueprintVersion: String,
309         artifactPrefix: String,
310         resolutionKey: String,
311         begin: Int,
312         end: Int
313     ): Map<Int, List<TemplateResolution>> = withContext(Dispatchers.IO) {
314
315         templateResolutionRepository.findOccurrencesWithinRange(
316             resolutionKey,
317             blueprintName,
318             blueprintVersion,
319             artifactPrefix,
320             begin,
321             end
322         ).groupBy(TemplateResolution::occurrence).toSortedMap(reverseOrder())
323     }
324
325     suspend fun readWithResolutionKey(
326         blueprintName: String,
327         blueprintVersion: String,
328         artifactPrefix: String,
329         resolutionKey: String
330     ): List<TemplateResolution> = withContext(Dispatchers.IO) {
331
332         templateResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
333             resolutionKey,
334             blueprintName,
335             blueprintVersion,
336             artifactPrefix
337         )
338     }
339 }