2  * Copyright © 2017-2018 AT&T Intellectual Property.
 
   3  * Modifications Copyright © 2019 Bell Canada.
 
   4  * Modifications Copyright © 2019 IBM.
 
   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
 
  10  *     http://www.apache.org/licenses/LICENSE-2.0
 
  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.
 
  19 package org.onap.ccsdk.apps.controllerblueprints.service.handler
 
  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
 
  44 import java.io.IOException
 
  48  * BlueprintModelHandler Purpose: Handler service to handle the request from BlurPrintModelRest
 
  50  * @author Brinda Santh
 
  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) {
 
  63      * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
 
  65      * @return List<BlueprintModelSearch> list of the controller blueprint archives
 
  66     </BlueprintModelSearch> */
 
  67     open fun allBlueprintModel(): List<BlueprintModelSearch> {
 
  68         return blueprintModelSearchRepository.findAll()
 
  72      * This is a saveBlueprintModel method
 
  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> {
 
  81             val cbaLocation = BluePrintFileUtils.getCbaStorageDirectory(bluePrintLoadConfiguration.blueprintArchivePath)
 
  82             return BluePrintEnhancerUtils.saveCBAFile(filePart, cbaLocation).map { fileName ->
 
  83                 var blueprintId: String? = null
 
  85                     blueprintId = bluePrintCatalogService.saveToDatabase(cbaLocation.resolve(fileName).toFile(), false)
 
  86                 } catch (e: BluePrintException) {
 
  87                     // FIXME handle expection
 
  89                 blueprintModelSearchRepository.findById(blueprintId!!).get()
 
  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)
 
  99      * This is a publishBlueprintModel method to change the status published to YES
 
 102      * @return BlueprintModelSearch
 
 103      * @throws BluePrintException BluePrintException
 
 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()
 
 112             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
 
 113             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
 
 115         blueprintModelSearch.published = ApplicationConstants.ACTIVE_Y
 
 116         return blueprintModelSearchRepository.saveAndFlush(blueprintModelSearch)
 
 120      * This is a searchBlueprintModels method
 
 123      * @return List<BlueprintModelSearch>
 
 124     </BlueprintModelSearch> */
 
 125     open fun searchBlueprintModels(tags: String): List<BlueprintModelSearch> {
 
 126         return blueprintModelSearchRepository.findByTagsContainingIgnoreCase(tags)
 
 130      * This is a getBlueprintModelSearchByNameAndVersion method
 
 133      * @param version version
 
 134      * @return BlueprintModelSearch
 
 135      * @throws BluePrintException BluePrintException
 
 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()
 
 145             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
 
 146                     String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version))
 
 148         return blueprintModelSearch
 
 152      * This is a downloadBlueprintModelFileByNameAndVersion method to download a Blueprint by Name and Version
 
 155      * @param version version
 
 156      * @return ResponseEntity<Resource>
 
 157      * @throws BluePrintException BluePrintException
 
 159     @Throws(BluePrintException::class)
 
 160     open fun downloadBlueprintModelFileByNameAndVersion(name: String,
 
 161                                                         version: String): ResponseEntity<Resource> {
 
 162         val blueprintModel: BlueprintModel
 
 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)
 
 169         val fileName = blueprintModel.id + ".zip"
 
 170         val file = blueprintModel.blueprintModelContent.content
 
 171         return prepareResourceEntity(fileName, file)
 
 175      * This is a downloadBlueprintModelFile method to find the target file to download and return a file resource
 
 177      * @return ResponseEntity<Resource>
 
 178      * @throws BluePrintException BluePrintException
 
 180     @Throws(BluePrintException::class)
 
 181     open fun downloadBlueprintModelFile(id: String): ResponseEntity<Resource> {
 
 182         val blueprintModel: BlueprintModel
 
 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)
 
 189         val fileName = blueprintModel.id + ".zip"
 
 190         val file = blueprintModel.blueprintModelContent.content
 
 191         return prepareResourceEntity(fileName, file)
 
 195      * @return ResponseEntity<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))
 
 205      * This is a getBlueprintModel method
 
 208      * @return BlueprintModel
 
 209      * @throws BluePrintException BluePrintException
 
 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()
 
 218             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
 
 219             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
 
 221         return blueprintModel
 
 225      * This is a getBlueprintModelByNameAndVersion method
 
 228      * @param version version
 
 229      * @return BlueprintModel
 
 230      * @throws BluePrintException BluePrintException
 
 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
 
 239             val msg = String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
 
 240             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
 
 245      * This is a getBlueprintModelSearch method
 
 248      * @return BlueprintModelSearch
 
 249      * @throws BluePrintException BluePrintException
 
 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()
 
 258             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
 
 259             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
 
 262         return blueprintModelSearch
 
 266      * This is a deleteBlueprintModel method
 
 269      * @throws BluePrintException BluePrintException
 
 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())
 
 279             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
 
 280             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
 
 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.
 
 292      * @param filePart filePart
 
 293      * @return ResponseEntity<Resource>
 
 294      * @throws BluePrintException BluePrintException
 
 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)
 
 303             BluePrintEnhancerUtils.decompressFilePart(filePart, blueprintArchive, blueprintEnrichmentDir)
 
 305             // Enhance the Blue Prints
 
 306             bluePrintEnhancerService.enhance(blueprintEnrichmentDir)
 
 308             return BluePrintEnhancerUtils.compressToFilePart(blueprintEnrichmentDir, blueprintArchive)
 
 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)
 
 314             BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintEnrichmentDir)
 
 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"