Allow multiple resolution for same node template 43/90243/9
authorAlexis de Talhouët <adetalhouet89@gmail.com>
Thu, 20 Jun 2019 18:14:37 +0000 (14:14 -0400)
committerAlexis de Talhouët <adetalhouet89@gmail.com>
Tue, 25 Jun 2019 18:33:28 +0000 (18:33 +0000)
- also fixing default mechanism
- fixes rest resolution when NullNode is returned as input value
- fixes rest resolution when data type specified so raw json isn't
returned, only the parsed json based on the data type

Change-Id: I1f4a35c6c97000b52620c9b0cc911f15016c4e80
Issue-ID: CCSDK-1422
Signed-off-by: Alexis de Talhouët <adetalhouet89@gmail.com>
components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintRuntimeService.kt
ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateServiceTest.kt

index f437a79..1c81b7f 100644 (file)
               "required": false,
               "type": "string"
             },
+            "occurrence": {
+              "description": "Number of time to perform the resolution.",
+              "required": false,
+              "default": 1,
+              "type": "integer"
+            },
             "store-result": {
               "description": "Whether or not to store the output.",
               "required": false,
index 8191db7..0bc8376 100644 (file)
 
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution
 
+import com.fasterxml.jackson.databind.node.JsonNodeFactory
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
+import org.onap.ccsdk.cds.controllerblueprints.core.asObjectNode
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 import org.springframework.beans.factory.config.ConfigurableBeanFactory
 import org.springframework.context.annotation.Scope
@@ -33,28 +34,36 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
 
     override suspend fun processNB(executionRequest: ExecutionServiceInput) {
 
-        val properties: MutableMap<String, Any> = mutableMapOf()
+        val occurrence = getOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE)
+        val key = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY)
+        val storeResult = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT)
 
-        try {
-            val key = getOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY)
-            val storeResult = getOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT)
-            properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY] = key.asText()
-            properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = storeResult.asBoolean()
-        } catch (e: BluePrintProcessorException) {
-            // NoOp - these property aren't mandatory, so don't fail the process if not provided.
-        }
+        val properties: MutableMap<String, Any> = mutableMapOf()
+        properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] =
+            storeResult?.asBoolean() ?: false
 
         val artifactPrefixNamesNode = getOperationInput(ResourceResolutionConstants.INPUT_ARTIFACT_PREFIX_NAMES)
         val artifactPrefixNames = JacksonUtils.getListFromJsonNode(artifactPrefixNamesNode, String::class.java)
 
-        val resolvedParamContents = resourceResolutionService.resolveResources(bluePrintRuntimeService,
-            nodeTemplateName,
-            artifactPrefixNames,
-            properties)
+        val jsonResponse = JsonNodeFactory.instance.objectNode()
+        for (j in 1..occurrence.asInt()) {
+
+            val response = resourceResolutionService.resolveResources(bluePrintRuntimeService,
+                nodeTemplateName,
+                artifactPrefixNames,
+                properties)
+
+            // provide indexed result in output if we have multiple resolution
+            if (occurrence.asInt() != 1) {
+                jsonResponse.set(key?.asText() + "-" + j, response.asJsonNode())
+            } else {
+                jsonResponse.setAll(response.asObjectNode())
+            }
+        }
 
         // Set Output Attributes
         bluePrintRuntimeService.setNodeTemplateAttributeValue(nodeTemplateName,
-            ResourceResolutionConstants.OUTPUT_ASSIGNMENT_PARAMS, resolvedParamContents.asJsonNode())
+            ResourceResolutionConstants.OUTPUT_ASSIGNMENT_PARAMS, jsonResponse)
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
index d605c88..9d422f1 100644 (file)
@@ -24,8 +24,9 @@ object ResourceResolutionConstants {
         const val INPUT_ARTIFACT_PREFIX_NAMES = "artifact-prefix-names"
         const val OUTPUT_ASSIGNMENT_PARAMS = "assignment-params"
         const val FILE_NAME_RESOURCE_DEFINITION_TYPES = "resources_definition_types.json"
-        const val RESOURCE_RESOLUTION_INPUT_KEY = "resolution-key";
-        const val RESOURCE_RESOLUTION_INPUT_STORE_RESULT = "store-result";
+        const val RESOURCE_RESOLUTION_INPUT_KEY = "resolution-key"
+        const val RESOURCE_RESOLUTION_INPUT_STORE_RESULT = "store-result"
+        const val RESOURCE_RESOLUTION_INPUT_OCCURRENCE = "occurrence"
 
 
 }
