Improve logging for ResourceAssingmentUtils
[ccsdk/cds.git] / ms / blueprintsprocessor / functions / resource-resolution / src / main / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / functions / resource / resolution / utils / ResourceAssignmentUtils.kt
index 7bb757b..1be9649 100644 (file)
@@ -19,6 +19,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.uti
 
 import com.fasterxml.jackson.databind.JsonNode
 import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.SerializationFeature
 import com.fasterxml.jackson.databind.node.ArrayNode
 import com.fasterxml.jackson.databind.node.NullNode
 import com.fasterxml.jackson.databind.node.ObjectNode
@@ -39,6 +40,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
 import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty
 import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintVelocityTemplateService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
@@ -127,6 +129,32 @@ class ResourceAssignmentUtils {
             raRuntimeService.putResolutionStore(resourceAssignment.name, value)
             raRuntimeService.putDictionaryStore(resourceAssignment.dictionaryName!!, value)
             resourceAssignment.property!!.value = value
+
+            val metadata = resourceAssignment.property?.metadata
+            metadata?.get(ResourceResolutionConstants.METADATA_TRANSFORM_TEMPLATE)
+                    ?.let { if (it.contains("$")) it else null }
+                    ?.let { template ->
+                        val resolutionStore = raRuntimeService.getResolutionStore()
+                                .mapValues { e -> e.value.asText() } as MutableMap<String, Any>
+                        val newValue: JsonNode
+                        try {
+                            newValue = BluePrintVelocityTemplateService
+                                    .generateContent(template, null, true, resolutionStore)
+                                    .also { if (hasLogProtect(metadata))
+                                        logger.info("Transformed value: $resourceAssignment.name")
+                                    else
+                                        logger.info("Transformed value: $value -> $it") }
+                                    .let { v -> v.asJsonType() }
+                        } catch (e: Exception) {
+                            throw BluePrintProcessorException(
+                                    "transform-template failed: $template", e)
+                        }
+                        with(resourceAssignment) {
+                            raRuntimeService.putResolutionStore(this.name, newValue)
+                            raRuntimeService.putDictionaryStore(this.dictionaryName!!, newValue)
+                            this.property!!.value = newValue
+                        }
+                    }
         }
 
         fun setFailedResourceDataValue(resourceAssignment: ResourceAssignment, message: String?) {
@@ -154,6 +182,7 @@ class ResourceAssignmentUtils {
             val result: String
             try {
                 val mapper = ObjectMapper()
+                mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true)
                 val root: ObjectNode = mapper.createObjectNode()
 
                 var containsLogProtected = false
@@ -169,7 +198,8 @@ class ResourceAssignmentUtils {
                         root.set<JsonNode>(rName, value)
                     }
                 }
-                result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root)
+                result = mapper.writerWithDefaultPrettyPrinter()
+                        .writeValueAsString(mapper.treeToValue(root, Object::class.java))
 
                 if (!containsLogProtected) {
                     logger.info("Generated Resource Param Data ($result)")
@@ -203,18 +233,40 @@ class ResourceAssignmentUtils {
             resourceAssignments: List<ResourceAssignment>,
             resourceDefinitions: Map<String, ResourceDefinition>
         ): String {
+            val emptyTextNode = TextNode.valueOf("")
             val resolutionSummaryList = resourceAssignments.map {
                 val definition = resourceDefinitions[it.name]
-                val payload = definition?.sources?.get(it.dictionarySource)
+                val description = definition?.property?.description ?: ""
+                val value = it.property?.value
+                        ?.let { v -> if (v.isNullOrMissing()) emptyTextNode else v }
+                        ?: emptyTextNode
+
+                var payload: JsonNode = definition?.sources?.get(it.dictionarySource)
                         ?.properties?.get("resolved-payload")
+                        ?.let { p -> if (p.isNullOrMissing()) emptyTextNode else p }
+                        ?: emptyTextNode
+
                 val metadata = definition?.property?.metadata
                         ?.map { e -> DictionaryMetadataEntry(e.key, e.value) }
                         ?.toMutableList() ?: mutableListOf()
-                val description = definition?.property?.description
+
+                val keyIdentifiers: MutableList<KeyIdentifier> = it.keyIdentifiers.map { k ->
+                    if (k.value.isNullOrMissing()) KeyIdentifier(k.name, emptyTextNode) else k
+                }.toMutableList()
+
                 ResolutionSummary(
-                        it.name, it.property?.value, it.property?.required, it.property?.type,
-                        it.keyIdentifiers, description, metadata, it.dictionaryName,
-                        it.dictionarySource, payload, it.status, it.message
+                        it.name,
+                        value,
+                        it.property?.required ?: false,
+                        it.property?.type ?: "",
+                        keyIdentifiers,
+                        description,
+                        metadata,
+                        it.dictionaryName ?: "",
+                        it.dictionarySource ?: "",
+                        payload,
+                        it.status ?: "",
+                        it.message ?: ""
                 )
             }
             // Wrapper needed for integration with SDNC