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.node.ArrayNode
23 import com.fasterxml.jackson.databind.node.NullNode
24 import com.fasterxml.jackson.databind.node.ObjectNode
25 import com.fasterxml.jackson.databind.node.TextNode
26 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService
27 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
28 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
29 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
30 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
31 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
32 import org.onap.ccsdk.cds.controllerblueprints.core.checkFileExists
33 import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
34 import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants.LOG_REDACTED
35 import org.onap.ccsdk.cds.controllerblueprints.core.isComplexType
36 import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty
37 import org.onap.ccsdk.cds.controllerblueprints.core.isNullOrMissing
38 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
39 import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty
40 import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap
41 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
42 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintVelocityTemplateService
43 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils
44 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
45 import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
46 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.DictionaryMetadataEntry
47 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier
48 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResolutionSummary
49 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
50 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
51 import org.slf4j.LoggerFactory
54 class ResourceAssignmentUtils {
57 private val logger = LoggerFactory.getLogger(ResourceAssignmentUtils::class.toString())
59 suspend fun resourceDefinitions(blueprintBasePath: String): MutableMap<String, ResourceDefinition> {
60 val dictionaryFile = normalizedFile(
61 blueprintBasePath, BluePrintConstants.TOSCA_DEFINITIONS_DIR,
62 ResourceResolutionConstants.FILE_NAME_RESOURCE_DEFINITION_TYPES
64 checkFileExists(dictionaryFile) { "resource definition file(${dictionaryFile.absolutePath}) is missing" }
65 return JacksonReactorUtils.getMapFromFile(dictionaryFile, ResourceDefinition::class.java)
68 @Throws(BluePrintProcessorException::class)
69 fun setResourceDataValue(
70 resourceAssignment: ResourceAssignment,
71 raRuntimeService: ResourceAssignmentRuntimeService,
74 // TODO("See if Validation is needed in future with respect to conversion and Types")
75 return setResourceDataValue(resourceAssignment, raRuntimeService, value.asJsonType())
78 @Throws(BluePrintProcessorException::class)
79 fun setResourceDataValue(
80 resourceAssignment: ResourceAssignment,
81 raRuntimeService: ResourceAssignmentRuntimeService,
84 val resourceProp = checkNotNull(resourceAssignment.property) {
85 "Failed in setting resource value for resource mapping $resourceAssignment"
87 checkNotEmpty(resourceAssignment.name) {
88 "Failed in setting resource value for resource mapping $resourceAssignment"
91 if (resourceAssignment.dictionaryName.isNullOrEmpty()) {
92 resourceAssignment.dictionaryName = resourceAssignment.name
94 "Missing dictionary key, setting with template key (${resourceAssignment.name}) " +
95 "as dictionary key (${resourceAssignment.dictionaryName})"
100 if (resourceProp.type.isNotEmpty()) {
101 val metadata = resourceAssignment.property!!.metadata
102 val valueToPrint = getValueToLog(metadata, value)
104 "Setting Resource Value ($valueToPrint) for Resource Name " +
105 "(${resourceAssignment.name}), definition(${resourceAssignment.dictionaryName}) " +
106 "of type (${resourceProp.type})"
108 setResourceValue(resourceAssignment, raRuntimeService, value)
109 resourceAssignment.updatedDate = Date()
110 resourceAssignment.updatedBy = BluePrintConstants.USER_SYSTEM
111 resourceAssignment.status = BluePrintConstants.STATUS_SUCCESS
113 } catch (e: Exception) {
114 throw BluePrintProcessorException(
115 "Failed in setting value for template key " +
116 "(${resourceAssignment.name}) and dictionary key (${resourceAssignment.dictionaryName}) of " +
117 "type (${resourceProp.type}) with error message (${e.message})", e
122 private fun setResourceValue(
123 resourceAssignment: ResourceAssignment,
124 raRuntimeService: ResourceAssignmentRuntimeService,
127 // TODO("See if Validation is needed wrt to type before storing")
128 raRuntimeService.putResolutionStore(resourceAssignment.name, value)
129 raRuntimeService.putDictionaryStore(resourceAssignment.dictionaryName!!, value)
130 resourceAssignment.property!!.value = value
132 val metadata = resourceAssignment.property?.metadata
133 metadata?.get(ResourceResolutionConstants.METADATA_TRANSFORM_TEMPLATE)
134 ?.let { if (it.contains("$")) it else null }
136 val resolutionStore = raRuntimeService.getResolutionStore()
137 .mapValues { e -> e.value.asText() } as MutableMap<String, Any>
138 val newValue: JsonNode
140 newValue = BluePrintVelocityTemplateService
141 .generateContent(template, null, true, resolutionStore)
142 .also { if (hasLogProtect(metadata))
143 logger.info("Transformed value: $resourceAssignment.name")
145 logger.info("Transformed value: $value -> $it") }
146 .let { v -> v.asJsonType() }
147 } catch (e: Exception) {
148 throw BluePrintProcessorException(
149 "transform-template failed: $template", e)
151 with(resourceAssignment) {
152 raRuntimeService.putResolutionStore(this.name, newValue)
153 raRuntimeService.putDictionaryStore(this.dictionaryName!!, newValue)
154 this.property!!.value = newValue
159 fun setFailedResourceDataValue(resourceAssignment: ResourceAssignment, message: String?) {
160 if (isNotEmpty(resourceAssignment.name)) {
161 resourceAssignment.updatedDate = Date()
162 resourceAssignment.updatedBy = BluePrintConstants.USER_SYSTEM
163 resourceAssignment.status = BluePrintConstants.STATUS_FAILURE
164 resourceAssignment.message = message
168 @Throws(BluePrintProcessorException::class)
169 fun assertTemplateKeyValueNotNull(resourceAssignment: ResourceAssignment) {
170 val resourceProp = checkNotNull(resourceAssignment.property) {
171 "Failed to populate mandatory resource resource mapping $resourceAssignment"
173 if (resourceProp.required != null && resourceProp.required!! && resourceProp.value.isNullOrMissing()) {
174 logger.error("failed to populate mandatory resource mapping ($resourceAssignment)")
175 throw BluePrintProcessorException("failed to populate mandatory resource mapping ($resourceAssignment)")
179 @Throws(BluePrintProcessorException::class)
180 fun generateResourceDataForAssignments(assignments: List<ResourceAssignment>): String {
183 val mapper = ObjectMapper()
184 val root: ObjectNode = mapper.createObjectNode()
186 var containsLogProtected = false
187 assignments.forEach {
188 if (isNotEmpty(it.name) && it.property != null) {
190 val metadata = it.property!!.metadata
191 val type = nullToEmpty(it.property?.type).toLowerCase()
192 val value = useDefaultValueIfNull(it, rName)
193 val valueToPrint = getValueToLog(metadata, value)
194 containsLogProtected = hasLogProtect(metadata)
195 logger.trace("Generating Resource name ($rName), type ($type), value ($valueToPrint)")
196 root.set<JsonNode>(rName, value)
199 result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root)
201 if (!containsLogProtected) {
202 logger.info("Generated Resource Param Data ($result)")
204 } catch (e: Exception) {
205 throw BluePrintProcessorException("Resource Assignment is failed with $e.message", e)
211 @Throws(BluePrintProcessorException::class)
212 fun generateResourceForAssignments(assignments: List<ResourceAssignment>): MutableMap<String, JsonNode> {
213 val data: MutableMap<String, JsonNode> = hashMapOf()
214 assignments.forEach {
215 if (isNotEmpty(it.name) && it.property != null) {
217 val metadata = it.property!!.metadata
218 val type = nullToEmpty(it.property?.type).toLowerCase()
219 val value = useDefaultValueIfNull(it, rName)
220 val valueToPrint = getValueToLog(metadata, value)
222 logger.trace("Generating Resource name ($rName), type ($type), value ($valueToPrint)")
229 fun generateResolutionSummaryData(
230 resourceAssignments: List<ResourceAssignment>,
231 resourceDefinitions: Map<String, ResourceDefinition>
233 val emptyTextNode = TextNode.valueOf("")
234 val resolutionSummaryList = resourceAssignments.map {
235 val definition = resourceDefinitions[it.name]
236 val description = definition?.property?.description ?: ""
237 val value = it.property?.value
238 ?.let { v -> if (v.isNullOrMissing()) emptyTextNode else v }
241 var payload: JsonNode = definition?.sources?.get(it.dictionarySource)
242 ?.properties?.get("resolved-payload")
243 ?.let { p -> if (p.isNullOrMissing()) emptyTextNode else p }
246 val metadata = definition?.property?.metadata
247 ?.map { e -> DictionaryMetadataEntry(e.key, e.value) }
248 ?.toMutableList() ?: mutableListOf()
250 val keyIdentifiers: MutableList<KeyIdentifier> = it.keyIdentifiers.map { k ->
251 if (k.value.isNullOrMissing()) KeyIdentifier(k.name, emptyTextNode) else k
257 it.property?.required ?: false,
258 it.property?.type ?: "",
262 it.dictionaryName ?: "",
263 it.dictionarySource ?: "",
269 // Wrapper needed for integration with SDNC
270 val data = mapOf("resolution-summary" to resolutionSummaryList)
271 return JacksonUtils.getJson(data, includeNull = true)
274 private fun useDefaultValueIfNull(
275 resourceAssignment: ResourceAssignment,
276 resourceAssignmentName: String
278 if (resourceAssignment.property?.value == null) {
279 val defaultValue = "\${$resourceAssignmentName}"
280 return TextNode(defaultValue)
282 return resourceAssignment.property!!.value!!
286 fun transformToRARuntimeService(
287 blueprintRuntimeService: BluePrintRuntimeService<*>,
288 templateArtifactName: String
289 ): ResourceAssignmentRuntimeService {
291 val resourceAssignmentRuntimeService = ResourceAssignmentRuntimeService(
292 blueprintRuntimeService.id(),
293 blueprintRuntimeService.bluePrintContext()
295 resourceAssignmentRuntimeService.createUniqueId(templateArtifactName)
296 resourceAssignmentRuntimeService.setExecutionContext(blueprintRuntimeService.getExecutionContext() as MutableMap<String, JsonNode>)
298 return resourceAssignmentRuntimeService
301 @Throws(BluePrintProcessorException::class)
303 raRuntimeService: ResourceAssignmentRuntimeService,
304 dataTypeName: String,
307 lateinit var type: String
310 checkNotNull(raRuntimeService.bluePrintContext().dataTypeByName(dataTypeName)?.properties)
312 val propertyDefinition = checkNotNull(dataTypeProps[propertyName])
313 type = checkNotEmpty(propertyDefinition.type) { "Couldn't get data type ($dataTypeName)" }
314 logger.trace("Data type({})'s property ({}) is ({})", dataTypeName, propertyName, type)
315 } catch (e: Exception) {
316 logger.error("couldn't get data type($dataTypeName)'s property ($propertyName), error message $e")
317 throw BluePrintProcessorException("${e.message}", e)
322 @Throws(BluePrintProcessorException::class)
323 fun parseResponseNode(
324 responseNode: JsonNode,
325 resourceAssignment: ResourceAssignment,
326 raRuntimeService: ResourceAssignmentRuntimeService,
327 outputKeyMapping: MutableMap<String, String>
329 val metadata = resourceAssignment.property!!.metadata
331 if ((resourceAssignment.property?.type).isNullOrEmpty()) {
332 throw BluePrintProcessorException("Couldn't get data dictionary type for dictionary name (${resourceAssignment.name})")
334 val type = resourceAssignment.property!!.type
335 val valueToPrint = getValueToLog(metadata, responseNode)
337 logger.info("For template key (${resourceAssignment.name}) trying to get value from responseNode ($valueToPrint)")
339 in BluePrintTypes.validPrimitiveTypes() -> {
341 parseResponseNodeForPrimitiveTypes(responseNode, resourceAssignment, outputKeyMapping)
343 in BluePrintTypes.validCollectionTypes() -> {
345 parseResponseNodeForCollection(responseNode, resourceAssignment, raRuntimeService, outputKeyMapping)
349 parseResponseNodeForComplexType(responseNode, resourceAssignment, raRuntimeService, outputKeyMapping)
352 } catch (e: Exception) {
353 logger.error("Fail to parse response data, error message $e")
354 throw BluePrintProcessorException("${e.message}", e)
358 private fun parseResponseNodeForPrimitiveTypes(
359 responseNode: JsonNode,
360 resourceAssignment: ResourceAssignment,
361 outputKeyMapping: MutableMap<String, String>
363 // Return responseNode if is not a Complex Type
364 if (!responseNode.isComplexType()) {
368 val outputKey = outputKeyMapping.keys.firstOrNull()
369 var returnNode = if (responseNode is ArrayNode) {
370 val arrayNode = responseNode.toList()
371 if (outputKey.isNullOrEmpty()) {
374 arrayNode.firstOrNull { element ->
375 element.isComplexType() && element.has(outputKeyMapping[outputKey])
382 if (returnNode.isNullOrMissing() || returnNode!!.isComplexType() && !returnNode.has(outputKeyMapping[outputKey])) {
383 throw BluePrintProcessorException("Fail to find output key mapping ($outputKey) in the responseNode.")
386 val returnValue = if (returnNode.isComplexType()) {
387 returnNode[outputKeyMapping[outputKey]]
392 outputKey?.let { KeyIdentifier(it, returnValue) }
393 ?.let { resourceAssignment.keyIdentifiers.add(it) }
397 private fun parseResponseNodeForCollection(
398 responseNode: JsonNode,
399 resourceAssignment: ResourceAssignment,
400 raRuntimeService: ResourceAssignmentRuntimeService,
401 outputKeyMapping: MutableMap<String, String>
403 val dName = resourceAssignment.dictionaryName
404 val metadata = resourceAssignment.property!!.metadata
405 var resultNode: JsonNode
406 if ((resourceAssignment.property?.entrySchema?.type).isNullOrEmpty()) {
407 throw BluePrintProcessorException(
408 "Couldn't get data type for dictionary type " +
409 "(${resourceAssignment.property!!.type}) and dictionary name ($dName)"
412 val entrySchemaType = resourceAssignment.property!!.entrySchema!!.type
414 var arrayNode = JacksonUtils.objectMapper.createArrayNode()
415 if (outputKeyMapping.isNotEmpty()) {
416 when (responseNode) {
418 val responseArrayNode = responseNode.toList()
419 for (responseSingleJsonNode in responseArrayNode) {
420 val arrayChildNode = parseSingleElementOfArrayResponseNode(
421 entrySchemaType, resourceAssignment,
422 outputKeyMapping, raRuntimeService, responseSingleJsonNode, metadata
424 arrayNode.add(arrayChildNode)
426 resultNode = arrayNode
429 val responseArrayNode = responseNode.rootFieldsToMap()
431 parseObjectResponseNode(
432 resourceAssignment, entrySchemaType, outputKeyMapping,
433 responseArrayNode, metadata
437 throw BluePrintProcessorException("Key-value response expected to match the responseNode.")
441 when (responseNode) {
443 responseNode.forEach { elementNode ->
444 arrayNode.add(elementNode)
446 resultNode = arrayNode
449 val responseArrayNode = responseNode.rootFieldsToMap()
450 for ((key, responseSingleJsonNode) in responseArrayNode) {
451 val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
452 logKeyValueResolvedResource(metadata, key, responseSingleJsonNode, entrySchemaType)
453 JacksonUtils.populateJsonNodeValues(
455 responseSingleJsonNode,
459 arrayNode.add(arrayChildNode)
461 resultNode = arrayNode
464 resultNode = responseNode
472 private fun parseSingleElementOfArrayResponseNode(
473 entrySchemaType: String,
474 resourceAssignment: ResourceAssignment,
475 outputKeyMapping: MutableMap<String, String>,
476 raRuntimeService: ResourceAssignmentRuntimeService,
477 responseNode: JsonNode,
478 metadata: MutableMap<String, String>?
480 val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping)
481 when (entrySchemaType) {
482 in BluePrintTypes.validPrimitiveTypes() -> {
483 if (outputKeyMappingHasOnlyOneElement) {
484 val outputKeyMap = outputKeyMapping.entries.first()
485 if (resourceAssignment.keyIdentifiers.none { it.name == outputKeyMap.key }) {
486 resourceAssignment.keyIdentifiers.add(
487 KeyIdentifier(outputKeyMap.key, JacksonUtils.objectMapper.createArrayNode())
490 return parseSingleElementNodeWithOneOutputKeyMapping(
499 throw BluePrintProcessorException("Expect one entry in output-key-mapping")
504 checkOutputKeyMappingAllElementsInDataTypeProperties(
509 parseSingleElementNodeWithAllOutputKeyMapping(
517 outputKeyMappingHasOnlyOneElement -> {
518 val outputKeyMap = outputKeyMapping.entries.first()
519 parseSingleElementNodeWithOneOutputKeyMapping(
529 throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType")
536 private fun parseObjectResponseNode(
537 resourceAssignment: ResourceAssignment,
538 entrySchemaType: String,
539 outputKeyMapping: MutableMap<String, String>,
540 responseArrayNode: MutableMap<String, JsonNode>,
541 metadata: MutableMap<String, String>?
543 val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping)
544 if (outputKeyMappingHasOnlyOneElement) {
545 val outputKeyMap = outputKeyMapping.entries.first()
546 val returnValue = parseObjectResponseNodeWithOneOutputKeyMapping(
547 responseArrayNode, outputKeyMap.key, outputKeyMap.value,
548 entrySchemaType, metadata
550 resourceAssignment.keyIdentifiers.add(KeyIdentifier(outputKeyMap.key, returnValue))
553 throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType")
557 private fun parseSingleElementNodeWithOneOutputKeyMapping(
558 resourceAssignment: ResourceAssignment,
559 responseSingleJsonNode: JsonNode,
560 outputKeyMappingKey: String,
561 outputKeyMappingValue: String,
563 metadata: MutableMap<String, String>?
565 val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
567 val responseKeyValue = if (responseSingleJsonNode.has(outputKeyMappingValue)) {
568 responseSingleJsonNode.get(outputKeyMappingValue)
570 NullNode.getInstance()
573 logKeyValueResolvedResource(metadata, outputKeyMappingKey, responseKeyValue, type)
574 JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, responseKeyValue, type, arrayChildNode)
575 resourceAssignment.keyIdentifiers.find { it.name == outputKeyMappingKey && it.value.isArray }
578 (it.value as ArrayNode).add(responseKeyValue)
580 resourceAssignment.keyIdentifiers.add(
581 KeyIdentifier(outputKeyMappingKey, responseKeyValue))
583 return arrayChildNode
586 private fun parseSingleElementNodeWithAllOutputKeyMapping(
587 resourceAssignment: ResourceAssignment,
588 responseSingleJsonNode: JsonNode,
589 outputKeyMapping: MutableMap<String, String>,
591 metadata: MutableMap<String, String>?
593 val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
594 outputKeyMapping.map {
595 val responseKeyValue = if (responseSingleJsonNode.has(it.value)) {
596 responseSingleJsonNode.get(it.value)
598 NullNode.getInstance()
601 logKeyValueResolvedResource(metadata, it.key, responseKeyValue, type)
602 JacksonUtils.populateJsonNodeValues(it.key, responseKeyValue, type, arrayChildNode)
603 resourceAssignment.keyIdentifiers.add(KeyIdentifier(it.key, responseKeyValue))
605 return arrayChildNode
608 private fun parseObjectResponseNodeWithOneOutputKeyMapping(
609 responseArrayNode: MutableMap<String, JsonNode>,
610 outputKeyMappingKey: String,
611 outputKeyMappingValue: String,
613 metadata: MutableMap<String, String>?
615 val objectNode = JacksonUtils.objectMapper.createObjectNode()
616 val responseSingleJsonNode = responseArrayNode.filterKeys { key ->
617 key == outputKeyMappingValue
618 }.entries.firstOrNull()
620 if (responseSingleJsonNode == null) {
621 logKeyValueResolvedResource(metadata, outputKeyMappingKey, NullNode.getInstance(), type)
622 JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, NullNode.getInstance(), type, objectNode)
624 logKeyValueResolvedResource(metadata, outputKeyMappingKey, responseSingleJsonNode.value, type)
625 JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, responseSingleJsonNode.value, type, objectNode)
630 private fun parseResponseNodeForComplexType(
631 responseNode: JsonNode,
632 resourceAssignment: ResourceAssignment,
633 raRuntimeService: ResourceAssignmentRuntimeService,
634 outputKeyMapping: MutableMap<String, String>
636 val entrySchemaType = resourceAssignment.property!!.type
637 val dictionaryName = resourceAssignment.dictionaryName!!
638 val metadata = resourceAssignment.property!!.metadata
639 val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping)
641 if (outputKeyMapping.isNotEmpty()) {
643 checkOutputKeyMappingAllElementsInDataTypeProperties(
648 parseSingleElementNodeWithAllOutputKeyMapping(
656 outputKeyMappingHasOnlyOneElement -> {
657 val outputKeyMap = outputKeyMapping.entries.first()
658 parseSingleElementNodeWithOneOutputKeyMapping(
659 resourceAssignment, responseNode, outputKeyMap.key,
660 outputKeyMap.value, entrySchemaType, metadata
664 throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType")
668 val childNode = JacksonUtils.objectMapper.createObjectNode()
669 JacksonUtils.populateJsonNodeValues(dictionaryName, responseNode, entrySchemaType, childNode)
674 private fun checkOutputKeyMappingAllElementsInDataTypeProperties(
675 dataTypeName: String,
676 outputKeyMapping: MutableMap<String, String>,
677 raRuntimeService: ResourceAssignmentRuntimeService
679 val dataTypeProps = raRuntimeService.bluePrintContext().dataTypeByName(dataTypeName)?.properties
680 val result = outputKeyMapping.filterKeys { !dataTypeProps!!.containsKey(it) }.keys.firstOrNull()
681 return result == null
684 private fun logKeyValueResolvedResource(
685 metadata: MutableMap<String, String>?,
690 val valueToPrint = getValueToLog(metadata, value)
693 "For List Type Resource: key ($key), value ($valueToPrint), " +
698 private fun checkIfOutputKeyMappingProvideOneElement(outputKeyMapping: MutableMap<String, String>): Boolean {
699 return (outputKeyMapping.size == 1)
702 fun getValueToLog(metadata: MutableMap<String, String>?, value: Any): Any =
703 if (hasLogProtect(metadata)) LOG_REDACTED else value