/* * Copyright © 2017-2018 AT&T Intellectual Property. * Modifications Copyright © 2018-2019 IBM, Bell Canada. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onap.ccsdk.cds.controllerblueprints.core.service import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.node.NullNode import com.fasterxml.jackson.databind.node.ObjectNode import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintError import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants.LOG_REDACTED import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactDefinition import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition import org.onap.ccsdk.cds.controllerblueprints.core.returnNullIfMissing import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect import org.slf4j.LoggerFactory import java.io.File interface BluePrintRuntimeService { fun id(): String fun bluePrintContext(): BluePrintContext fun getExecutionContext(): T fun setExecutionContext(executionContext: T) fun put(key: String, value: JsonNode) fun get(key: String): JsonNode? fun check(key: String): Boolean fun cleanRuntime() fun getAsString(key: String): String? fun getAsBoolean(key: String): Boolean? fun getAsInt(key: String): Int? fun getAsDouble(key: String): Double? fun getBluePrintError(): BluePrintError fun setBluePrintError(bluePrintError: BluePrintError) fun loadEnvironments(type: String, fileName: String) fun resolveWorkflowOutputs(workflowName: String): MutableMap fun resolveDSLExpression(dslPropertyName: String): JsonNode /** Resolve Property Definition [definitionName] for type [definitionType] with [propertyDefinitions] * Definition Type may be : node_template, relationship_template, dsl, workflow * Assumption is Definition holds the expressions or value assigned in it. Mainly used for workflow outputs. */ fun resolvePropertyDefinitions( definitionType: String, definitionName: String, propertyDefinitions: MutableMap ): MutableMap /** Resolve Property Assignments [definitionName] for type [definitionType] with [propertyDefinitions] * and [propertyAssignments] * Definition Type may be : node_template, relationship_template, dsl, workflow */ fun resolvePropertyAssignments( definitionType: String, definitionName: String, propertyDefinitions: MutableMap, propertyAssignments: MutableMap ): MutableMap /** Resolve Property Assignments [definitionName] for type [definitionType] with [propertyAssignments] * Definition Type may be : node_template, relationship_template, dsl, workflow */ fun resolvePropertyAssignments( definitionType: String, definitionName: String, propertyAssignments: MutableMap ): MutableMap /** Resolve Node Template [nodeTemplateName] Property Assignments */ fun resolveNodeTemplateProperties(nodeTemplateName: String): MutableMap /** Resolve Node Template [nodeTemplateName] Property Assignments with [propertyDefinitions] and [propertyAssignments]*/ fun resolveNodeTemplatePropertyAssignments( nodeTemplateName: String, propertyDefinitions: MutableMap, propertyAssignments: MutableMap ): MutableMap fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String): MutableMap fun resolveNodeTemplateInterfaceOperationInputs( nodeTemplateName: String, interfaceName: String, operationName: String ): MutableMap fun resolveNodeTemplateInterfaceOperationOutputs( nodeTemplateName: String, interfaceName: String, operationName: String ): MutableMap suspend fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String fun resolveNodeTemplateArtifactDefinition(nodeTemplateName: String, artifactName: String): ArtifactDefinition /** Resolve Node Template [relationshipTemplateName] Property Assignments */ fun resolveRelationshipTemplateProperties(relationshipTemplateName: String): MutableMap /** Resolve Relationship Template [relationshipTemplateName] Property Assignments with * [propertyDefinitions] and [propertyAssignments] */ fun resolveRelationshipTemplatePropertyAssignments( relationshipTemplateName: String, propertyDefinitions: MutableMap, propertyAssignments: MutableMap ): MutableMap fun setInputValue(propertyName: String, value: JsonNode) fun setWorkflowInputValue( workflowName: String, propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode ) fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode) fun setNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String, value: JsonNode) fun setNodeTemplateOperationPropertyValue( nodeTemplateName: String, interfaceName: String, operationName: String, propertyName: String, value: JsonNode ) fun setNodeTemplateOperationInputValue( nodeTemplateName: String, interfaceName: String, operationName: String, propertyName: String, value: JsonNode ) fun setNodeTemplateOperationOutputValue( nodeTemplateName: String, interfaceName: String, operationName: String, propertyName: String, value: JsonNode ) fun getInputValue(propertyName: String): JsonNode fun getNodeTemplateOperationOutputValue( nodeTemplateName: String, interfaceName: String, operationName: String, propertyName: String ): JsonNode fun getNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String): JsonNode? fun getNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String): JsonNode? fun getRelationshipTemplatePropertyValue(relationshipTemplateName: String, propertyName: String): JsonNode? fun getRelationshipTemplateAttributeValue(relationshipTemplateName: String, attributeName: String): JsonNode? fun assignInputs(jsonNode: JsonNode) fun assignWorkflowInputs(workflowName: String, jsonNode: JsonNode) fun getJsonForNodeTemplateAttributeProperties(nodeTemplateName: String, keys: List): JsonNode suspend fun close() } /** * * * @author Brinda Santh */ open class DefaultBluePrintRuntimeService(private var id: String, private var bluePrintContext: BluePrintContext) : BluePrintRuntimeService> { @Transient private val log = LoggerFactory.getLogger(BluePrintRuntimeService::class.toString()) private var store: MutableMap = hashMapOf() private var bluePrintError = BluePrintError() init { /** * Load Blueprint Environments Properties */ val absoluteEnvFilePath = bluePrintContext.rootPath.plus(File.separator) .plus(BluePrintConstants.TOSCA_ENVIRONMENTS_DIR) loadEnvironments(BluePrintConstants.PROPERTY_BPP, absoluteEnvFilePath) } override fun id(): String { return id } override fun bluePrintContext(): BluePrintContext { return bluePrintContext } override fun getExecutionContext(): MutableMap { return store } @Suppress("UNCHECKED_CAST") override fun setExecutionContext(executionContext: MutableMap) { this.store = executionContext } override fun put(key: String, value: JsonNode) { store[key] = value } override fun get(key: String): JsonNode { return store[key] ?: throw BluePrintProcessorException("failed to get execution property($key)") } override fun check(key: String): Boolean { return store.containsKey(key) } override fun cleanRuntime() { store.clear() } private fun getJsonNode(key: String): JsonNode { return get(key) } override fun getAsString(key: String): String? { return get(key).asText() } override fun getAsBoolean(key: String): Boolean? { return get(key).asBoolean() } override fun getAsInt(key: String): Int? { return get(key).asInt() } override fun getAsDouble(key: String): Double? { return get(key).asDouble() } override fun getBluePrintError(): BluePrintError { return this.bluePrintError } override fun setBluePrintError(bluePrintError: BluePrintError) { this.bluePrintError = bluePrintError } override fun loadEnvironments(type: String, fileName: String) { BluePrintMetadataUtils.environmentFileProperties(fileName).forEach { key, value -> setNodeTemplateAttributeValue(type, key.toString(), value.asJsonType()) } } override fun resolveWorkflowOutputs(workflowName: String): MutableMap { log.info("resolveWorkflowOutputs for workflow($workflowName)") val outputs = bluePrintContext.workflowByName(workflowName).outputs ?: mutableMapOf() return resolvePropertyDefinitions(BluePrintConstants.MODEL_DEFINITION_TYPE_WORKFLOW, "WORKFLOW", outputs) } /** * Read the DSL Property reference, If there is any expression, then resolve those expression and return as Json * Type */ override fun resolveDSLExpression(dslPropertyName: String): JsonNode { val propertyAssignments = bluePrintContext.dslPropertiesByName(dslPropertyName) return if (BluePrintExpressionService.checkContainsExpression(propertyAssignments) && propertyAssignments is ObjectNode ) { val rootKeyMap = propertyAssignments.rootFieldsToMap() val propertyAssignmentValue: MutableMap = hashMapOf() rootKeyMap.forEach { (propertyName, propertyValue) -> val propertyAssignmentExpression = PropertyAssignmentService(this) propertyAssignmentValue[propertyName] = propertyAssignmentExpression .resolveAssignmentExpression( BluePrintConstants.MODEL_DEFINITION_TYPE_DSL, "DSL", propertyName, propertyValue ) } propertyAssignmentValue.asJsonNode() } else { propertyAssignments } } override fun resolvePropertyDefinitions( definitionType: String, definitionName: String, propertyDefinitions: MutableMap ): MutableMap { val propertyAssignmentValue: MutableMap = hashMapOf() propertyDefinitions.forEach { (propertyName, propertyDefinition) -> val propertyAssignmentExpression = PropertyAssignmentService(this) val expression = propertyDefinition.value ?: propertyDefinition.defaultValue if (expression != null) { propertyAssignmentValue[propertyName] = propertyAssignmentExpression.resolveAssignmentExpression( definitionType, definitionName, propertyName, expression ) } } return propertyAssignmentValue } override fun resolvePropertyAssignments( definitionType: String, definitionName: String, propertyDefinitions: MutableMap, propertyAssignments: MutableMap ): MutableMap { val propertyAssignmentValue: MutableMap = hashMapOf() propertyDefinitions.forEach { (nodeTypePropertyName, nodeTypeProperty) -> // Get the Express or Value for the Node Template val propertyAssignment: JsonNode? = propertyAssignments[nodeTypePropertyName] var resolvedValue: JsonNode = NullNode.getInstance() if (propertyAssignment != null) { // Resolve the Expressing val propertyAssignmentExpression = PropertyAssignmentService(this) resolvedValue = propertyAssignmentExpression.resolveAssignmentExpression( definitionType, definitionName, nodeTypePropertyName, propertyAssignment ) } // Set default value if null if (resolvedValue is NullNode) { nodeTypeProperty.defaultValue?.let { resolvedValue = nodeTypeProperty.defaultValue!! } } /** If property is Map type, then resolve the property value, It may have expressions */ if (nodeTypeProperty.type == BluePrintConstants.DATA_TYPE_MAP && resolvedValue.returnNullIfMissing() != null ) { val mapResolvedValue = resolvePropertyAssignments( definitionType, definitionName, resolvedValue.rootFieldsToMap() ) resolvedValue = mapResolvedValue.asJsonNode() } // Set for Return of method propertyAssignmentValue[nodeTypePropertyName] = resolvedValue } return propertyAssignmentValue } override fun resolvePropertyAssignments( definitionType: String, definitionName: String, propertyAssignments: MutableMap ): MutableMap { val propertyAssignmentValue: MutableMap = hashMapOf() propertyAssignments.forEach { (propertyName, propertyExpression) -> val propertyAssignmentExpression = PropertyAssignmentService(this) propertyAssignmentValue[propertyName] = propertyAssignmentExpression.resolveAssignmentExpression( definitionType, definitionName, propertyName, propertyExpression ) } return propertyAssignmentValue } override fun resolveNodeTemplateProperties(nodeTemplateName: String): MutableMap { log.info("resolveNodeTemplatePropertyValues for node template ({})", nodeTemplateName) val nodeTemplate: NodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName) val propertyAssignments: MutableMap = nodeTemplate.properties!! // Get the Node Type Definitions val nodeTypePropertiesDefinitions: MutableMap = bluePrintContext .nodeTypeChainedProperties(nodeTemplate.type)!! /** * Resolve the NodeTemplate Property Assignment Values. */ return resolveNodeTemplatePropertyAssignments( nodeTemplateName, nodeTypePropertiesDefinitions, propertyAssignments ) } /** * Resolve any property assignments for the node */ override fun resolveNodeTemplatePropertyAssignments( nodeTemplateName: String, propertyDefinitions: MutableMap, propertyAssignments: MutableMap ): MutableMap { return resolvePropertyAssignments( BluePrintConstants.MODEL_DEFINITION_TYPE_NODE_TEMPLATE, nodeTemplateName, propertyDefinitions, propertyAssignments ) } override fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String): MutableMap { log.info("resolveNodeTemplateCapabilityProperties for node template($nodeTemplateName) capability($capabilityName)") val nodeTemplate: NodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName) val propertyAssignments = nodeTemplate.capabilities?.get(capabilityName)?.properties ?: hashMapOf() val propertyDefinitions = bluePrintContext.nodeTemplateNodeType(nodeTemplateName) .capabilities?.get(capabilityName)?.properties ?: hashMapOf() /** * Resolve the Capability Property Assignment Values. */ return resolveNodeTemplatePropertyAssignments(nodeTemplateName, propertyDefinitions, propertyAssignments) } override fun resolveNodeTemplateInterfaceOperationInputs( nodeTemplateName: String, interfaceName: String, operationName: String ): MutableMap { log.info( "resolveNodeTemplateInterfaceOperationInputs for node template ($nodeTemplateName), " + "interface name($interfaceName), operationName($operationName)" ) val propertyAssignments: MutableMap = bluePrintContext.nodeTemplateInterfaceOperationInputs(nodeTemplateName, interfaceName, operationName) ?: hashMapOf() val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type val nodeTypeInterfaceOperationInputs: MutableMap = bluePrintContext.nodeTypeInterfaceOperationInputs(nodeTypeName, interfaceName, operationName) ?: hashMapOf() log.info("input definition for node template ($nodeTemplateName), values ($propertyAssignments)") /** * Resolve the Property Input Assignment Values. */ return resolveNodeTemplatePropertyAssignments( nodeTemplateName, nodeTypeInterfaceOperationInputs, propertyAssignments ) } override fun resolveNodeTemplateInterfaceOperationOutputs( nodeTemplateName: String, interfaceName: String, operationName: String ): MutableMap { log.info( "resolveNodeTemplateInterfaceOperationOutputs for node template ($nodeTemplateName),interface name " + "($interfaceName), operationName($operationName)" ) val propertyAssignments: MutableMap = bluePrintContext.nodeTemplateInterfaceOperationOutputs(nodeTemplateName, interfaceName, operationName) ?: hashMapOf() val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type val nodeTypeInterfaceOperationOutputs: MutableMap = bluePrintContext.nodeTypeInterfaceOperationOutputs(nodeTypeName, interfaceName, operationName) ?: hashMapOf() /** * Resolve the Property Output Assignment Values. */ val propertyAssignmentValue = resolveNodeTemplatePropertyAssignments( nodeTemplateName, nodeTypeInterfaceOperationOutputs, propertyAssignments ) // Store operation output values into context propertyAssignmentValue.forEach { (key, value) -> setNodeTemplateOperationOutputValue(nodeTemplateName, interfaceName, operationName, key, value) } return propertyAssignmentValue } override suspend fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String { val artifactDefinition: ArtifactDefinition = resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName) val propertyAssignmentExpression = PropertyAssignmentService(this) return propertyAssignmentExpression.artifactContent(artifactDefinition) } override fun resolveNodeTemplateArtifactDefinition( nodeTemplateName: String, artifactName: String ): ArtifactDefinition { val nodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName) return nodeTemplate.artifacts?.get(artifactName) ?: throw BluePrintProcessorException( "failed to get artifact definition($artifactName) from the node template" ) } override fun resolveRelationshipTemplateProperties(relationshipTemplateName: String): MutableMap { log.info("resolveRelationshipTemplateProperties for relationship template ({})", relationshipTemplateName) val relationshipTemplate = bluePrintContext.relationshipTemplateByName(relationshipTemplateName) val propertyAssignments = relationshipTemplate.properties!! // Get the Relationship Type Definitions val propertiesDefinitions = bluePrintContext.relationshipTypeByName(relationshipTemplate.type).properties ?: throw BluePrintProcessorException("failed to get ${relationshipTemplate.type} properties.") /** * Resolve the RelationshipTemplate Property Assignment Values. */ return resolveRelationshipTemplatePropertyAssignments( relationshipTemplateName, propertiesDefinitions, propertyAssignments ) } override fun resolveRelationshipTemplatePropertyAssignments( relationshipTemplateName: String, propertyDefinitions: MutableMap, propertyAssignments: MutableMap ): MutableMap { return resolvePropertyAssignments( BluePrintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TYPE, relationshipTemplateName, propertyDefinitions, propertyAssignments ) } override fun setInputValue(propertyName: String, value: JsonNode) { val path = """${BluePrintConstants.PATH_INPUTS}${BluePrintConstants.PATH_DIVIDER}$propertyName""" put(path, value) } 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() 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() 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() put(path, value) } 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() log.trace("setting operation property path ({}), values ({})", path, value) put(path, value) } override fun setNodeTemplateOperationInputValue( 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_INPUTS) .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() put(path, value) } override fun setNodeTemplateOperationOutputValue( 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_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() 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() 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() 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() return getJsonNode(path) } override fun getRelationshipTemplatePropertyValue( relationshipTemplateName: String, propertyName: String ): JsonNode? { val path: String = StringBuilder(BluePrintConstants.PATH_RELATIONSHIP_TEMPLATES) .append(BluePrintConstants.PATH_DIVIDER).append(relationshipTemplateName) .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() return getJsonNode(path) } override fun getRelationshipTemplateAttributeValue( relationshipTemplateName: String, attributeName: String ): JsonNode? { val path: String = StringBuilder(BluePrintConstants.PATH_RELATIONSHIP_TEMPLATES) .append(BluePrintConstants.PATH_DIVIDER).append(relationshipTemplateName) .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES) .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString() return getJsonNode(path) } override fun assignInputs(jsonNode: JsonNode) { log.info("assignInputs from input JSON ({})", jsonNode.toString()) bluePrintContext.inputs()?.forEach { propertyName, property -> val valueNode: JsonNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName) ?: property.defaultValue ?: NullNode.getInstance() setInputValue(propertyName, valueNode) } } override fun assignWorkflowInputs(workflowName: String, jsonNode: JsonNode) { log.info("Deriving input data for workflow: ($workflowName)") val dynamicInputPropertiesName = "$workflowName-properties" bluePrintContext.workflowByName(workflowName).inputs ?.filter { (propertyName, property) -> propertyName != dynamicInputPropertiesName } ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, jsonNode) } // Load Dynamic data Types jsonNode.get(dynamicInputPropertiesName)?.let { bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName") ?.properties ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, it) } } } private fun findAndSetInputValue(propertyName: String, property: PropertyDefinition, jsonNode: JsonNode) { val valueNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName) .returnNullIfMissing() ?: property.defaultValue ?: NullNode.getInstance() val loggableValue = if (hasLogProtect(property)) LOG_REDACTED else valueNode.toString() log.trace("Setting input data - attribute:($propertyName) value:($loggableValue)") setInputValue(propertyName, valueNode) } override fun getJsonForNodeTemplateAttributeProperties(nodeTemplateName: String, keys: List): JsonNode { 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() store.keys.filter { it.startsWith(path) }.map { val key = it.replace(path, "") if (keys.contains(key)) { val value = store[it] as JsonNode jsonNode.set(key, value) } } return jsonNode } override suspend fun close() { store.clear() } }