\ No newline at end of file
index 7eefe95..6cf1c0b 100644 (file)
@@ -19,6 +19,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.pro
 
 import com.fasterxml.jackson.databind.node.ArrayNode
 import com.fasterxml.jackson.databind.node.MissingNode
+import com.fasterxml.jackson.databind.node.NullNode
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.RestResourceSource
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
@@ -54,20 +55,20 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
 
             // Check if It has Input
             val value = getFromInput(resourceAssignment)
-            if (value == null || value is MissingNode) {
+            if (value == null || value is MissingNode || value is NullNode) {
                 val dName = resourceAssignment.dictionaryName
                 val dSource = resourceAssignment.dictionarySource
                 val resourceDefinition = resourceDictionaries[dName]
-                        ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dName")
+                    ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dName")
 
                 val resourceSource = resourceDefinition.sources[dSource]
-                        ?: throw BluePrintProcessorException("couldn't get resource definition $dName source($dSource)")
+                    ?: throw BluePrintProcessorException("couldn't get resource definition $dName source($dSource)")
 
                 val resourceSourceProperties =
-                        checkNotNull(resourceSource.properties) { "failed to get source properties for $dName " }
+                    checkNotNull(resourceSource.properties) { "failed to get source properties for $dName " }
 
                 val sourceProperties =
-                        JacksonUtils.getInstanceFromMap(resourceSourceProperties, RestResourceSource::class.java)
+                    JacksonUtils.getInstanceFromMap(resourceSourceProperties, RestResourceSource::class.java)
 
                 val path = nullToEmpty(sourceProperties.path)
                 val inputKeyMapping =
@@ -77,7 +78,7 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
                 // Resolving content Variables
                 val payload = resolveFromInputKeyMapping(nullToEmpty(sourceProperties.payload), resolvedInputKeyMapping)
                 val urlPath =
-                        resolveFromInputKeyMapping(checkNotNull(sourceProperties.urlPath), resolvedInputKeyMapping)
+                    resolveFromInputKeyMapping(checkNotNull(sourceProperties.urlPath), resolvedInputKeyMapping)
                 val verb = resolveFromInputKeyMapping(nullToEmpty(sourceProperties.verb), resolvedInputKeyMapping)
 
                 logger.info("$dSource dictionary information : ($urlPath), ($inputKeyMapping), (${sourceProperties.outputKeyMapping})")
@@ -90,7 +91,8 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
                 if (responseStatusCode in 200..299 && !responseBody.isBlank()) {
                     populateResource(resourceAssignment, sourceProperties, responseBody, path)
                 } else {
-                    val errMsg = "Failed to get $dSource result for dictionary name ($dName) using urlPath ($urlPath) response_code: ($responseStatusCode)"
+                    val errMsg =
+                        "Failed to get $dSource result for dictionary name ($dName) using urlPath ($urlPath) response_code: ($responseStatusCode)"
                     logger.warn(errMsg)
                     throw BluePrintProcessorException(errMsg)
                 }
@@ -100,12 +102,12 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
         } catch (e: Exception) {
             ResourceAssignmentUtils.setFailedResourceDataValue(resourceAssignment, e.message)
             throw BluePrintProcessorException("Failed in template key ($resourceAssignment) assignments with: ${e.message}",
-                    e)
+                e)
         }
     }
 
     fun blueprintWebClientService(resourceAssignment: ResourceAssignment,
-                                          restResourceSource: RestResourceSource): BlueprintWebClientService {
+                                  restResourceSource: RestResourceSource): BlueprintWebClientService {
         return if (isNotEmpty(restResourceSource.endpointSelector)) {
             val restPropertiesJson = raRuntimeService.resolveDSLExpression(restResourceSource.endpointSelector!!)
             blueprintRestLibPropertyService.blueprintWebClientService(restPropertiesJson)
@@ -143,7 +145,7 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
                 entrySchemaType = checkNotEmpty(resourceAssignment.property?.entrySchema?.type) {
                     "Entry schema is not defined for dictionary ($dName) info"
                 }
-                val arrayNode = responseNode as ArrayNode
+                val arrayNode = JacksonUtils.objectMapper.createArrayNode()
 
                 if (entrySchemaType !in BluePrintTypes.validPrimitiveTypes()) {
 
@@ -155,13 +157,13 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
                         outputKeyMapping.map {
                             val responseKeyValue = responseSingleJsonNode.get(it.key)
                             val propertyTypeForDataType = ResourceAssignmentUtils
-                                    .getPropertyType(raRuntimeService, entrySchemaType, it.key)
+                                .getPropertyType(raRuntimeService, entrySchemaType, it.key)
 
                             logger.info("For List Type Resource: key (${it.key}), value ($responseKeyValue), " +
                                     "type  ({$propertyTypeForDataType})")
 
                             JacksonUtils.populateJsonNodeValues(it.value,
-                                    responseKeyValue, propertyTypeForDataType, arrayChildNode)
+                                responseKeyValue, propertyTypeForDataType, arrayChildNode)
                         }
                         arrayNode.add(arrayChildNode)
                     }
@@ -179,7 +181,7 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
                 outputKeyMapping.map {
                     val responseKeyValue = responseNode.get(it.key)
                     val propertyTypeForDataType = ResourceAssignmentUtils
-                            .getPropertyType(raRuntimeService, entrySchemaType, it.key)
+                        .getPropertyType(raRuntimeService, entrySchemaType, it.key)
 
                     logger.info("For List Type Resource: key (${it.key}), value ($responseKeyValue), type  ({$propertyTypeForDataType})")
                     JacksonUtils.populateJsonNodeValues(it.value, responseKeyValue, propertyTypeForDataType, objectNode)
index 0819ed7..b48e446 100644 (file)
@@ -91,7 +91,8 @@ interface BluePrintRuntimeService<T> {
 
     fun setInputValue(propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode)
 
-    fun setWorkflowInputValue(workflowName: String, propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode)
+    fun setWorkflowInputValue(workflowName: String, propertyName: String, propertyDefinition: PropertyDefinition,
+                              value: JsonNode)
 
     fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode)
 
@@ -133,7 +134,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
     : BluePrintRuntimeService<MutableMap<String, JsonNode>> {
 
     @Transient
-    private val log= LoggerFactory.getLogger(BluePrintRuntimeService::class.toString())
+    private val log = LoggerFactory.getLogger(BluePrintRuntimeService::class.toString())
 
     private var store: MutableMap<String, JsonNode> = hashMapOf()
 
@@ -144,7 +145,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
          * Load Blueprint Environments Properties
          */
         val absoluteEnvFilePath = bluePrintContext.rootPath.plus(File.separator)
-                .plus(BluePrintConstants.TOSCA_ENVIRONMENTS_DIR)
+            .plus(BluePrintConstants.TOSCA_ENVIRONMENTS_DIR)
         loadEnvironments(BluePrintConstants.PROPERTY_BPP, absoluteEnvFilePath)
 
     }
@@ -213,7 +214,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
     override fun loadEnvironments(type: String, fileName: String) {
         BluePrintMetadataUtils.environmentFileProperties(fileName).forEach { key, value ->
             setNodeTemplateAttributeValue(type, key.toString(), value.toString()
-                    .asJsonPrimitive())
+                .asJsonPrimitive())
         }
     }
 
@@ -227,7 +228,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
 
         val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
 
-        propertyDefinitions.forEach { nodeTypePropertyName, nodeTypeProperty ->
+        propertyDefinitions.forEach { (nodeTypePropertyName, nodeTypeProperty) ->
             // Get the Express or Value for the Node Template
             val propertyAssignment: JsonNode? = propertyAssignments[nodeTypePropertyName]
 
@@ -236,13 +237,14 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
                 // Resolve the Expressing
                 val propertyAssignmentExpression = PropertyAssignmentService(this)
                 resolvedValue = propertyAssignmentExpression.resolveAssignmentExpression(nodeTemplateName,
-                        nodeTypePropertyName, propertyAssignment)
-            } else {
-                // Assign default value to the Operation
-                nodeTypeProperty.defaultValue?.let {
-                    resolvedValue = nodeTypeProperty.defaultValue!!
-                }
+                    nodeTypePropertyName, propertyAssignment)
             }
+
+            // Set default value if null
+            if (resolvedValue is NullNode) {
+                nodeTypeProperty.defaultValue?.let { resolvedValue = nodeTypeProperty.defaultValue!! }
+            }
+
             // Set for Return of method
             propertyAssignmentValue[nodeTypePropertyName] = resolvedValue
         }
