Formatting Code base with ktlint
[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  * Modifications Copyright © 2019 IBM.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 package org.onap.ccsdk.cds.controllerblueprints.core.utils
20
21 import kotlinx.coroutines.runBlocking
22 import org.apache.commons.io.FileUtils
23 import org.apache.commons.lang3.StringUtils
24 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
25 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
26 import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
27 import org.onap.ccsdk.cds.controllerblueprints.core.data.ImportDefinition
28 import org.onap.ccsdk.cds.controllerblueprints.core.data.ServiceTemplate
29 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
30 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
31 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
32 import org.slf4j.LoggerFactory
33 import java.io.File
34 import java.io.FileFilter
35 import java.nio.file.Files
36 import java.nio.file.Path
37 import java.nio.file.Paths
38 import java.nio.file.StandardOpenOption
39
40 class BluePrintFileUtils {
41     companion object {
42
43         private val log = LoggerFactory.getLogger(this::class.toString())
44
45         fun createEmptyBluePrint(basePath: String) {
46
47             val blueprintDir = File(basePath)
48             FileUtils.deleteDirectory(blueprintDir)
49
50             Files.createDirectories(blueprintDir.toPath())
51
52             val metaDataDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_DIR))
53             Files.createDirectories(metaDataDir.toPath())
54
55             val metaFile = File(
56                 blueprintDir.absolutePath.plus(File.separator).plus(
57                     BluePrintConstants
58                         .TOSCA_METADATA_ENTRY_DEFINITION_FILE
59                 )
60             )
61             Files.write(metaFile.toPath(), getMetaDataContent().toByteArray(), StandardOpenOption.CREATE_NEW)
62
63             val definitionsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR))
64             Files.createDirectories(definitionsDir.toPath())
65
66             val scriptsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_SCRIPTS_DIR))
67             Files.createDirectories(scriptsDir.toPath())
68
69             val plansDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_PLANS_DIR))
70             Files.createDirectories(plansDir.toPath())
71
72             val templatesDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_TEMPLATES_DIR))
73             Files.createDirectories(templatesDir.toPath())
74         }
75
76         fun copyBluePrint(sourcePath: String, targetPath: String) {
77             val sourceFile = File(sourcePath)
78             val targetFile = File(targetPath)
79             sourceFile.copyRecursively(targetFile, true)
80         }
81
82         fun deleteBluePrintTypes(basePath: String) {
83             val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
84             log.info("deleting definition types under : $definitionPath")
85
86             val definitionDir = File(definitionPath)
87             // Find the Type Definitions
88             val fileFilter = FileFilter { pathname -> pathname.absolutePath.endsWith("_types.json") }
89             // Delete the Type Files
90             definitionDir.listFiles(fileFilter).forEach {
91                 Files.deleteIfExists(it.toPath())
92             }
93         }
94
95         fun writeEnhancedBluePrint(blueprintContext: BluePrintContext) {
96
97             // Write Blueprint Types
98             writeBluePrintTypes(blueprintContext)
99             // Re Populate the Imports
100             populateDefaultImports(blueprintContext)
101             // Rewrite the Entry Definition Files
102             writeEntryDefinitionFile(blueprintContext)
103         }
104
105         fun writeBluePrintTypes(blueprintContext: BluePrintContext) {
106
107             val basePath = blueprintContext.rootPath
108             val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
109             val definitionDir = File(definitionPath)
110
111             check(definitionDir.exists()) {
112                 throw BluePrintException(
113                     ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
114                             "path(${definitionDir.absolutePath})"
115                 )
116             }
117
118             blueprintContext.serviceTemplate.dataTypes?.let {
119                 val dataTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_DATA_TYPES, it.toSortedMap(), true)
120                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_DATA_TYPES, dataTypesContent)
121             }
122
123             blueprintContext.serviceTemplate.relationshipTypes?.let {
124                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_RELATIONSHIP_TYPES, it.toSortedMap(), true)
125                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_RELATIONSHIP_TYPES, nodeTypesContent)
126             }
127
128             blueprintContext.serviceTemplate.artifactTypes?.let {
129                 val artifactTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_ARTIFACT_TYPES, it.toSortedMap(), true)
130                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_ARTIFACT_TYPES, artifactTypesContent)
131             }
132
133             blueprintContext.serviceTemplate.nodeTypes?.let {
134                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_NODE_TYPES, it.toSortedMap(), true)
135                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_NODE_TYPES, nodeTypesContent)
136             }
137
138             blueprintContext.serviceTemplate.policyTypes?.let {
139                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_POLICY_TYPES, it.toSortedMap(), true)
140                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_POLICY_TYPES, nodeTypesContent)
141             }
142         }
143
144         private fun populateDefaultImports(blueprintContext: BluePrintContext) {
145             // Get the Default Types
146             val types = arrayListOf(
147                 BluePrintConstants.PATH_DATA_TYPES, BluePrintConstants.PATH_RELATIONSHIP_TYPES,
148                 BluePrintConstants.PATH_ARTIFACT_TYPES, BluePrintConstants.PATH_NODE_TYPES,
149                 BluePrintConstants.PATH_POLICY_TYPES
150             )
151
152             // Clean Type Imports
153             cleanImportTypes(blueprintContext.serviceTemplate)
154
155             val imports = mutableListOf<ImportDefinition>()
156             types.forEach { typeName ->
157                 val import = ImportDefinition()
158                 import.file = BluePrintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
159                 imports.add(import)
160             }
161
162             blueprintContext.serviceTemplate.imports = imports
163         }
164
165         fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
166             // Clean the Type imports
167             val toDeleteTypes = serviceTemplate.imports?.filter {
168                 it.file.endsWith("_types.json")
169             }
170
171             if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
172                 serviceTemplate.imports?.removeAll(toDeleteTypes)
173             }
174         }
175
176         /**
177          * Re Generate the Blueprint Service Template Definition file based on BluePrint Context.
178          */
179         private fun writeEntryDefinitionFile(blueprintContext: BluePrintContext) {
180
181             val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
182
183             val serviceTemplate = blueprintContext.serviceTemplate
184
185             // Clone the Service Template
186             val writeServiceTemplate = serviceTemplate.clone()
187             writeServiceTemplate.dataTypes = null
188             writeServiceTemplate.artifactTypes = null
189             writeServiceTemplate.policyTypes = null
190             writeServiceTemplate.relationshipTypes = null
191             writeServiceTemplate.nodeTypes = null
192
193             // Write the Service Template
194             writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
195         }
196
197         fun writeDefinitionFile(definitionFileName: String, content: String) = runBlocking {
198             val definitionFile = File(definitionFileName)
199             // Delete the File If exists
200             Files.deleteIfExists(definitionFile.toPath())
201
202             Files.write(definitionFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
203             check(definitionFile.exists()) {
204                 throw BluePrintException(
205                     ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write definition file under " +
206                             "path(${definitionFile.absolutePath})"
207                 )
208             }
209         }
210
211         private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
212             val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
213
214             Files.write(typeFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
215             check(typeFile.exists()) {
216                 throw BluePrintException(
217                     ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write $type.json file under " +
218                             "path(${typeFile.absolutePath})"
219                 )
220             }
221         }
222
223         private fun getMetaDataContent(): String {
224             return "TOSCA-Meta-File-Version: 1.0.0" +
225                     "\nCSAR-Version: <VERSION>" +
226                     "\nCreated-By: <AUTHOR NAME>" +
227                     "\nEntry-Definitions: Definitions/<BLUEPRINT_NAME>.json" +
228                     "\nTemplate-Name: <BLUEPRINT_NAME>" +
229                     "\nTemplate-Tags: <BLUEPRINT_VERSION>" +
230                     "\nTemplate-Tags: <TAGS>"
231         }
232
233         fun getBluePrintFile(fileName: String, targetPath: Path): File {
234             val filePath = targetPath.resolve(fileName).toString()
235             val file = File(filePath)
236             check(file.exists()) {
237                 throw BluePrintException(
238                     ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
239                             "path(${file.absolutePath})"
240                 )
241             }
242             return file
243         }
244
245         fun getCbaStorageDirectory(path: String): Path {
246             check(StringUtils.isNotBlank(path)) {
247                 throw BluePrintException(
248                     ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get " +
249                             "Blueprint folder under path($path)"
250                 )
251             }
252
253             val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
254
255             if (!Files.exists(fileStorageLocation))
256                 Files.createDirectories(fileStorageLocation)
257
258             return fileStorageLocation
259         }
260
261         fun compileCacheKey(basePath: String): String {
262             return normalizedPathName(basePath)
263         }
264
265         private fun compileJarFileName(artifactName: String, artifactVersion: String): String {
266             return "$artifactName-$artifactVersion-cba-kts.jar"
267         }
268
269         fun compileJarFilePathName(basePath: String, artifactName: String, artifactVersion: String): String {
270             return normalizedPathName(
271                 basePath, BluePrintConstants.TOSCA_SCRIPTS_KOTLIN_DIR,
272                 compileJarFileName(artifactName, artifactVersion)
273             )
274         }
275
276         fun compileJarFile(basePath: String, artifactName: String, artifactVersion: String): File {
277             return normalizedFile(
278                 compileJarFilePathName(
279                     basePath,
280                     artifactName, artifactVersion
281                 )
282             )
283         }
284
285         fun stripFileExtension(fileName: String): String {
286             val dotIndexe = fileName.lastIndexOf('.')
287
288             // In case dot is in first position, we are dealing with a hidden file rather than an extension
289             return if (dotIndexe > 0) fileName.substring(0, dotIndexe) else fileName
290         }
291     }
292 }