Refactoring Resource Resolution Service
[ccsdk/cds.git] / ms / blueprintsprocessor / functions / resource-resolution / src / main / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / functions / resource / resolution / ResourceResolutionService.kt
index b9b7103..7272a3d 100644 (file)
@@ -26,122 +26,182 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.R
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolutionService
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.ResourceAssignmentProcessor
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
-import org.onap.ccsdk.cds.controllerblueprints.core.*
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceDefinitionUtils.createResourceAssignments
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
+import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
+import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants.LOG_REDACTED
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.utils.BulkResourceSequencingUtils
 import org.slf4j.LoggerFactory
 import org.springframework.context.ApplicationContext
 import org.springframework.stereotype.Service
+import java.util.UUID
 
 interface ResourceResolutionService {
 
     fun registeredResourceSources(): List<String>
 
-    suspend fun resolveFromDatabase(bluePrintRuntimeService: BluePrintRuntimeService<*>, artifactTemplate: String,
-                                    resolutionKey: String): String
-
-    suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
-                                 artifactNames: List<String>, properties: Map<String, Any>): MutableMap<String, JsonNode>
-
-    suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
-                                 artifactPrefix: String, properties: Map<String, Any>): String
-
-    suspend fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>,
-                                           resourceDefinitions: MutableMap<String, ResourceDefinition>,
-                                           resourceAssignments: MutableList<ResourceAssignment>,
-                                           artifactPrefix: String,
-                                           properties: Map<String, Any>)
+    suspend fun resolveFromDatabase(
+        bluePrintRuntimeService: BluePrintRuntimeService<*>,
+        artifactTemplate: String,
+        resolutionKey: String
+    ): String
+
+    suspend fun resolveResources(
+        bluePrintRuntimeService: BluePrintRuntimeService<*>,
+        nodeTemplateName: String,
+        artifactNames: List<String>,
+        properties: Map<String, Any>
+    ): MutableMap<String, String>
+
+    suspend fun resolveResources(
+        bluePrintRuntimeService: BluePrintRuntimeService<*>,
+        nodeTemplateName: String,
+        artifactPrefix: String,
+        properties: Map<String, Any>
+    ): String
+
+    /** Resolve resources for all the sources defined in a particular resource Definition[resolveDefinition]
+     * with other [resourceDefinitions] dependencies for the sources [sources]
+     * Used to get the same resource values from multiple sources. **/
+    suspend fun resolveResourceDefinition(
+        blueprintRuntimeService: BluePrintRuntimeService<*>,
+        resourceDefinitions: MutableMap<String, ResourceDefinition>,
+        resolveDefinition: String,
+        sources: List<String>
+    ):
+            MutableMap<String, JsonNode>
+
+    suspend fun resolveResourceAssignments(
+        blueprintRuntimeService: BluePrintRuntimeService<*>,
+        resourceDefinitions: MutableMap<String, ResourceDefinition>,
+        resourceAssignments: MutableList<ResourceAssignment>,
+        artifactPrefix: String,
+        properties: Map<String, Any>
+    )
 }
 
 @Service(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)