@@ -258,7 +260,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
             val expression = propertyDefinition.value ?: propertyDefinition.defaultValue
             if (expression != null) {
                 propertyAssignmentValue[propertyName] = propertyAssignmentExpression.resolveAssignmentExpression(name,
-                        propertyName, expression)
+                    propertyName, expression)
             }
         }
         return propertyAssignmentValue
@@ -272,7 +274,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         propertyAssignments.forEach { propertyName, propertyExpression ->
             val propertyAssignmentExpression = PropertyAssignmentService(this)
             propertyAssignmentValue[propertyName] = propertyAssignmentExpression.resolveAssignmentExpression(name,
-                    propertyName, propertyExpression)
+                propertyName, propertyExpression)
         }
         return propertyAssignmentValue
     }
@@ -286,13 +288,13 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
 
         // Get the Node Type Definitions
         val nodeTypePropertieDefinitions: MutableMap<String, PropertyDefinition> = bluePrintContext
-                .nodeTypeChainedProperties(nodeTemplate.type)!!
+            .nodeTypeChainedProperties(nodeTemplate.type)!!
 
         /**
          * Resolve the NodeTemplate Property Assignment Values.
          */
         return resolveNodeTemplatePropertyAssignments(nodeTemplateName, nodeTypePropertieDefinitions,
-                propertyAssignments)
+            propertyAssignments)
     }
 
     override fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String):
