841cc524274462be3536f99015e4c8b73a12c5e4
[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 resolveRelationshipTemplateProperties(relationshipTemplateName: String): MutableMap<String, JsonNode>
106
107     fun resolveDSLExpression(dslPropertyName: String): JsonNode
108
109     fun setInputValue(propertyName: String, value: JsonNode)
110
111     fun setWorkflowInputValue(
112         workflowName: String,
113         propertyName: String,
114         propertyDefinition: PropertyDefinition,
115         value: JsonNode
116     )
117
118     fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode)
119
120     fun setNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String, value: JsonNode)
121
122     fun setNodeTemplateOperationPropertyValue(
123         nodeTemplateName: String,
124         interfaceName: String,
125         operationName: String,
126         propertyName: String,
127         value: JsonNode
128     )
129
130     fun setNodeTemplateOperationInputValue(
131         nodeTemplateName: String,
132         interfaceName: String,
133         operationName: String,
134         propertyName: String,
135         value: JsonNode
136     )
137
138     fun setNodeTemplateOperationOutputValue(
139         nodeTemplateName: String,
140         interfaceName: String,
141         operationName: String,
142         propertyName: String,
143         value: JsonNode
144     )
145
146     fun getInputValue(propertyName: String): JsonNode
147
148     fun getNodeTemplateOperationOutputValue(
149         nodeTemplateName: String,
150         interfaceName: String,
151         operationName: String,
152         propertyName: String
153     ): JsonNode
154
155     fun getNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String): JsonNode?
156
157     fun getNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String): JsonNode?
158
159     fun assignInputs(jsonNode: JsonNode)
160
161     fun assignWorkflowInputs(workflowName: String, jsonNode: JsonNode)
162
163     fun resolveWorkflowOutputs(workflowName: String): MutableMap<String, JsonNode>
164
165     fun getJsonForNodeTemplateAttributeProperties(nodeTemplateName: String, keys: List<String>): JsonNode
166 }
167
168 /**
169  *
170  *
171  * @author Brinda Santh
172  */
173 open class DefaultBluePrintRuntimeService(private var id: String, private var bluePrintContext: BluePrintContext) :
174     BluePrintRuntimeService<MutableMap<String, JsonNode>> {
175
176     @Transient
177     private val log = LoggerFactory.getLogger(BluePrintRuntimeService::class.toString())
178
179     private var store: MutableMap<String, JsonNode> = hashMapOf()
180
181     private var bluePrintError = BluePrintError()
182
183     init {
184         /**
185          * Load Blueprint Environments Properties
186          */
187         val absoluteEnvFilePath = bluePrintContext.rootPath.plus(File.separator)
188             .plus(BluePrintConstants.TOSCA_ENVIRONMENTS_DIR)
189         loadEnvironments(BluePrintConstants.PROPERTY_BPP, absoluteEnvFilePath)
190     }
191
192     override fun id(): String {
193         return id
194     }
195
196     override fun bluePrintContext(): BluePrintContext {
197         return bluePrintContext
198     }
199
200     override fun getExecutionContext(): MutableMap<String, JsonNode> {
201         return store
202     }
203
204     @Suppress("UNCHECKED_CAST")
205     override fun setExecutionContext(executionContext: MutableMap<String, JsonNode>) {
206         this.store = executionContext
207     }
208
209     override fun put(key: String, value: JsonNode) {
210         store[key] = value
211     }
212
213     override fun get(key: String): JsonNode {
214         return store[key] ?: throw BluePrintProcessorException("failed to get execution property($key)")
215     }
216
217     override fun check(key: String): Boolean {
218         return store.containsKey(key)
219     }
220
221     override fun cleanRuntime() {
222         store.clear()
223     }
224
225     private fun getJsonNode(key: String): JsonNode {
226         return get(key)
227     }
228
229     override fun getAsString(key: String): String? {
230         return get(key).asText()
231     }
232
233     override fun getAsBoolean(key: String): Boolean? {
234         return get(key).asBoolean()
235     }
236
237     override fun getAsInt(key: String): Int? {
238         return get(key).asInt()
239     }
240
241     override fun getAsDouble(key: String): Double? {
242         return get(key).asDouble()
243     }
244
245     override fun getBluePrintError(): BluePrintError {
246         return this.bluePrintError
247     }
248
249     override fun setBluePrintError(bluePrintError: BluePrintError) {
250         this.bluePrintError = bluePrintError
251     }
252
253     override fun loadEnvironments(type: String, fileName: String) {
254         BluePrintMetadataUtils.environmentFileProperties(fileName).forEach { key, value ->
255             setNodeTemplateAttributeValue(type, key.toString(), value.asJsonType())
256         }
257     }
258
259     /**
260      * Resolve any property assignments for the node
261      */
262     override fun resolveNodeTemplatePropertyAssignments(
263         nodeTemplateName: String,
264         propertyDefinitions: MutableMap<String, PropertyDefinition>,
265         propertyAssignments: MutableMap<String, JsonNode>
266     ):
267         MutableMap<String, JsonNode> {
268
269         val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
270
271         propertyDefinitions.forEach { (nodeTypePropertyName, nodeTypeProperty) ->
272             // Get the Express or Value for the Node Template
273             val propertyAssignment: JsonNode? = propertyAssignments[nodeTypePropertyName]
274
275             var resolvedValue: JsonNode = NullNode.getInstance()
276             if (propertyAssignment != null) {
277                 // Resolve the Expressing
278                 val propertyAssignmentExpression = PropertyAssignmentService(this)
279                 resolvedValue = propertyAssignmentExpression.resolveAssignmentExpression(
280                     nodeTemplateName, nodeTypePropertyName, propertyAssignment
281                 )
282             }
283
284             // Set default value if null
285             if (resolvedValue is NullNode) {
286                 nodeTypeProperty.defaultValue?.let { resolvedValue = nodeTypeProperty.defaultValue!! }
287             }
288
289             /** If property is Map type, then resolve the property value, It may have expressiong */
290             if (nodeTypeProperty.type == BluePrintConstants.DATA_TYPE_MAP &&
291                 resolvedValue.returnNullIfMissing() != null
292             ) {
293                 val mapResolvedValue = resolvePropertyAssignments(nodeTemplateName, resolvedValue.rootFieldsToMap())
294                 resolvedValue = mapResolvedValue.asJsonNode()
295             }
296
297             // Set for Return of method
298             propertyAssignmentValue[nodeTypePropertyName] = resolvedValue
299         }
300         return propertyAssignmentValue
301     }
302
303     override fun resolvePropertyDefinitions(name: String, propertyDefinitions: MutableMap<String, PropertyDefinition>):
304         MutableMap<String, JsonNode> {
305         val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
306
307         propertyDefinitions.forEach { propertyName, propertyDefinition ->
308             val propertyAssignmentExpression = PropertyAssignmentService(this)
309             val expression = propertyDefinition.value ?: propertyDefinition.defaultValue
310             if (expression != null) {
311                 propertyAssignmentValue[propertyName] =
312                     propertyAssignmentExpression.resolveAssignmentExpression(name, propertyName, expression)
313             }
314         }
315         return propertyAssignmentValue
316     }
317
318     override fun resolvePropertyAssignments(name: String, propertyAssignments: MutableMap<String, JsonNode>):
319         MutableMap<String, JsonNode> {
320         val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
321
322         propertyAssignments.forEach { (propertyName, propertyExpression) ->
323             val propertyAssignmentExpression = PropertyAssignmentService(this)
324             propertyAssignmentValue[propertyName] =
325                 propertyAssignmentExpression.resolveAssignmentExpression(name, propertyName, propertyExpression)
326         }
327         return propertyAssignmentValue
328     }
329
330     override fun resolveNodeTemplateProperties(nodeTemplateName: String): MutableMap<String, JsonNode> {
331         log.info("resolveNodeTemplatePropertyValues for node template ({})", nodeTemplateName)
332
333         val nodeTemplate: NodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName)
334
335         val propertyAssignments: MutableMap<String, JsonNode> = nodeTemplate.properties!!
336
337         // Get the Node Type Definitions
338         val nodeTypePropertiesDefinitions: MutableMap<String, PropertyDefinition> = bluePrintContext
339             .nodeTypeChainedProperties(nodeTemplate.type)!!
340
341         /**
342          * Resolve the NodeTemplate Property Assignment Values.
343          */
344         return resolveNodeTemplatePropertyAssignments(
345             nodeTemplateName,
346             nodeTypePropertiesDefinitions,
347             propertyAssignments
348         )
349     }
350
351     override fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String):
352         MutableMap<String, JsonNode> {
353         log.info("resolveNodeTemplateCapabilityProperties for node template($nodeTemplateName) capability($capabilityName)")
354         val nodeTemplate: NodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName)
355
356         val propertyAssignments = nodeTemplate.capabilities?.get(capabilityName)?.properties ?: hashMapOf()
357
358         val propertyDefinitions = bluePrintContext.nodeTemplateNodeType(nodeTemplateName)
359             .capabilities?.get(capabilityName)?.properties ?: hashMapOf()
360
361         /**
362          * Resolve the Capability Property Assignment Values.
363          */
364         return resolveNodeTemplatePropertyAssignments(nodeTemplateName, propertyDefinitions, propertyAssignments)
365     }
366
367     override fun resolveNodeTemplateInterfaceOperationInputs(
368         nodeTemplateName: String,
369         interfaceName: String,
370         operationName: String
371     ): MutableMap<String, JsonNode> {
372         log.info(
373             "resolveNodeTemplateInterfaceOperationInputs for node template ($nodeTemplateName), " +
374                 "interface name($interfaceName), operationName($operationName)"
375         )
376
377         val propertyAssignments: MutableMap<String, JsonNode> =
378             bluePrintContext.nodeTemplateInterfaceOperationInputs(nodeTemplateName, interfaceName, operationName)
379                 ?: hashMapOf()
380
381         val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type
382
383         val nodeTypeInterfaceOperationInputs: MutableMap<String, PropertyDefinition> =
384             bluePrintContext.nodeTypeInterfaceOperationInputs(nodeTypeName, interfaceName, operationName)
385                 ?: hashMapOf()
386
387         log.info("input definition for node template ($nodeTemplateName), values ($propertyAssignments)")
388
389         /**
390          * Resolve the Property Input Assignment Values.
391          */
392         return resolveNodeTemplatePropertyAssignments(
393             nodeTemplateName,
394             nodeTypeInterfaceOperationInputs,
395             propertyAssignments
396         )
397     }
398
399     override fun resolveNodeTemplateInterfaceOperationOutputs(
400         nodeTemplateName: String,
401         interfaceName: String,
402         operationName: String
403     ): MutableMap<String, JsonNode> {
404         log.info(
405             "resolveNodeTemplateInterfaceOperationOutputs for node template ($nodeTemplateName),interface name " +
406                 "($interfaceName), operationName($operationName)"
407         )
408
409         val propertyAssignments: MutableMap<String, JsonNode> =
410             bluePrintContext.nodeTemplateInterfaceOperationOutputs(nodeTemplateName, interfaceName, operationName)
411                 ?: hashMapOf()
412
413         val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type
414
415         val nodeTypeInterfaceOperationOutputs: MutableMap<String, PropertyDefinition> =
416             bluePrintContext.nodeTypeInterfaceOperationOutputs(nodeTypeName, interfaceName, operationName)
417                 ?: hashMapOf()
418         /**
419          * Resolve the Property Output Assignment Values.
420          */
421         val propertyAssignmentValue =
422             resolveNodeTemplatePropertyAssignments(
423                 nodeTemplateName,
424                 nodeTypeInterfaceOperationOutputs,
425                 propertyAssignments
426             )
427
428         // Store  operation output values into context
429         propertyAssignmentValue.forEach { (key, value) ->
430             setNodeTemplateOperationOutputValue(nodeTemplateName, interfaceName, operationName, key, value)
431         }
432         return propertyAssignmentValue
433     }
434
435     override fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String {
436         val artifactDefinition: ArtifactDefinition =
437             resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName)
438         val propertyAssignmentExpression = PropertyAssignmentService(this)
439         return propertyAssignmentExpression.artifactContent(artifactDefinition)
440     }
441
442     override fun resolveNodeTemplateArtifactDefinition(
443         nodeTemplateName: String,
444         artifactName: String
445     ): ArtifactDefinition {
446         val nodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName)
447
448         return nodeTemplate.artifacts?.get(artifactName)
449             ?: throw BluePrintProcessorException(
450                 "failed to get artifact definition($artifactName) from the node template"
451             )
452     }
453
454     override fun resolveRelationshipTemplateProperties(relationshipTemplateName: String): MutableMap<String, JsonNode> {
455         log.info("resolveRelationshipTemplateProperties for relationship template ({})", relationshipTemplateName)
456
457         val relationshipTemplate = bluePrintContext.relationshipTemplateByName(relationshipTemplateName)
458
459         val propertyAssignments = relationshipTemplate.properties!!
460
461         // Get the Relationship Type Definitions
462         val propertiesDefinitions = bluePrintContext.relationshipTypeByName(relationshipTemplate.type).properties
463             ?: throw BluePrintProcessorException("failed to get ${relationshipTemplate.type} properties.")
464
465         /**
466          * Resolve the RelationshipTemplate Property Assignment Values.
467          * TODO("Now it supports only input, node not SELF(propert, attribute, artifact) expressions, later it will support SELF expressions")
468          */
469         return resolveNodeTemplatePropertyAssignments(
470             "DSL",
471             propertiesDefinitions,
472             propertyAssignments
473         )
474     }
475
476     /**
477      * Read the DSL Property reference, If there is any expression, then resolve those expression and return as Json
478      * Type
479      */
480     override fun resolveDSLExpression(dslPropertyName: String): JsonNode {
481         val propertyAssignments = bluePrintContext.dslPropertiesByName(dslPropertyName)
482         return if (BluePrintExpressionService.checkContainsExpression(propertyAssignments) &&
483             propertyAssignments is ObjectNode
484         ) {
485
486             val rootKeyMap = propertyAssignments.rootFieldsToMap()
487             val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
488             rootKeyMap.forEach { (propertyName, propertyValue) ->
489                 val propertyAssignmentExpression = PropertyAssignmentService(this)
490                 propertyAssignmentValue[propertyName] = propertyAssignmentExpression
491                     .resolveAssignmentExpression("DSL", propertyName, propertyValue)
492             }
493             propertyAssignmentValue.asJsonNode()
494         } else {
495             propertyAssignments
496         }
497     }
498
499     override fun setInputValue(propertyName: String, value: JsonNode) {
500         val path = """${BluePrintConstants.PATH_INPUTS}${BluePrintConstants.PATH_DIVIDER}$propertyName"""
501         put(path, value)
502     }
503
504     override fun setWorkflowInputValue(
505         workflowName: String,
506         propertyName: String,
507         propertyDefinition: PropertyDefinition,
508         value: JsonNode
509     ) {
510         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_WORKFLOWS)
511             .append(BluePrintConstants.PATH_DIVIDER).append(workflowName)
512             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS)
513             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
514             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
515         put(path, value)
516     }
517
518     override fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode) {
519         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
520             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
521             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
522             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
523         put(path, value)
524     }
525
526     override fun setNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String, value: JsonNode) {
527         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
528             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
529             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
530             .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
531         put(path, value)
532     }
533
534     override fun setNodeTemplateOperationPropertyValue(
535         nodeTemplateName: String,
536         interfaceName: String,
537         operationName: String,
538         propertyName: String,
539         value: JsonNode
540     ) {
541         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
542             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
543             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
544             .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
545             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
546             .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
547             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
548             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
549         log.trace("setting operation property path ({}), values ({})", path, value)
550         put(path, value)
551     }
552
553     override fun setNodeTemplateOperationInputValue(
554         nodeTemplateName: String,
555         interfaceName: String,
556         operationName: String,
557         propertyName: String,
558         value: JsonNode
559     ) {
560         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
561             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
562             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
563             .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
564             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
565             .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
566             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS)
567             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
568             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
569         put(path, value)
570     }
571
572     override fun setNodeTemplateOperationOutputValue(
573         nodeTemplateName: String,
574         interfaceName: String,
575         operationName: String,
576         propertyName: String,
577         value: JsonNode
578     ) {
579         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
580             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
581             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
582             .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
583             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
584             .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
585             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS)
586             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
587             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
588         put(path, value)
589     }
590
591     override fun getInputValue(propertyName: String): JsonNode {
592         val path = StringBuilder(BluePrintConstants.PATH_INPUTS)
593             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
594         return getJsonNode(path)
595     }
596
597     override fun getNodeTemplateOperationOutputValue(
598         nodeTemplateName: String,
599         interfaceName: String,
600         operationName: String,
601         propertyName: String
602     ): JsonNode {
603         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
604             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
605             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
606             .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
607             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
608             .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
609             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS)
610             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
611             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
612         return getJsonNode(path)
613     }
614
615     override fun getNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String): JsonNode {
616         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
617             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
618             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
619             .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
620         return getJsonNode(path)
621     }
622
623     override fun getNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String): JsonNode {
624         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
625             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
626             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
627             .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
628         return getJsonNode(path)
629     }
630
631     override fun assignInputs(jsonNode: JsonNode) {
632         log.info("assignInputs from input JSON ({})", jsonNode.toString())
633         bluePrintContext.inputs()?.forEach { propertyName, property ->
634             val valueNode: JsonNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName)
635                 ?: property.defaultValue
636                 ?: NullNode.getInstance()
637             setInputValue(propertyName, valueNode)
638         }
639     }
640
641     override fun assignWorkflowInputs(workflowName: String, jsonNode: JsonNode) {
642         log.info("Deriving input data for workflow: ($workflowName)")
643
644         val dynamicInputPropertiesName = "$workflowName-properties"
645
646         bluePrintContext.workflowByName(workflowName).inputs
647                 ?.filter { (propertyName, property) -> propertyName != dynamicInputPropertiesName }
648                 ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, jsonNode) }
649         // Load Dynamic data Types
650         jsonNode.get(dynamicInputPropertiesName)?.let {
651             bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName")
652                     ?.properties
653                     ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, it) }
654         }
655     }
656
657     private fun findAndSetInputValue(propertyName: String, property: PropertyDefinition, jsonNode: JsonNode) {
658         val valueNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName)
659                 .returnNullIfMissing()
660                 ?: property.defaultValue
661                 ?: NullNode.getInstance()
662         val loggableValue = if (hasLogProtect(property)) LOG_REDACTED else valueNode.toString()
663         log.info("Setting input data - attribute:($propertyName) value:($loggableValue)")
664         setInputValue(propertyName, valueNode)
665     }
666
667     override fun resolveWorkflowOutputs(workflowName: String): MutableMap<String, JsonNode> {
668         log.info("resolveWorkflowOutputs for workflow($workflowName)")
669         val outputs = bluePrintContext.workflowByName(workflowName).outputs ?: mutableMapOf()
670         return resolvePropertyDefinitions("WORKFLOW", outputs)
671     }
672
673     override fun getJsonForNodeTemplateAttributeProperties(nodeTemplateName: String, keys: List<String>): JsonNode {
674
675         val jsonNode: ObjectNode = jacksonObjectMapper().createObjectNode()
676         val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
677             .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
678             .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
679             .append(BluePrintConstants.PATH_DIVIDER).toString()
680         store.keys.filter {
681             it.startsWith(path)
682         }.map {
683             val key = it.replace(path, "")
684             if (keys.contains(key)) {
685                 val value = store[it] as JsonNode
686                 jsonNode.set(key, value)
687             }
688         }
689         return jsonNode
690     }
691 }