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