@@ -304,13 +306,13 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         val propertyAssignments = nodeTemplate.capabilities?.get(capabilityName)?.properties ?: hashMapOf()
 
         val propertyDefinitions = bluePrintContext.nodeTemplateNodeType(nodeTemplateName)
-                .capabilities?.get(capabilityName)?.properties ?: hashMapOf()
+            .capabilities?.get(capabilityName)?.properties ?: hashMapOf()
 
         /**
          * Resolve the Capability Property Assignment Values.
          */
         return resolveNodeTemplatePropertyAssignments(nodeTemplateName, propertyDefinitions,
-                propertyAssignments)
+            propertyAssignments)
     }
 
     override fun resolveNodeTemplateInterfaceOperationInputs(nodeTemplateName: String,
@@ -320,14 +322,14 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
                 "($interfaceName), operationName($operationName)")
 
         val propertyAssignments: MutableMap<String, JsonNode> =
-                bluePrintContext.nodeTemplateInterfaceOperationInputs(nodeTemplateName, interfaceName, operationName)
-                        ?: hashMapOf()
+            bluePrintContext.nodeTemplateInterfaceOperationInputs(nodeTemplateName, interfaceName, operationName)
+                ?: hashMapOf()
 
         val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type
 
         val nodeTypeInterfaceOperationInputs: MutableMap<String, PropertyDefinition> =
