2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright (c) 2019 IBM, Bell Canada.
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.SerializationFeature
23 import com.fasterxml.jackson.databind.node.ArrayNode
24 import com.fasterxml.jackson.databind.node.NullNode
25 import com.fasterxml.jackson.databind.node.ObjectNode
26 import com.fasterxml.jackson.databind.node.TextNode
27 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService
28 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
29 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
30 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
31 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
32 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
33 import org.onap.ccsdk.cds.controllerblueprints.core.checkFileExists
34 import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
35 import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants.LOG_REDACTED
36 import org.onap.ccsdk.cds.controllerblueprints.core.isComplexType
37 import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty
38 import org.onap.ccsdk.cds.controllerblueprints.core.isNullOrMissing
39 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
40 import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty
41 import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap
42 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
43 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintVelocityTemplateService
44 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils
45 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
46 import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
47 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.DictionaryMetadataEntry
48 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier
49 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResolutionSummary
50 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
51 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
52 import org.slf4j.LoggerFactory
55 class ResourceAssignmentUtils {
58 private val logger = LoggerFactory.getLogger(ResourceAssignmentUtils::class.toString())
60 suspend fun resourceDefinitions(blueprintBasePath: String): MutableMap<String, ResourceDefinition> {
61 val dictionaryFile = normalizedFile(
62 blueprintBasePath, BluePrintConstants.TOSCA_DEFINITIONS_DIR,
63 ResourceResolutionConstants.FILE_NAME_RESOURCE_DEFINITION_TYPES
65 checkFileExists(dictionaryFile) { "resource definition file(${dictionaryFile.absolutePath}) is missing" }
66 return JacksonReactorUtils.getMapFromFile(dictionaryFile, ResourceDefinition::class.java)
69 @Throws(BluePrintProcessorException::class)
70 fun setResourceDataValue(
71 resourceAssignment: ResourceAssignment,
72 raRuntimeService: ResourceAssignmentRuntimeService,
75 // TODO("See if Validation is needed in future with respect to conversion and Types")
76 return setResourceDataValue(resourceAssignment, raRuntimeService, value.asJsonType())
79 @Throws(BluePrintProcessorException::class)
80 fun setResourceDataValue(
81 resourceAssignment: ResourceAssignment,
82 raRuntimeService: ResourceAssignmentRuntimeService,
85 val resourceProp = checkNotNull(resourceAssignment.property) {
86 "Failed in setting resource value for resource mapping $resourceAssignment"
88 checkNotEmpty(resourceAssignment.name) {
89 "Failed in setting resource value for resource mapping $resourceAssignment"
92 if (resourceAssignment.dictionaryName.isNullOrEmpty()) {
93 resourceAssignment.dictionaryName = resourceAssignment.name
95 "Missing dictionary key, setting with template key (${resourceAssignment.name}) " +
96 "as dictionary key (${resourceAssignment.dictionaryName})"
101 if (resourceProp.type.isNotEmpty()) {
102 val metadata = resourceAssignment.property!!.metadata
103 val valueToPrint = getValueToLog(metadata, value)
105 "Setting Resource Value ($valueToPrint) for Resource Name " +
106 "(${resourceAssignment.name}), definition(${resourceAssignment.dictionaryName}) " +
107 "of type (${resourceProp.type})"
109 setResourceValue(resourceAssignment, raRuntimeService, value)
110 resourceAssignment.updatedDate = Date()
111 resourceAssignment.updatedBy = BluePrintConstants.USER_SYSTEM
112 resourceAssignment.status = BluePrintConstants.STATUS_SUCCESS
114 } catch (e: Exception) {
115 throw BluePrintProcessorException(
116 "Failed in setting value for template key " +
117 "(${resourceAssignment.name}) and dictionary key (${resourceAssignment.dictionaryName}) of " +
118 "type (${resourceProp.type}) with error message (${e.message})", e
123 private fun setResourceValue(
124 resourceAssignment: ResourceAssignment,
125 raRuntimeService: ResourceAssignmentRuntimeService,
128 // TODO("See if Validation is needed wrt to type before storing")
129 raRuntimeService.putResolutionStore(resourceAssignment.name, value)
130 raRuntimeService.putDictionaryStore(resourceAssignment.dictionaryName!!, value)
131 resourceAssignment.property!!.value = value
133 val metadata = resourceAssignment.property?.metadata
134 metadata?.get(ResourceResolutionConstants.METADATA_TRANSFORM_TEMPLATE)
135 ?.let { if (it.contains("$")) it else null }
137 val resolutionStore = raRuntimeService.getResolutionStore()
138 .mapValues { e -> e.value.asText() } as MutableMap<String, Any>
139 val newValue: JsonNode
141 newValue = BluePrintVelocityTemplateService
142 .generateContent(template, null, true, resolutionStore)
143 .also { if (hasLogProtect(metadata))
144 logger.info("Transformed value: $resourceAssignment.name")
146 logger.info("Transformed value: $value -> $it") }
147 .let { v -> v.asJsonType() }
148 } catch (e: Exception) {
149 throw BluePrintProcessorException(
150 "transform-template failed: $template", e)
152 with(resourceAssignment) {
153 raRuntimeService.putResolutionStore(this.name, newValue)
154 raRuntimeService.putDictionaryStore(this.dictionaryName!!, newValue)
155 this.property!!.value = newValue
160 fun setFailedResourceDataValue(resourceAssignment: ResourceAssignment, message: String?) {
161 if (isNotEmpty(resourceAssignment.name)) {
162 resourceAssignment.updatedDate = Date()
163 resourceAssignment.updatedBy = BluePrintConstants.USER_SYSTEM
164 resourceAssignment.status = BluePrintConstants.STATUS_FAILURE
165 resourceAssignment.message = message
169 @Throws(BluePrintProcessorException::class)
170 fun assertTemplateKeyValueNotNull(resourceAssignment: ResourceAssignment) {
171 val resourceProp = checkNotNull(resourceAssignment.property) {
172 "Failed to populate mandatory resource resource mapping $resourceAssignment"
174 if (resourceProp.required != null && resourceProp.required!! && resourceProp.value.isNullOrMissing()) {
175 logger.error("failed to populate mandatory resource mapping ($resourceAssignment)")
176 throw BluePrintProcessorException("failed to populate mandatory resource mapping ($resourceAssignment)")
180 @Throws(BluePrintProcessorException::class)
181 fun generateResourceDataForAssignments(assignments: List<ResourceAssignment>): String {
184 val mapper = ObjectMapper()
185 mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true)
186 val root: ObjectNode = mapper.createObjectNode()
188 var containsLogProtected = false
189 assignments.forEach {
190 if (isNotEmpty(it.name) && it.property != null) {
192 val metadata = it.property!!.metadata
193 val type = nullToEmpty(it.property?.type).toLowerCase()
194 val value = useDefaultValueIfNull(it, rName)
195 val valueToPrint = getValueToLog(metadata, value)
196 containsLogProtected = hasLogProtect(metadata)
197 logger.trace("Generating Resource name ($rName), type ($type), value ($valueToPrint)")
198 root.set<JsonNode>(rName, value)
201 result = mapper.writerWithDefaultPrettyPrinter()
202 .writeValueAsString(mapper.treeToValue(root, Object::class.java))
204 if (!containsLogProtected) {
205 logger.info("Generated Resource Param Data ($result)")
207 } catch (e: Exception) {
208 throw BluePrintProcessorException("Resource Assignment is failed with $e.message", e)
214 @Throws(BluePrintProcessorException::class)
215 fun generateResourceForAssignments(assignments: List<ResourceAssignment>): MutableMap<String, JsonNode> {
216 val data: MutableMap<String, JsonNode> = hashMapOf()
217 assignments.forEach {
218 if (isNotEmpty(it.name) && it.property != null) {
220 val metadata = it.property!!.metadata
221 val type = nullToEmpty(it.property?.type).toLowerCase()
222 val value = useDefaultValueIfNull(it, rName)
223 val valueToPrint = getValueToLog(metadata, value)
225 logger.trace("Generating Resource name ($rName), type ($type), value ($valueToPrint)")
232 fun generateResolutionSummaryData(
233 resourceAssignments: List<ResourceAssignment>,
234 resourceDefinitions: Map<String, ResourceDefinition>
236 val emptyTextNode = TextNode.valueOf("")
237 val resolutionSummaryList = resourceAssignments.map {
238 val definition = resourceDefinitions[it.name]
239 val description = definition?.property?.description ?: ""
240 val value = it.property?.value
241 ?.let { v -> if (v.isNullOrMissing()) emptyTextNode else v }
244 var payload: JsonNode = definition?.sources?.get(it.dictionarySource)
245 ?.properties?.get("resolved-payload")
246 ?.let { p -> if (p.isNullOrMissing()) emptyTextNode else p }
249 val metadata = definition?.property?.metadata
250 ?.map { e -> DictionaryMetadataEntry(e.key, e.value) }
251 ?.toMutableList() ?: mutableListOf()
253 val keyIdentifiers: MutableList<KeyIdentifier> = it.keyIdentifiers.map { k ->
254 if (k.value.isNullOrMissing()) KeyIdentifier(k.name, emptyTextNode) else k
260 it.property?.required ?: false,
261 it.property?.type ?: "",
265 it.dictionaryName ?: "",
266 it.dictionarySource ?: "",
272 // Wrapper needed for integration with SDNC
273 val data = mapOf("resolution-summary" to resolutionSummaryList)
274 return JacksonUtils.getJson(data, includeNull = true)
277 fun generateAssignmentMap(
278 artifactPrefix: String,
279 resourceAssignments: List<ResourceAssignment>
280 ): ObjectNode = resourceAssignments.associateBy({ it.name }, { it.property?.value })
281 .let { mutableMapOf(artifactPrefix to it) }
282 .let { JacksonUtils.objectNodeFromObject(it) }
284 private fun useDefaultValueIfNull(
285 resourceAssignment: ResourceAssignment,
286 resourceAssignmentName: String
288 if (resourceAssignment.property?.value == null) {
289 val defaultValue = "\${$resourceAssignmentName}"
290 return TextNode(defaultValue)
292 return resourceAssignment.property!!.value!!
296 fun transformToRARuntimeService(
297 blueprintRuntimeService: BluePrintRuntimeService<*>,
298 templateArtifactName: String
299 ): ResourceAssignmentRuntimeService {
301 val resourceAssignmentRuntimeService = ResourceAssignmentRuntimeService(
302 blueprintRuntimeService.id(),
303 blueprintRuntimeService.bluePrintContext()
305 resourceAssignmentRuntimeService.createUniqueId(templateArtifactName)
306 resourceAssignmentRuntimeService.setExecutionContext(blueprintRuntimeService.getExecutionContext() as MutableMap<String, JsonNode>)
308 return resourceAssignmentRuntimeService
311 @Throws(BluePrintProcessorException::class)
313 raRuntimeService: ResourceAssignmentRuntimeService,
314 dataTypeName: String,
317 lateinit var type: String
320 checkNotNull(raRuntimeService.bluePrintContext().dataTypeByName(dataTypeName)?.properties)
322 val propertyDefinition = checkNotNull(dataTypeProps[propertyName])
323 type = checkNotEmpty(propertyDefinition.type) { "Couldn't get data type ($dataTypeName)" }
324 logger.trace("Data type({})'s property ({}) is ({})", dataTypeName, propertyName, type)
325 } catch (e: Exception) {
326 logger.error("couldn't get data type($dataTypeName)'s property ($propertyName), error message $e")
327 throw BluePrintProcessorException("${e.message}", e)
332 @Throws(BluePrintProcessorException::class)
333 fun parseResponseNode(
334 responseNode: JsonNode,
335 resourceAssignment: ResourceAssignment,
336 raRuntimeService: ResourceAssignmentRuntimeService,
337 outputKeyMapping: MutableMap<String, String>
339 val metadata = resourceAssignment.property!!.metadata
341 if ((resourceAssignment.property?.type).isNullOrEmpty()) {
342 throw BluePrintProcessorException("Couldn't get data dictionary type for dictionary name (${resourceAssignment.name})")
344 val type = resourceAssignment.property!!.type
345 val valueToPrint = getValueToLog(metadata, responseNode)
347 logger.info("For template key (${resourceAssignment.name}) trying to get value from responseNode ($valueToPrint)")
349 in BluePrintTypes.validPrimitiveTypes() -> {
351 parseResponseNodeForPrimitiveTypes(responseNode, resourceAssignment, outputKeyMapping)
353 in BluePrintTypes.validCollectionTypes() -> {
355 parseResponseNodeForCollection(responseNode, resourceAssignment, raRuntimeService, outputKeyMapping)
359 parseResponseNodeForComplexType(responseNode, resourceAssignment, raRuntimeService, outputKeyMapping)
362 } catch (e: Exception) {
363 logger.error("Fail to parse response data, error message $e")
364 throw BluePrintProcessorException("${e.message}", e)
368 private fun parseResponseNodeForPrimitiveTypes(
369 responseNode: JsonNode,
370 resourceAssignment: ResourceAssignment,
371 outputKeyMapping: MutableMap<String, String>
373 // Return responseNode if is not a Complex Type
374 if (!responseNode.isComplexType()) {
378 val outputKey = outputKeyMapping.keys.firstOrNull()
379 var returnNode = if (responseNode is ArrayNode) {
380 val arrayNode = responseNode.toList()
381 if (outputKey.isNullOrEmpty()) {
384 arrayNode.firstOrNull { element ->
385 element.isComplexType() && element.has(outputKeyMapping[outputKey])
392 if (returnNode.isNullOrMissing() || returnNode!!.isComplexType() && !returnNode.has(outputKeyMapping[outputKey])) {
393 throw BluePrintProcessorException("Fail to find output key mapping ($outputKey) in the responseNode.")
396 val returnValue = if (returnNode.isComplexType()) {
397 returnNode[outputKeyMapping[outputKey]]
402 outputKey?.let { KeyIdentifier(it, returnValue) }
403 ?.let { resourceAssignment.keyIdentifiers.add(it) }
407 private fun parseResponseNodeForCollection(
408 responseNode: JsonNode,
409 resourceAssignment: ResourceAssignment,
410 raRuntimeService: ResourceAssignmentRuntimeService,
411 outputKeyMapping: MutableMap<String, String>
413 val dName = resourceAssignment.dictionaryName
414 val metadata = resourceAssignment.property!!.metadata
415 var resultNode: JsonNode
416 if ((resourceAssignment.property?.entrySchema?.type).isNullOrEmpty()) {
417 throw BluePrintProcessorException(
418 "Couldn't get data type for dictionary type " +
419 "(${resourceAssignment.property!!.type}) and dictionary name ($dName)"
422 val entrySchemaType = resourceAssignment.property!!.entrySchema!!.type
424 var arrayNode = JacksonUtils.objectMapper.createArrayNode()
425 if (outputKeyMapping.isNotEmpty()) {
426 when (responseNode) {
428 val responseArrayNode = responseNode.toList()
429 for (responseSingleJsonNode in responseArrayNode) {
430 val arrayChildNode = parseSingleElementOfArrayResponseNode(
431 entrySchemaType, resourceAssignment,
432 outputKeyMapping, raRuntimeService, responseSingleJsonNode, metadata
434 arrayNode.add(arrayChildNode)
436 resultNode = arrayNode
439 val responseArrayNode = responseNode.rootFieldsToMap()
441 parseObjectResponseNode(
442 resourceAssignment, entrySchemaType, outputKeyMapping,
443 responseArrayNode, metadata
447 throw BluePrintProcessorException("Key-value response expected to match the responseNode.")
451 when (responseNode) {
453 responseNode.forEach { elementNode ->
454 arrayNode.add(elementNode)
456 resultNode = arrayNode
459 val responseArrayNode = responseNode.rootFieldsToMap()
460 for ((key, responseSingleJsonNode) in responseArrayNode) {
461 val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
462 logKeyValueResolvedResource(metadata, key, responseSingleJsonNode, entrySchemaType)
463 JacksonUtils.populateJsonNodeValues(
465 responseSingleJsonNode,
469 arrayNode.add(arrayChildNode)
471 resultNode = arrayNode
474 resultNode = responseNode
482 private fun parseSingleElementOfArrayResponseNode(
483 entrySchemaType: String,
484 resourceAssignment: ResourceAssignment,
485 outputKeyMapping: MutableMap<String, String>,
486 raRuntimeService: ResourceAssignmentRuntimeService,
487 responseNode: JsonNode,
488 metadata: MutableMap<String, String>?
490 val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping)
491 when (entrySchemaType) {
492 in BluePrintTypes.validPrimitiveTypes() -> {
493 if (outputKeyMappingHasOnlyOneElement) {
494 val outputKeyMap = outputKeyMapping.entries.first()
495 if (resourceAssignment.keyIdentifiers.none { it.name == outputKeyMap.key }) {
496 resourceAssignment.keyIdentifiers.add(
497 KeyIdentifier(outputKeyMap.key, JacksonUtils.objectMapper.createArrayNode())
500 return parseSingleElementNodeWithOneOutputKeyMapping(
509 throw BluePrintProcessorException("Expect one entry in output-key-mapping")
514 checkOutputKeyMappingAllElementsInDataTypeProperties(
519 parseSingleElementNodeWithAllOutputKeyMapping(
527 outputKeyMappingHasOnlyOneElement -> {
528 val outputKeyMap = outputKeyMapping.entries.first()
529 parseSingleElementNodeWithOneOutputKeyMapping(
539 throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType")
546 private fun parseObjectResponseNode(
547 resourceAssignment: ResourceAssignment,
548 entrySchemaType: String,
549 outputKeyMapping: MutableMap<String, String>,
550 responseArrayNode: MutableMap<String, JsonNode>,
551 metadata: MutableMap<String, String>?
553 val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping)
554 if (outputKeyMappingHasOnlyOneElement) {
555 val outputKeyMap = outputKeyMapping.entries.first()
556 val returnValue = parseObjectResponseNodeWithOneOutputKeyMapping(
557 responseArrayNode, outputKeyMap.key, outputKeyMap.value,
558 entrySchemaType, metadata
560 resourceAssignment.keyIdentifiers.add(KeyIdentifier(outputKeyMap.key, returnValue))
563 throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType")
567 private fun parseSingleElementNodeWithOneOutputKeyMapping(
568 resourceAssignment: ResourceAssignment,
569 responseSingleJsonNode: JsonNode,
570 outputKeyMappingKey: String,
571 outputKeyMappingValue: String,
573 metadata: MutableMap<String, String>?
575 val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
577 val responseKeyValue = if (responseSingleJsonNode.has(outputKeyMappingValue)) {
578 responseSingleJsonNode.get(outputKeyMappingValue)
580 NullNode.getInstance()
583 logKeyValueResolvedResource(metadata, outputKeyMappingKey, responseKeyValue, type)
584 JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, responseKeyValue, type, arrayChildNode)
585 resourceAssignment.keyIdentifiers.find { it.name == outputKeyMappingKey && it.value.isArray }
588 (it.value as ArrayNode).add(responseKeyValue)
590 resourceAssignment.keyIdentifiers.add(
591 KeyIdentifier(outputKeyMappingKey, responseKeyValue))
593 return arrayChildNode
596 private fun parseSingleElementNodeWithAllOutputKeyMapping(
597 resourceAssignment: ResourceAssignment,
598 responseSingleJsonNode: JsonNode,
599 outputKeyMapping: MutableMap<String, String>,
601 metadata: MutableMap<String, String>?
603 val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
604 outputKeyMapping.map {
605 val responseKeyValue = if (responseSingleJsonNode.has(it.value)) {
606 responseSingleJsonNode.get(it.value)
608 NullNode.getInstance()
611 logKeyValueResolvedResource(metadata, it.key, responseKeyValue, type)
612 JacksonUtils.populateJsonNodeValues(it.key, responseKeyValue, type, arrayChildNode)
613 resourceAssignment.keyIdentifiers.add(KeyIdentifier(it.key, responseKeyValue))
615 return arrayChildNode
618 private fun parseObjectResponseNodeWithOneOutputKeyMapping(
619 responseArrayNode: MutableMap<String, JsonNode>,
620 outputKeyMappingKey: String,
621 outputKeyMappingValue: String,
623 metadata: MutableMap<String, String>?
625 val objectNode = JacksonUtils.objectMapper.createObjectNode()
626 val responseSingleJsonNode = responseArrayNode.filterKeys { key ->
627 key == outputKeyMappingValue
628 }.entries.firstOrNull()
630 if (responseSingleJsonNode == null) {
631 logKeyValueResolvedResource(metadata, outputKeyMappingKey, NullNode.getInstance(), type)
632 JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, NullNode.getInstance(), type, objectNode)
634 logKeyValueResolvedResource(metadata, outputKeyMappingKey, responseSingleJsonNode.value, type)
635 JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, responseSingleJsonNode.value, type, objectNode)
640 private fun parseResponseNodeForComplexType(
641 responseNode: JsonNode,
642 resourceAssignment: ResourceAssignment,
643 raRuntimeService: ResourceAssignmentRuntimeService,
644 outputKeyMapping: MutableMap<String, String>
646 val entrySchemaType = resourceAssignment.property!!.type
647 val dictionaryName = resourceAssignment.dictionaryName!!
648 val metadata = resourceAssignment.property!!.metadata
649 val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping)
651 if (outputKeyMapping.isNotEmpty()) {
653 checkOutputKeyMappingAllElementsInDataTypeProperties(
658 parseSingleElementNodeWithAllOutputKeyMapping(
666 outputKeyMappingHasOnlyOneElement -> {
667 val outputKeyMap = outputKeyMapping.entries.first()
668 parseSingleElementNodeWithOneOutputKeyMapping(
669 resourceAssignment, responseNode, outputKeyMap.key,
670 outputKeyMap.value, entrySchemaType, metadata
674 throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType")
678 val childNode = JacksonUtils.objectMapper.createObjectNode()
679 JacksonUtils.populateJsonNodeValues(dictionaryName, responseNode, entrySchemaType, childNode)
684 private fun checkOutputKeyMappingAllElementsInDataTypeProperties(
685 dataTypeName: String,
686 outputKeyMapping: MutableMap<String, String>,
687 raRuntimeService: ResourceAssignmentRuntimeService
689 val dataTypeProps = raRuntimeService.bluePrintContext().dataTypeByName(dataTypeName)?.properties
690 val result = outputKeyMapping.filterKeys { !dataTypeProps!!.containsKey(it) }.keys.firstOrNull()
691 return result == null
694 private fun logKeyValueResolvedResource(
695 metadata: MutableMap<String, String>?,
700 val valueToPrint = getValueToLog(metadata, value)
703 "For List Type Resource: key ($key), value ($valueToPrint), " +
708 private fun checkIfOutputKeyMappingProvideOneElement(outputKeyMapping: MutableMap<String, String>): Boolean {
709 return (outputKeyMapping.size == 1)
712 fun getValueToLog(metadata: MutableMap<String, String>?, value: Any): Any =
713 if (hasLogProtect(metadata)) LOG_REDACTED else value