-open class ResourceResolutionServiceImpl(private var applicationContext: ApplicationContext,
-                                         private var templateResolutionDBService: TemplateResolutionService,
-                                         private var blueprintTemplateService: BluePrintTemplateService,
-                                         private var resourceResolutionDBService: ResourceResolutionDBService) :
-        ResourceResolutionService {
+open class ResourceResolutionServiceImpl(
+    private var applicationContext: ApplicationContext,
+    private var templateResolutionDBService: TemplateResolutionService,
+    private var blueprintTemplateService: BluePrintTemplateService,
+    private var resourceResolutionDBService: ResourceResolutionDBService
+) :
+    ResourceResolutionService {
 
     private val log = LoggerFactory.getLogger(ResourceResolutionService::class.java)
 
     override fun registeredResourceSources(): List<String> {
         return applicationContext.getBeanNamesForType(ResourceAssignmentProcessor::class.java)
-                .filter { it.startsWith(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) }
-                .map { it.substringAfter(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) }
+            .filter { it.startsWith(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) }
+            .map { it.substringAfter(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) }
     }
 
-    override suspend fun resolveFromDatabase(bluePrintRuntimeService: BluePrintRuntimeService<*>,
-                                             artifactTemplate: String,
-                                             resolutionKey: String): String {
+    override suspend fun resolveFromDatabase(
+        bluePrintRuntimeService: BluePrintRuntimeService<*>,
+        artifactTemplate: String,
+        resolutionKey: String
+    ): String {
         return templateResolutionDBService.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
-                bluePrintRuntimeService,
-                artifactTemplate,
-                resolutionKey)
+            bluePrintRuntimeService,
+            artifactTemplate,
+            resolutionKey
+        )
     }
 
-    override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
-                                          artifactNames: List<String>,
-                                          properties: Map<String, Any>): MutableMap<String, JsonNode> {
+    override suspend fun resolveResources(
+        bluePrintRuntimeService: BluePrintRuntimeService<*>,
+        nodeTemplateName: String,
+        artifactNames: List<String>,
+        properties: Map<String, Any>
+    ): MutableMap<String, String> {
 
         val resourceAssignmentRuntimeService =
             ResourceAssignmentUtils.transformToRARuntimeService(bluePrintRuntimeService, artifactNames.toString())
 
-        val resolvedParams: MutableMap<String, JsonNode> = hashMapOf()
+        val resolvedParams: MutableMap<String, String> = hashMapOf()
         artifactNames.forEach { artifactName ->
-            val resolvedContent = resolveResources(resourceAssignmentRuntimeService, nodeTemplateName,
-                artifactName, properties)
+            val resolvedContent = resolveResources(
+                resourceAssignmentRuntimeService, nodeTemplateName,
+                artifactName, properties
+            )
 
-            resolvedParams[artifactName] = resolvedContent.asJsonType()
+            resolvedParams[artifactName] = resolvedContent
         }
         return resolvedParams
     }
 
-
-    override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
-                                          artifactPrefix: String, properties: Map<String, Any>): String {
+    override suspend fun resolveResources(
+        bluePrintRuntimeService: BluePrintRuntimeService<*>,
+        nodeTemplateName: String,
+        artifactPrefix: String,
+        properties: Map<String, Any>
+    ): String {
 
         // Velocity Artifact Definition Name
         val artifactTemplate = "$artifactPrefix-template"
         // Resource Assignment Artifact Definition Name
         val artifactMapping = "$artifactPrefix-mapping"
 
-        val resolvedContent: String
-        log.info("Resolving resource for template artifact($artifactTemplate) with resource assignment artifact($artifactMapping)")
+        log.info("Resolving resource with resource assignment artifact($artifactMapping)")
 
         val resourceAssignmentContent =
-                bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactMapping)
+            bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactMapping)
 
         val resourceAssignments: MutableList<ResourceAssignment> =
-                JacksonUtils.getListFromJson(resourceAssignmentContent, ResourceAssignment::class.java)
-                        as? MutableList<ResourceAssignment>
-                        ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions")
+            JacksonUtils.getListFromJson(resourceAssignmentContent, ResourceAssignment::class.java)
+                    as? MutableList<ResourceAssignment>
+                ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions")
 
         if (isToStore(properties)) {
             val existingResourceResolution = isNewResolution(bluePrintRuntimeService, properties, artifactPrefix)
             if (existingResourceResolution.isNotEmpty()) {
-                updateResourceAssignmentWithExisting(bluePrintRuntimeService as ResourceAssignmentRuntimeService,
-                    existingResourceResolution, resourceAssignments)
+                updateResourceAssignmentWithExisting(
+                    bluePrintRuntimeService as ResourceAssignmentRuntimeService,
+                    existingResourceResolution, resourceAssignments
+                )
             }
         }
 
         // Get the Resource Dictionary Name
         val resourceDefinitions: MutableMap<String, ResourceDefinition> = ResourceAssignmentUtils
-                .resourceDefinitions(bluePrintRuntimeService.bluePrintContext().rootPath)
+            .resourceDefinitions(bluePrintRuntimeService.bluePrintContext().rootPath)
 
         // Resolve resources
-        resolveResourceAssignments(bluePrintRuntimeService,
-                resourceDefinitions,
-                resourceAssignments,
-                artifactPrefix,
-                properties)
+        resolveResourceAssignments(
+            bluePrintRuntimeService,
+            resourceDefinitions,
+            resourceAssignments,
+            artifactPrefix,
+            properties
+        )
 
         val resolvedParamJsonContent =
