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 / PropertyAssignmentService.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 org.onap.ccsdk.cds.controllerblueprints.core.BlueprintConstants
23 import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintException
24 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
25 import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactDefinition
26 import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactExpression
27 import org.onap.ccsdk.cds.controllerblueprints.core.data.AttributeExpression
28 import org.onap.ccsdk.cds.controllerblueprints.core.data.ExpressionData
29 import org.onap.ccsdk.cds.controllerblueprints.core.data.OperationOutputExpression
30 import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyExpression
31 import org.onap.ccsdk.cds.controllerblueprints.core.format
32 import org.onap.ccsdk.cds.controllerblueprints.core.isComplexType
33 import org.onap.ccsdk.cds.controllerblueprints.core.jsonPathParse
34 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
35 import org.onap.ccsdk.cds.controllerblueprints.core.utils.ResourceResolverUtils
36 import org.slf4j.LoggerFactory
37
38 /**
39  *
40  *
41  * @author Brinda Santh
42  */
43 open class PropertyAssignmentService(var bluePrintRuntimeService: BlueprintRuntimeService<MutableMap<String, JsonNode>>) {
44
45     private val log = LoggerFactory.getLogger(this::class.toString())
46
47     private var bluePrintContext: BlueprintContext = bluePrintRuntimeService.bluePrintContext()
48
49     /*
50
51     If Property Assignment is Expression.
52         Get the Expression
53         Recursively resolve the expression
54      */
55
56     fun resolveAssignmentExpression(
57         definitionType: String,
58         definitionName: String,
59         assignmentName: String,
60         assignment: JsonNode
61     ): JsonNode {
62         log.trace("Assignment ({})", assignment)
63         val expressionData = BlueprintExpressionService.getExpressionData(assignment)
64
65         return if (expressionData.isExpression) {
66             resolveExpression(definitionType, definitionName, assignmentName, expressionData)
67         } else {
68             expressionData.valueNode
69         }
70     }
71
72     fun resolveExpression(
73         definitionType: String,
74         definitionName: String,
75         propName: String,
76         expressionData: ExpressionData
77     ): JsonNode {
78
79         var valueNode: JsonNode = NullNode.getInstance()
80
81         if (expressionData.isExpression) {
82             val command = expressionData.command!!
83
84             when (command) {
85                 BlueprintConstants.EXPRESSION_GET_INPUT -> {
86                     valueNode = bluePrintRuntimeService.getInputValue(expressionData.inputExpression?.propertyName!!)
87                 }
88                 BlueprintConstants.EXPRESSION_GET_ATTRIBUTE -> {
89                     valueNode =
90                         resolveAttributeExpression(definitionType, definitionName, expressionData.attributeExpression!!)
91                 }
92                 BlueprintConstants.EXPRESSION_GET_PROPERTY -> {
93                     valueNode =
94                         resolvePropertyExpression(definitionType, definitionName, expressionData.propertyExpression!!)
95                 }
96                 BlueprintConstants.EXPRESSION_GET_OPERATION_OUTPUT -> {
97                     valueNode =
98                         resolveOperationOutputExpression(definitionName, expressionData.operationOutputExpression!!)
99                 }
100                 BlueprintConstants.EXPRESSION_GET_ARTIFACT -> {
101                     valueNode = resolveArtifactExpression(definitionName, expressionData.artifactExpression!!)
102                 }
103                 BlueprintConstants.EXPRESSION_DSL_REFERENCE -> {
104                     valueNode =
105                         bluePrintRuntimeService.resolveDSLExpression(expressionData.dslExpression!!.propertyName)
106                 }
107                 BlueprintConstants.EXPRESSION_GET_NODE_OF_TYPE -> {
108                 }
109                 else -> {
110                     throw BlueprintException(
111                         "for $definitionType($definitionName) property ($propName), " +
112                             "command ($command) is not supported "
113                     )
114                 }
115             }
116         }
117         return valueNode
118     }
119
120     /*
121     get_attribute: [ <modelable_entity_name>, <optional_req_or_cap_name>, <property_name>,
122     <nested_property_name_or_index_1>, ..., <nested_property_name_or_index_n> ]
123  */
124     fun resolveAttributeExpression(
125         definitionType: String,
126         definitionName: String,
127         attributeExpression: AttributeExpression
128     ): JsonNode {
129         var valueNode: JsonNode
130
131         val attributeName = attributeExpression.attributeName
132         val subAttributeName: String? = attributeExpression.subAttributeName
133
134         var attributeDefinitionName = definitionName
135         /**
136          * Attributes are dynamic runtime properties information. There are multiple types of Attributes,
137          * ENV : Environment Variables
138          * APP : Application properties ( ie Spring resolved properties )
139          * BPP : Blueprint Properties, Specific to Blue Print execution.
140          * SELF : Current Node Template properties.
141          */
142         when (attributeExpression.modelableEntityName) {
143             BlueprintConstants.PROPERTY_ENV -> {
144                 val environmentValue = System.getenv(attributeName)
145                 valueNode = environmentValue.asJsonPrimitive()
146             }
147             BlueprintConstants.PROPERTY_APP -> {
148                 val environmentValue = System.getProperty(attributeName)
149                 valueNode = environmentValue.asJsonPrimitive()
150             }
151             BlueprintConstants.PROPERTY_BPP -> {
152                 valueNode = bluePrintRuntimeService.getNodeTemplateAttributeValue(
153                     BlueprintConstants.PROPERTY_BPP,
154                     attributeName
155                 ) ?: throw BlueprintException("failed to get env attribute name ($attributeName) ")
156             }
157             else -> {
158                 if (!attributeExpression.modelableEntityName.equals(BlueprintConstants.PROPERTY_SELF, true)) {
159                     attributeDefinitionName = attributeExpression.modelableEntityName
160                 }
161
162                 /** This block is to Validate, if Attribute definition is present */
163                 when (definitionType) {
164                     BlueprintConstants.MODEL_DEFINITION_TYPE_NODE_TEMPLATE,
165                     BlueprintConstants.MODEL_DEFINITION_TYPE_WORKFLOW,
166                     BlueprintConstants.MODEL_DEFINITION_TYPE_DSL ->
167                         bluePrintContext.nodeTemplateNodeType(attributeDefinitionName).attributes
168                     BlueprintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TEMPLATE ->
169                         bluePrintContext.relationshipTemplateRelationshipType(attributeDefinitionName).attributes
170                     else -> throw BlueprintException("failed to understand template type($definitionType), it is not supported")
171                 }?.get(attributeName)
172                     ?: throw BlueprintException(
173                         "failed to get attribute definitions for " +
174                             "$definitionType ($attributeDefinitionName)'s attribute name ($attributeName) "
175                     )
176
177                 valueNode = when (definitionType) {
178                     BlueprintConstants.MODEL_DEFINITION_TYPE_NODE_TEMPLATE,
179                     BlueprintConstants.MODEL_DEFINITION_TYPE_WORKFLOW,
180                     BlueprintConstants.MODEL_DEFINITION_TYPE_DSL ->
181                         bluePrintRuntimeService.getNodeTemplateAttributeValue(attributeDefinitionName, attributeName)
182                     BlueprintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TEMPLATE ->
183                         bluePrintRuntimeService.getRelationshipTemplateAttributeValue(
184                             attributeDefinitionName,
185                             attributeName
186                         )
187                     else -> throw BlueprintException("failed to understand template type($definitionType), it is not supported")
188                 }
189                     ?: throw BlueprintException("failed to get node template ($attributeDefinitionName)'s attribute name ($attributeName) ")
190             }
191         }
192         if (subAttributeName != null) {
193             if (valueNode.isComplexType())
194                 valueNode = valueNode.jsonPathParse(subAttributeName)
195         }
196         return valueNode
197     }
198
199     /*
200         get_property: [ <modelable_entity_name>, <optional_req_or_cap_name>, <property_name>,
201         <nested_property_name_or_index_1>, ..., <nested_property_name_or_index_n> ]
202      */
203     fun resolvePropertyExpression(
204         definitionType: String,
205         definitionName: String,
206         propertyExpression: PropertyExpression
207     ): JsonNode {
208         var valueNode: JsonNode
209
210         val propertyName = propertyExpression.propertyName
211         val subPropertyName: String? = propertyExpression.subPropertyName
212
213         var propertyDefinitionName = definitionName
214
215         if (!propertyExpression.modelableEntityName.equals(BlueprintConstants.PROPERTY_SELF, true)) {
216             propertyDefinitionName = propertyExpression.modelableEntityName
217         }
218
219         val nodeTemplatePropertyExpression = when (definitionType) {
220             BlueprintConstants.MODEL_DEFINITION_TYPE_NODE_TEMPLATE,
221             BlueprintConstants.MODEL_DEFINITION_TYPE_WORKFLOW,
222             BlueprintConstants.MODEL_DEFINITION_TYPE_DSL ->
223                 bluePrintContext.nodeTemplateByName(propertyDefinitionName).properties
224             BlueprintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TEMPLATE ->
225                 bluePrintContext.relationshipTemplateByName(propertyDefinitionName).properties
226             else -> throw BlueprintException("failed to understand template type($definitionType), it is not supported")
227         }?.get(propertyName)
228             ?: throw BlueprintException("failed to get property assignment for node template ($definitionName)'s property name ($propertyName).")
229
230         /** This block is to Validate, if Property definition is present */
231         when (definitionType) {
232             BlueprintConstants.MODEL_DEFINITION_TYPE_NODE_TEMPLATE,
233             BlueprintConstants.MODEL_DEFINITION_TYPE_WORKFLOW,
234             BlueprintConstants.MODEL_DEFINITION_TYPE_DSL ->
235                 bluePrintContext.nodeTemplateNodeType(propertyDefinitionName).properties
236             BlueprintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TEMPLATE ->
237                 bluePrintContext.relationshipTemplateRelationshipType(propertyDefinitionName).properties
238             else -> throw BlueprintException("failed to understand template type($definitionType), it is not supported")
239         }?.get(propertyName)
240             ?: throw BlueprintException("failed to get property definition for node template ($definitionName)'s property name ($propertyName).")
241
242         log.info(
243             "$definitionType($propertyDefinitionName), property($propertyName) resolved value ($nodeTemplatePropertyExpression)"
244         )
245
246         // Check it it is a nested expression
247         valueNode = resolveAssignmentExpression(
248             definitionType,
249             propertyDefinitionName,
250             propertyName,
251             nodeTemplatePropertyExpression
252         )
253
254         if (subPropertyName != null) {
255             if (valueNode.isComplexType())
256                 valueNode = valueNode.jsonPathParse(subPropertyName)
257         }
258         return valueNode
259     }
260
261     /*
262     get_operation_output: <modelable_entity_name>, <interface_name>, <operation_name>, <output_variable_name>
263      */
264     fun resolveOperationOutputExpression(
265         nodeTemplateName: String,
266         operationOutputExpression: OperationOutputExpression
267     ): JsonNode {
268         var outputNodeTemplateName = nodeTemplateName
269         if (!operationOutputExpression.modelableEntityName.equals("SELF", true)) {
270             outputNodeTemplateName = operationOutputExpression.modelableEntityName
271         }
272
273         var valueNode = bluePrintRuntimeService.getNodeTemplateOperationOutputValue(
274             outputNodeTemplateName,
275             operationOutputExpression.interfaceName, operationOutputExpression.operationName,
276             operationOutputExpression.propertyName
277         )
278
279         val subPropertyName: String? = operationOutputExpression.subPropertyName
280         if (subPropertyName != null) {
281             if (valueNode.isComplexType())
282                 valueNode = valueNode.jsonPathParse(subPropertyName)
283         }
284         return valueNode
285     }
286
287     /*
288     get_artifact: [ <modelable_entity_name>, <artifact_name>, <location>, <remove> ]
289      */
290     fun resolveArtifactExpression(nodeTemplateName: String, artifactExpression: ArtifactExpression): JsonNode {
291
292         var artifactNodeTemplateName = nodeTemplateName
293         if (!artifactExpression.modelableEntityName.equals("SELF", true)) {
294             artifactNodeTemplateName = artifactExpression.modelableEntityName
295         }
296         val artifactDefinition: ArtifactDefinition = bluePrintContext.nodeTemplateByName(artifactNodeTemplateName)
297             .artifacts?.get(artifactExpression.artifactName)
298             ?: throw BlueprintException(
299                 format(
300                     "failed to get artifact definitions for node template ({})'s " +
301                         "artifact name ({}) ",
302                     nodeTemplateName, artifactExpression.artifactName
303                 )
304             )
305
306         return JacksonUtils.jsonNodeFromObject(artifactContent(artifactDefinition))
307     }
308
309     fun artifactContent(artifactDefinition: ArtifactDefinition): String {
310         val bluePrintBasePath: String = bluePrintContext.rootPath
311
312         if (artifactDefinition.repository != null) {
313             TODO()
314         } else if (artifactDefinition.file != null) {
315             return ResourceResolverUtils.getFileContent(artifactDefinition.file, bluePrintBasePath)
316         }
317         return ""
318     }
319 }