Migrate "ms/controllerblueprints" from ccsdk/apps
[ccsdk/cds.git] / ms / controllerblueprints / modules / blueprint-core / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / core / service / BluePrintExpressionService.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2018 IBM.
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.att.eelf.configuration.EELFLogger
21 import com.att.eelf.configuration.EELFManager
22 import com.fasterxml.jackson.databind.JsonNode
23 import com.fasterxml.jackson.databind.node.ArrayNode
24 import com.fasterxml.jackson.databind.node.ObjectNode
25 import com.fasterxml.jackson.databind.node.TextNode
26 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
27 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
28 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
29 import org.onap.ccsdk.cds.controllerblueprints.core.data.*
30
31 /**
32  *
33  *
34  * @author Brinda Santh
35  */
36 object BluePrintExpressionService {
37     val log: EELFLogger = EELFManager.getInstance().getLogger(this::class.toString())
38
39     @JvmStatic
40     fun checkContainsExpression(propertyAssignmentNode: JsonNode): Boolean {
41         val json = propertyAssignmentNode.toString()
42         // FIXME("Check if any Optimisation needed")
43         return (json.contains(BluePrintConstants.EXPRESSION_GET_INPUT)
44                 || json.contains(BluePrintConstants.EXPRESSION_GET_ATTRIBUTE)
45                 || json.contains(BluePrintConstants.EXPRESSION_GET_PROPERTY))
46
47     }
48
49     @JvmStatic
50     fun getExpressionData(propertyAssignmentNode: JsonNode): ExpressionData {
51         log.trace("Assignment Data/Expression : {}", propertyAssignmentNode)
52         val expressionData = ExpressionData(valueNode = propertyAssignmentNode)
53         if (propertyAssignmentNode is ObjectNode) {
54             val commands: Set<String> = propertyAssignmentNode.fieldNames().asSequence().toList().intersect(BluePrintTypes.validCommands())
55             if (commands.isNotEmpty()) {
56                 expressionData.isExpression = true
57                 expressionData.command = commands.first()
58                 expressionData.expressionNode = propertyAssignmentNode
59
60                 when (expressionData.command) {
61                     BluePrintConstants.EXPRESSION_GET_INPUT -> {
62                         expressionData.inputExpression = populateInputExpression(propertyAssignmentNode)
63                     }
64                     BluePrintConstants.EXPRESSION_GET_ATTRIBUTE -> {
65                         expressionData.attributeExpression = populateAttributeExpression(propertyAssignmentNode)
66                     }
67                     BluePrintConstants.EXPRESSION_GET_PROPERTY -> {
68                         expressionData.propertyExpression = populatePropertyExpression(propertyAssignmentNode)
69                     }
70                     BluePrintConstants.EXPRESSION_GET_OPERATION_OUTPUT -> {
71                         expressionData.operationOutputExpression = populateOperationOutputExpression(propertyAssignmentNode)
72                     }
73                     BluePrintConstants.EXPRESSION_GET_ARTIFACT -> {
74                         expressionData.artifactExpression = populateArtifactExpression(propertyAssignmentNode)
75                     }
76                 }
77             }
78         } else if (propertyAssignmentNode is TextNode
79                 && propertyAssignmentNode.textValue().startsWith(BluePrintConstants.EXPRESSION_DSL_REFERENCE)) {
80             expressionData.isExpression = true
81             expressionData.command = BluePrintConstants.EXPRESSION_DSL_REFERENCE
82             expressionData.dslExpression = populateDSLExpression(propertyAssignmentNode)
83         }
84         return expressionData
85     }
86
87     @JvmStatic
88     fun populateDSLExpression(jsonNode: TextNode): DSLExpression {
89         return DSLExpression(propertyName = jsonNode.textValue()
90                 .removePrefix(BluePrintConstants.EXPRESSION_DSL_REFERENCE))
91     }
92
93     @JvmStatic
94     fun populateInputExpression(jsonNode: JsonNode): InputExpression {
95         return InputExpression(propertyName = jsonNode.first().textValue())
96     }
97
98     @JvmStatic
99     fun populatePropertyExpression(jsonNode: JsonNode): PropertyExpression {
100         val arrayNode: ArrayNode = jsonNode.first() as ArrayNode
101         check(arrayNode.size() >= 2) {
102             throw BluePrintException(String.format("missing property expression, " +
103                     "it should be [ <modelable_entity_name>, <optional_req_or_cap_name>, <property_name>, " +
104                     "<nested_property_name_or_index_1>, ..., <nested_property_name_or_index_n> ] , but present {}", jsonNode))
105         }
106         var reqOrCapEntityName: String? = null
107         var propertyName = ""
108         var subProperty: String? = null
109         when {
110             arrayNode.size() == 2 -> propertyName = arrayNode[1].textValue()
111             arrayNode.size() == 3 -> {
112                 reqOrCapEntityName = arrayNode[1].textValue()
113                 propertyName = arrayNode[2].textValue()
114             }
115             arrayNode.size() > 3 -> {
116                 reqOrCapEntityName = arrayNode[1].textValue()
117                 propertyName = arrayNode[2].textValue()
118                 val propertyPaths: List<String> = arrayNode.filterIndexed { index, _ ->
119                     index >= 3
120                 }.map { it.textValue() }
121                 subProperty = propertyPaths.joinToString("/")
122             }
123         }
124
125         return PropertyExpression(modelableEntityName = arrayNode[0].asText(),
126                 reqOrCapEntityName = reqOrCapEntityName,
127                 propertyName = propertyName,
128                 subPropertyName = subProperty
129         )
130     }
131
132     @JvmStatic
133     fun populateAttributeExpression(jsonNode: JsonNode): AttributeExpression {
134         val arrayNode: ArrayNode = jsonNode.first() as ArrayNode
135         check(arrayNode.size() >= 2) {
136             throw BluePrintException(String.format("missing attribute expression, " +
137                     "it should be [ <modelable_entity_name>, <optional_req_or_cap_name>, <attribute_name>," +
138                     " <nested_attribute_name_or_index_1>, ..., <nested_attribute_name_or_index_n> ] , but present {}", jsonNode))
139         }
140
141         var reqOrCapEntityName: String? = null
142         var attributeName = ""
143         var subAttributeName: String? = null
144         when {
145             arrayNode.size() == 2 -> attributeName = arrayNode[1].textValue()
146             arrayNode.size() == 3 -> {
147                 reqOrCapEntityName = arrayNode[1].textValue()
148                 attributeName = arrayNode[2].textValue()
149             }
150             arrayNode.size() > 3 -> {
151                 reqOrCapEntityName = arrayNode[1].textValue()
152                 attributeName = arrayNode[2].textValue()
153                 val propertyPaths: List<String> = arrayNode.filterIndexed { index, _ ->
154                     index >= 3
155                 }.map { it.textValue() }
156                 subAttributeName = propertyPaths.joinToString("/")
157             }
158         }
159         return AttributeExpression(modelableEntityName = arrayNode[0].asText(),
160                 reqOrCapEntityName = reqOrCapEntityName,
161                 attributeName = attributeName,
162                 subAttributeName = subAttributeName
163         )
164     }
165
166     @JvmStatic
167     fun populateOperationOutputExpression(jsonNode: JsonNode): OperationOutputExpression {
168         val arrayNode: ArrayNode = jsonNode.first() as ArrayNode
169
170         check(arrayNode.size() >= 4) {
171             throw BluePrintException(String.format("missing operation output expression, " +
172                     "it should be (<modelable_entity_name>, <interface_name>, <operation_name>, <output_variable_name>) , but present {}", jsonNode))
173         }
174         return OperationOutputExpression(modelableEntityName = arrayNode[0].asText(),
175                 interfaceName = arrayNode[1].asText(),
176                 operationName = arrayNode[2].asText(),
177                 propertyName = arrayNode[3].asText()
178         )
179     }
180
181     @JvmStatic
182     fun populateArtifactExpression(jsonNode: JsonNode): ArtifactExpression {
183         val arrayNode: ArrayNode = jsonNode.first() as ArrayNode
184
185         check(arrayNode.size() >= 2) {
186             throw BluePrintException(String.format("missing artifact expression, " +
187                     "it should be [ <modelable_entity_name>, <artifact_name>, <location>, <remove> ] , but present {}", jsonNode))
188         }
189         return ArtifactExpression(modelableEntityName = arrayNode[0].asText(),
190                 artifactName = arrayNode[1].asText(),
191                 location = arrayNode[2]?.asText() ?: "LOCAL_FILE",
192                 remove = arrayNode[3]?.asBoolean() ?: false
193         )
194     }
195 }