a7ed577dd87de4386e41476a07f6c0afb9fd78ad
[ccsdk/cds.git] /
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2018-2019 IBM, Bell Canada.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package org.onap.ccsdk.cds.controllerblueprints.core.service
19
20 import com.fasterxml.jackson.databind.JsonNode
21 import com.fasterxml.jackson.databind.node.NullNode
22 import com.fasterxml.jackson.databind.node.ObjectNode
23 import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
24 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
25 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintError
26 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
27 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
28 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
29 import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants.LOG_REDACTED
30 import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactDefinition
31 import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate
32 import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
33 import org.onap.ccsdk.cds.controllerblueprints.core.returnNullIfMissing
34 import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap
35 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
36 import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
37 import org.slf4j.LoggerFactory
38 import java.io.File
39
40 interface BluePrintRuntimeService<T> {
41
42     fun id(): String
43
44     fun bluePrintContext(): BluePrintContext
45
46     fun getExecutionContext(): T
47
48     fun setExecutionContext(executionContext: T)
49
50     fun put(key: String, value: JsonNode)
51
52     fun get(key: String): JsonNode?
53
54     fun check(key: String): Boolean
55
56     fun cleanRuntime()
57
58     fun getAsString(key: String): String?
59
60     fun getAsBoolean(key: String): Boolean?
61
62     fun getAsInt(key: String): Int?
63
64     fun getAsDouble(key: String): Double?
65
66     fun getBluePrintError(): BluePrintError
67
68     fun setBluePrintError(bluePrintError: BluePrintError)
69
70     fun loadEnvironments(type: String, fileName: String)
71
72     fun resolveNodeTemplatePropertyAssignments(
73         nodeTemplateName: String,
74         propertyDefinitions: MutableMap<String, PropertyDefinition>,
75         propertyAssignments: MutableMap<String, JsonNode>
76     ): MutableMap<String, JsonNode>
77
78     fun resolvePropertyDefinitions(name: String, propertyDefinitions: MutableMap<String, PropertyDefinition>):
79             MutableMap<String, JsonNode>
80
81     fun resolvePropertyAssignments(name: String, propertyAssignments: MutableMap<String, JsonNode>):
82             MutableMap<String, JsonNode>
83
84     fun resolveNodeTemplateProperties(nodeTemplateName: String): MutableMap<String, JsonNode>
85
86     fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String): MutableMap<String,
87             JsonNode>
88
89     fun resolveNodeTemplateInterfaceOperationInputs(
90         nodeTemplateName: String,
91         interfaceName: String,
92         operationName: String
93     ): MutableMap<String, JsonNode>
94
95     fun resolveNodeTemplateInterfaceOperationOutputs(
96         nodeTemplateName: String,
97         interfaceName: String,
98         operationName: String
99     ): MutableMap<String, JsonNode>
100
101     fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String
102
103     fun resolveNodeTemplateArtifactDefinition(nodeTemplateName: String, artifactName: String): ArtifactDefinition
104
105     fun resolveDSLExpression(dslPropertyName: String): JsonNode
106
107     fun setInputValue(propertyName: String, value: JsonNode)
108
109     fun setWorkflowInputValue(
110         workflowName: String,
111         propertyName: String,
112         propertyDefinition: PropertyDefinition,
113         value: JsonNode
114     )
115
116     fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode)
117
118     fun setNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String, value: JsonNode)
119
120     fun setNodeTemplateOperationPropertyValue(
121         nodeTemplateName: String,
122         interfaceName: String,
123         operationName: String,
124         propertyName: String,
125         value: JsonNode
126     )
127
128     fun setNodeTemplateOperationInputValue(
129         nodeTemplateName: String,
130         interfaceName: String,
131         operationName: String,
132         propertyName: String,
133         value: JsonNode
134     )
135
136     fun setNodeTemplateOperationOutputValue(
137         nodeTemplateName: String,
138         interfaceName: String,
139         operationName: String,
140         propertyName: String,
141         value: JsonNode
142     )
143
144     fun getInputValue(propertyName: String): JsonNode
145
146     fun getNodeTemplateOperationOutputValue(
147         nodeTemplateName: String,
148         interfaceName: String,
149         operationName: String,
150         propertyName: String
151     ): JsonNode
152
153     fun getNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String): JsonNode?
154
155     fun getNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String): JsonNode?
156
157     fun assignInputs(jsonNode: JsonNode)
158
159     fun assignWorkflowInputs(workflowName: String, jsonNode: JsonNode)
160
161     fun resolveWorkflowOutputs(workflowName: String): MutableMap<String, JsonNode>
162
163     fun getJsonForNodeTemplateAttributeProperties(nodeTemplateName: String, keys: List<String>): JsonNode
164 }
165
166 /**
167  *
168  *
169  * @author Brinda Santh
170  */
171 open class DefaultBluePrintRuntimeService(private var id: String, private var bluePrintContext: BluePrintContext) :
172     BluePrintRuntimeService<MutableMap<String, JsonNode>> {
173
174     @Transient
175     private val log = LoggerFactory.getLogger(BluePrintRuntimeService::class.toString())
176
177     private var store: MutableMap<String, JsonNode> = hashMapOf()
178
179     private var bluePrintError = BluePrintError()
180
181     init {
182         /**
183          * Load Blueprint Environments Properties
184          */
185         val absoluteEnvFilePath = bluePrintContext.rootPath.plus(File.separator)
186             .plus(BluePrintConstants.TOSCA_ENVIRONMENTS_DIR)
187         loadEnvironments(BluePrintConstants.PROPERTY_BPP, absoluteEnvFilePath)
188     }
189
190     override fun id(): String {
191         return id
192     }
193
194     override fun bluePrintContext(): BluePrintContext {
195         return bluePrintContext
196     }
197
198     override fun getExecutionContext(): MutableMap<String, JsonNode> {
199         return store
200     }
201
202     @Suppress("UNCHECKED_CAST")
203     override fun setExecutionContext(executionContext: MutableMap<String, JsonNode>) {
204         this.store = executionContext
205     }
206
207     override fun put(key: String, value: JsonNode) {
208         store[key] = value
209     }
210
211     override fun get(key: String): JsonNode {
212         return store[key] ?: throw BluePrintProcessorException("failed to get execution property($key)")
213     }
214
215     override fun check(key: String): Boolean {
216         return store.containsKey(key)
217     }
218
219     override fun cleanRuntime() {
220         store.clear()
221     }
222
223     private fun getJsonNode(key: String): JsonNode {
224         return get(key)
225     }
226
227     override fun getAsString(key: String): String? {
228         return get(key).asText()
229     }
230
231     override fun getAsBoolean(key: String): Boolean? {
232         return get(key).asBoolean()
233     }
234
235     override fun getAsInt(key: String): Int? {
236         return get(key).asInt()
237     }
238
239     override fun getAsDouble(key: String): Double? {
240         return get(key).asDouble()
241     }
242
243     override fun getBluePrintError(): BluePrintError {
244         return this.bluePrintError
245     }
246
247     override fun setBluePrintError(bluePrintError: BluePrintError) {
248         this.bluePrintError = bluePrintError
249     }
250
251     override fun loadEnvironments(type: String, fileName: String) {
252         BluePrintMetadataUtils.environmentFileProperties(fileName).forEach { key, value ->
253             setNodeTemplateAttributeValue(type, key.toString(), value.asJsonType())
254         }
255     }
256
257     /**
258      * Resolve any property assignments for the node
259      */
260     override fun resolveNodeTemplatePropertyAssignments(
261         nodeTemplateName: String,
262         propertyDefinitions: MutableMap<String, PropertyDefinition>,
263         propertyAssignments: MutableMap<String, JsonNode>
264     ):
265             MutableMap<String, JsonNode> {
266
267         val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
268
269         propertyDefinitions.forEach { (nodeTypePropertyName, nodeTypeProperty) ->
270             // Get the Express or Value for the Node Template
271             val propertyAssignment: JsonNode? = propertyAssignments[nodeTypePropertyName]
272
273             var resolvedValue: JsonNode = NullNode.getInstance()
274             if (propertyAssignment != null) {
275                 // Resolve the Expressing
276                 val propertyAssignmentExpression = PropertyAssignmentService(this)
277                 resolvedValue = propertyAssignmentExpression.resolveAssignmentExpression(
278                     nodeTemplateName, nodeTypePropertyName, propertyAssignment
279                 )
280             }
281
282             // Set default value if null
283             if (resolvedValue is NullNode) {
284                 nodeTypeProperty.defaultValue?.let { resolvedValue = nodeTypeProperty.defaultValue!! }
285             }
286
287             // Set for Return of method
288             propertyAssignmentValue[nodeTypePropertyName] = resolvedValue
289         }
290         return propertyAssignmentValue
291     }
292
293     override fun resolvePropertyDefinitions(name: String, propertyDefinitions: MutableMap<String, PropertyDefinition>):
294             MutableMap<String, JsonNode> {
295         val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
296
297         propertyDefinitions.forEach { propertyName, propertyDefinition ->
298             val propertyAssignmentExpression = PropertyAssignmentService(this)
299             val expression = propertyDefinition.value ?: propertyDefinition.defaultValue
300             if (expression != null) {
301                 propertyAssignmentValue[propertyName] =
302                     propertyAssignmentExpression.resolveAssignmentExpression(name, propertyName, expression)
303             }
304         }
305         return propertyAssignmentValue
306     }
307
308     override fun resolvePropertyAssignments(name: String, propertyAssignments: MutableMap<String, JsonNode>):
309             MutableMap<String, JsonNode> {
310         val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
311
312         propertyAssignments.forEach { (propertyName, propertyExpression) ->
313             val propertyAssignmentExpression = PropertyAssignmentService(this)
314             propertyAssignmentValue[propertyName] =
315                 propertyAssignmentExpression.resolveAssignmentExpression(name, propertyName, propertyExpression)
316         }
317         return propertyAssignmentValue
318     }
319
320     override fun resolveNodeTemplateProperties(nodeTemplateName: String): MutableMap<String, JsonNode> {
321         log.info("resolveNodeTemplatePropertyValues for node template ({})", nodeTemplateName)
322
323         val nodeTemplate: NodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName)
324
325         val propertyAssignments: MutableMap<String, JsonNode> = nodeTemplate.properties!!
326
327         // Get the Node Type Definitions
328         val nodeTypePropertiesDefinitions: MutableMap<String, PropertyDefinition> = bluePrintContext
329             .nodeTypeChainedProperties(nodeTemplate.type)!!
330
331         /**
332          * Resolve the NodeTemplate Property Assignment Values.
333          */
334         return resolveNodeTemplatePropertyAssignments(nodeTemplateName, nodeTypePropertiesDefinitions, propertyAssignments)
335     }
336
337     override fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String):
338             MutableMap<String, JsonNode> {
339         log.info("resolveNodeTemplateCapabilityProperties for node template($nodeTemplateName) capability($capabilityName)")
340         val nodeTemplate: NodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName)
341
342         val propertyAssignments = nodeTemplate.capabilities?.get(capabilityName)?.properties ?: hashMapOf()
343
344         val propertyDefinitions = bluePrintContext.nodeTemplateNodeType(nodeTemplateName)
345             .capabilities?.get(capabilityName)?.properties ?: hashMapOf()
346
347         /**
348          * Resolve the Capability Property Assignment Values.
349          */
350         return resolveNodeTemplatePropertyAssignments(nodeTemplateName, propertyDefinitions, propertyAssignments)
351     }
352
353     override fun resolveNodeTemplateInterfaceOperationInputs(
354         nodeTemplateName: String,
355         interfaceName: String,
356         operationName: String
357     ): MutableMap<String, JsonNode> {
358         log.info(
359             "resolveNodeTemplateInterfaceOperationInputs for node template ($nodeTemplateName), " +
360                     "interface name($interfaceName), operationName($operationName)"
361         )
362
363         val propertyAssignments: MutableMap<String, JsonNode> =
364             bluePrintContext.nodeTemplateInterfaceOperationInputs(nodeTemplateName, interfaceName, operationName)
365                 ?: hashMapOf()
366
367         val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type
368
369         val nodeTypeInterfaceOperationInputs: MutableMap<String, PropertyDefinition> =
370             bluePrintContext.nodeTypeInterfaceOperationInputs(nodeTypeName, interfaceName, operationName)
371                 ?: hashMapOf()
372
373         log.info("input definition for node template ($nodeTemplateName), values ($propertyAssignments)")
374
375         /**
376          * Resolve the Property Input Assignment Values.
377          */
378         return resolveNodeTemplatePropertyAssignments(nodeTemplateName, nodeTypeInterfaceOperationInputs, propertyAssignments)
379     }
380
381     override fun resolveNodeTemplateInterfaceOperationOutputs(
382         nodeTemplateName: String,
383         interfaceName: String,
384         operationName: String
385     ): MutableMap<String, JsonNode> {
386         log.info(
387             "resolveNodeTemplateInterfaceOperationOutputs for node template ($nodeTemplateName),interface name " +
388                     "($interfaceName), operationName($operationName)"
389         )
390
391         val propertyAssignments: MutableMap<String, JsonNode> =
392             bluePrintContext.nodeTemplateInterfaceOperationOutputs(nodeTemplateName, interfaceName, operationName)
393                 ?: hashMapOf()
394
395         val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type
396
397         val nodeTypeInterfaceOperationOutputs: MutableMap<String, PropertyDefinition> =
398             bluePrintContext.nodeTypeInterfaceOperationOutputs(nodeTypeName, interfaceName, operationName)
399                 ?: hashMapOf()
400         /**
401          * Resolve the Property Output Assignment Values.
402          */
403         val propertyAssignmentValue =
404             resolveNodeTemplatePropertyAssignments(nodeTemplateName, nodeTypeInterfaceOperationOutputs, propertyAssignments)
405
406         // Store  operation output values into context
407         propertyAssignmentValue.forEach { (key, value) ->
408             setNodeTemplateOperationOutputValue(nodeTemplateName, interfaceName, operationName, key, value)
409         }
410         return propertyAssignmentValue
411     }
412
413     override fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String {
414         val artifactDefinition: ArtifactDefinition =
415             resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName)
416         val propertyAssignmentExpression = PropertyAssignmentService(this)
417         return propertyAssignmentExpression.artifactContent(artifactDefinition)
418     }
419
420     override fun resolveNodeTemplateArtifactDefinition(
421         nodeTemplateName: String,
422         artifactName: String
423     ): ArtifactDefinition {
424         val nodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName)
425
426         return nodeTemplate.artifacts?.get(artifactName)
427             ?: throw BluePrintProcessorException(
428                 "failed to get artifact definition($artifactName) from the node template"
429             )
430     }
431
432     /**
433      * Read the DSL Property reference, If there is any expression, then resolve those expression and return as Json
434      * Type
435      */
436     override fun resolveDSLExpression(dslPropertyName: String): JsonNode {
437         val propertyAssignments = bluePrintContext.dslPropertiesByName(dslPropertyName)
438         return if (BluePrintExpressionService.checkContainsExpression(propertyAssignments) &&
439             propertyAssignments is ObjectNode
440         ) {
441
442             val rootKeyMap = propertyAssignments.rootFieldsToMap()
443             val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
444             rootKeyMap.forEach { (propertyName, propertyValue) ->
445                 val propertyAssignmentExpression = PropertyAssignmentService(this)
446                 propertyAssignmentValue[propertyName] = propertyAssignmentExpression
447                     .resolveAssignmentExpression("DSL", propertyName, propertyValue)
448             }
449             propertyAssignmentValue.asJsonNode()
450         } else {
451             propertyAssignments
452         }
453     }
454
455     override fun setInputValue(propertyName: String, value: JsonNode) {
456         val path = """${BluePrintConstants.PATH_INPUTS}${BluePrintConstants.PATH_DIVIDER}$propertyName"""
457         put(path, value)
458     }
459
460     override fun setWorkflowInputValue(
461         workflowName: String,
462         propertyName: String,
463         propertyDefinition: PropertyDefinition,
464         value: JsonNode
465     ) {
466         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_WORKFLOWS)
467             .append(BluePrintConstants.PATH_DIVIDER).append(workflowName)
468             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS)
469             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
470             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
471         put(path, value)
472     }
473
474     override fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode) {
475         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
476             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
477             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
478             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
479         put(path, value)
480     }
481
482     override fun setNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String, value: JsonNode) {
483         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
484             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
485             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
486             .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
487         put(path, value)
488     }
489
490     override fun setNodeTemplateOperationPropertyValue(
491         nodeTemplateName: String,
492         interfaceName: String,
493         operationName: String,
494         propertyName: String,
495         value: JsonNode
496     ) {
497         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
498             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
499             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
500             .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
501             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
502             .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
503             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
504             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
505         log.trace("setting operation property path ({}), values ({})", path, value)
506         put(path, value)
507     }
508
509     override fun setNodeTemplateOperationInputValue(
510         nodeTemplateName: String,
511         interfaceName: String,
512         operationName: String,
513         propertyName: String,
514         value: JsonNode
515     ) {
516         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
517             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
518             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
519             .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
520             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
521             .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
522             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS)
523             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
524             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
525         put(path, value)
526     }
527
528     override fun setNodeTemplateOperationOutputValue(
529         nodeTemplateName: String,
530         interfaceName: String,
531         operationName: String,
532         propertyName: String,
533         value: JsonNode
534     ) {
535         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
536             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
537             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
538             .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
539             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
540             .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
541             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS)
542             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
543             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
544         put(path, value)
545     }
546
547     override fun getInputValue(propertyName: String): JsonNode {
548         val path = StringBuilder(BluePrintConstants.PATH_INPUTS)
549             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
550         return getJsonNode(path)
551     }
552
553     override fun getNodeTemplateOperationOutputValue(
554         nodeTemplateName: String,
555         interfaceName: String,
556         operationName: String,
557         propertyName: String
558     ): JsonNode {
559         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
560             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
561             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
562             .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
563             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
564             .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
565             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS)
566             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
567             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
568         return getJsonNode(path)
569     }
570
571     override fun getNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String): JsonNode {
572         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
573             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
574             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
575             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
576         return getJsonNode(path)
577     }
578
579     override fun getNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String): JsonNode {
580         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
581             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
582             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
583             .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
584         return getJsonNode(path)
585     }
586
587     override fun assignInputs(jsonNode: JsonNode) {
588         log.info("assignInputs from input JSON ({})", jsonNode.toString())
589         bluePrintContext.inputs()?.forEach { propertyName, property ->
590             val valueNode: JsonNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName)
591                 ?: property.defaultValue
592                 ?: NullNode.getInstance()
593             setInputValue(propertyName, valueNode)
594         }
595     }
596
597     override fun assignWorkflowInputs(workflowName: String, jsonNode: JsonNode) {
598         log.info("Deriving input data for workflow: ($workflowName)")
599
600         val dynamicInputPropertiesName = "$workflowName-properties"
601
602         bluePrintContext.workflowByName(workflowName).inputs
603                 ?.filter { (propertyName, property) -> propertyName != dynamicInputPropertiesName }
604                 ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, jsonNode) }
605         // Load Dynamic data Types
606         jsonNode.get(dynamicInputPropertiesName)?.let {
607             bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName")
608                     ?.properties
609                     ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, it) }
610         }
611     }
612
613     private fun findAndSetInputValue(propertyName: String, property: PropertyDefinition, jsonNode: JsonNode) {
614         val valueNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName)
615                 .returnNullIfMissing()
616                 ?: property.defaultValue
617                 ?: NullNode.getInstance()
618         val loggableValue = if (hasLogProtect(property)) LOG_REDACTED else valueNode.toString()
619         log.info("Setting input data - attribute:($propertyName) value:($loggableValue)")
620         setInputValue(propertyName, valueNode)
621     }
622
623     override fun resolveWorkflowOutputs(workflowName: String): MutableMap<String, JsonNode> {
624         log.info("resolveWorkflowOutputs for workflow($workflowName)")
625         val outputs = bluePrintContext.workflowByName(workflowName).outputs ?: mutableMapOf()
626         return resolvePropertyDefinitions("WORKFLOW", outputs)
627     }
628
629     override fun getJsonForNodeTemplateAttributeProperties(nodeTemplateName: String, keys: List<String>): JsonNode {
630
631         val jsonNode: ObjectNode = jacksonObjectMapper().createObjectNode()
632         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
633             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
634             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
635             .append(BluePrintConstants.PATH_DIVIDER).toString()
636         store.keys.filter {
637             it.startsWith(path)
638         }.map {
639             val key = it.replace(path, "")
640             if (keys.contains(key)) {
641                 val value = store[it] as JsonNode
642                 jsonNode.set(key, value)
643             }
644         }
645         return jsonNode
646     }
647 }