-                bluePrintContext.nodeTypeInterfaceOperationInputs(nodeTypeName, interfaceName, operationName)
-                        ?: hashMapOf()
+            bluePrintContext.nodeTypeInterfaceOperationInputs(nodeTypeName, interfaceName, operationName)
+                ?: hashMapOf()
 
         log.info("input definition for node template ($nodeTemplateName), values ($propertyAssignments)")
 
@@ -335,7 +337,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
          * Resolve the Property Input Assignment Values.
          */
         return resolveNodeTemplatePropertyAssignments(nodeTemplateName, nodeTypeInterfaceOperationInputs,
-                propertyAssignments)
+            propertyAssignments)
 
     }
 
@@ -347,19 +349,19 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
                 "($interfaceName), operationName($operationName)")
 
         val propertyAssignments: MutableMap<String, JsonNode> =
-                bluePrintContext.nodeTemplateInterfaceOperationOutputs(nodeTemplateName, interfaceName, operationName)
-                        ?: hashMapOf()
+            bluePrintContext.nodeTemplateInterfaceOperationOutputs(nodeTemplateName, interfaceName, operationName)
+                ?: hashMapOf()
 
         val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type
 
         val nodeTypeInterfaceOperationOutputs: MutableMap<String, PropertyDefinition> =
-                bluePrintContext.nodeTypeInterfaceOperationOutputs(nodeTypeName, interfaceName, operationName)
-                        ?: hashMapOf()
+            bluePrintContext.nodeTypeInterfaceOperationOutputs(nodeTypeName, interfaceName, operationName)
+                ?: hashMapOf()
         /**
          * Resolve the Property Output Assignment Values.
          */
         val propertyAssignmentValue = resolveNodeTemplatePropertyAssignments(nodeTemplateName,
-                nodeTypeInterfaceOperationOutputs, propertyAssignments)
+            nodeTypeInterfaceOperationOutputs, propertyAssignments)
 
         // Store  operation output values into context
         propertyAssignmentValue.forEach { key, value ->
@@ -369,17 +371,19 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
     }
 
     override fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String {
-        val artifactDefinition: ArtifactDefinition = resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName)
+        val artifactDefinition: ArtifactDefinition =
+            resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName)
         val propertyAssignmentExpression = PropertyAssignmentService(this)
         return propertyAssignmentExpression.artifactContent(artifactDefinition)
     }
 
-    override fun resolveNodeTemplateArtifactDefinition(nodeTemplateName: String, artifactName: String): ArtifactDefinition {
+    override fun resolveNodeTemplateArtifactDefinition(nodeTemplateName: String,
+                                                       artifactName: String): ArtifactDefinition {
         val nodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName)
 
         return nodeTemplate.artifacts?.get(artifactName)
-                ?: throw BluePrintProcessorException("failed to get artifat definition($artifactName) from the node " +
-                        "template")
+            ?: throw BluePrintProcessorException("failed to get artifat definition($artifactName) from the node " +
+                    "template")
 
     }
 
