4239abbab17306ccc4ed8a3dbfba2ebbfad5f34a
[ccsdk/cds.git] / ms / controllerblueprints / modules / service / src / main / kotlin / org / onap / ccsdk / apps / controllerblueprints / service / handler / BluePrintModelHandler.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2019 Bell Canada.
4  * Modifications Copyright © 2019 IBM.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 package org.onap.ccsdk.apps.controllerblueprints.service.handler
20
21 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException
22 import org.onap.ccsdk.apps.controllerblueprints.core.common.ApplicationConstants
23 import org.onap.ccsdk.apps.controllerblueprints.core.config.BluePrintLoadConfiguration
24 import org.onap.ccsdk.apps.controllerblueprints.core.data.ErrorCode
25 import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BluePrintCatalogService
26 import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BluePrintEnhancerService
27 import org.onap.ccsdk.apps.controllerblueprints.core.utils.BluePrintFileUtils
28 import org.onap.ccsdk.apps.controllerblueprints.service.domain.BlueprintModel
29 import org.onap.ccsdk.apps.controllerblueprints.service.domain.BlueprintModelSearch
30 import org.onap.ccsdk.apps.controllerblueprints.service.repository.ControllerBlueprintModelContentRepository
31 import org.onap.ccsdk.apps.controllerblueprints.service.repository.ControllerBlueprintModelRepository
32 import org.onap.ccsdk.apps.controllerblueprints.service.repository.ControllerBlueprintModelSearchRepository
33 import org.onap.ccsdk.apps.controllerblueprints.service.utils.BluePrintEnhancerUtils
34 import org.springframework.core.io.ByteArrayResource
35 import org.springframework.core.io.Resource
36 import org.springframework.http.HttpHeaders
37 import org.springframework.http.MediaType
38 import org.springframework.http.ResponseEntity
39 import org.springframework.http.codec.multipart.FilePart
40 import org.springframework.stereotype.Service
41 import org.springframework.transaction.annotation.Transactional
42 import reactor.core.publisher.Mono
43 import java.io.File
44 import java.io.IOException
45 import java.util.*
46
47 /**
48  * BlueprintModelHandler Purpose: Handler service to handle the request from BlurPrintModelRest
49  *
50  * @author Brinda Santh
51  * @version 1.0
52  */
53
54 @Service
55 open class BluePrintModelHandler(private val bluePrintCatalogService: BluePrintCatalogService,
56                                  private val bluePrintLoadConfiguration: BluePrintLoadConfiguration,
57                                  private val blueprintModelSearchRepository: ControllerBlueprintModelSearchRepository,
58                                  private val blueprintModelRepository: ControllerBlueprintModelRepository,
59                                  private val blueprintModelContentRepository: ControllerBlueprintModelContentRepository,
60                                  private val bluePrintEnhancerService: BluePrintEnhancerService) {
61
62     /**
63      * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
64      *
65      * @return List<BlueprintModelSearch> list of the controller blueprint archives
66     </BlueprintModelSearch> */
67     open fun allBlueprintModel(): List<BlueprintModelSearch> {
68         return blueprintModelSearchRepository.findAll()
69     }
70
71     /**
72      * This is a saveBlueprintModel method
73      *
74      * @param filePart filePart
75      * @return Mono<BlueprintModelSearch>
76      * @throws BluePrintException BluePrintException
77     </BlueprintModelSearch> */
78     @Throws(BluePrintException::class)
79     open fun saveBlueprintModel(filePart: FilePart): Mono<BlueprintModelSearch> {
80         try {
81             val cbaLocation = BluePrintFileUtils.getCbaStorageDirectory(bluePrintLoadConfiguration.blueprintArchivePath)
82             return BluePrintEnhancerUtils.saveCBAFile(filePart, cbaLocation).map { fileName ->
83                 var blueprintId: String? = null
84                 try {
85                     blueprintId = bluePrintCatalogService.saveToDatabase(cbaLocation.resolve(fileName).toFile(), false)
86                 } catch (e: BluePrintException) {
87                     // FIXME handle expection
88                 }
89                 blueprintModelSearchRepository.findById(blueprintId!!).get()
90             }
91         } catch (e: IOException) {
92             throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
93                     String.format("I/O Error while uploading the CBA file: %s", e.message), e)
94         }
95
96     }
97
98     /**
99      * This is a publishBlueprintModel method to change the status published to YES
100      *
101      * @param id id
102      * @return BlueprintModelSearch
103      * @throws BluePrintException BluePrintException
104      */
105     @Throws(BluePrintException::class)
106     open fun publishBlueprintModel(id: String): BlueprintModelSearch {
107         val blueprintModelSearch: BlueprintModelSearch
108         val dbBlueprintModel = blueprintModelSearchRepository.findById(id)
109         if (dbBlueprintModel.isPresent) {
110             blueprintModelSearch = dbBlueprintModel.get()
111         } else {
112             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
113             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
114         }
115         blueprintModelSearch.published = ApplicationConstants.ACTIVE_Y
116         return blueprintModelSearchRepository.saveAndFlush(blueprintModelSearch)
117     }
118
119     /**
120      * This is a searchBlueprintModels method
121      *
122      * @param tags tags
123      * @return List<BlueprintModelSearch>
124     </BlueprintModelSearch> */
125     open fun searchBlueprintModels(tags: String): List<BlueprintModelSearch> {
126         return blueprintModelSearchRepository.findByTagsContainingIgnoreCase(tags)
127     }
128
129     /**
130      * This is a getBlueprintModelSearchByNameAndVersion method
131      *
132      * @param name name
133      * @param version version
134      * @return BlueprintModelSearch
135      * @throws BluePrintException BluePrintException
136      */
137     @Throws(BluePrintException::class)
138     open fun getBlueprintModelSearchByNameAndVersion(name: String, version: String): BlueprintModelSearch {
139         val blueprintModelSearch: BlueprintModelSearch
140         val dbBlueprintModel = blueprintModelSearchRepository
141                 .findByArtifactNameAndArtifactVersion(name, version)
142         if (dbBlueprintModel.isPresent) {
143             blueprintModelSearch = dbBlueprintModel.get()
144         } else {
145             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
146                     String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version))
147         }
148         return blueprintModelSearch
149     }
150
151     /**
152      * This is a downloadBlueprintModelFileByNameAndVersion method to download a Blueprint by Name and Version
153      *
154      * @param name name
155      * @param version version
156      * @return ResponseEntity<Resource>
157      * @throws BluePrintException BluePrintException
158     </Resource> */
159     @Throws(BluePrintException::class)
160     open fun downloadBlueprintModelFileByNameAndVersion(name: String,
161                                                         version: String): ResponseEntity<Resource> {
162         val blueprintModel: BlueprintModel
163         try {
164             blueprintModel = getBlueprintModelByNameAndVersion(name, version)
165         } catch (e: BluePrintException) {
166             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, String.format("Error while " + "downloading the CBA file: %s", e.message), e)
167         }
168
169         val fileName = blueprintModel.id + ".zip"
170         val file = blueprintModel.blueprintModelContent.content
171         return prepareResourceEntity(fileName, file)
172     }
173
174     /**
175      * This is a downloadBlueprintModelFile method to find the target file to download and return a file resource
176      *
177      * @return ResponseEntity<Resource>
178      * @throws BluePrintException BluePrintException
179     </Resource> */
180     @Throws(BluePrintException::class)
181     open fun downloadBlueprintModelFile(id: String): ResponseEntity<Resource> {
182         val blueprintModel: BlueprintModel
183         try {
184             blueprintModel = getBlueprintModel(id)
185         } catch (e: BluePrintException) {
186             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, String.format("Error while " + "downloading the CBA file: %s", e.message), e)
187         }
188
189         val fileName = blueprintModel.id + ".zip"
190         val file = blueprintModel.blueprintModelContent.content
191         return prepareResourceEntity(fileName, file)
192     }
193
194     /**
195      * @return ResponseEntity<Resource>
196     </Resource> */
197     private fun prepareResourceEntity(fileName: String, file: ByteArray): ResponseEntity<Resource> {
198         return ResponseEntity.ok()
199                 .contentType(MediaType.parseMediaType("text/plain"))
200                 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$fileName\"")
201                 .body(ByteArrayResource(file))
202     }
203
204     /**
205      * This is a getBlueprintModel method
206      *
207      * @param id id
208      * @return BlueprintModel
209      * @throws BluePrintException BluePrintException
210      */
211     @Throws(BluePrintException::class)
212     open fun getBlueprintModel(id: String): BlueprintModel {
213         val blueprintModel: BlueprintModel
214         val dbBlueprintModel = blueprintModelRepository.findById(id)
215         if (dbBlueprintModel.isPresent) {
216             blueprintModel = dbBlueprintModel.get()
217         } else {
218             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
219             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
220         }
221         return blueprintModel
222     }
223
224     /**
225      * This is a getBlueprintModelByNameAndVersion method
226      *
227      * @param name name
228      * @param version version
229      * @return BlueprintModel
230      * @throws BluePrintException BluePrintException
231      */
232     @Throws(BluePrintException::class)
233     open fun getBlueprintModelByNameAndVersion(name: String, version: String): BlueprintModel {
234         val blueprintModel = blueprintModelRepository
235                 .findByArtifactNameAndArtifactVersion(name, version)
236         if (blueprintModel != null) {
237             return blueprintModel
238         } else {
239             val msg = String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
240             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
241         }
242     }
243
244     /**
245      * This is a getBlueprintModelSearch method
246      *
247      * @param id id
248      * @return BlueprintModelSearch
249      * @throws BluePrintException BluePrintException
250      */
251     @Throws(BluePrintException::class)
252     open fun getBlueprintModelSearch(id: String): BlueprintModelSearch {
253         val blueprintModelSearch: BlueprintModelSearch
254         val dbBlueprintModel = blueprintModelSearchRepository.findById(id)
255         if (dbBlueprintModel.isPresent) {
256             blueprintModelSearch = dbBlueprintModel.get()
257         } else {
258             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
259             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
260         }
261
262         return blueprintModelSearch
263     }
264
265     /**
266      * This is a deleteBlueprintModel method
267      *
268      * @param id id
269      * @throws BluePrintException BluePrintException
270      */
271     @Transactional
272     @Throws(BluePrintException::class)
273     open fun deleteBlueprintModel(id: String) {
274         val dbBlueprintModel = blueprintModelRepository.findById(id)
275         if (dbBlueprintModel.isPresent) {
276             blueprintModelContentRepository.deleteByBlueprintModel(dbBlueprintModel.get())
277             blueprintModelRepository.delete(dbBlueprintModel.get())
278         } else {
279             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
280             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
281         }
282     }
283
284     /**
285      * This is a CBA enrichBlueprint method
286      * Save the Zip File in archive location and extract the cba content.
287      * Populate the Enhancement Location
288      * Enhance the CBA content
289      * Compress the Enhanced Content
290      * Return back the the compressed content back to the caller.
291      *
292      * @param filePart filePart
293      * @return ResponseEntity<Resource>
294      * @throws BluePrintException BluePrintException
295      */
296     @Throws(BluePrintException::class)
297     open suspend fun enrichBlueprint(filePart: FilePart): ResponseEntity<Resource> {
298         val enhanceId = UUID.randomUUID().toString()
299         val blueprintArchive = bluePrintLoadConfiguration.blueprintArchivePath.plus(File.separator).plus(enhanceId)
300         val blueprintEnrichmentDir = bluePrintLoadConfiguration.blueprintEnrichmentPath.plus(File.separator).plus(enhanceId)
301
302         try {
303             BluePrintEnhancerUtils.decompressFilePart(filePart, blueprintArchive, blueprintEnrichmentDir)
304
305             // Enhance the Blue Prints
306             bluePrintEnhancerService.enhance(blueprintEnrichmentDir)
307
308             return BluePrintEnhancerUtils.compressToFilePart(blueprintEnrichmentDir, blueprintArchive)
309
310         } catch (e: IOException) {
311             throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
312                     String.format("I/O Error while uploading the CBA file: %s", e.message), e)
313         } finally {
314             BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintEnrichmentDir)
315         }
316     }
317
318     companion object {
319
320         private const val BLUEPRINT_MODEL_ID_FAILURE_MSG = "failed to get blueprint model id(%s) from repo"
321         private const val BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG = "failed to get blueprint model by name(%s)" + " and version(%s) from repo"
322     }
323 }