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(k, 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(propName: String, prop: PropertyDefinition, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
178 updatePropertyInfo(propName, prop, ctx, res)
179 addDataType(prop.type, ctx, res)
180 if (prop.entrySchema != null && prop.entrySchema!!.type != null) {
181 addDataType(prop.entrySchema!!.type, ctx, res)
185 private fun updatePropertyInfo(name: String, prop: PropertyDefinition, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
186 if (prop.inputparam == null || prop.inputparam == false) {
187 var workflow = ctx.workflowByName(res.workFlowData.workFlowName)
188 for ((k, v) in workflow.steps!!) {
189 var arts = ctx.nodeTemplateArtifacts(v.target!!)
191 for ((k, v) in arts.entries!!) {
192 if (v.type == "artifact-mapping-resource") {
193 val file: String = v.file
194 val completePath = ctx.rootPath.plus(File.separator).plus(file)
195 val resourceAssignment = JacksonUtils.getListFromFile(completePath, ResourceAssignment::class.java)
196 for (res in resourceAssignment) {
197 if (res.name == name && res.inputParameter) {
198 prop.inputparam = true
209 private fun addDataType(name: String, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
210 var data = ctx.dataTypeByName(name)
212 res.dataTypes?.put(name, data)
213 addParentDataType(data, ctx, res)
217 private fun addParentDataType(data: DataType, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
218 if (data.properties != null) {
219 for ((k, v) in data.properties!!) {
220 addPropertyInfo(k, v, ctx, res)
225 // wrap CBA workflows list in WorkflowsResponse object
226 @Throws(BluePrintException::class)
227 open suspend fun getWorkflowNames(name: String, version: String): WorkFlowsResponse {
228 var workflows = getWorkflowsFromRepository(name, version)
229 if (workflows == null) throw httpProcessorException(
230 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
231 "Failed to find workflows list for blueprint: ($name) version: ($version) from filesystem."
234 var res = WorkFlowsResponse()
235 res.blueprintName = name
236 res.version = version
237 res.workflows = workflows.keys.toMutableSet()
242 * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
244 * @return List<BlueprintModelSearch> list of the controller blueprint archives
245 </BlueprintModelSearch> */
246 open fun allBlueprintModel(): List<BlueprintModelSearch> {
247 return blueprintModelSearchRepository.findAll()
251 * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
253 * @return List<BlueprintModelSearch> list of the controller blueprint archives
254 </BlueprintModelSearch> */
255 open fun allBlueprintModel(pageRequest: Pageable): Page<BlueprintModelSearch> {
256 return blueprintModelSearchRepository.findAll(pageRequest)
259 open fun allBlueprintModelByPublished(published: Boolean, pageRequest: Pageable): Page<BlueprintModelSearch> {
260 val dbPublished = if (published) "Y" else "N"
261 return blueprintModelSearchRepository.findByPublished(dbPublished, pageRequest)
265 * This is a saveBlueprintModel method
267 * @param filePart filePart
268 * @return Mono<BlueprintModelSearch>
269 * @throws BluePrintException BluePrintException
270 </BlueprintModelSearch> */
271 @Throws(BluePrintException::class)
272 open suspend fun saveBlueprintModel(filePart: FilePart): BlueprintModelSearch {
274 return upload(filePart, false)
275 } catch (e: IOException) {
276 log.error("saveBlueprintModel fails ${e.message}", e)
277 throw httpProcessorException(
278 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
279 "Error in Save CBA: ${e.message}", e.errorCauseOrDefault()
285 * This is a searchBlueprintModels method
288 * @return List<BlueprintModelSearch>
289 </BlueprintModelSearch> */
290 open fun searchBlueprintModels(tags: String): List<BlueprintModelSearch> {
291 return blueprintModelSearchRepository.findByTagsContainingIgnoreCase(tags)
295 * This is a getBlueprintModelSearchByNameAndVersion method
298 * @param version version
299 * @return BlueprintModelSearch
300 * @throws BluePrintException BluePrintException
302 @Throws(BluePrintException::class)
303 open fun getBlueprintModelSearchByNameAndVersion(name: String, version: String): BlueprintModelSearch? {
304 return blueprintModelSearchRepository.findByArtifactNameAndArtifactVersion(name, version)
305 /*?: throw BluePrintException(
306 ErrorCode.RESOURCE_NOT_FOUND.value,
307 String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
312 * This is a downloadBlueprintModelFileByNameAndVersion method to download a Blueprint by Name and Version
315 * @param version version
316 * @return ResponseEntity<Resource>
317 * @throws BluePrintException BluePrintException
319 @Throws(BluePrintException::class)
320 open fun downloadBlueprintModelFileByNameAndVersion(
323 ): ResponseEntity<Resource> {
325 val archiveByteArray = download(name, version)
326 val fileName = "${name}_$version.zip"
327 return prepareResourceEntity(fileName, archiveByteArray)
328 } catch (e: BluePrintProcessorException) {
329 e.http(ErrorCatalogCodes.RESOURCE_NOT_FOUND)
330 val errorMsg = "Error while downloading the CBA file by Blueprint Name ($name) and Version ($version)."
331 throw e.updateErrorMessage(
332 DesignerApiDomains.DESIGNER_API, errorMsg,
333 "Wrong resource definition or resolution failed."
339 * This is a downloadBlueprintModelFile method to find the target file to download and return a file resource
341 * @return ResponseEntity<Resource>
342 * @throws BluePrintException BluePrintException
344 @Throws(BluePrintException::class)
345 open fun downloadBlueprintModelFile(id: String): ResponseEntity<Resource> {
346 val blueprintModel: BlueprintModel
348 blueprintModel = getBlueprintModel(id)
349 } catch (e: BluePrintException) {
350 throw httpProcessorException(
351 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
352 "Error while downloading the CBA file: couldn't get blueprint modelby ID ($id)",
353 e.errorCauseOrDefault()
357 val fileName = "${blueprintModel.artifactName}_${blueprintModel.artifactVersion}.zip"
358 val file = blueprintModel.blueprintModelContent?.content
359 ?: throw httpProcessorException(
360 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
361 "Error while downloading the CBA file: couldn't get model content"
363 return prepareResourceEntity(fileName, file)
367 * @return ResponseEntity<Resource>
369 private fun prepareResourceEntity(fileName: String, file: ByteArray): ResponseEntity<Resource> {
370 return ResponseEntity.ok()
371 .contentType(MediaType.parseMediaType("text/plain"))
372 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$fileName\"")
373 .body(ByteArrayResource(file))
377 * This is a getBlueprintModel method
380 * @return BlueprintModel
381 * @throws BluePrintException BluePrintException
383 @Throws(BluePrintException::class)
384 open fun getBlueprintModel(id: String): BlueprintModel {
385 val blueprintModel: BlueprintModel
386 val dbBlueprintModel = blueprintModelRepository.findById(id)
387 if (dbBlueprintModel.isPresent) {
388 blueprintModel = dbBlueprintModel.get()
390 val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
391 throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg)
393 return blueprintModel
397 * This is a getBlueprintModelByNameAndVersion method
400 * @param version version
401 * @return BlueprintModel
402 * @throws BluePrintException BluePrintException
404 @Throws(BluePrintException::class)
405 open fun getBlueprintModelByNameAndVersion(name: String, version: String): BlueprintModel {
406 val blueprintModel = blueprintModelRepository
407 .findByArtifactNameAndArtifactVersion(name, version)
408 if (blueprintModel != null) {
409 return blueprintModel
411 val msg = String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
412 throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg)
417 * This is a getBlueprintModelSearch method
420 * @return BlueprintModelSearch
421 * @throws BluePrintException BluePrintException
423 @Throws(BluePrintException::class)
424 open fun getBlueprintModelSearch(id: String): BlueprintModelSearch {
425 return blueprintModelSearchRepository.findById(id)
426 ?: throw httpProcessorException(
427 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
428 String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
433 * This is a searchBluePrintModelsByKeyWord method to retrieve specific BlueprintModel in Database
434 * where keyword equals updatedBy or tags or artifcat name or artifcat version or artifact type
435 * @author Shaaban Ebrahim
438 * @return List<BlueprintModelSearch> list of the controller blueprint
439 </BlueprintModelSearch> */
440 open fun searchBluePrintModelsByKeyWord(keyWord: String): List<BlueprintModelSearch> {
441 return blueprintModelSearchRepository.findByUpdatedByOrTagsOrOrArtifactNameOrOrArtifactVersionOrArtifactType(
442 keyWord, keyWord, keyWord, keyWord, keyWord
447 * This is a searchBluePrintModelsByKeyWordPagebale method to retrieve specific BlueprintModel in Database
448 * where keyword equals updatedBy or tags or artifcat name or artifcat version or artifact type and pageable
449 * @author Shaaban Ebrahim
452 * @return List<BlueprintModelSearch> list of the controller blueprint
453 </BlueprintModelSearch> */
454 open fun searchBluePrintModelsByKeyWordPaged(keyWord: String, pageRequest: PageRequest): Page<BlueprintModelSearch> {
455 return blueprintModelSearchRepository.findByUpdatedByContainingIgnoreCaseOrTagsContainingIgnoreCaseOrArtifactNameContainingIgnoreCaseOrArtifactVersionContainingIgnoreCaseOrArtifactTypeContainingIgnoreCase(
466 * This is a deleteBlueprintModel method
469 * @throws BluePrintException BluePrintException
472 @Throws(BluePrintException::class)
473 open fun deleteBlueprintModel(id: String) {
474 val dbBlueprintModel = blueprintModelRepository.findById(id)
475 if (dbBlueprintModel.isPresent) {
476 blueprintModelContentRepository.deleteByBlueprintModel(dbBlueprintModel.get())
477 blueprintModelRepository.delete(dbBlueprintModel.get())
479 val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
480 throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg)
484 open suspend fun deleteBlueprintModel(name: String, version: String) {
485 blueprintsProcessorCatalogService.deleteFromDatabase(name, version)
489 * This is a CBA enrichBlueprint method
490 * Save the Zip File in archive location and extract the cba content.
491 * Populate the Enhancement Location
492 * Enhance the CBA content
493 * Compress the Enhanced Content
494 * Return back the the compressed content back to the caller.
496 * @param filePart filePart
497 * @return ResponseEntity<Resource>
498 * @throws BluePrintException BluePrintException
500 @Throws(BluePrintException::class)
501 open suspend fun enrichBlueprint(filePart: FilePart): ResponseEntity<Resource> {
503 val enhancedByteArray = enrichBlueprintFileSource(filePart)
504 return BluePrintEnhancerUtils.prepareResourceEntity("enhanced-cba.zip", enhancedByteArray)
505 } catch (e: BluePrintProcessorException) {
506 e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
507 val errorMsg = "Error while enhancing the CBA package."
508 throw e.updateErrorMessage(
509 DesignerApiDomains.DESIGNER_API, errorMsg,
510 "Wrong CBA file provided, please verify and enrich Again."
512 } catch (e: Exception) {
513 throw httpProcessorException(
514 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
515 "EnrichBlueprint: ${e.message}", e.errorCauseOrDefault()
521 * This is a publishBlueprintModel method to change the status published to YES
522 * NOTE: this method is meant for enriched blueprints only.
524 * @param filePart filePart
525 * @return BlueprintModelSearch
526 * @throws BluePrintException BluePrintException
528 @Throws(BluePrintException::class)
529 open suspend fun publishBlueprint(filePart: FilePart): BlueprintModelSearch {
531 return upload(filePart, true)
532 } catch (e: BluePrintProcessorException) {
533 e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
534 val errorMsg = "Error in Publishing CBA."
535 throw e.updateErrorMessage(
536 DesignerApiDomains.DESIGNER_API, errorMsg,
537 "Wrong CBA provided, please verify and enrich your CBA."
539 } catch (e: Exception) {
540 throw httpProcessorException(
541 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
542 "Error in Publishing CBA: ${e.message}", e.errorCauseOrDefault()
548 * Enrich and publish the blueprint.
549 * NOTE: this method is meant for the unenriched vs publishBlueprint(filePart)
550 * which is used for enriched blueprints.
552 * @param filePart filePart
553 * @return BlueprintModelSearch
554 * @throws BluePrintException BluePrintException
556 @Throws(BluePrintException::class)
557 open suspend fun enrichAndPublishBlueprint(filePart: FilePart): BlueprintModelSearch {
559 val enhancedByteArray = enrichBlueprintFileSource(filePart)
560 return upload(enhancedByteArray, true)
561 } catch (e: BluePrintProcessorException) {
562 val errorMsg = "Error while enhancing and uploading the CBA package."
563 log.error(errorMsg, e)
564 e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
565 throw e.updateErrorMessage(
566 DesignerApiDomains.DESIGNER_API, errorMsg,
567 "Wrong CBA file provided, please verify the source CBA."
569 } catch (e: Exception) {
570 log.error("Error enriching/uploading CBA", e)
571 throw httpProcessorException(
572 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
573 "EnrichBlueprint: ${e.message}", e.errorCauseOrDefault()
578 /** Common CBA Save and Publish function for RestController and GRPC Handler, the [fileSource] may be
579 * byteArray or File Part type.*/
580 open suspend fun upload(fileSource: Any, validate: Boolean): BlueprintModelSearch {
581 val saveId = UUID.randomUUID().toString()
582 val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, saveId)
583 val blueprintWorking = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId)
585 val compressedFile = normalizedFile(blueprintArchive, "cba.zip")
587 is FilePart -> BluePrintEnhancerUtils.filePartAsFile(fileSource, compressedFile)
588 is ByteArray -> BluePrintEnhancerUtils.byteArrayAsFile(fileSource, compressedFile)
590 // Save the Copied file to Database
591 val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(saveId, compressedFile, validate)
593 return blueprintModelSearchRepository.findById(blueprintId)
594 ?: throw httpProcessorException(
595 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
596 String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, blueprintId)
598 } catch (e: BluePrintException) {
599 e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
600 val errorMsg = "Error in Upload CBA."
601 throw e.updateErrorMessage(
602 DesignerApiDomains.DESIGNER_API, errorMsg,
603 "Wrong enriched CBA."
605 } catch (e: IOException) {
606 throw httpProcessorException(
607 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
608 "Error in Upload CBA: ${e.errorMessageOrDefault()}", e.errorCauseOrDefault()
611 // Clean blueprint script cache
612 val cacheKey = BluePrintFileUtils
613 .compileCacheKey(normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId))
614 BluePrintCompileCache.cleanClassLoader(cacheKey)
615 deleteNBDir(blueprintArchive)
616 deleteNBDir(blueprintWorking)
620 /** Common CBA download function for RestController and GRPC Handler, the [fileSource] may be
621 * byteArray or File Part type.*/
622 open fun download(name: String, version: String): ByteArray {
624 val blueprintModel = getBlueprintModelByNameAndVersion(name, version)
625 return blueprintModel.blueprintModelContent?.content
626 ?: throw httpProcessorException(
627 ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
628 "Error while downloading the CBA file: couldn't get model content"
630 } catch (e: BluePrintException) {
631 e.http(ErrorCatalogCodes.RESOURCE_NOT_FOUND)
632 val errorMsg = "Fail to get Blueprint Model content."
633 throw e.updateErrorMessage(
634 DesignerApiDomains.DESIGNER_API, errorMsg,
635 "Wrong name and version was provide."
640 /** Common CBA Enrich function for RestController and GRPC Handler, the [fileSource] may be
641 * byteArray or File Part type.*/
642 open suspend fun enrichBlueprintFileSource(fileSource: Any): ByteArray {
643 val enhanceId = UUID.randomUUID().toString()
644 val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, enhanceId)
645 val blueprintWorkingDir = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, enhanceId)
649 BluePrintEnhancerUtils
650 .copyFilePartToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
652 BluePrintEnhancerUtils
653 .copyByteArrayToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
654 } // Enhance the Blue Prints
655 bluePrintEnhancerService.enhance(blueprintWorkingDir)
657 return BluePrintEnhancerUtils.compressEnhanceDirAndReturnByteArray(blueprintWorkingDir, blueprintArchive)
658 } catch (e: BluePrintException) {
659 e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
660 val errorMsg = "Fail Enriching the CBA."
661 throw e.updateErrorMessage(DesignerApiDomains.DESIGNER_API, errorMsg)
662 } catch (e: IOException) {
663 throw httpProcessorException(
664 ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
665 "Error while Enriching the CBA file.", e.errorCauseOrDefault()
668 BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir)
674 private const val BLUEPRINT_MODEL_ID_FAILURE_MSG = "failed to get blueprint model id(%s) from repo"
675 private const val BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG = "failed to get blueprint model by name(%s)" + " and version(%s) from repo"