2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2019 IBM.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils
20 import com.fasterxml.jackson.databind.JsonNode
21 import com.fasterxml.jackson.databind.ObjectMapper
22 import com.fasterxml.jackson.databind.node.ArrayNode
23 import com.fasterxml.jackson.databind.node.ObjectNode
24 import com.fasterxml.jackson.databind.node.TextNode
25 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService
26 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
27 import org.onap.ccsdk.cds.controllerblueprints.core.*
28 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
29 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils
30 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
31 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
32 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
33 import org.slf4j.LoggerFactory
36 class ResourceAssignmentUtils {
39 private val logger = LoggerFactory.getLogger(ResourceAssignmentUtils::class.toString())
41 suspend fun resourceDefinitions(blueprintBasePath: String): MutableMap<String, ResourceDefinition> {
42 val dictionaryFile = normalizedFile(blueprintBasePath, BluePrintConstants.TOSCA_DEFINITIONS_DIR,
43 ResourceResolutionConstants.FILE_NAME_RESOURCE_DEFINITION_TYPES)
44 checkFileExists(dictionaryFile) { "resource definition file(${dictionaryFile.absolutePath}) is missing" }
45 return JacksonReactorUtils.getMapFromFile(dictionaryFile, ResourceDefinition::class.java)
48 @Throws(BluePrintProcessorException::class)
49 fun setResourceDataValue(resourceAssignment: ResourceAssignment,
50 raRuntimeService: ResourceAssignmentRuntimeService, value: Any?) {
51 // TODO("See if Validation is needed in future with respect to conversion and Types")
52 return setResourceDataValue(resourceAssignment, raRuntimeService, value.asJsonType())
55 @Throws(BluePrintProcessorException::class)
56 fun setResourceDataValue(resourceAssignment: ResourceAssignment,
57 raRuntimeService: ResourceAssignmentRuntimeService, value: JsonNode) {
58 val resourceProp = checkNotNull(resourceAssignment.property) {
59 "Failed in setting resource value for resource mapping $resourceAssignment"
61 checkNotEmpty(resourceAssignment.name) {
62 "Failed in setting resource value for resource mapping $resourceAssignment"
65 if (resourceAssignment.dictionaryName.isNullOrEmpty()) {
66 resourceAssignment.dictionaryName = resourceAssignment.name
67 logger.warn("Missing dictionary key, setting with template key (${resourceAssignment.name}) " +
68 "as dictionary key (${resourceAssignment.dictionaryName})")
72 if (resourceProp.type.isNotEmpty()) {
73 logger.info("Setting Resource Value ($value) for Resource Name " +
74 "(${resourceAssignment.name}), definition(${resourceAssignment.dictionaryName}) " +
75 "of type (${resourceProp.type})")
76 setResourceValue(resourceAssignment, raRuntimeService, value)
77 resourceAssignment.updatedDate = Date()
78 resourceAssignment.updatedBy = BluePrintConstants.USER_SYSTEM
79 resourceAssignment.status = BluePrintConstants.STATUS_SUCCESS
81 } catch (e: Exception) {
82 throw BluePrintProcessorException("Failed in setting value for template key " +
83 "(${resourceAssignment.name}) and dictionary key (${resourceAssignment.dictionaryName}) of " +
84 "type (${resourceProp.type}) with error message (${e.message})", e)
88 private fun setResourceValue(resourceAssignment: ResourceAssignment,
89 raRuntimeService: ResourceAssignmentRuntimeService, value: JsonNode) {
90 // TODO("See if Validation is needed wrt to type before storing")
91 raRuntimeService.putResolutionStore(resourceAssignment.name, value)
92 raRuntimeService.putDictionaryStore(resourceAssignment.dictionaryName!!, value)
93 resourceAssignment.property!!.value = value
96 fun setFailedResourceDataValue(resourceAssignment: ResourceAssignment, message: String?) {
97 if (isNotEmpty(resourceAssignment.name)) {
98 resourceAssignment.updatedDate = Date()
99 resourceAssignment.updatedBy = BluePrintConstants.USER_SYSTEM
100 resourceAssignment.status = BluePrintConstants.STATUS_FAILURE
101 resourceAssignment.message = message
105 @Throws(BluePrintProcessorException::class)
106 fun assertTemplateKeyValueNotNull(resourceAssignment: ResourceAssignment) {
107 val resourceProp = checkNotNull(resourceAssignment.property) {
108 "Failed to populate mandatory resource resource mapping $resourceAssignment"
110 if (resourceProp.required != null && resourceProp.required!!
111 && (resourceProp.value == null || resourceProp.value!!.returnNullIfMissing() == null)) {
112 logger.error("failed to populate mandatory resource mapping ($resourceAssignment)")
113 throw BluePrintProcessorException("failed to populate mandatory resource mapping ($resourceAssignment)")
117 @Throws(BluePrintProcessorException::class)
118 fun generateResourceDataForAssignments(assignments: List<ResourceAssignment>): String {
121 val mapper = ObjectMapper()
122 val root: ObjectNode = mapper.createObjectNode()
124 assignments.forEach {
125 if (isNotEmpty(it.name) && it.property != null) {
127 val type = nullToEmpty(it.property?.type).toLowerCase()
128 val value = useDefaultValueIfNull(it, rName)
129 logger.info("Generating Resource name ($rName), type ($type), value ($value)")
130 root.set(rName, value)
133 result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root)
134 logger.info("Generated Resource Param Data ($result)")
135 } catch (e: Exception) {
136 throw BluePrintProcessorException("Resource Assignment is failed with $e.message", e)
142 @Throws(BluePrintProcessorException::class)
143 fun generateResourceForAssignments(assignments: List<ResourceAssignment>): MutableMap<String, JsonNode> {
144 val data: MutableMap<String, JsonNode> = hashMapOf()
145 assignments.forEach {
146 if (isNotEmpty(it.name) && it.property != null) {
148 val type = nullToEmpty(it.property?.type).toLowerCase()
149 val value = useDefaultValueIfNull(it, rName)
150 logger.trace("Generating Resource name ($rName), type ($type), value ($value)")
157 private fun useDefaultValueIfNull(resourceAssignment: ResourceAssignment, resourceAssignmentName: String): JsonNode {
158 if (resourceAssignment.property?.value == null) {
159 val defaultValue = "\${$resourceAssignmentName}"
160 return TextNode(defaultValue)
162 return resourceAssignment.property!!.value!!
166 fun transformToRARuntimeService(blueprintRuntimeService: BluePrintRuntimeService<*>,
167 templateArtifactName: String): ResourceAssignmentRuntimeService {
169 val resourceAssignmentRuntimeService = ResourceAssignmentRuntimeService(blueprintRuntimeService.id(),
170 blueprintRuntimeService.bluePrintContext())
171 resourceAssignmentRuntimeService.createUniqueId(templateArtifactName)
172 resourceAssignmentRuntimeService.setExecutionContext(blueprintRuntimeService.getExecutionContext() as MutableMap<String, JsonNode>)
174 return resourceAssignmentRuntimeService
177 @Throws(BluePrintProcessorException::class)
178 fun getPropertyType(raRuntimeService: ResourceAssignmentRuntimeService, dataTypeName: String,
179 propertyName: String): String {
180 lateinit var type: String
182 val dataTypeProps = checkNotNull(raRuntimeService.bluePrintContext().dataTypeByName(dataTypeName)?.properties)
184 val propertyDefinition = checkNotNull(dataTypeProps[propertyName])
185 type = checkNotEmpty(propertyDefinition.type) { "Couldn't get data type ($dataTypeName)" }
186 logger.trace("Data type({})'s property ({}) is ({})", dataTypeName, propertyName, type)
187 } catch (e: Exception) {
188 logger.error("couldn't get data type($dataTypeName)'s property ($propertyName), error message $e")
189 throw BluePrintProcessorException("${e.message}", e)
194 @Throws(BluePrintProcessorException::class)
195 fun parseResponseNode(responseNode: JsonNode, resourceAssignment: ResourceAssignment,
196 raRuntimeService: ResourceAssignmentRuntimeService, outputKeyMapping: MutableMap<String, String>): JsonNode {
197 val dName = resourceAssignment.dictionaryName
198 val dSource = resourceAssignment.dictionarySource
199 val type = nullToEmpty(resourceAssignment.property?.type)
200 lateinit var entrySchemaType: String
202 in BluePrintTypes.validPrimitiveTypes() -> {
203 if (dSource !in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES)
204 logger.info("For template key (${resourceAssignment.name}) setting value as ($responseNode)")
205 val result = if (responseNode is ArrayNode)
209 return if (result.isComplexType()) {
210 check(result.has(outputKeyMapping[dName])) {
211 "Fail to find output key mapping ($dName) in result."
213 result[outputKeyMapping[dName]]
218 in BluePrintTypes.validCollectionTypes() -> {
220 entrySchemaType = checkNotEmpty(resourceAssignment.property?.entrySchema?.type) {
221 "Entry schema is not defined for dictionary ($dName) info"
223 val arrayNode = JacksonUtils.objectMapper.createArrayNode()
224 lateinit var responseValueNode: JsonNode
225 lateinit var propertyType: String
226 outputKeyMapping.map {
227 val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
228 val responseArrayNode = responseNode.rootFieldsToMap()
229 outer@ for ((key, responseSingleJsonNode) in responseArrayNode) {
231 if (entrySchemaType in BluePrintTypes.validPrimitiveTypes()) {
232 responseValueNode = responseSingleJsonNode
233 propertyType = entrySchemaType
236 responseValueNode = responseSingleJsonNode.get(it.key)
237 propertyType = getPropertyType(raRuntimeService, entrySchemaType, it.key)
239 if (resourceAssignment.dictionarySource !in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES)
240 logger.info("For List Type Resource: key (${it.key}), value ($responseValueNode), " +
241 "type ({$propertyType})")
242 JacksonUtils.populateJsonNodeValues(it.value,
243 responseValueNode, propertyType, arrayChildNode)
244 arrayNode.add(arrayChildNode)
249 if (resourceAssignment.dictionarySource !in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES)
250 logger.info("For template key (${resourceAssignment.name}) setting value as ($arrayNode)")
256 entrySchemaType = checkNotEmpty(resourceAssignment.property?.type) {
257 "Entry schema is not defined for dictionary ($dName) info"
259 val objectNode = JacksonUtils.objectMapper.createObjectNode()
260 outputKeyMapping.map {
261 val responseKeyValue = responseNode.get(it.key)
262 val propertyTypeForDataType = ResourceAssignmentUtils
263 .getPropertyType(raRuntimeService, entrySchemaType, it.key)
265 if (resourceAssignment.dictionarySource !in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES)
266 logger.info("For List Type Resource: key (${it.key}), value ($responseKeyValue), type ({$propertyTypeForDataType})")
267 JacksonUtils.populateJsonNodeValues(it.value, responseKeyValue, propertyTypeForDataType, objectNode)
270 if (resourceAssignment.dictionarySource !in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES)
271 logger.info("For template key (${resourceAssignment.name}) setting value as ($objectNode)")