2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2019 Bell Canada.
4 * Modifications Copyright © 2019 IBM.
5 * Modifications Copyright © 2019 Orange.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 package org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler
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.data.Workflow
43 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
44 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintEnhancerService
45 import org.onap.ccsdk.cds.controllerblueprints.core.logger
46 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
47 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
48 import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintCompileCache
49 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
50 import org.onap.ccsdk.cds.controllerblueprints.core.updateErrorMessage
51 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils
52 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
53 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
54 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
55 import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes
56 import org.onap.ccsdk.cds.error.catalog.core.utils.errorCauseOrDefault
57 import org.onap.ccsdk.cds.error.catalog.core.utils.errorMessageOrDefault
58 import org.springframework.core.io.ByteArrayResource
59 import org.springframework.core.io.Resource
60 import org.springframework.data.domain.Page
61 import org.springframework.data.domain.PageRequest
62 import org.springframework.data.domain.Pageable
63 import org.springframework.http.HttpHeaders
64 import org.springframework.http.MediaType
65 import org.springframework.http.ResponseEntity
66 import org.springframework.http.codec.multipart.FilePart
67 import org.springframework.stereotype.Service
68 import org.springframework.transaction.annotation.Transactional
70 import java.io.IOException
74 * BlueprintModelHandler Purpose: Handler service to handle the request from BlurPrintModelRest
76 * @author Brinda Santh
81 open class BluePrintModelHandler(
82 private val bluePrintDatabaseLoadService: BluePrintDatabaseLoadService,
83 private val blueprintsProcessorCatalogService: BluePrintCatalogService,
84 private val bluePrintLoadConfiguration: BluePrintLoadConfiguration,
85 private val blueprintModelSearchRepository: BlueprintModelSearchRepository,
86 private val blueprintModelRepository: BlueprintModelRepository,
87 private val blueprintModelContentRepository: BlueprintModelContentRepository,
88 private val bluePrintEnhancerService: BluePrintEnhancerService
91 private val log = logger(BluePrintModelHandler::class)
93 open suspend fun bootstrapBlueprint(bootstrapRequest: BootstrapRequest) {
95 "Bootstrap request with type load(${bootstrapRequest.loadModelType}), " +
96 "resource dictionary load(${bootstrapRequest.loadResourceDictionary}) and " +
97 "cba load(${bootstrapRequest.loadCBA})"
99 if (bootstrapRequest.loadModelType) {
100 bluePrintDatabaseLoadService.initModelTypes()
102 if (bootstrapRequest.loadResourceDictionary) {
103 bluePrintDatabaseLoadService.initResourceDictionary()
105 if (bootstrapRequest.loadCBA) {
106 bluePrintDatabaseLoadService.initBluePrintCatalog()
110 @Throws(BluePrintException::class)
111 private suspend fun getBlueprintCtxByNameAndVersion(blueprintName: String, version: String): BluePrintContext {
112 val basePath = blueprintsProcessorCatalogService.getFromDatabase(blueprintName, version)
113 log.info("blueprint base path $basePath for blueprint: $blueprintName version:$version")
114 return BluePrintMetadataUtils.getBluePrintContext(basePath.toString())
117 @Throws(BluePrintException::class)
119 * Try to get workflows cached from the BLUEPRINT_MODEL table first,
120 * failing that, load the CBA from the filesystem and extract workflows.
121 * The second case is possible during update scenario - current CDS DB already contains desired CBAs and reupload
124 open suspend fun getWorkflowsFromRepository(name: String, version: String): Map<String, Workflow> {
125 var workflowsFromCache: Map<String, Workflow>
127 workflowsFromCache = blueprintModelRepository.findByArtifactNameAndArtifactVersion(name, version)?.workflows!!
128 if (workflowsFromCache.isEmpty()) {
129 log.info("findByArtifactNameAndArtifactVersion did not return list of workflows for blueprintName:($name) version:($version), falling back to loading CBA from filesystem.")
130 workflowsFromCache = getBlueprintCtxByNameAndVersion(name, version).workflows()!!
131 // TODO: does it make sense to update the BLUEPRINT_MODEL workflows in this case or just wait for CBA reupload?
133 } catch (e: Exception) {
134 throw BluePrintException("Failed to get workflows from DB cache or by reading CBA", e)
136 return workflowsFromCache
139 // lookup workflows list from field.
140 open suspend fun getWorkflowNamesFromRepository(name: String, version: String): Set<String> {
141 return getWorkflowsFromRepository(name, version).keys
144 @Throws(BluePrintException::class)
145 open suspend fun prepareWorkFlowSpec(req: WorkFlowSpecRequest): WorkFlowSpecResponse {
146 val basePath = blueprintsProcessorCatalogService.getFromDatabase(req.blueprintName, req.version)
147 log.info("blueprint base path $basePath")
149 val blueprintContext = BluePrintMetadataUtils.getBluePrintContext(basePath.toString())
150 val workFlow = blueprintContext.workflowByName(req.workflowName)
152 val wfRes = WorkFlowSpecResponse()
153 wfRes.blueprintName = req.blueprintName
154 wfRes.version = req.version
156 val workFlowData = WorkFlowData()
157 workFlowData.workFlowName = req.workflowName
158 workFlowData.inputs = workFlow.inputs
159 workFlowData.outputs = workFlow.outputs
161 if (workFlow.inputs != null) {
162 for ((k, v) in workFlow.inputs!!) {
163 addPropertyInfo(v, blueprintContext, wfRes)
167 if (workFlow.outputs != null) {
168 for ((k, v) in workFlow.outputs!!) {
169 addPropertyInfo(k, v, blueprintContext, wfRes)
173 wfRes.workFlowData = workFlowData
177 private fun addPropertyInfo(prop: PropertyDefinition, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
178 addDataType(prop.type, ctx, res)
179 if (prop.entrySchema != null && prop.entrySchema!!.type != null) {
180 addDataType(prop.entrySchema!!.type, ctx, res)
184 private fun addPropertyInfo(propName: String, prop: PropertyDefinition, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
185 updatePropertyInfo(propName, prop, ctx, res)
186 addDataType(prop.type, ctx, res)
187 if (prop.entrySchema != null && prop.entrySchema!!.type != null) {
188 addDataType(prop.entrySchema!!.type, ctx, res)
192 private fun updatePropertyInfo(name: String, prop: PropertyDefinition, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
193 if (prop.inputparam == null || prop.inputparam == false) {
194 var workflow = ctx.workflowByName(res.workFlowData.workFlowName)
195 for ((k, v) in workflow.steps!!) {
196 var arts = ctx.nodeTemplateArtifacts(v.target!!)
198 for ((k, v) in arts.entries!!) {
199 if (v.type == "artifact-mapping-resource") {
200 val file: String = v.file
201 val completePath = ctx.rootPath.plus(File.separator).plus(file)
202 val resourceAssignment = JacksonUtils.getListFromFile(completePath, ResourceAssignment::class.java)
203 for (res in resourceAssignment) {
204 if (res.name == name && res.inputParameter) {
205 prop.inputparam = true
216 private fun addDataType(name: String, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
217 var data = ctx.dataTypeByName(name)
219 res.dataTypes?.put(name, data)
220 addParentDataType(data, ctx, res)
224 private fun addParentDataType(data: DataType, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
225 if (data.properties != null) {
226 for ((k, v) in data.properties!!) {
227 addPropertyInfo(k, v, ctx, res)
232 // wrap CBA workflows list in WorkflowsResponse object
233 @Throws(BluePrintException::class)
234 open suspend fun getWorkflowNames(name: String, version: String): WorkFlowsResponse {
235 var workflows = getWorkflowsFromRepository(name, version)
236 if (workflows == null) throw httpProcessorException(
237 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
238 "Failed to find workflows list for blueprint: ($name) version: ($version) from filesystem."
241 var res = WorkFlowsResponse()
242 res.blueprintName = name
243 res.version = version
244 res.workflows = workflows.keys.toMutableSet()
249 * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
251 * @return List<BlueprintModelSearch> list of the controller blueprint archives
252 </BlueprintModelSearch> */
253 open fun allBlueprintModel(): List<BlueprintModelSearch> {
254 return blueprintModelSearchRepository.findAll()
258 * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
260 * @return List<BlueprintModelSearch> list of the controller blueprint archives
261 </BlueprintModelSearch> */
262 open fun allBlueprintModel(pageRequest: Pageable): Page<BlueprintModelSearch> {
263 return blueprintModelSearchRepository.findAll(pageRequest)
267 * This is a saveBlueprintModel method
269 * @param filePart filePart
270 * @return Mono<BlueprintModelSearch>
271 * @throws BluePrintException BluePrintException
272 </BlueprintModelSearch> */
273 @Throws(BluePrintException::class)
274 open suspend fun saveBlueprintModel(filePart: FilePart): BlueprintModelSearch {
276 return upload(filePart, false)
277 } catch (e: IOException) {
278 log.error("saveBlueprintModel fails ${e.message}", e)
279 throw httpProcessorException(
280 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
281 "Error in Save CBA: ${e.message}", e.errorCauseOrDefault()
287 * This is a searchBlueprintModels method
290 * @return List<BlueprintModelSearch>
291 </BlueprintModelSearch> */
292 open fun searchBlueprintModels(tags: String): List<BlueprintModelSearch> {
293 return blueprintModelSearchRepository.findByTagsContainingIgnoreCase(tags)
297 * This is a getBlueprintModelSearchByNameAndVersion method
300 * @param version version
301 * @return BlueprintModelSearch
302 * @throws BluePrintException BluePrintException
304 @Throws(BluePrintException::class)
305 open fun getBlueprintModelSearchByNameAndVersion(name: String, version: String): BlueprintModelSearch? {
306 return blueprintModelSearchRepository.findByArtifactNameAndArtifactVersion(name, version)
307 /*?: throw BluePrintException(
308 ErrorCode.RESOURCE_NOT_FOUND.value,
309 String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
314 * This is a downloadBlueprintModelFileByNameAndVersion method to download a Blueprint by Name and Version
317 * @param version version
318 * @return ResponseEntity<Resource>
319 * @throws BluePrintException BluePrintException
321 @Throws(BluePrintException::class)
322 open fun downloadBlueprintModelFileByNameAndVersion(
325 ): ResponseEntity<Resource> {
327 val archiveByteArray = download(name, version)
328 val fileName = "${name}_$version.zip"
329 return prepareResourceEntity(fileName, archiveByteArray)
330 } catch (e: BluePrintProcessorException) {
331 e.http(ErrorCatalogCodes.RESOURCE_NOT_FOUND)
332 val errorMsg = "Error while downloading the CBA file by Blueprint Name ($name) and Version ($version)."
333 throw e.updateErrorMessage(
334 DesignerApiDomains.DESIGNER_API, errorMsg,
335 "Wrong resource definition or resolution failed."
341 * This is a downloadBlueprintModelFile method to find the target file to download and return a file resource
343 * @return ResponseEntity<Resource>
344 * @throws BluePrintException BluePrintException
346 @Throws(BluePrintException::class)
347 open fun downloadBlueprintModelFile(id: String): ResponseEntity<Resource> {
348 val blueprintModel: BlueprintModel
350 blueprintModel = getBlueprintModel(id)
351 } catch (e: BluePrintException) {
352 throw httpProcessorException(
353 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
354 "Error while downloading the CBA file: couldn't get blueprint modelby ID ($id)",
355 e.errorCauseOrDefault()
359 val fileName = "${blueprintModel.artifactName}_${blueprintModel.artifactVersion}.zip"
360 val file = blueprintModel.blueprintModelContent?.content
361 ?: throw httpProcessorException(
362 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
363 "Error while downloading the CBA file: couldn't get model content"
365 return prepareResourceEntity(fileName, file)
369 * @return ResponseEntity<Resource>
371 private fun prepareResourceEntity(fileName: String, file: ByteArray): ResponseEntity<Resource> {
372 return ResponseEntity.ok()
373 .contentType(MediaType.parseMediaType("text/plain"))
374 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$fileName\"")
375 .body(ByteArrayResource(file))
379 * This is a getBlueprintModel method
382 * @return BlueprintModel
383 * @throws BluePrintException BluePrintException
385 @Throws(BluePrintException::class)
386 open fun getBlueprintModel(id: String): BlueprintModel {
387 val blueprintModel: BlueprintModel
388 val dbBlueprintModel = blueprintModelRepository.findById(id)
389 if (dbBlueprintModel.isPresent) {
390 blueprintModel = dbBlueprintModel.get()
392 val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
393 throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg)
395 return blueprintModel
399 * This is a getBlueprintModelByNameAndVersion method
402 * @param version version
403 * @return BlueprintModel
404 * @throws BluePrintException BluePrintException
406 @Throws(BluePrintException::class)
407 open fun getBlueprintModelByNameAndVersion(name: String, version: String): BlueprintModel {
408 val blueprintModel = blueprintModelRepository
409 .findByArtifactNameAndArtifactVersion(name, version)
410 if (blueprintModel != null) {
411 return blueprintModel
413 val msg = String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
414 throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg)
419 * This is a getBlueprintModelSearch method
422 * @return BlueprintModelSearch
423 * @throws BluePrintException BluePrintException
425 @Throws(BluePrintException::class)
426 open fun getBlueprintModelSearch(id: String): BlueprintModelSearch {
427 return blueprintModelSearchRepository.findById(id)
428 ?: throw httpProcessorException(
429 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
430 String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
435 * This is a searchBluePrintModelsByKeyWord method to retrieve specific BlueprintModel in Database
436 * where keyword equals updatedBy or tags or artifcat name or artifcat version or artifact type
437 * @author Shaaban Ebrahim
440 * @return List<BlueprintModelSearch> list of the controller blueprint
441 </BlueprintModelSearch> */
442 open fun searchBluePrintModelsByKeyWord(keyWord: String): List<BlueprintModelSearch> {
443 return blueprintModelSearchRepository.findByUpdatedByOrTagsOrOrArtifactNameOrOrArtifactVersionOrArtifactType(
444 keyWord, keyWord, keyWord, keyWord, keyWord
449 * This is a searchBluePrintModelsByKeyWordPagebale method to retrieve specific BlueprintModel in Database
450 * where keyword equals updatedBy or tags or artifcat name or artifcat version or artifact type and pageable
451 * @author Shaaban Ebrahim
454 * @return List<BlueprintModelSearch> list of the controller blueprint
455 </BlueprintModelSearch> */
456 open fun searchBluePrintModelsByKeyWordPaged(keyWord: String, pageRequest: PageRequest): Page<BlueprintModelSearch> {
457 return blueprintModelSearchRepository.findByUpdatedByContainingIgnoreCaseOrTagsContainingIgnoreCaseOrArtifactNameContainingIgnoreCaseOrArtifactVersionContainingIgnoreCaseOrArtifactTypeContainingIgnoreCase(
468 * This is a deleteBlueprintModel method
471 * @throws BluePrintException BluePrintException
474 @Throws(BluePrintException::class)
475 open fun deleteBlueprintModel(id: String) {
476 val dbBlueprintModel = blueprintModelRepository.findById(id)
477 if (dbBlueprintModel.isPresent) {
478 blueprintModelContentRepository.deleteByBlueprintModel(dbBlueprintModel.get())
479 blueprintModelRepository.delete(dbBlueprintModel.get())
481 val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
482 throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg)
486 open suspend fun deleteBlueprintModel(name: String, version: String) {
487 blueprintsProcessorCatalogService.deleteFromDatabase(name, version)
491 * This is a CBA enrichBlueprint method
492 * Save the Zip File in archive location and extract the cba content.
493 * Populate the Enhancement Location
494 * Enhance the CBA content
495 * Compress the Enhanced Content
496 * Return back the the compressed content back to the caller.
498 * @param filePart filePart
499 * @return ResponseEntity<Resource>
500 * @throws BluePrintException BluePrintException
502 @Throws(BluePrintException::class)
503 open suspend fun enrichBlueprint(filePart: FilePart): ResponseEntity<Resource> {
505 val enhancedByteArray = enrichBlueprintFileSource(filePart)
506 return BluePrintEnhancerUtils.prepareResourceEntity("enhanced-cba.zip", enhancedByteArray)
507 } catch (e: BluePrintProcessorException) {
508 e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
509 val errorMsg = "Error while enhancing the CBA package."
510 throw e.updateErrorMessage(
511 DesignerApiDomains.DESIGNER_API, errorMsg,
512 "Wrong CBA file provided, please verify and enrich Again."
514 } catch (e: Exception) {
515 throw httpProcessorException(
516 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
517 "EnrichBlueprint: ${e.message}", e.errorCauseOrDefault()
523 * This is a publishBlueprintModel method to change the status published to YES
524 * NOTE: this method is meant for enriched blueprints only.
526 * @param filePart filePart
527 * @return BlueprintModelSearch
528 * @throws BluePrintException BluePrintException
530 @Throws(BluePrintException::class)
531 open suspend fun publishBlueprint(filePart: FilePart): BlueprintModelSearch {
533 return upload(filePart, true)
534 } catch (e: BluePrintProcessorException) {
535 e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
536 val errorMsg = "Error in Publishing CBA."
537 throw e.updateErrorMessage(
538 DesignerApiDomains.DESIGNER_API, errorMsg,
539 "Wrong CBA provided, please verify and enrich your CBA."
541 } catch (e: Exception) {
542 throw httpProcessorException(
543 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
544 "Error in Publishing CBA: ${e.message}", e.errorCauseOrDefault()
550 * Enrich and publish the blueprint.
551 * NOTE: this method is meant for the unenriched vs publishBlueprint(filePart)
552 * which is used for enriched blueprints.
554 * @param filePart filePart
555 * @return BlueprintModelSearch
556 * @throws BluePrintException BluePrintException
558 @Throws(BluePrintException::class)
559 open suspend fun enrichAndPublishBlueprint(filePart: FilePart): BlueprintModelSearch {
561 val enhancedByteArray = enrichBlueprintFileSource(filePart)
562 return upload(enhancedByteArray, true)
563 } catch (e: BluePrintProcessorException) {
564 val errorMsg = "Error while enhancing and uploading the CBA package."
565 log.error(errorMsg, e)
566 e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
567 throw e.updateErrorMessage(
568 DesignerApiDomains.DESIGNER_API, errorMsg,
569 "Wrong CBA file provided, please verify the source CBA."
571 } catch (e: Exception) {
572 log.error("Error enriching/uploading CBA", e)
573 throw httpProcessorException(
574 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
575 "EnrichBlueprint: ${e.message}", e.errorCauseOrDefault()
580 /** Common CBA Save and Publish function for RestController and GRPC Handler, the [fileSource] may be
581 * byteArray or File Part type.*/
582 open suspend fun upload(fileSource: Any, validate: Boolean): BlueprintModelSearch {
583 val saveId = UUID.randomUUID().toString()
584 val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, saveId)
585 val blueprintWorking = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId)
587 val compressedFile = normalizedFile(blueprintArchive, "cba.zip")
589 is FilePart -> BluePrintEnhancerUtils.filePartAsFile(fileSource, compressedFile)
590 is ByteArray -> BluePrintEnhancerUtils.byteArrayAsFile(fileSource, compressedFile)
592 // Save the Copied file to Database
593 val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(saveId, compressedFile, validate)
595 return blueprintModelSearchRepository.findById(blueprintId)
596 ?: throw httpProcessorException(
597 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
598 String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, blueprintId)
600 } catch (e: BluePrintException) {
601 e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
602 val errorMsg = "Error in Upload CBA."
603 throw e.updateErrorMessage(
604 DesignerApiDomains.DESIGNER_API, errorMsg,
605 "Wrong enriched CBA."
607 } catch (e: IOException) {
608 throw httpProcessorException(
609 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
610 "Error in Upload CBA: ${e.errorMessageOrDefault()}", e.errorCauseOrDefault()
613 // Clean blueprint script cache
614 val cacheKey = BluePrintFileUtils
615 .compileCacheKey(normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId))
616 BluePrintCompileCache.cleanClassLoader(cacheKey)
617 deleteNBDir(blueprintArchive)
618 deleteNBDir(blueprintWorking)
622 /** Common CBA download function for RestController and GRPC Handler, the [fileSource] may be
623 * byteArray or File Part type.*/
624 open fun download(name: String, version: String): ByteArray {
626 val blueprintModel = getBlueprintModelByNameAndVersion(name, version)
627 return blueprintModel.blueprintModelContent?.content
628 ?: throw httpProcessorException(
629 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
630 "Error while downloading the CBA file: couldn't get model content"
632 } catch (e: BluePrintException) {
633 e.http(ErrorCatalogCodes.RESOURCE_NOT_FOUND)
634 val errorMsg = "Fail to get Blueprint Model content."
635 throw e.updateErrorMessage(
636 DesignerApiDomains.DESIGNER_API, errorMsg,
637 "Wrong name and version was provide."
642 /** Common CBA Enrich function for RestController and GRPC Handler, the [fileSource] may be
643 * byteArray or File Part type.*/
644 open suspend fun enrichBlueprintFileSource(fileSource: Any): ByteArray {
645 val enhanceId = UUID.randomUUID().toString()
646 val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, enhanceId)
647 val blueprintWorkingDir = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, enhanceId)
651 BluePrintEnhancerUtils
652 .copyFilePartToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
654 BluePrintEnhancerUtils
655 .copyByteArrayToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
656 } // Enhance the Blue Prints
657 bluePrintEnhancerService.enhance(blueprintWorkingDir)
659 return BluePrintEnhancerUtils.compressEnhanceDirAndReturnByteArray(blueprintWorkingDir, blueprintArchive)
660 } catch (e: BluePrintException) {
661 e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
662 val errorMsg = "Fail Enriching the CBA."
663 throw e.updateErrorMessage(DesignerApiDomains.DESIGNER_API, errorMsg)
664 } catch (e: IOException) {
665 throw httpProcessorException(
666 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
667 "Error while Enriching the CBA file.", e.errorCauseOrDefault()
670 BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir)
676 private const val BLUEPRINT_MODEL_ID_FAILURE_MSG = "failed to get blueprint model id(%s) from repo"
677 private const val BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG = "failed to get blueprint model by name(%s)" + " and version(%s) from repo"