Fixing Blueprint Typo's and docs
[ccsdk/cds.git] / ms / blueprintsprocessor / modules / inbounds / designer-api / src / main / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / designer / api / handler / BlueprintModelHandler.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2019 Bell Canada.
4  * Modifications Copyright © 2019 IBM.
5  * Modifications Copyright © 2019 Orange.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 package org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler
21
22 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.domain.BlueprintModel
23 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.domain.BlueprintModelSearch
24 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelContentRepository
25 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelRepository
26 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelSearchRepository
27 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.BootstrapRequest
28 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.DesignerApiDomains
29 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowData
30 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowSpecRequest
31 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowSpecResponse
32 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowsResponse
33 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.load.BlueprintDatabaseLoadService
34 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.utils.BlueprintEnhancerUtils
35 import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintException
36 import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintProcessorException
37 import org.onap.ccsdk.cds.controllerblueprints.core.config.BlueprintLoadConfiguration
38 import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType
39 import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
40 import org.onap.ccsdk.cds.controllerblueprints.core.deleteNBDir
41 import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException
42 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintCatalogService
43 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintEnhancerService
44 import org.onap.ccsdk.cds.controllerblueprints.core.logger
45 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
46 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
47 import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BlueprintCompileCache
48 import org.onap.ccsdk.cds.controllerblueprints.core.service.BlueprintContext
49 import org.onap.ccsdk.cds.controllerblueprints.core.updateErrorMessage
50 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BlueprintFileUtils
51 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BlueprintMetadataUtils
52 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
53 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
54 import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes
55 import org.onap.ccsdk.cds.error.catalog.core.utils.errorCauseOrDefault
56 import org.onap.ccsdk.cds.error.catalog.core.utils.errorMessageOrDefault
57 import org.springframework.core.io.ByteArrayResource
58 import org.springframework.core.io.Resource
59 import org.springframework.data.domain.Page
60 import org.springframework.data.domain.PageRequest
61 import org.springframework.data.domain.Pageable
62 import org.springframework.http.HttpHeaders
63 import org.springframework.http.MediaType
64 import org.springframework.http.ResponseEntity
65 import org.springframework.http.codec.multipart.FilePart
66 import org.springframework.stereotype.Service
67 import org.springframework.transaction.annotation.Transactional
68 import java.io.File
69 import java.io.IOException
70 import java.util.UUID
71
72 /**
73  * BlueprintModelHandler Purpose: Handler service to handle the request from BlurPrintModelRest
74  *
75  * @author Brinda Santh
76  * @version 1.0
77  */
78
79 @Service
80 open class BlueprintModelHandler(
81     private val bluePrintDatabaseLoadService: BlueprintDatabaseLoadService,
82     private val blueprintsProcessorCatalogService: BlueprintCatalogService,
83     private val bluePrintLoadConfiguration: BlueprintLoadConfiguration,
84     private val blueprintModelSearchRepository: BlueprintModelSearchRepository,
85     private val blueprintModelRepository: BlueprintModelRepository,
86     private val blueprintModelContentRepository: BlueprintModelContentRepository,
87     private val bluePrintEnhancerService: BlueprintEnhancerService
88 ) {
89
90     private val log = logger(BlueprintModelHandler::class)
91
92     open suspend fun bootstrapBlueprint(bootstrapRequest: BootstrapRequest) {
93         log.info(
94             "Bootstrap request with type load(${bootstrapRequest.loadModelType}), " +
95                 "resource dictionary load(${bootstrapRequest.loadResourceDictionary}) and " +
96                 "cba load(${bootstrapRequest.loadCBA})"
97         )
98         if (bootstrapRequest.loadModelType) {
99             bluePrintDatabaseLoadService.initModelTypes()
100         }
101         if (bootstrapRequest.loadResourceDictionary) {
102             bluePrintDatabaseLoadService.initResourceDictionary()
103         }
104         if (bootstrapRequest.loadCBA) {
105             bluePrintDatabaseLoadService.initBlueprintCatalog()
106         }
107     }
108
109     @Throws(BlueprintException::class)
110     open suspend fun prepareWorkFlowSpec(req: WorkFlowSpecRequest):
111         WorkFlowSpecResponse {
112             val basePath = blueprintsProcessorCatalogService.getFromDatabase(
113                 req
114                     .blueprintName,
115                 req.version
116             )
117             log.info("blueprint base path $basePath")
118
119             val blueprintContext = BlueprintMetadataUtils.getBlueprintContext(basePath.toString())
120             val workFlow = blueprintContext.workflowByName(req.workflowName)
121
122             val wfRes = WorkFlowSpecResponse()
123             wfRes.blueprintName = req.blueprintName
124             wfRes.version = req.version
125
126             val workFlowData = WorkFlowData()
127             workFlowData.workFlowName = req.workflowName
128             workFlowData.inputs = workFlow.inputs
129             workFlowData.outputs = workFlow.outputs
130             wfRes.workFlowData = workFlowData
131
132             if (workFlow.inputs != null) {
133                 for ((k, v) in workFlow.inputs!!) {
134                     addPropertyInfo(k, v, blueprintContext, wfRes)
135                 }
136             }
137
138             if (workFlow.outputs != null) {
139                 for ((k, v) in workFlow.outputs!!) {
140                     addPropertyInfo(k, v, blueprintContext, wfRes)
141                 }
142             }
143
144             return wfRes
145         }
146
147     private fun addPropertyInfo(propName: String, prop: PropertyDefinition, ctx: BlueprintContext, res: WorkFlowSpecResponse) {
148         updatePropertyInfo(propName, prop, ctx, res)
149         addDataType(prop.type, ctx, res)
150         if (prop.entrySchema != null && prop.entrySchema!!.type != null) {
151             addDataType(prop.entrySchema!!.type, ctx, res)
152         }
153     }
154
155     private fun updatePropertyInfo(name: String, prop: PropertyDefinition, ctx: BlueprintContext, res: WorkFlowSpecResponse) {
156         if (prop.inputparam == null || prop.inputparam == false) {
157             var workflow = ctx.workflowByName(res.workFlowData.workFlowName)
158             for ((k, v) in workflow.steps!!) {
159                 var arts = ctx.nodeTemplateArtifacts(v.target!!)
160                 if (arts != null) {
161                     for ((k, v) in arts.entries!!) {
162                         if (v.type == "artifact-mapping-resource") {
163                             val file: String = v.file
164                             val completePath = ctx.rootPath.plus(File.separator).plus(file)
165                             val resourceAssignment = JacksonUtils.getListFromFile(completePath, ResourceAssignment::class.java)
166                             for (res in resourceAssignment) {
167                                 if (res.name == name && res.inputParameter) {
168                                     prop.inputparam = true
169                                     return
170                                 }
171                             }
172                         }
173                     }
174                 }
175             }
176         }
177     }
178
179     private fun addDataType(name: String, ctx: BlueprintContext, res: WorkFlowSpecResponse) {
180         var data = ctx.dataTypeByName(name)
181         if (data != null) {
182             res.dataTypes?.put(name, data)
183             addParentDataType(data, ctx, res)
184         }
185     }
186
187     private fun addParentDataType(data: DataType, ctx: BlueprintContext, res: WorkFlowSpecResponse) {
188         if (data.properties != null) {
189             for ((k, v) in data.properties!!) {
190                 addPropertyInfo(k, v, ctx, res)
191             }
192         }
193     }
194
195     @Throws(BlueprintException::class)
196     open suspend fun getWorkflowNames(name: String, version: String): WorkFlowsResponse {
197         val basePath = blueprintsProcessorCatalogService.getFromDatabase(
198             name, version
199         )
200         log.info("blueprint base path $basePath")
201
202         var res = WorkFlowsResponse()
203         res.blueprintName = name
204         res.version = version
205
206         val blueprintContext = BlueprintMetadataUtils.getBlueprintContext(
207             basePath.toString()
208         )
209         if (blueprintContext.workflows() != null) {
210             res.workflows = blueprintContext.workflows()!!.keys
211         }
212         return res
213     }
214
215     /**
216      * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
217      *
218      * @return List<BlueprintModelSearch> list of the controller blueprint archives
219      </BlueprintModelSearch> */
220     open fun allBlueprintModel(): List<BlueprintModelSearch> {
221         return blueprintModelSearchRepository.findAll()
222     }
223
224     /**
225      * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
226      *
227      * @return List<BlueprintModelSearch> list of the controller blueprint archives
228      </BlueprintModelSearch> */
229     open fun allBlueprintModel(pageRequest: Pageable): Page<BlueprintModelSearch> {
230         return blueprintModelSearchRepository.findAll(pageRequest)
231     }
232
233     /**
234      * This is a saveBlueprintModel method
235      *
236      * @param filePart filePart
237      * @return Mono<BlueprintModelSearch>
238      * @throws BlueprintException BlueprintException
239      </BlueprintModelSearch> */
240     @Throws(BlueprintException::class)
241     open suspend fun saveBlueprintModel(filePart: FilePart): BlueprintModelSearch {
242         try {
243             return upload(filePart, false)
244         } catch (e: IOException) {
245             throw httpProcessorException(
246                 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
247                 "Error in Save CBA: ${e.message}", e.errorCauseOrDefault()
248             )
249         }
250     }
251
252     /**
253      * This is a searchBlueprintModels method
254      *
255      * @param tags tags
256      * @return List<BlueprintModelSearch>
257      </BlueprintModelSearch> */
258     open fun searchBlueprintModels(tags: String): List<BlueprintModelSearch> {
259         return blueprintModelSearchRepository.findByTagsContainingIgnoreCase(tags)
260     }
261
262     /**
263      * This is a getBlueprintModelSearchByNameAndVersion method
264      *
265      * @param name name
266      * @param version version
267      * @return BlueprintModelSearch
268      * @throws BlueprintException BlueprintException
269      */
270     @Throws(BlueprintException::class)
271     open fun getBlueprintModelSearchByNameAndVersion(name: String, version: String): BlueprintModelSearch? {
272         return blueprintModelSearchRepository.findByArtifactNameAndArtifactVersion(name, version)
273         /*?: throw BlueprintException(
274             ErrorCode.RESOURCE_NOT_FOUND.value,
275             String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
276         )*/
277     }
278
279     /**
280      * This is a downloadBlueprintModelFileByNameAndVersion method to download a Blueprint by Name and Version
281      *
282      * @param name name
283      * @param version version
284      * @return ResponseEntity<Resource>
285      * @throws BlueprintException BlueprintException
286      </Resource> */
287     @Throws(BlueprintException::class)
288     open fun downloadBlueprintModelFileByNameAndVersion(
289         name: String,
290         version: String
291     ): ResponseEntity<Resource> {
292         try {
293             val archiveByteArray = download(name, version)
294             val fileName = "${name}_$version.zip"
295             return prepareResourceEntity(fileName, archiveByteArray)
296         } catch (e: BlueprintProcessorException) {
297             e.http(ErrorCatalogCodes.RESOURCE_NOT_FOUND)
298             val errorMsg = "Error while downloading the CBA file by Blueprint Name ($name) and Version ($version)."
299             throw e.updateErrorMessage(
300                 DesignerApiDomains.DESIGNER_API, errorMsg,
301                 "Wrong resource definition or resolution failed."
302             )
303         }
304     }
305
306     /**
307      * This is a downloadBlueprintModelFile method to find the target file to download and return a file resource
308      *
309      * @return ResponseEntity<Resource>
310      * @throws BlueprintException BlueprintException
311      </Resource> */
312     @Throws(BlueprintException::class)
313     open fun downloadBlueprintModelFile(id: String): ResponseEntity<Resource> {
314         val blueprintModel: BlueprintModel
315         try {
316             blueprintModel = getBlueprintModel(id)
317         } catch (e: BlueprintException) {
318             throw httpProcessorException(
319                 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
320                 "Error while downloading the CBA file: couldn't get blueprint modelby ID ($id)",
321                 e.errorCauseOrDefault()
322             )
323         }
324
325         val fileName = "${blueprintModel.artifactName}_${blueprintModel.artifactVersion}.zip"
326         val file = blueprintModel.blueprintModelContent?.content
327             ?: throw httpProcessorException(
328                 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
329                 "Error while downloading the CBA file: couldn't get model content"
330             )
331         return prepareResourceEntity(fileName, file)
332     }
333
334     /**
335      * @return ResponseEntity<Resource>
336      </Resource> */
337     private fun prepareResourceEntity(fileName: String, file: ByteArray): ResponseEntity<Resource> {
338         return ResponseEntity.ok()
339             .contentType(MediaType.parseMediaType("text/plain"))
340             .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$fileName\"")
341             .body(ByteArrayResource(file))
342     }
343
344     /**
345      * This is a getBlueprintModel method
346      *
347      * @param id id
348      * @return BlueprintModel
349      * @throws BlueprintException BlueprintException
350      */
351     @Throws(BlueprintException::class)
352     open fun getBlueprintModel(id: String): BlueprintModel {
353         val blueprintModel: BlueprintModel
354         val dbBlueprintModel = blueprintModelRepository.findById(id)
355         if (dbBlueprintModel.isPresent) {
356             blueprintModel = dbBlueprintModel.get()
357         } else {
358             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
359             throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg)
360         }
361         return blueprintModel
362     }
363
364     /**
365      * This is a getBlueprintModelByNameAndVersion method
366      *
367      * @param name name
368      * @param version version
369      * @return BlueprintModel
370      * @throws BlueprintException BlueprintException
371      */
372     @Throws(BlueprintException::class)
373     open fun getBlueprintModelByNameAndVersion(name: String, version: String): BlueprintModel {
374         val blueprintModel = blueprintModelRepository
375             .findByArtifactNameAndArtifactVersion(name, version)
376         if (blueprintModel != null) {
377             return blueprintModel
378         } else {
379             val msg = String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
380             throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg)
381         }
382     }
383
384     /**
385      * This is a getBlueprintModelSearch method
386      *
387      * @param id id
388      * @return BlueprintModelSearch
389      * @throws BlueprintException BlueprintException
390      */
391     @Throws(BlueprintException::class)
392     open fun getBlueprintModelSearch(id: String): BlueprintModelSearch {
393         return blueprintModelSearchRepository.findById(id)
394             ?: throw httpProcessorException(
395                 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
396                 String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
397             )
398     }
399
400     /**
401      * This is a searchBlueprintModelsByKeyWord method to retrieve specific  BlueprintModel in Database
402      * where keyword equals updatedBy or tags or artifcat name or artifcat version or artifact type
403      * @author Shaaban Ebrahim
404      * @param keyWord
405      *
406      * @return List<BlueprintModelSearch> list of the controller blueprint
407      </BlueprintModelSearch> */
408     open fun searchBlueprintModelsByKeyWord(keyWord: String): List<BlueprintModelSearch> {
409         return blueprintModelSearchRepository.findByUpdatedByOrTagsOrOrArtifactNameOrOrArtifactVersionOrArtifactType(
410             keyWord, keyWord, keyWord, keyWord, keyWord
411         )
412     }
413
414     /**
415      * This is a searchBlueprintModelsByKeyWordPagebale method to retrieve specific  BlueprintModel in Database
416      * where keyword equals updatedBy or tags or artifcat name or artifcat version or artifact type and pageable
417      * @author Shaaban Ebrahim
418      * @param keyWord
419      *
420      * @return List<BlueprintModelSearch> list of the controller blueprint
421      </BlueprintModelSearch> */
422     open fun searchBlueprintModelsByKeyWordPaged(keyWord: String, pageRequest: PageRequest): Page<BlueprintModelSearch> {
423         return blueprintModelSearchRepository.findByUpdatedByContainingIgnoreCaseOrTagsContainingIgnoreCaseOrArtifactNameContainingIgnoreCaseOrArtifactVersionContainingIgnoreCaseOrArtifactTypeContainingIgnoreCase(
424             keyWord,
425             keyWord,
426             keyWord,
427             keyWord,
428             keyWord,
429             pageRequest
430         )
431     }
432
433     /**
434      * This is a deleteBlueprintModel method
435      *
436      * @param id id
437      * @throws BlueprintException BlueprintException
438      */
439     @Transactional
440     @Throws(BlueprintException::class)
441     open fun deleteBlueprintModel(id: String) {
442         val dbBlueprintModel = blueprintModelRepository.findById(id)
443         if (dbBlueprintModel.isPresent) {
444             blueprintModelContentRepository.deleteByBlueprintModel(dbBlueprintModel.get())
445             blueprintModelRepository.delete(dbBlueprintModel.get())
446         } else {
447             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
448             throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg)
449         }
450     }
451
452     open suspend fun deleteBlueprintModel(name: String, version: String) {
453         blueprintsProcessorCatalogService.deleteFromDatabase(name, version)
454     }
455
456     /**
457      * This is a CBA enrichBlueprint method
458      * Save the Zip File in archive location and extract the cba content.
459      * Populate the Enhancement Location
460      * Enhance the CBA content
461      * Compress the Enhanced Content
462      * Return back the the compressed content back to the caller.
463      *
464      * @param filePart filePart
465      * @return ResponseEntity<Resource>
466      * @throws BlueprintException BlueprintException
467      */
468     @Throws(BlueprintException::class)
469     open suspend fun enrichBlueprint(filePart: FilePart): ResponseEntity<Resource> {
470         try {
471             val enhancedByteArray = enrichBlueprintFileSource(filePart)
472             return BlueprintEnhancerUtils.prepareResourceEntity("enhanced-cba.zip", enhancedByteArray)
473         } catch (e: BlueprintProcessorException) {
474             e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
475             val errorMsg = "Error while enhancing the CBA package."
476             throw e.updateErrorMessage(
477                 DesignerApiDomains.DESIGNER_API, errorMsg,
478                 "Wrong CBA file provided, please verify and enrich Again."
479             )
480         } catch (e: Exception) {
481             throw httpProcessorException(
482                 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
483                 "EnrichBlueprint: ${e.message}", e.errorCauseOrDefault()
484             )
485         }
486     }
487
488     /**
489      * This is a publishBlueprintModel method to change the status published to YES
490      * NOTE: this method is meant for enriched blueprints only.
491      *
492      * @param filePart filePart
493      * @return BlueprintModelSearch
494      * @throws BlueprintException BlueprintException
495      */
496     @Throws(BlueprintException::class)
497     open suspend fun publishBlueprint(filePart: FilePart): BlueprintModelSearch {
498         try {
499             return upload(filePart, true)
500         } catch (e: BlueprintProcessorException) {
501             e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
502             val errorMsg = "Error in Publishing CBA."
503             throw e.updateErrorMessage(
504                 DesignerApiDomains.DESIGNER_API, errorMsg,
505                 "Wrong CBA provided, please verify and enrich your CBA."
506             )
507         } catch (e: Exception) {
508             throw httpProcessorException(
509                 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
510                 "Error in Publishing CBA: ${e.message}", e.errorCauseOrDefault()
511             )
512         }
513     }
514
515     /**
516      * Enrich and publish the blueprint.
517      * NOTE: this method is meant for the unenriched vs publishBlueprint(filePart)
518      *       which is used for enriched blueprints.
519      *
520      * @param filePart filePart
521      * @return BlueprintModelSearch
522      * @throws BlueprintException BlueprintException
523      */
524     @Throws(BlueprintException::class)
525     open suspend fun enrichAndPublishBlueprint(filePart: FilePart): BlueprintModelSearch {
526         try {
527             val enhancedByteArray = enrichBlueprintFileSource(filePart)
528             return upload(enhancedByteArray, true)
529         } catch (e: BlueprintProcessorException) {
530             e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
531             val errorMsg = "Error while enhancing and uploading the CBA package."
532             throw e.updateErrorMessage(
533                 DesignerApiDomains.DESIGNER_API, errorMsg,
534                 "Wrong CBA file provided, please verify the source CBA."
535             )
536         } catch (e: Exception) {
537             throw httpProcessorException(
538                 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
539                 "EnrichBlueprint: ${e.message}", e.errorCauseOrDefault()
540             )
541         }
542     }
543
544     /** Common CBA Save and Publish function for RestController and GRPC Handler, the [fileSource] may be
545      * byteArray or File Part type.*/
546     open suspend fun upload(fileSource: Any, validate: Boolean): BlueprintModelSearch {
547         val saveId = UUID.randomUUID().toString()
548         val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, saveId)
549         val blueprintWorking = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId)
550         try {
551             val compressedFile = normalizedFile(blueprintArchive, "cba.zip")
552             when (fileSource) {
553                 is FilePart -> BlueprintEnhancerUtils.filePartAsFile(fileSource, compressedFile)
554                 is ByteArray -> BlueprintEnhancerUtils.byteArrayAsFile(fileSource, compressedFile)
555             }
556             // Save the Copied file to Database
557             val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(saveId, compressedFile, validate)
558
559             return blueprintModelSearchRepository.findById(blueprintId)
560                 ?: throw httpProcessorException(
561                     ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
562                     String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, blueprintId)
563                 )
564         } catch (e: BlueprintException) {
565             e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
566             val errorMsg = "Error in Upload CBA."
567             throw e.updateErrorMessage(
568                 DesignerApiDomains.DESIGNER_API, errorMsg,
569                 "Wrong enriched CBA."
570             )
571         } catch (e: IOException) {
572             throw httpProcessorException(
573                 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
574                 "Error in Upload CBA: ${e.errorMessageOrDefault()}", e.errorCauseOrDefault()
575             )
576         } finally {
577             // Clean blueprint script cache
578             val cacheKey = BlueprintFileUtils
579                 .compileCacheKey(normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId))
580             BlueprintCompileCache.cleanClassLoader(cacheKey)
581             deleteNBDir(blueprintArchive)
582             deleteNBDir(blueprintWorking)
583         }
584     }
585
586     /** Common CBA download function for RestController and GRPC Handler, the [fileSource] may be
587      * byteArray or File Part type.*/
588     open fun download(name: String, version: String): ByteArray {
589         try {
590             val blueprintModel = getBlueprintModelByNameAndVersion(name, version)
591             return blueprintModel.blueprintModelContent?.content
592                 ?: throw httpProcessorException(
593                     ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
594                     "Error while downloading the CBA file: couldn't get model content"
595                 )
596         } catch (e: BlueprintException) {
597             e.http(ErrorCatalogCodes.RESOURCE_NOT_FOUND)
598             val errorMsg = "Fail to get Blueprint Model content."
599             throw e.updateErrorMessage(
600                 DesignerApiDomains.DESIGNER_API, errorMsg,
601                 "Wrong name and version was provide."
602             )
603         }
604     }
605
606     /** Common CBA Enrich function for RestController and GRPC Handler, the [fileSource] may be
607      * byteArray or File Part type.*/
608     open suspend fun enrichBlueprintFileSource(fileSource: Any): ByteArray {
609         val enhanceId = UUID.randomUUID().toString()
610         val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, enhanceId)
611         val blueprintWorkingDir = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, enhanceId)
612         try {
613             when (fileSource) {
614                 is FilePart ->
615                     BlueprintEnhancerUtils
616                         .copyFilePartToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
617                 is ByteArray ->
618                     BlueprintEnhancerUtils
619                         .copyByteArrayToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
620             } // Enhance the Blue Prints
621             bluePrintEnhancerService.enhance(blueprintWorkingDir)
622
623             return BlueprintEnhancerUtils.compressEnhanceDirAndReturnByteArray(blueprintWorkingDir, blueprintArchive)
624         } catch (e: BlueprintException) {
625             e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
626             val errorMsg = "Fail Enriching the CBA."
627             throw e.updateErrorMessage(DesignerApiDomains.DESIGNER_API, errorMsg)
628         } catch (e: IOException) {
629             throw httpProcessorException(
630                 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
631                 "Error while Enriching the CBA file.", e.errorCauseOrDefault()
632             )
633         } finally {
634             BlueprintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir)
635         }
636     }
637
638     companion object {
639
640         private const val BLUEPRINT_MODEL_ID_FAILURE_MSG = "failed to get blueprint model id(%s) from repo"
641         private const val BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG = "failed to get blueprint model by name(%s)" + " and version(%s) from repo"
642     }
643 }