-                ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList())
-
-        resolvedContent = blueprintTemplateService.generateContent(bluePrintRuntimeService, nodeTemplateName,
-                artifactTemplate, resolvedParamJsonContent)
+            ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList())
+
+        val artifactTemplateDefinition = bluePrintRuntimeService.bluePrintContext().checkNodeTemplateArtifact(nodeTemplateName, artifactTemplate)
+
+        val resolvedContent = if (artifactTemplateDefinition != null) {
+            blueprintTemplateService.generateContent(
+                bluePrintRuntimeService, nodeTemplateName,
+                artifactTemplate, resolvedParamJsonContent, false,
+                mutableMapOf(
+                    ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE to
+                            properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE].asJsonPrimitive()
+                )
+            )
+        } else {
+            resolvedParamJsonContent
+        }
 
         if (isToStore(properties)) {
             templateResolutionDBService.write(properties, resolvedContent, bluePrintRuntimeService, artifactPrefix)
@@ -151,81 +211,109 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
         return resolvedContent
     }
 
+    override suspend fun resolveResourceDefinition(
+        blueprintRuntimeService: BluePrintRuntimeService<*>,
+        resourceDefinitions: MutableMap<String, ResourceDefinition>,
+        resolveDefinition: String,
+        sources: List<String>
+    ): MutableMap<String, JsonNode> {
+
+        // Populate Dummy Resource Assignments
+        val resourceAssignments = createResourceAssignments(resourceDefinitions, resolveDefinition, sources)
+
+        resolveResourceAssignments(
+            blueprintRuntimeService, resourceDefinitions, resourceAssignments,
+            UUID.randomUUID().toString(), hashMapOf()
+        )
+
+        // Get the data from Resource Assignments
+        return ResourceAssignmentUtils.generateResourceForAssignments(resourceAssignments)
+    }
+
     /**
      * Iterate the Batch, get the Resource Assignment, dictionary Name, Look for the Resource definition for the
      * name, then get the type of the Resource Definition, Get the instance for the Resource Type and process the
      * request.
      */
