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