bf2954684675e0411de9fa715eea3000231b6966
[ccsdk/cds.git] /
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.ccsdk.apps.controllerblueprints.core.validation
18
19 import com.att.eelf.configuration.EELFLogger
20 import com.att.eelf.configuration.EELFManager
21 import com.fasterxml.jackson.databind.JsonNode
22 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException
23 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintTypes
24 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintValidationError
25 import org.onap.ccsdk.apps.controllerblueprints.core.data.*
26 import org.onap.ccsdk.apps.controllerblueprints.core.format
27 import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BluePrintNodeTemplateValidator
28 import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BluePrintTypeValidatorService
29 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintContext
30 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintExpressionService
31 import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils
32
33
34 open class BluePrintNodeTemplateValidatorImpl(private val bluePrintTypeValidatorService: BluePrintTypeValidatorService) : BluePrintNodeTemplateValidator {
35
36     private val log: EELFLogger = EELFManager.getInstance().getLogger(BluePrintNodeTemplateValidatorImpl::class.toString())
37
38     var bluePrintContext: BluePrintContext? = null
39     var error: BluePrintValidationError? = null
40     var paths: MutableList<String> = arrayListOf()
41
42     override fun validate(bluePrintContext: BluePrintContext, error: BluePrintValidationError, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
43
44         paths.add(nodeTemplateName)
45
46         val type: String = nodeTemplate.type
47
48         val nodeType: NodeType = bluePrintContext.serviceTemplate.nodeTypes?.get(type)
49                 ?: throw BluePrintException("Failed to get NodeType($type) definition for NodeTemplate($nodeTemplateName)")
50
51         nodeTemplate.artifacts?.let { validateArtifactDefinitions(nodeTemplate.artifacts!!) }
52         nodeTemplate.properties?.let { validatePropertyAssignments(nodeType.properties!!, nodeTemplate.properties!!) }
53         nodeTemplate.capabilities?.let { validateCapabilityAssignments(nodeType, nodeTemplateName, nodeTemplate) }
54         nodeTemplate.requirements?.let { validateRequirementAssignments(nodeType, nodeTemplateName, nodeTemplate) }
55         nodeTemplate.interfaces?.let { validateInterfaceAssignments(nodeType, nodeTemplateName, nodeTemplate) }
56
57         paths.removeAt(paths.lastIndex)
58     }
59
60     @Throws(BluePrintException::class)
61     open fun validateArtifactDefinitions(artifacts: MutableMap<String, ArtifactDefinition>) {
62         paths.add("artifacts")
63         artifacts.forEach { artifactDefinitionName, artifactDefinition ->
64             paths.add(artifactDefinitionName)
65             val type: String = artifactDefinition.type
66                     ?: throw BluePrintException("type is missing for ArtifactDefinition$artifactDefinitionName)")
67             // Check Artifact Type
68             checkValidArtifactType(artifactDefinitionName, type)
69
70             val file: String = artifactDefinition.file
71                     ?: throw BluePrintException("file is missing for ArtifactDefinition($artifactDefinitionName)")
72
73             paths.removeAt(paths.lastIndex)
74         }
75         paths.removeAt(paths.lastIndex)
76     }
77
78
79     @Throws(BluePrintException::class)
80     open fun validatePropertyAssignments(nodeTypeProperties: MutableMap<String, PropertyDefinition>,
81                                          properties: MutableMap<String, JsonNode>) {
82         properties.forEach { propertyName, propertyAssignment ->
83             val propertyDefinition: PropertyDefinition = nodeTypeProperties[propertyName]
84                     ?: throw BluePrintException("failed to get definition for the property ($propertyName)")
85
86             validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
87
88         }
89     }
90
91     @Throws(BluePrintException::class)
92     open fun validatePropertyAssignment(propertyName: String, propertyDefinition: PropertyDefinition,
93                                         propertyAssignment: JsonNode) {
94         // Check and Validate if Expression Node
95         val expressionData = BluePrintExpressionService.getExpressionData(propertyAssignment)
96         if (!expressionData.isExpression) {
97             checkPropertyValue(propertyName, propertyDefinition, propertyAssignment)
98         }
99     }
100
101     @Throws(BluePrintException::class)
102     open fun validateCapabilityAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
103         val capabilities = nodeTemplate.capabilities
104         paths.add("capabilities")
105         capabilities?.forEach { capabilityName, capabilityAssignment ->
106             paths.add(capabilityName)
107
108             val capabilityDefinition = nodeType.capabilities?.get(capabilityName)
109                     ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) capability definition ($capabilityName) " +
110                             "from NodeType(${nodeTemplate.type})")
111
112             validateCapabilityAssignment(nodeTemplateName, capabilityName, capabilityDefinition, capabilityAssignment)
113
114             paths.removeAt(paths.lastIndex)
115         }
116         paths.removeAt(paths.lastIndex)
117     }
118
119     @Throws(BluePrintException::class)
120     open fun validateCapabilityAssignment(nodeTemplateName: String, capabilityName: String,
121                                           capabilityDefinition: CapabilityDefinition, capabilityAssignment: CapabilityAssignment) {
122
123         capabilityAssignment.properties?.let { validatePropertyAssignments(capabilityDefinition.properties!!, capabilityAssignment.properties!!) }
124
125     }
126
127     @Throws(BluePrintException::class)
128     open fun validateRequirementAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
129         val requirements = nodeTemplate.requirements
130         paths.add("requirements")
131         requirements?.forEach { requirementName, requirementAssignment ->
132             paths.add(requirementName)
133             val requirementDefinition = nodeType.requirements?.get(requirementName)
134                     ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) requirement definition ($requirementName) from" +
135                             " NodeType(${nodeTemplate.type})")
136             // Validate Requirement Assignment
137             validateRequirementAssignment(nodeTemplateName, requirementName, requirementDefinition, requirementAssignment)
138             paths.removeAt(paths.lastIndex)
139         }
140         paths.removeAt(paths.lastIndex)
141
142     }
143
144     @Throws(BluePrintException::class)
145     open fun validateRequirementAssignment(nodeTemplateName: String, requirementAssignmentName: String,
146                                            requirementDefinition: RequirementDefinition, requirementAssignment: RequirementAssignment) {
147         log.info("Validating NodeTemplate({}) requirement assignment ({}) ", nodeTemplateName, requirementAssignmentName)
148         val requirementNodeTemplateName = requirementAssignment.node!!
149         val capabilityName = requirementAssignment.capability
150         val relationship = requirementAssignment.relationship!!
151
152         check(BluePrintTypes.validRelationShipDerivedFroms.contains(relationship)) {
153             throw BluePrintException("Failed to get relationship type ($relationship) for NodeTemplate($nodeTemplateName)'s requirement($requirementAssignmentName)")
154         }
155
156         val relationShipNodeTemplate = bluePrintContext!!.serviceTemplate.topologyTemplate?.nodeTemplates?.get(requirementNodeTemplateName)
157                 ?: throw BluePrintException("Failed to get requirement NodeTemplate($requirementNodeTemplateName)'s " +
158                         "for NodeTemplate($nodeTemplateName) requirement($requirementAssignmentName)")
159
160         relationShipNodeTemplate.capabilities?.get(capabilityName)
161                 ?: throw BluePrintException("Failed to get requirement NodeTemplate($requirementNodeTemplateName)'s " +
162                         "capability($capabilityName) for NodeTemplate ($nodeTemplateName)'s requirement($requirementAssignmentName)")
163
164
165     }
166
167     @Throws(BluePrintException::class)
168     open fun validateInterfaceAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
169
170         val interfaces = nodeTemplate.interfaces
171         paths.add("interfaces")
172         interfaces?.forEach { interfaceAssignmentName, interfaceAssignment ->
173             paths.add(interfaceAssignmentName)
174             val interfaceDefinition = nodeType.interfaces?.get(interfaceAssignmentName)
175                     ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) interface definition ($interfaceAssignmentName) from" +
176                             " NodeType(${nodeTemplate.type})")
177
178             validateInterfaceAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,
179                     interfaceAssignment)
180             paths.removeAt(paths.lastIndex)
181         }
182         paths.removeAt(paths.lastIndex)
183
184
185     }
186
187     @Throws(BluePrintException::class)
188     open fun validateInterfaceAssignment(nodeTemplateName: String, interfaceAssignmentName: String,
189                                          interfaceDefinition: InterfaceDefinition,
190                                          interfaceAssignment: InterfaceAssignment) {
191
192         val operations = interfaceAssignment.operations
193         operations?.let {
194             validateInterfaceOperationsAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,
195                     interfaceAssignment)
196         }
197
198     }
199
200     @Throws(BluePrintException::class)
201     open fun validateInterfaceOperationsAssignment(nodeTemplateName: String, interfaceAssignmentName: String,
202                                                    interfaceDefinition: InterfaceDefinition,
203                                                    interfaceAssignment: InterfaceAssignment) {
204
205         val operations = interfaceAssignment.operations
206         operations?.let {
207             it.forEach { operationAssignmentName, operationAssignments ->
208
209                 val operationDefinition = interfaceDefinition.operations?.get(operationAssignmentName)
210                         ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) operation definition ($operationAssignmentName)")
211
212                 log.info("Validation NodeTemplate({}) Interface({}) Operation ({})", nodeTemplateName,
213                         interfaceAssignmentName, operationAssignmentName)
214
215                 val inputs = operationAssignments.inputs
216                 val outputs = operationAssignments.outputs
217
218                 inputs?.forEach { propertyName, propertyAssignment ->
219                     val propertyDefinition = operationDefinition.inputs?.get(propertyName)
220                             ?: throw BluePrintException("Failed to get NodeTemplate(nodeTemplateName) operation " +
221                                     "definition (operationAssignmentName) property definition(propertyName)")
222                     // Check the property values with property definition
223                     validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
224                 }
225
226                 outputs?.forEach { propertyName, propertyAssignment ->
227                     val propertyDefinition = operationDefinition.outputs?.get(propertyName)
228                             ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) operation definition ($operationAssignmentName) " +
229                                     "output property definition($propertyName)")
230                     // Check the property values with property definition
231                     validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
232                 }
233
234             }
235         }
236
237     }
238
239     open fun checkValidArtifactType(artifactDefinitionName: String, artifactTypeName: String) {
240
241         val artifactType = bluePrintContext!!.serviceTemplate.artifactTypes?.get(artifactTypeName)
242                 ?: throw BluePrintException("failed to artifactType($artifactTypeName) for ArtifactDefinition($artifactDefinitionName)")
243
244         checkValidArtifactTypeDerivedFrom(artifactTypeName, artifactType.derivedFrom)
245     }
246
247     @Throws(BluePrintException::class)
248     open fun checkValidArtifactTypeDerivedFrom(artifactTypeName: String, derivedFrom: String) {
249         check(BluePrintTypes.validArtifactTypeDerivedFroms.contains(derivedFrom)) {
250             throw BluePrintException("failed to get artifactType($artifactTypeName)'s derivedFrom($derivedFrom) definition")
251         }
252     }
253
254     open fun checkPropertyValue(propertyName: String, propertyDefinition: PropertyDefinition, propertyAssignment: JsonNode) {
255         val propertyType = propertyDefinition.type
256         val isValid: Boolean
257
258         if (BluePrintTypes.validPrimitiveTypes().contains(propertyType)) {
259             isValid = JacksonUtils.checkJsonNodeValueOfPrimitiveType(propertyType, propertyAssignment)
260
261         } else if (BluePrintTypes.validCollectionTypes().contains(propertyType)) {
262
263             val entrySchemaType = propertyDefinition.entrySchema?.type
264                     ?: throw BluePrintException(format("Failed to get EntrySchema type for the collection property ({})", propertyName))
265
266             if (!BluePrintTypes.validPropertyTypes().contains(entrySchemaType)) {
267                 checkPropertyDataType(entrySchemaType, propertyName)
268             }
269             isValid = JacksonUtils.checkJsonNodeValueOfCollectionType(propertyType, propertyAssignment)
270         } else {
271             checkPropertyDataType(propertyType, propertyName)
272             isValid = true
273         }
274
275         check(isValid) {
276             throw BluePrintException("property(propertyName) defined of type(propertyType) is not comptable with the value (propertyAssignment)")
277         }
278     }
279
280     private fun checkPropertyDataType(dataTypeName: String, propertyName: String) {
281
282         val dataType = bluePrintContext!!.serviceTemplate.dataTypes?.get(dataTypeName)
283                 ?: throw BluePrintException("DataType ($dataTypeName) for the property ($propertyName) not found")
284
285         checkValidDataTypeDerivedFrom(propertyName, dataType.derivedFrom)
286
287     }
288
289     private fun checkValidDataTypeDerivedFrom(dataTypeName: String, derivedFrom: String) {
290         check(BluePrintTypes.validDataTypeDerivedFroms.contains(derivedFrom)) {
291             throw BluePrintException("Failed to get DataType($dataTypeName)'s  derivedFrom($derivedFrom) definition ")
292         }
293     }
294
295 }