-    override suspend fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>,
-                                                    resourceDefinitions: MutableMap<String, ResourceDefinition>,
-                                                    resourceAssignments: MutableList<ResourceAssignment>,
-                                                    artifactPrefix: String,
-                                                    properties: Map<String, Any>) {
+    override suspend fun resolveResourceAssignments(
+        blueprintRuntimeService: BluePrintRuntimeService<*>,
+        resourceDefinitions: MutableMap<String, ResourceDefinition>,
+        resourceAssignments: MutableList<ResourceAssignment>,
+        artifactPrefix: String,
+        properties: Map<String, Any>
+    ) {
 
         val bulkSequenced = BulkResourceSequencingUtils.process(resourceAssignments)
 
         // Check the BlueprintRuntime Service Should be ResourceAssignmentRuntimeService
-        val resourceAssignmentRuntimeService = if (!(blueprintRuntimeService is ResourceAssignmentRuntimeService)) {
+        val resourceAssignmentRuntimeService = if (blueprintRuntimeService !is ResourceAssignmentRuntimeService) {
             ResourceAssignmentUtils.transformToRARuntimeService(blueprintRuntimeService, artifactPrefix)
         } else {
             blueprintRuntimeService
         }
 
+        exposeOccurrencePropertyInResourceAssignments(resourceAssignmentRuntimeService, properties)
 
         coroutineScope {
             bulkSequenced.forEach { batchResourceAssignments ->
                 // Execute Non Dependent Assignments in parallel ( ie asynchronously )
                 val deferred = batchResourceAssignments
-                        .filter { it.name != "*" && it.name != "start" }
-                        .filter { it.status != BluePrintConstants.STATUS_SUCCESS }
-                        .map { resourceAssignment ->
-                            async {
-                                val dictionaryName = resourceAssignment.dictionaryName
-                                val dictionarySource = resourceAssignment.dictionarySource
-
-                                val processorName = processorName(dictionaryName!!, dictionarySource!!, resourceDefinitions)
-
-                                val resourceAssignmentProcessor =
-                                        applicationContext.getBean(processorName) as? ResourceAssignmentProcessor
-                                                ?: throw BluePrintProcessorException("failed to get resource processor ($processorName) " +
-                                                        "for resource assignment(${resourceAssignment.name})")
-                                try {
-                                    // Set BluePrint Runtime Service
-                                    resourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService
-                                    // Set Resource Dictionaries
-                                    resourceAssignmentProcessor.resourceDictionaries = resourceDefinitions
-                                    // Invoke Apply Method
-                                    resourceAssignmentProcessor.applyNB(resourceAssignment)
-
-                                    if (isToStore(properties)) {
-                                        resourceResolutionDBService.write(properties,
-                                                blueprintRuntimeService,
-                                                artifactPrefix,
-                                                resourceAssignment)
-                                        log.info("Resource resolution saved into database successfully : ($resourceAssignment)")
-                                    }
-
-                                    // Set errors from RA
-                                    blueprintRuntimeService.setBluePrintError(resourceAssignmentRuntimeService.getBluePrintError())
-                                } catch (e: RuntimeException) {
-                                    log.error("Fail in processing ${resourceAssignment.name}", e)
-                                    throw BluePrintProcessorException(e)
+                    .filter { it.name != "*" && it.name != "start" }
+                    .filter { it.status != BluePrintConstants.STATUS_SUCCESS }
+                    .map { resourceAssignment ->
+                        async {
+                            val dictionaryName = resourceAssignment.dictionaryName
+                            val dictionarySource = resourceAssignment.dictionarySource
+
+                            val processorName = processorName(dictionaryName!!, dictionarySource!!, resourceDefinitions)
+
+                            val resourceAssignmentProcessor =
+                                applicationContext.getBean(processorName) as? ResourceAssignmentProcessor
+                                    ?: throw BluePrintProcessorException(
+                                        "failed to get resource processor ($processorName) " +
+                                                "for resource assignment(${resourceAssignment.name})"
+                                    )
+                            try {
+                                // Set BluePrint Runtime Service
+                                resourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService
+                                // Set Resource Dictionaries
+                                resourceAssignmentProcessor.resourceDictionaries = resourceDefinitions
+                                // Invoke Apply Method
+                                resourceAssignmentProcessor.applyNB(resourceAssignment)
+
+                                if (isToStore(properties)) {
+                                    resourceResolutionDBService.write(
+                                        properties,
+                                        blueprintRuntimeService,
+                                        artifactPrefix,
+                                        resourceAssignment
+                                    )
+                                    log.info("Resource resolution saved into database successfully : (${resourceAssignment.name})")
                                 }
+
+                                // Set errors from RA
+                                blueprintRuntimeService.setBluePrintError(resourceAssignmentRuntimeService.getBluePrintError())
+                            } catch (e: RuntimeException) {
+                                log.error("Fail in processing ${resourceAssignment.name}", e)
+                                throw BluePrintProcessorException(e)
                             }
                         }
+                    }
                 log.debug("Resolving (${deferred.size})resources parallel.")
                 deferred.awaitAll()
             }
         }
-
     }
 
     /**
      * If the Source instance is "input", then it is not mandatory to have source Resource Definition, So it can
      *  derive the default input processor.
      */
-    private fun processorName(dictionaryName: String, dictionarySource: String,
-                              resourceDefinitions: MutableMap<String, ResourceDefinition>): String {
+    private fun processorName(
+        dictionaryName: String,
+        dictionarySource: String,
+        resourceDefinitions: MutableMap<String, ResourceDefinition>
+    ): String {
         val processorName: String = when (dictionarySource) {
             "input" -> {
                 "${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-input"
@@ -235,10 +323,10 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
             }
             else -> {
                 val resourceDefinition = resourceDefinitions[dictionaryName]
-                        ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dictionaryName")
+                    ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dictionaryName")
 
                 val resourceSource = resourceDefinition.sources[dictionarySource]
-                        ?: throw BluePrintProcessorException("couldn't get resource definition $dictionaryName source($dictionarySource)")
+                    ?: throw BluePrintProcessorException("couldn't get resource definition $dictionaryName source($dictionarySource)")
 
                 ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR.plus(resourceSource.type)
             }
@@ -248,19 +336,20 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
         }
 
         return processorName
-
     }
 
     // Check whether to store or not the resolution of resource and template
     private fun isToStore(properties: Map<String, Any>): Boolean {
-        return properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT)
-                && properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean
+        return properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) &&
+                properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean
     }
 
     // Check whether resolution already exist in the database for the specified resolution-key or resourceId/resourceType
-    private suspend fun isNewResolution(bluePrintRuntimeService: BluePrintRuntimeService<*>,
-                                        properties: Map<String, Any>,
-                                        artifactPrefix: String): List<ResourceResolution> {
+    private suspend fun isNewResolution(
+        bluePrintRuntimeService: BluePrintRuntimeService<*>,
+        properties: Map<String, Any>,
+        artifactPrefix: String
+    ): List<ResourceResolution> {
         val occurrence = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] as Int
         val resolutionKey = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] as String
         val resourceId = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] as String
@@ -268,28 +357,34 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
 
         if (resolutionKey.isNotEmpty()) {
             val existingResourceAssignments =
-                    resourceResolutionDBService.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
-                            bluePrintRuntimeService,
-                            resolutionKey,
-                            occurrence,
-                            artifactPrefix)
+                resourceResolutionDBService.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
+                    bluePrintRuntimeService,
+                    resolutionKey,
+                    occurrence,
+                    artifactPrefix
+                )
             if (existingResourceAssignments.isNotEmpty()) {
-                log.info("Resolution with resolutionKey=($resolutionKey) already exist - will resolve all resources not already resolved.",
-                        resolutionKey)
+                log.info(
+                    "Resolution with resolutionKey=($resolutionKey) already exist - will resolve all resources not already resolved.",
+                    resolutionKey
+                )
             }
             return existingResourceAssignments
         } else if (resourceId.isNotEmpty() && resourceType.isNotEmpty()) {
             val existingResourceAssignments =
-                    resourceResolutionDBService.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
-                            bluePrintRuntimeService,
-                            resourceId,
-                            resourceType,
-
-                            occurrence,
-                            artifactPrefix)
+                resourceResolutionDBService.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
+                    bluePrintRuntimeService,
+                    resourceId,
+                    resourceType,
+
+                    occurrence,
+                    artifactPrefix
+                )
             if (existingResourceAssignments.isNotEmpty()) {
-                log.info("Resolution with resourceId=($resourceId) and resourceType=($resourceType) already exist - will resolve " +
-                        "all resources not already resolved.")
+                log.info(
+                    "Resolution with resourceId=($resourceId) and resourceType=($resourceType) already exist - will resolve " +
+                            "all resources not already resolved."
+                )
             }
             return existingResourceAssignments
         }
