Migrate ccsdk/apps to ccsdk/cds
[ccsdk/cds.git] / ms / controllerblueprints / modules / blueprint-core / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / core / utils / BluePrintFileUtils.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2019 Bell Canada.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package org.onap.ccsdk.cds.controllerblueprints.core.utils
19
20 import com.att.eelf.configuration.EELFLogger
21 import com.att.eelf.configuration.EELFManager
22 import kotlinx.coroutines.runBlocking
23 import org.apache.commons.io.FileUtils
24 import org.apache.commons.lang3.StringUtils
25 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
26 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
27 import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
28 import org.onap.ccsdk.cds.controllerblueprints.core.data.ImportDefinition
29 import org.onap.ccsdk.cds.controllerblueprints.core.data.ServiceTemplate
30 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
31 import java.io.File
32 import java.io.FileFilter
33 import java.nio.file.Files
34 import java.nio.file.Path
35 import java.nio.file.Paths
36 import java.nio.file.StandardOpenOption
37
38
39 class BluePrintFileUtils {
40     companion object {
41
42         private val log: EELFLogger = EELFManager.getInstance().getLogger(this::class.toString())
43
44         fun createEmptyBluePrint(basePath: String) {
45
46             val blueprintDir = File(basePath)
47             FileUtils.deleteDirectory(blueprintDir)
48
49             Files.createDirectories(blueprintDir.toPath())
50
51             val metaDataDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_DIR))
52             Files.createDirectories(metaDataDir.toPath())
53
54             val metaFile = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants
55                     .TOSCA_METADATA_ENTRY_DEFINITION_FILE))
56             Files.write(metaFile.toPath(), getMetaDataContent().toByteArray(), StandardOpenOption.CREATE_NEW)
57
58             val definitionsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR))
59             Files.createDirectories(definitionsDir.toPath())
60
61             val scriptsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_SCRIPTS_DIR))
62             Files.createDirectories(scriptsDir.toPath())
63
64             val plansDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_PLANS_DIR))
65             Files.createDirectories(plansDir.toPath())
66
67             val templatesDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_TEMPLATES_DIR))
68             Files.createDirectories(templatesDir.toPath())
69
70         }
71
72         fun copyBluePrint(sourcePath: String, targetPath: String) {
73             val sourceFile = File(sourcePath)
74             val targetFile = File(targetPath)
75             sourceFile.copyRecursively(targetFile, true)
76         }
77
78         fun deleteBluePrintTypes(basePath: String) {
79             val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
80             log.info("deleting definition types under : $definitionPath")
81
82             val definitionDir = File(definitionPath)
83             // Find the Type Definitions
84             val fileFilter = FileFilter { pathname -> pathname.absolutePath.endsWith("_types.json") }
85             // Delete the Type Files
86             definitionDir.listFiles(fileFilter).forEach {
87                 Files.deleteIfExists(it.toPath())
88             }
89         }
90
91         fun writeEnhancedBluePrint(blueprintContext: BluePrintContext) {
92
93             // Write Blueprint Types
94             writeBluePrintTypes(blueprintContext)
95             // Re Populate the Imports
96             populateDefaultImports(blueprintContext)
97             // Rewrite the Entry Definition Files
98             writeEntryDefinitionFile(blueprintContext)
99
100         }
101
102         fun writeBluePrintTypes(blueprintContext: BluePrintContext) {
103
104             val basePath = blueprintContext.rootPath
105             val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
106             val definitionDir = File(definitionPath)
107
108             check(definitionDir.exists()) {
109                 throw BluePrintException(ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
110                         "path(${definitionDir.absolutePath})")
111             }
112
113             blueprintContext.serviceTemplate.dataTypes?.let {
114                 val dataTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_DATA_TYPES, it.toSortedMap(), true)
115                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_DATA_TYPES, dataTypesContent)
116             }
117
118             blueprintContext.serviceTemplate.relationshipTypes?.let {
119                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_RELATIONSHIP_TYPES, it.toSortedMap(), true)
120                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_RELATIONSHIP_TYPES, nodeTypesContent)
121             }
122
123             blueprintContext.serviceTemplate.artifactTypes?.let {
124                 val artifactTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_ARTIFACT_TYPES, it.toSortedMap(), true)
125                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_ARTIFACT_TYPES, artifactTypesContent)
126             }
127
128             blueprintContext.serviceTemplate.nodeTypes?.let {
129                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_NODE_TYPES, it.toSortedMap(), true)
130                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_NODE_TYPES, nodeTypesContent)
131             }
132
133             blueprintContext.serviceTemplate.policyTypes?.let {
134                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_POLICY_TYPES, it.toSortedMap(), true)
135                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_POLICY_TYPES, nodeTypesContent)
136             }
137         }
138
139         private fun populateDefaultImports(blueprintContext: BluePrintContext) {
140             // Get the Default Types
141             val types = arrayListOf(BluePrintConstants.PATH_DATA_TYPES, BluePrintConstants.PATH_RELATIONSHIP_TYPES,
142                     BluePrintConstants.PATH_ARTIFACT_TYPES, BluePrintConstants.PATH_NODE_TYPES,
143                     BluePrintConstants.PATH_POLICY_TYPES)
144
145             // Clean Type Imports
146             cleanImportTypes(blueprintContext.serviceTemplate)
147
148             val imports = mutableListOf<ImportDefinition>()
149             types.forEach { typeName ->
150                 val import = ImportDefinition()
151                 import.file = BluePrintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
152                 imports.add(import)
153             }
154
155             blueprintContext.serviceTemplate.imports = imports
156         }
157
158         fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
159             // Clean the Type imports
160             val toDeleteTypes = serviceTemplate.imports?.filter {
161                 it.file.endsWith("_types.json")
162             }
163
164             if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
165                 serviceTemplate.imports?.removeAll(toDeleteTypes)
166             }
167         }
168
169         /**
170          * Re Generate the Blueprint Service Template Definition file based on BluePrint Context.
171          */
172         private fun writeEntryDefinitionFile(blueprintContext: BluePrintContext) {
173
174             val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
175
176             val serviceTemplate = blueprintContext.serviceTemplate
177
178             // Clone the Service Template
179             val writeServiceTemplate = serviceTemplate.clone()
180             writeServiceTemplate.dataTypes = null
181             writeServiceTemplate.artifactTypes = null
182             writeServiceTemplate.policyTypes = null
183             writeServiceTemplate.relationshipTypes = null
184             writeServiceTemplate.nodeTypes = null
185
186             // Write the Service Template
187             writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
188         }
189
190         fun writeDefinitionFile(definitionFileName: String, content: String) = runBlocking {
191             val definitionFile = File(definitionFileName)
192             // Delete the File If exists
193             Files.deleteIfExists(definitionFile.toPath())
194
195             Files.write(definitionFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
196             check(definitionFile.exists()) {
197                 throw BluePrintException(ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write definition file under " +
198                         "path(${definitionFile.absolutePath})")
199             }
200         }
201
202         private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
203             val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
204
205             Files.write(typeFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
206             check(typeFile.exists()) {
207                 throw BluePrintException(ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write $type.json file under " +
208                         "path(${typeFile.absolutePath})")
209             }
210         }
211
212         private fun getMetaDataContent(): String {
213             return "TOSCA-Meta-File-Version: 1.0.0" +
214                     "\nCSAR-Version: <VERSION>" +
215                     "\nCreated-By: <AUTHOR NAME>" +
216                     "\nEntry-Definitions: Definitions/<BLUEPRINT_NAME>.json" +
217                     "\nTemplate-Tags: <TAGS>"
218         }
219
220        
221         fun getBluePrintFile(fileName: String, targetPath: Path) : File {
222             val filePath = targetPath.resolve(fileName).toString()
223             val file = File(filePath)
224             check(file.exists()) {
225                 throw BluePrintException(ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
226                         "path(${file.absolutePath})")
227             }
228             return file
229         }
230
231         fun getCbaStorageDirectory(path: String): Path {
232             check(StringUtils.isNotBlank(path)) {
233                 throw BluePrintException(ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get " +
234                         "Blueprint folder under path($path)")
235             }
236
237             val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
238
239             if (!Files.exists(fileStorageLocation))
240                 Files.createDirectories(fileStorageLocation)
241
242             return fileStorageLocation
243         }
244
245         fun stripFileExtension(fileName: String): String {
246             val dotIndexe = fileName.lastIndexOf('.')
247
248             // In case dot is in first position, we are dealing with a hidden file rather than an extension
249             return if (dotIndexe > 0) fileName.substring(0, dotIndexe) else fileName
250         }
251
252     }
253 }