178373704127d8f4aea91b5dc2a7d08586a26627
[ccsdk/cds.git] / components / core / src / main / kotlin / org / onap / ccsdk / apps / controllerblueprints / core / service / BluePrintValidatorService.kt
1 /*\r
2  * Copyright © 2017-2018 AT&T Intellectual Property.\r
3  * Modifications Copyright © 2018 IBM.\r
4  *\r
5  * Licensed under the Apache License, Version 2.0 (the "License");\r
6  * you may not use this file except in compliance with the License.\r
7  * You may obtain a copy of the License at\r
8  *\r
9  *     http://www.apache.org/licenses/LICENSE-2.0\r
10  *\r
11  * Unless required by applicable law or agreed to in writing, software\r
12  * distributed under the License is distributed on an "AS IS" BASIS,\r
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
14  * See the License for the specific language governing permissions and\r
15  * limitations under the License.\r
16  */\r
17 \r
18 package org.onap.ccsdk.apps.controllerblueprints.core.service\r
19 \r
20 import com.att.eelf.configuration.EELFLogger\r
21 import com.att.eelf.configuration.EELFManager\r
22 import com.fasterxml.jackson.databind.JsonNode\r
23 import com.google.common.base.Preconditions\r
24 import org.apache.commons.lang3.StringUtils\r
25 import org.onap.ccsdk.apps.controllerblueprints.core.*\r
26 import org.onap.ccsdk.apps.controllerblueprints.core.data.*\r
27 import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils\r
28 import java.io.Serializable\r
29 \r
30 /**\r
31  *\r
32  *\r
33  * @author Brinda Santh\r
34  */\r
35 interface BluePrintValidatorService : Serializable {\r
36 \r
37     @Throws(BluePrintException::class)\r
38     fun validateBlueprint(bluePrintContext: BluePrintContext, properties: MutableMap<String, Any>)\r
39 \r
40     @Throws(BluePrintException::class)\r
41     fun validateBlueprint(serviceTemplate: ServiceTemplate, properties: MutableMap<String, Any>)\r
42 }\r
43 \r
44 open class BluePrintValidatorDefaultService : BluePrintValidatorService {\r
45 \r
46     val log: EELFLogger = EELFManager.getInstance().getLogger(BluePrintValidatorDefaultService::class.toString())\r
47 \r
48     lateinit var bluePrintContext: BluePrintContext\r
49     lateinit var serviceTemplate: ServiceTemplate\r
50     lateinit var properties: MutableMap<String, Any>\r
51     var message: StringBuilder = StringBuilder()\r
52     private val separator: String = BluePrintConstants.PATH_DIVIDER\r
53     var paths: MutableList<String> = arrayListOf()\r
54 \r
55     @Throws(BluePrintException::class)\r
56     override fun validateBlueprint(bluePrintContext: BluePrintContext, properties: MutableMap<String, Any>) {\r
57         validateBlueprint(bluePrintContext.serviceTemplate, properties)\r
58     }\r
59 \r
60     @Throws(BluePrintException::class)\r
61     override fun validateBlueprint(serviceTemplate: ServiceTemplate, properties: MutableMap<String, Any>) {\r
62         this.bluePrintContext = BluePrintContext(serviceTemplate)\r
63         this.serviceTemplate = serviceTemplate\r
64         this.properties = properties\r
65         try {\r
66             message.appendln("-> Config Blueprint")\r
67             serviceTemplate.metadata?.let { validateMetadata(serviceTemplate.metadata!!) }\r
68             serviceTemplate.artifactTypes?.let { validateArtifactTypes(serviceTemplate.artifactTypes!!) }\r
69             serviceTemplate.dataTypes?.let { validateDataTypes(serviceTemplate.dataTypes!!) }\r
70             serviceTemplate.nodeTypes?.let { validateNodeTypes(serviceTemplate.nodeTypes!!) }\r
71             serviceTemplate.topologyTemplate?.let { validateTopologyTemplate(serviceTemplate.topologyTemplate!!) }\r
72         } catch (e: Exception) {\r
73             log.error("validation failed in the path : {}", paths.joinToString(separator), e)\r
74             log.error("validation trace message :{} ", message)\r
75             throw BluePrintException(e,\r
76                     format("failed to validate blueprint on path ({}) with message {}"\r
77                             , paths.joinToString(separator), e.message))\r
78         }\r
79     }\r
80 \r
81     @Throws(BluePrintException::class)\r
82     open fun validateMetadata(metaDataMap: MutableMap<String, String>) {\r
83         paths.add("metadata")\r
84 \r
85         val templateName = metaDataMap[BluePrintConstants.METADATA_TEMPLATE_NAME]\r
86         val templateVersion = metaDataMap[BluePrintConstants.METADATA_TEMPLATE_VERSION]\r
87         val templateTags = metaDataMap[BluePrintConstants.METADATA_TEMPLATE_TAGS]\r
88         val templateAuthor = metaDataMap[BluePrintConstants.METADATA_TEMPLATE_AUTHOR]\r
89 \r
90         Preconditions.checkArgument(StringUtils.isNotBlank(templateName), "failed to get template name metadata")\r
91         Preconditions.checkArgument(StringUtils.isNotBlank(templateVersion), "failed to get template version metadata")\r
92         Preconditions.checkArgument(StringUtils.isNotBlank(templateTags), "failed to get template tags metadata")\r
93         Preconditions.checkArgument(StringUtils.isNotBlank(templateAuthor), "failed to get template author metadata")\r
94         paths.removeAt(paths.lastIndex)\r
95     }\r
96 \r
97     @Throws(BluePrintException::class)\r
98     open fun validateArtifactTypes(artifactTypes: MutableMap<String, ArtifactType>) {\r
99         paths.add("artifact_types")\r
100         artifactTypes.forEach { artifactName, artifactType ->\r
101             paths.add(artifactName)\r
102             message.appendln("--> Artifact Type :" + paths.joinToString(separator))\r
103             artifactType.properties?.let { validatePropertyDefinitions(artifactType.properties!!) }\r
104             paths.removeAt(paths.lastIndex)\r
105         }\r
106         paths.removeAt(paths.lastIndex)\r
107     }\r
108 \r
109     @Throws(BluePrintException::class)\r
110     open fun validateDataTypes(dataTypes: MutableMap<String, DataType>) {\r
111         paths.add("dataTypes")\r
112         dataTypes.forEach { dataTypeName, dataType ->\r
113             paths.add(dataTypeName)\r
114             message.appendln("--> DataType :" + paths.joinToString(separator))\r
115             dataType.properties?.let { validatePropertyDefinitions(dataType.properties!!) }\r
116             paths.removeAt(paths.lastIndex)\r
117         }\r
118         paths.removeAt(paths.lastIndex)\r
119     }\r
120 \r
121     @Throws(BluePrintException::class)\r
122     open fun validateNodeTypes(nodeTypes: MutableMap<String, NodeType>) {\r
123         paths.add("nodeTypes")\r
124         nodeTypes.forEach { nodeTypeName, nodeType ->\r
125             // Validate Single Node Type\r
126             validateNodeType(nodeTypeName, nodeType)\r
127         }\r
128         paths.removeAt(paths.lastIndex)\r
129     }\r
130 \r
131     @Throws(BluePrintException::class)\r
132     open fun validateNodeType(nodeTypeName: String, nodeType: NodeType) {\r
133         paths.add(nodeTypeName)\r
134         message.appendln("--> Node Type :" + paths.joinToString(separator))\r
135         val derivedFrom: String = nodeType.derivedFrom\r
136         //Check Derived From\r
137         checkValidNodeTypesDerivedFrom(nodeTypeName, derivedFrom)\r
138 \r
139         if (!BluePrintTypes.rootNodeTypes().contains(derivedFrom)) {\r
140             serviceTemplate.nodeTypes?.get(derivedFrom)\r
141                     ?: throw BluePrintException(format("Failed to get derivedFrom NodeType({})'s for NodeType({}) ",\r
142                             derivedFrom, nodeTypeName))\r
143         }\r
144 \r
145         nodeType.properties?.let { validatePropertyDefinitions(nodeType.properties!!) }\r
146         nodeType.capabilities?.let { validateCapabilityDefinitions(nodeTypeName, nodeType) }\r
147         nodeType.requirements?.let { validateRequirementDefinitions(nodeTypeName, nodeType) }\r
148         nodeType.interfaces?.let { validateInterfaceDefinitions(nodeType.interfaces!!) }\r
149         paths.removeAt(paths.lastIndex)\r
150     }\r
151 \r
152     @Throws(BluePrintException::class)\r
153     open fun checkValidNodeTypesDerivedFrom(nodeTypeName: String, derivedFrom: String) {\r
154         check(BluePrintTypes.validNodeTypeDerivedFroms.contains(derivedFrom)) {\r
155             throw BluePrintException(format("Failed to get node type ({})'s  derivedFrom({}) definition ", nodeTypeName, derivedFrom))\r
156         }\r
157     }\r
158 \r
159     @Throws(BluePrintException::class)\r
160     open fun validateTopologyTemplate(topologyTemplate: TopologyTemplate) {\r
161         paths.add("topology")\r
162         message.appendln("--> Topology Template")\r
163         topologyTemplate.inputs?.let { validateInputs(topologyTemplate.inputs!!) }\r
164         topologyTemplate.nodeTemplates?.let { validateNodeTemplates(topologyTemplate.nodeTemplates!!) }\r
165         topologyTemplate.workflows?.let { validateWorkFlows(topologyTemplate.workflows!!) }\r
166         paths.removeAt(paths.lastIndex)\r
167     }\r
168 \r
169     @Throws(BluePrintException::class)\r
170     open fun validateInputs(inputs: MutableMap<String, PropertyDefinition>) {\r
171         paths.add("inputs")\r
172         message.appendln("---> Input :" + paths.joinToString(separator))\r
173         validatePropertyDefinitions(inputs)\r
174         paths.removeAt(paths.lastIndex)\r
175     }\r
176 \r
177     @Throws(BluePrintException::class)\r
178     open fun validateNodeTemplates(nodeTemplates: MutableMap<String, NodeTemplate>) {\r
179         paths.add("nodeTemplates")\r
180         nodeTemplates.forEach { nodeTemplateName, nodeTemplate ->\r
181             validateNodeTemplate(nodeTemplateName, nodeTemplate)\r
182         }\r
183         paths.removeAt(paths.lastIndex)\r
184     }\r
185 \r
186     @Throws(BluePrintException::class)\r
187     open fun validateNodeTemplate(nodeTemplateName: String, nodeTemplate: NodeTemplate) {\r
188         paths.add(nodeTemplateName)\r
189         message.appendln("---> NodeTemplate :" + paths.joinToString(separator))\r
190         val type: String = nodeTemplate.type\r
191 \r
192         val nodeType: NodeType = serviceTemplate.nodeTypes?.get(type)\r
193                 ?: throw BluePrintException(format("Failed to get NodeType({}) definition for NodeTemplate({})", type, nodeTemplateName))\r
194 \r
195         nodeTemplate.artifacts?.let { validateArtifactDefinitions(nodeTemplate.artifacts!!) }\r
196         nodeTemplate.properties?.let { validatePropertyAssignments(nodeType.properties!!, nodeTemplate.properties!!) }\r
197         nodeTemplate.capabilities?.let { validateCapabilityAssignments(nodeType, nodeTemplateName, nodeTemplate) }\r
198         nodeTemplate.requirements?.let { validateRequirementAssignments(nodeType, nodeTemplateName, nodeTemplate) }\r
199         nodeTemplate.interfaces?.let { validateInterfaceAssignments(nodeType, nodeTemplateName, nodeTemplate) }\r
200         paths.removeAt(paths.lastIndex)\r
201     }\r
202 \r
203     @Throws(BluePrintException::class)\r
204     open fun validateArtifactDefinitions(artifacts: MutableMap<String, ArtifactDefinition>) {\r
205         paths.add("artifacts")\r
206         artifacts.forEach { artifactDefinitionName, artifactDefinition ->\r
207             paths.add(artifactDefinitionName)\r
208             message.appendln("Validating artifact " + paths.joinToString(separator))\r
209             val type: String = artifactDefinition.type\r
210                     ?: throw BluePrintException(format("type is missing for ArtifactDefinition({})", artifactDefinitionName))\r
211             // Check Artifact Type\r
212             checkValidArtifactType(artifactDefinitionName, type)\r
213 \r
214             val file: String = artifactDefinition.file\r
215                     ?: throw BluePrintException(format("file is missing for ArtifactDefinition({})", artifactDefinitionName))\r
216 \r
217             paths.removeAt(paths.lastIndex)\r
218         }\r
219         paths.removeAt(paths.lastIndex)\r
220     }\r
221 \r
222     @Throws(BluePrintException::class)\r
223     open fun validateWorkFlows(workflows: MutableMap<String, Workflow>) {\r
224         paths.add("workflows")\r
225         workflows.forEach { workflowName, workflow ->\r
226 \r
227             // Validate Single workflow\r
228             validateWorkFlow(workflowName, workflow)\r
229         }\r
230         paths.removeAt(paths.lastIndex)\r
231     }\r
232 \r
233     @Throws(BluePrintException::class)\r
234     open fun validateWorkFlow(workflowName: String, workflow: Workflow) {\r
235         paths.add(workflowName)\r
236         message.appendln("---> Workflow :" + paths.joinToString(separator))\r
237         // Step Validation Start\r
238         paths.add("steps")\r
239         workflow.steps?.forEach { stepName, _ ->\r
240             paths.add(stepName)\r
241             message.appendln("----> Steps :" + paths.joinToString(separator))\r
242             paths.removeAt(paths.lastIndex)\r
243         }\r
244         paths.removeAt(paths.lastIndex)\r
245         // Step Validation Ends\r
246         paths.removeAt(paths.lastIndex)\r
247     }\r
248 \r
249     @Throws(BluePrintException::class)\r
250     open fun validatePropertyDefinitions(properties: MutableMap<String, PropertyDefinition>) {\r
251         paths.add("properties")\r
252         properties.forEach { propertyName, propertyDefinition ->\r
253             paths.add(propertyName)\r
254             val dataType: String = propertyDefinition.type\r
255             when {\r
256                 BluePrintTypes.validPrimitiveTypes().contains(dataType) -> {\r
257                     // Do Nothing\r
258                 }\r
259                 BluePrintTypes.validCollectionTypes().contains(dataType) -> {\r
260                     val entrySchemaType: String = propertyDefinition.entrySchema?.type\r
261                             ?: throw BluePrintException(format("Entry schema for DataType ({}) for the property ({}) not found", dataType, propertyName))\r
262                     checkPrimitiveOrComplex(entrySchemaType, propertyName)\r
263                 }\r
264                 else -> checkPropertyDataType(dataType, propertyName)\r
265             }\r
266             message.appendln("property " + paths.joinToString(separator) + " of type " + dataType)\r
267             paths.removeAt(paths.lastIndex)\r
268         }\r
269         paths.removeAt(paths.lastIndex)\r
270     }\r
271 \r
272     @Throws(BluePrintException::class)\r
273     open fun validatePropertyAssignments(nodeTypeProperties: MutableMap<String, PropertyDefinition>,\r
274                                          properties: MutableMap<String, JsonNode>) {\r
275         properties.forEach { propertyName, propertyAssignment ->\r
276             val propertyDefinition: PropertyDefinition = nodeTypeProperties[propertyName]\r
277                     ?: throw BluePrintException(format("failed to get definition for the property ({})", propertyName))\r
278 \r
279             validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)\r
280 \r
281         }\r
282     }\r
283 \r
284     @Throws(BluePrintException::class)\r
285     open fun validatePropertyAssignment(propertyName: String, propertyDefinition: PropertyDefinition,\r
286                                         propertyAssignment: JsonNode) {\r
287         // Check and Validate if Expression Node\r
288         val expressionData = BluePrintExpressionService.getExpressionData(propertyAssignment)\r
289         if (!expressionData.isExpression) {\r
290             checkPropertyValue(propertyName, propertyDefinition, propertyAssignment)\r
291         }\r
292     }\r
293 \r
294     @Throws(BluePrintException::class)\r
295     open fun validateCapabilityAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {\r
296         val capabilities = nodeTemplate.capabilities\r
297         paths.add("capabilities")\r
298         capabilities?.forEach { capabilityName, capabilityAssignment ->\r
299             paths.add(capabilityName)\r
300 \r
301             val capabilityDefinition = nodeType.capabilities?.get(capabilityName)\r
302                     ?: throw BluePrintException(format("Failed to get NodeTemplate({}) capability definition ({}) " +\r
303                             "from NodeType({}) ", nodeTemplateName, capabilityName, nodeTemplate.type))\r
304 \r
305             validateCapabilityAssignment(nodeTemplateName, capabilityName, capabilityDefinition, capabilityAssignment)\r
306 \r
307             paths.removeAt(paths.lastIndex)\r
308         }\r
309         paths.removeAt(paths.lastIndex)\r
310     }\r
311 \r
312     @Throws(BluePrintException::class)\r
313     open fun validateCapabilityAssignment(nodeTemplateName: String, capabilityName: String,\r
314                                           capabilityDefinition: CapabilityDefinition, capabilityAssignment: CapabilityAssignment) {\r
315 \r
316         capabilityAssignment.properties?.let { validatePropertyAssignments(capabilityDefinition.properties!!, capabilityAssignment.properties!!) }\r
317 \r
318     }\r
319 \r
320     @Throws(BluePrintException::class)\r
321     open fun validateRequirementAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {\r
322         val requirements = nodeTemplate.requirements\r
323         paths.add("requirements")\r
324         requirements?.forEach { requirementName, requirementAssignment ->\r
325             paths.add(requirementName)\r
326             val requirementDefinition = nodeType.requirements?.get(requirementName)\r
327                     ?: throw BluePrintException(format("Failed to get NodeTemplate({}) requirement definition ({}) from" +\r
328                             " NodeType({}) ", nodeTemplateName, requirementName, nodeTemplate.type))\r
329             // Validate Requirement Assignment\r
330             validateRequirementAssignment(nodeTemplateName, requirementName, requirementDefinition, requirementAssignment)\r
331             paths.removeAt(paths.lastIndex)\r
332         }\r
333         paths.removeAt(paths.lastIndex)\r
334 \r
335     }\r
336 \r
337     @Throws(BluePrintException::class)\r
338     open fun validateRequirementAssignment(nodeTemplateName: String, requirementAssignmentName: String,\r
339                                            requirementDefinition: RequirementDefinition, requirementAssignment: RequirementAssignment) {\r
340         log.info("Validating NodeTemplate({}) requirement assignment ({}) ", nodeTemplateName, requirementAssignmentName)\r
341         val requirementNodeTemplateName = requirementAssignment.node!!\r
342         val capabilityName = requirementAssignment.capability\r
343         val relationship = requirementAssignment.relationship!!\r
344 \r
345         check(BluePrintTypes.validRelationShipDerivedFroms.contains(relationship)) {\r
346             throw BluePrintException(format("Failed to get relationship type ({}) for NodeTemplate({})'s requirement({}) ",\r
347                     relationship, nodeTemplateName, requirementAssignmentName))\r
348         }\r
349 \r
350         val relationShipNodeTemplate = serviceTemplate.topologyTemplate?.nodeTemplates?.get(requirementNodeTemplateName)\r
351                 ?: throw BluePrintException(format("Failed to get requirement NodeTemplate({})'s for NodeTemplate({}) requirement({}) ",\r
352                         requirementNodeTemplateName, nodeTemplateName, requirementAssignmentName))\r
353 \r
354         relationShipNodeTemplate.capabilities?.get(capabilityName)\r
355                 ?: throw BluePrintException(format("Failed to get requirement NodeTemplate({})'s capability({}) for NodeTemplate ({})'s requirement({}) ",\r
356                         requirementNodeTemplateName, capabilityName, nodeTemplateName, requirementAssignmentName))\r
357 \r
358 \r
359     }\r
360 \r
361     @Throws(BluePrintException::class)\r
362     open fun validateInterfaceAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {\r
363 \r
364         val interfaces = nodeTemplate.interfaces\r
365         paths.add("interfaces")\r
366         interfaces?.forEach { interfaceAssignmentName, interfaceAssignment ->\r
367             paths.add(interfaceAssignmentName)\r
368             val interfaceDefinition = nodeType.interfaces?.get(interfaceAssignmentName)\r
369                     ?: throw BluePrintException(format("Failed to get NodeTemplate({}) interface definition ({}) from" +\r
370                             " NodeType({}) ", nodeTemplateName, interfaceAssignmentName, nodeTemplate.type))\r
371 \r
372             validateInterfaceAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,\r
373                     interfaceAssignment)\r
374             paths.removeAt(paths.lastIndex)\r
375         }\r
376         paths.removeAt(paths.lastIndex)\r
377 \r
378 \r
379     }\r
380 \r
381     @Throws(BluePrintException::class)\r
382     open fun validateInterfaceAssignment(nodeTemplateName: String, interfaceAssignmentName: String,\r
383                                          interfaceDefinition: InterfaceDefinition,\r
384                                          interfaceAssignment: InterfaceAssignment) {\r
385 \r
386         val operations = interfaceAssignment.operations\r
387         operations?.let {\r
388             validateInterfaceOperationsAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,\r
389                     interfaceAssignment)\r
390         }\r
391 \r
392     }\r
393 \r
394     @Throws(BluePrintException::class)\r
395     open fun validateInterfaceOperationsAssignment(nodeTemplateName: String, interfaceAssignmentName: String,\r
396                                                    interfaceDefinition: InterfaceDefinition,\r
397                                                    interfaceAssignment: InterfaceAssignment) {\r
398 \r
399         val operations = interfaceAssignment.operations\r
400         operations?.let {\r
401             it.forEach { operationAssignmentName, operationAssignments ->\r
402 \r
403                 val operationDefinition = interfaceDefinition.operations?.get(operationAssignmentName)\r
404                         ?: throw BluePrintException(format("Failed to get NodeTemplate({}) operation definition ({}) ",\r
405                                 nodeTemplateName, operationAssignmentName))\r
406 \r
407                 log.info("Validation NodeTemplate({}) Interface({}) Operation ({})", nodeTemplateName,\r
408                         interfaceAssignmentName, operationAssignmentName)\r
409 \r
410                 val inputs = operationAssignments.inputs\r
411                 val outputs = operationAssignments.outputs\r
412 \r
413                 inputs?.forEach { propertyName, propertyAssignment ->\r
414                     val propertyDefinition = operationDefinition.inputs?.get(propertyName)\r
415                             ?: throw BluePrintException(format("Failed to get NodeTemplate({}) operation definition ({}) " +\r
416                                     "property definition({})", nodeTemplateName, operationAssignmentName, propertyName))\r
417                     // Check the property values with property definition\r
418                     validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)\r
419                 }\r
420 \r
421                 outputs?.forEach { propertyName, propertyAssignment ->\r
422                     val propertyDefinition = operationDefinition.outputs?.get(propertyName)\r
423                             ?: throw BluePrintException(format("Failed to get NodeTemplate({}) operation definition ({}) " +\r
424                                     "output property definition({})", nodeTemplateName, operationAssignmentName,\r
425                                     propertyName))\r
426                     // Check the property values with property definition\r
427                     validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)\r
428                 }\r
429 \r
430             }\r
431         }\r
432 \r
433     }\r
434 \r
435     @Throws(BluePrintException::class)\r
436     open fun validateCapabilityDefinitions(nodeTypeName: String, nodeType: NodeType) {\r
437         val capabilities = nodeType.capabilities\r
438         paths.add("capabilities")\r
439         capabilities?.forEach { capabilityName, capabilityDefinition ->\r
440             paths.add(capabilityName)\r
441 \r
442             validateCapabilityDefinition(nodeTypeName, nodeType, capabilityName, capabilityDefinition)\r
443 \r
444             paths.removeAt(paths.lastIndex)\r
445         }\r
446         paths.removeAt(paths.lastIndex)\r
447     }\r
448 \r
449     @Throws(BluePrintException::class)\r
450     open fun validateCapabilityDefinition(nodeTypeName: String, nodeType: NodeType, capabilityName: String,\r
451                                           capabilityDefinition: CapabilityDefinition) {\r
452         val capabilityType = capabilityDefinition.type\r
453         check(BluePrintTypes.validCapabilityTypes.contains(capabilityType)) {\r
454             throw BluePrintException(format("Failed to get CapabilityType({}) for NodeType({})",\r
455                     capabilityType, nodeTypeName))\r
456         }\r
457     }\r
458 \r
459     @Throws(BluePrintException::class)\r
460     open fun validateRequirementDefinitions(nodeName: String, nodeType: NodeType) {\r
461         paths.add("requirements")\r
462         val requirements = nodeType.requirements\r
463 \r
464         requirements?.forEach { requirementDefinitionName, requirementDefinition ->\r
465             paths.add(requirementDefinitionName)\r
466             message.appendln("Validating : " + paths.joinToString(separator))\r
467             validateRequirementDefinition(nodeName, nodeType, requirementDefinitionName, requirementDefinition)\r
468             paths.removeAt(paths.lastIndex)\r
469         }\r
470         paths.removeAt(paths.lastIndex)\r
471     }\r
472 \r
473     @Throws(BluePrintException::class)\r
474     open fun validateRequirementDefinition(nodeTypeName: String, nodeType: NodeType, requirementDefinitionName: String,\r
475                                            requirementDefinition: RequirementDefinition) {\r
476 \r
477         log.info("Validating NodeType({}) RequirementDefinition ({}) ", nodeTypeName, requirementDefinitionName)\r
478         val requirementNodeTypeName = requirementDefinition.node!!\r
479         val capabilityName = requirementDefinition.capability\r
480         val relationship = requirementDefinition.relationship!!\r
481 \r
482         check(BluePrintTypes.validRelationShipDerivedFroms.contains(relationship)) {\r
483             throw BluePrintException(format("Failed to get relationship({}) for NodeType({})'s requirement({}) ",\r
484                     relationship, nodeTypeName, requirementDefinitionName))\r
485         }\r
486 \r
487         val relationShipNodeType = serviceTemplate.nodeTypes?.get(requirementNodeTypeName)\r
488                 ?: throw BluePrintException(format("Failed to get requirement NodeType({})'s for requirement({}) ",\r
489                         requirementNodeTypeName, requirementDefinitionName))\r
490 \r
491         relationShipNodeType.capabilities?.get(capabilityName)\r
492                 ?: throw BluePrintException(format("Failed to get requirement NodeType({})'s capability({}) for NodeType ({})'s requirement({}) ",\r
493                         requirementNodeTypeName, capabilityName, nodeTypeName, requirementDefinitionName))\r
494 \r
495     }\r
496 \r
497 \r
498     @Throws(BluePrintException::class)\r
499     open fun validateInterfaceDefinitions(interfaces: MutableMap<String, InterfaceDefinition>) {\r
500         paths.add("interfaces")\r
501         interfaces.forEach { interfaceName, interfaceDefinition ->\r
502             paths.add(interfaceName)\r
503             message.appendln("Validating : " + paths.joinToString(separator))\r
504             interfaceDefinition.operations?.let { validateOperationDefinitions(interfaceDefinition.operations!!) }\r
505             paths.removeAt(paths.lastIndex)\r
506         }\r
507         paths.removeAt(paths.lastIndex)\r
508     }\r
509 \r
510     @Throws(BluePrintException::class)\r
511     open fun validateOperationDefinitions(operations: MutableMap<String, OperationDefinition>) {\r
512         paths.add("operations")\r
513         operations.forEach { opertaionName, operationDefinition ->\r
514             paths.add(opertaionName)\r
515             message.appendln("Validating : " + paths.joinToString(separator))\r
516             operationDefinition.implementation?.let { validateImplementation(operationDefinition.implementation!!) }\r
517             operationDefinition.inputs?.let { validatePropertyDefinitions(operationDefinition.inputs!!) }\r
518             operationDefinition.outputs?.let { validatePropertyDefinitions(operationDefinition.outputs!!) }\r
519             paths.removeAt(paths.lastIndex)\r
520         }\r
521         paths.removeAt(paths.lastIndex)\r
522     }\r
523 \r
524     @Throws(BluePrintException::class)\r
525     open fun validateImplementation(implementation: Implementation) {\r
526         checkNotEmptyNThrow(implementation.primary)\r
527     }\r
528 \r
529     @Throws(BluePrintException::class)\r
530     open fun checkValidArtifactType(artifactDefinitionName: String, artifactTypeName: String) {\r
531 \r
532         val artifactType = serviceTemplate.artifactTypes?.get(artifactTypeName)\r
533                 ?: throw BluePrintException("failed to artifactType($artifactTypeName) for ArtifactDefinition($artifactDefinitionName)")\r
534 \r
535         checkValidArtifactTypeDerivedFrom(artifactTypeName, artifactType.derivedFrom)\r
536     }\r
537 \r
538     @Throws(BluePrintException::class)\r
539     open fun checkValidArtifactTypeDerivedFrom(artifactTypeName: String, derivedFrom: String) {\r
540         check(BluePrintTypes.validArtifactTypeDerivedFroms.contains(derivedFrom)) {\r
541             throw BluePrintException("failed to get artifactType($artifactTypeName)'s derivedFrom($derivedFrom) definition")\r
542         }\r
543     }\r
544 \r
545     @Throws(BluePrintException::class)\r
546     open fun checkValidDataTypeDerivedFrom(dataTypeName: String, derivedFrom: String) {\r
547         check(BluePrintTypes.validDataTypeDerivedFroms.contains(derivedFrom)) {\r
548             throw BluePrintException(format("Failed to get DataType({})'s  derivedFrom({}) definition ", dataTypeName, derivedFrom))\r
549         }\r
550     }\r
551 \r
552     @Throws(BluePrintException::class)\r
553     open fun checkValidRelationshipTypeDerivedFrom(relationshipTypeName: String, derivedFrom: String) {\r
554         check(BluePrintTypes.validRelationShipDerivedFroms.contains(derivedFrom)) {\r
555             throw BluePrintException(format("Failed to get relationship type ({})'s  derivedFrom({}) definition ", relationshipTypeName, derivedFrom))\r
556         }\r
557     }\r
558 \r
559     open fun checkPropertyValue(propertyName: String, propertyDefinition: PropertyDefinition, propertyAssignment: JsonNode) {\r
560         val propertyType = propertyDefinition.type\r
561         val isValid: Boolean\r
562 \r
563         if (BluePrintTypes.validPrimitiveTypes().contains(propertyType)) {\r
564             isValid = JacksonUtils.checkJsonNodeValueOfPrimitiveType(propertyType, propertyAssignment)\r
565 \r
566         } else if (BluePrintTypes.validCollectionTypes().contains(propertyType)) {\r
567 \r
568             val entrySchemaType = propertyDefinition.entrySchema?.type\r
569                     ?: throw BluePrintException(format("Failed to get EntrySchema type for the collection property ({})", propertyName))\r
570 \r
571             if (!BluePrintTypes.validPropertyTypes().contains(entrySchemaType)) {\r
572                 checkPropertyDataType(entrySchemaType, propertyName)\r
573             }\r
574             isValid = JacksonUtils.checkJsonNodeValueOfCollectionType(propertyType, propertyAssignment)\r
575         } else {\r
576             checkPropertyDataType(propertyType, propertyName)\r
577             isValid = true\r
578         }\r
579 \r
580         check(isValid) {\r
581             throw BluePrintException(format("property({}) defined of type({}) is not comptable with the value ({})",\r
582                     propertyName, propertyType, propertyAssignment))\r
583         }\r
584     }\r
585 \r
586     private fun checkPropertyDataType(dataTypeName: String, propertyName: String) {\r
587 \r
588         val dataType = serviceTemplate.dataTypes?.get(dataTypeName)\r
589                 ?: throw BluePrintException(format("DataType ({}) for the property ({}) not found", dataTypeName, propertyName))\r
590 \r
591         checkValidDataTypeDerivedFrom(propertyName, dataType.derivedFrom)\r
592 \r
593     }\r
594 \r
595     private fun checkPrimitiveOrComplex(dataType: String, propertyName: String): Boolean {\r
596         if (BluePrintTypes.validPrimitiveTypes().contains(dataType) || checkDataType(dataType)) {\r
597             return true\r
598         } else {\r
599             throw BluePrintException(format("DataType({}) for the property({}) is not valid", dataType, propertyName))\r
600         }\r
601     }\r
602 \r
603     private fun checkDataType(key: String): Boolean {\r
604         return serviceTemplate.dataTypes?.containsKey(key) ?: false\r
605     }\r
606 \r
607 }