@@ -297,15 +392,22 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
     }
 
     // Update the resource assignment list with the status of the resource that have already been resolved
-    private fun updateResourceAssignmentWithExisting(raRuntimeService : ResourceAssignmentRuntimeService,
-                                                     resourceResolutionList: List<ResourceResolution>,
-                                                     resourceAssignmentList: MutableList<ResourceAssignment>) {
+    private fun updateResourceAssignmentWithExisting(
+        raRuntimeService: ResourceAssignmentRuntimeService,
+        resourceResolutionList: List<ResourceResolution>,
+        resourceAssignmentList: MutableList<ResourceAssignment>
+    ) {
         resourceResolutionList.forEach { resourceResolution ->
             if (resourceResolution.status == BluePrintConstants.STATUS_SUCCESS) {
                 resourceAssignmentList.forEach {
                     if (compareOne(resourceResolution, it)) {
-                        log.info("Resource ({}) already resolve: value=({})", it.name, resourceResolution.value)
-                        val value = resourceResolution.value!!.asJsonPrimitive()
+                        log.info(
+                            "Resource ({}) already resolved: value=({})", it.name,
+                            if (hasLogProtect(it.property)) LOG_REDACTED else resourceResolution.value
+                        )
+
+                        // Make sure to recreate value as per the defined type.
+                        val value = resourceResolution.value!!.asJsonType(it.property!!.type)
                         it.property!!.value = value
                         it.status = resourceResolution.status
                         ResourceAssignmentUtils.setResourceDataValue(it, raRuntimeService, value)
@@ -317,10 +419,19 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
 
     // Comparision between what we have in the database vs what we have to assign.
     private fun compareOne(resourceResolution: ResourceResolution, resourceAssignment: ResourceAssignment): Boolean {
-        return (resourceResolution.name == resourceAssignment.name
-                && resourceResolution.dictionaryName == resourceAssignment.dictionaryName
-                && resourceResolution.dictionarySource == resourceAssignment.dictionarySource
-                && resourceResolution.dictionaryVersion == resourceAssignment.version)
+        return (resourceResolution.name == resourceAssignment.name &&
+                resourceResolution.dictionaryName == resourceAssignment.dictionaryName &&
+                resourceResolution.dictionarySource == resourceAssignment.dictionarySource &&
+                resourceResolution.dictionaryVersion == resourceAssignment.version)
     }
 
+    private fun exposeOccurrencePropertyInResourceAssignments(
+        raRuntimeService: ResourceAssignmentRuntimeService,
+        properties: Map<String, Any>
+    ) {
+        raRuntimeService.putResolutionStore(
+            ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE,
+            properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE].asJsonPrimitive()
+        )
+    }
 }