@@ -390,14 +394,14 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
     override fun resolveDSLExpression(dslPropertyName: String): JsonNode {
         val propertyAssignments = bluePrintContext.dslPropertiesByName(dslPropertyName)
         return if (BluePrintExpressionService.checkContainsExpression(propertyAssignments)
-                && propertyAssignments is ObjectNode) {
+            && propertyAssignments is ObjectNode) {
 
             val rootKeyMap = propertyAssignments.rootFieldsToMap()
             val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
             rootKeyMap.forEach { propertyName, propertyValue ->
                 val propertyAssignmentExpression = PropertyAssignmentService(this)
                 propertyAssignmentValue[propertyName] = propertyAssignmentExpression
-                        .resolveAssignmentExpression("DSL", propertyName, propertyValue)
+                    .resolveAssignmentExpression("DSL", propertyName, propertyValue)
             }
             propertyAssignmentValue.asJsonNode()
         } else {
@@ -407,7 +411,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
 
     override fun setInputValue(propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode) {
         val path = StringBuilder(BluePrintConstants.PATH_INPUTS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
         log.trace("setting input path ({}), values ({})", path, value)
         put(path, value)
     }
@@ -415,41 +419,42 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
     override fun setWorkflowInputValue(workflowName: String, propertyName: String,
                                        propertyDefinition: PropertyDefinition, value: JsonNode) {
         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_WORKFLOWS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(workflowName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(workflowName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
         put(path, value)
     }
 
     override fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode) {
 
         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
         put(path, value)
     }
 
     override fun setNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String, value: JsonNode) {
 
         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
         put(path, value)
     }
 
-    override fun setNodeTemplateOperationPropertyValue(nodeTemplateName: String, interfaceName: String, operationName: String, propertyName: String,
+    override fun setNodeTemplateOperationPropertyValue(nodeTemplateName: String, interfaceName: String,
+                                                       operationName: String, propertyName: String,
                                                        value: JsonNode) {
         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
+            .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
         log.trace("setting operation property path ({}), values ({})", path, value)
         put(path, value)
     }
@@ -458,14 +463,14 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
                                                     operationName: String, propertyName: String,
                                                     value: JsonNode) {
         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
+            .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
         put(path, value)
     }
 
@@ -473,51 +478,51 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
                                                      operationName: String, propertyName: String,
                                                      value: JsonNode) {
         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
+            .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
         put(path, value)
     }
 
 
     override fun getInputValue(propertyName: String): JsonNode {
         val path = StringBuilder(BluePrintConstants.PATH_INPUTS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
         return getJsonNode(path)
     }
 
     override fun getNodeTemplateOperationOutputValue(nodeTemplateName: String, interfaceName: String,
                                                      operationName: String, propertyName: String): JsonNode {
         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
+            .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
         return getJsonNode(path)
     }
 
     override fun getNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String): JsonNode {
         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
         return getJsonNode(path)
     }
 
     override fun getNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String): JsonNode {
         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
         return getJsonNode(path)
     }
 
@@ -525,7 +530,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         log.info("assignInputs from input JSON ({})", jsonNode.toString())
         bluePrintContext.inputs()?.forEach { propertyName, property ->
             val valueNode: JsonNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName)
-                    ?: NullNode.getInstance()
+                ?: NullNode.getInstance()
             setInputValue(propertyName, property, valueNode)
         }
     }
@@ -538,7 +543,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         bluePrintContext.workflowByName(workflowName).inputs?.forEach { propertyName, property ->
             if (propertyName != dynamicInputPropertiesName) {
                 val valueNode: JsonNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName)
-                        ?: NullNode.getInstance()
+                    ?: NullNode.getInstance()
                 setInputValue(propertyName, property, valueNode)
             }
         }
@@ -546,8 +551,10 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         val workflowDynamicInputs: JsonNode? = jsonNode.get(dynamicInputPropertiesName)
 
         workflowDynamicInputs?.let {
-            bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName")?.properties?.forEach { propertyName, property ->
-                val valueNode: JsonNode = workflowDynamicInputs.at(BluePrintConstants.PATH_DIVIDER + propertyName).returnNullIfMissing()
+            bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName")
+                ?.properties?.forEach { propertyName, property ->
+                val valueNode: JsonNode =
+                    workflowDynamicInputs.at(BluePrintConstants.PATH_DIVIDER + propertyName).returnNullIfMissing()
                         ?: property.defaultValue
                         ?: NullNode.getInstance()
                 setInputValue(propertyName, property, valueNode)
@@ -566,9 +573,9 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
 
         val jsonNode: ObjectNode = jacksonObjectMapper().createObjectNode()
         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
-                .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
-                .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
-                .append(BluePrintConstants.PATH_DIVIDER).toString()
+            .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
+            .append(BluePrintConstants.PATH_DIVIDER).toString()
         store.keys.filter {
             it.startsWith(path)
         }.map {