8c00e0a15e0c218061f49dccbb9084391a496a93
[ccsdk/cds.git] /
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.fasterxml.jackson.databind.JsonNode\r
21 import com.google.common.base.Preconditions\r
22 import org.apache.commons.lang3.StringUtils\r
23 import org.onap.ccsdk.apps.controllerblueprints.core.*\r
24 import org.onap.ccsdk.apps.controllerblueprints.core.data.*\r
25 import com.att.eelf.configuration.EELFLogger\r
26 import com.att.eelf.configuration.EELFManager\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.requirements?.let { validateRequirementDefinitions(nodeTypeName, nodeType) }\r
147         nodeType.interfaces?.let { validateInterfaceDefinitions(nodeType.interfaces!!) }\r
148         paths.removeAt(paths.lastIndex)\r
149     }\r
150 \r
151     @Throws(BluePrintException::class)\r
152     open fun checkValidNodeTypesDerivedFrom(nodeTypeName: String, derivedFrom: String) {\r
153         check(BluePrintTypes.validNodeTypeDerivedFroms.contains(derivedFrom)) {\r
154             throw BluePrintException(format("Failed to get node type ({})'s  derivedFrom({}) definition ", nodeTypeName, derivedFrom))\r
155         }\r
156     }\r
157 \r
158     @Throws(BluePrintException::class)\r
159     open fun validateTopologyTemplate(topologyTemplate: TopologyTemplate) {\r
160         paths.add("topology")\r
161         message.appendln("--> Topology Template")\r
162         topologyTemplate.inputs?.let { validateInputs(topologyTemplate.inputs!!) }\r
163         topologyTemplate.nodeTemplates?.let { validateNodeTemplates(topologyTemplate.nodeTemplates!!) }\r
164         topologyTemplate.workflows?.let { validateWorkFlows(topologyTemplate.workflows!!) }\r
165         paths.removeAt(paths.lastIndex)\r
166     }\r
167 \r
168     @Throws(BluePrintException::class)\r
169     open fun validateInputs(inputs: MutableMap<String, PropertyDefinition>) {\r
170         paths.add("inputs")\r
171         message.appendln("---> Input :" + paths.joinToString(separator))\r
172         validatePropertyDefinitions(inputs)\r
173         paths.removeAt(paths.lastIndex)\r
174     }\r
175 \r
176     @Throws(BluePrintException::class)\r
177     open fun validateNodeTemplates(nodeTemplates: MutableMap<String, NodeTemplate>) {\r
178         paths.add("nodeTemplates")\r
179         nodeTemplates.forEach { nodeTemplateName, nodeTemplate ->\r
180             validateNodeTemplate(nodeTemplateName, nodeTemplate)\r
181         }\r
182         paths.removeAt(paths.lastIndex)\r
183     }\r
184 \r
185     @Throws(BluePrintException::class)\r
186     open fun validateNodeTemplate(nodeTemplateName: String, nodeTemplate: NodeTemplate) {\r
187         paths.add(nodeTemplateName)\r
188         message.appendln("---> NodeTemplate :" + paths.joinToString(separator))\r
189         val type: String = nodeTemplate.type\r
190 \r
191         val nodeType: NodeType = serviceTemplate.nodeTypes?.get(type)\r
192                 ?: throw BluePrintException(format("Failed to get NodeType({}) definition for NodeTemplate({})", type, nodeTemplateName))\r
193 \r
194         nodeTemplate.artifacts?.let { validateArtifactDefinitions(nodeTemplate.artifacts!!) }\r
195         nodeTemplate.properties?.let { validatePropertyAssignments(nodeType.properties!!, nodeTemplate.properties!!) }\r
196         nodeTemplate.capabilities?.let { validateCapabilityAssignments(nodeType, nodeTemplateName, nodeTemplate) }\r
197         nodeTemplate.requirements?.let { validateRequirementAssignments(nodeType, nodeTemplateName, nodeTemplate) }\r
198         nodeTemplate.interfaces?.let { validateInterfaceAssignments(nodeType, nodeTemplateName, nodeTemplate) }\r
199         paths.removeAt(paths.lastIndex)\r
200     }\r
201 \r
202     @Throws(BluePrintException::class)\r
203     open fun validateArtifactDefinitions(artifacts: MutableMap<String, ArtifactDefinition>) {\r
204         paths.add("artifacts")\r
205         artifacts.forEach { artifactDefinitionName, artifactDefinition ->\r
206             paths.add(artifactDefinitionName)\r
207             message.appendln("Validating artifact " + paths.joinToString(separator))\r
208             val type: String = artifactDefinition.type\r
209                     ?: throw BluePrintException(format("type is missing for ArtifactDefinition({})", artifactDefinitionName))\r
210             // Check Artifact Type\r
211             checkValidArtifactType(artifactDefinitionName, type)\r
212 \r
213             val file: String = artifactDefinition.file\r
214                     ?: throw BluePrintException(format("file is missing for ArtifactDefinition({})", artifactDefinitionName))\r
215 \r
216             paths.removeAt(paths.lastIndex)\r
217         }\r
218         paths.removeAt(paths.lastIndex)\r
219     }\r
220 \r
221     @Throws(BluePrintException::class)\r
222     open fun validateWorkFlows(workflows: MutableMap<String, Workflow>) {\r
223         paths.add("workflows")\r
224         workflows.forEach { workflowName, workflow ->\r
225 \r
226             // Validate Single workflow\r
227             validateWorkFlow(workflowName, workflow)\r
228         }\r
229         paths.removeAt(paths.lastIndex)\r
230     }\r
231 \r
232     @Throws(BluePrintException::class)\r
233     open fun validateWorkFlow(workflowName: String, workflow: Workflow) {\r
234         paths.add(workflowName)\r
235         message.appendln("---> Workflow :" + paths.joinToString(separator))\r
236         // Step Validation Start\r
237         paths.add("steps")\r
238         workflow.steps?.forEach { stepName, step ->\r
239             paths.add(stepName)\r
240             message.appendln("----> Steps :" + paths.joinToString(separator))\r
241             paths.removeAt(paths.lastIndex)\r
242         }\r
243         paths.removeAt(paths.lastIndex)\r
244         // Step Validation Ends\r
245         paths.removeAt(paths.lastIndex)\r
246     }\r
247 \r
248     @Throws(BluePrintException::class)\r
249     open fun validatePropertyDefinitions(properties: MutableMap<String, PropertyDefinition>) {\r
250         paths.add("properties")\r
251         properties.forEach { propertyName, propertyDefinition ->\r
252             paths.add(propertyName)\r
253             val dataType: String = propertyDefinition.type\r
254             when {\r
255                 BluePrintTypes.validPrimitiveTypes().contains(dataType) -> {\r
256                     // Do Nothing\r
257                 }\r
258                 BluePrintTypes.validCollectionTypes().contains(dataType) -> {\r
259                     val entrySchemaType: String = propertyDefinition.entrySchema?.type\r
260                             ?: throw BluePrintException(format("Entry schema for DataType ({}) for the property ({}) not found", dataType, propertyName))\r
261                     checkPrimitiveOrComplex(entrySchemaType, propertyName)\r
262                 }\r
263                 else -> checkPropertyDataType(dataType, propertyName)\r
264             }\r
265             message.appendln("property " + paths.joinToString(separator) + " of type " + dataType)\r
266             paths.removeAt(paths.lastIndex)\r
267         }\r
268         paths.removeAt(paths.lastIndex)\r
269     }\r
270 \r
271     @Throws(BluePrintException::class)\r
272     open fun validatePropertyAssignments(nodeTypeProperties: MutableMap<String, PropertyDefinition>,\r
273                                          properties: MutableMap<String, JsonNode>) {\r
274         properties.forEach { propertyName, propertyAssignment ->\r
275             val propertyDefinition: PropertyDefinition = nodeTypeProperties[propertyName]\r
276                     ?: throw BluePrintException(format("failed to get definition for the property ({})", propertyName))\r
277 \r
278             validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)\r
279 \r
280         }\r
281     }\r
282 \r
283     @Throws(BluePrintException::class)\r
284     open fun validatePropertyAssignment(propertyName: String, propertyDefinition: PropertyDefinition,\r
285                                         propertyAssignment: JsonNode) {\r
286         // Check and Validate if Expression Node\r
287         val expressionData = BluePrintExpressionService.getExpressionData(propertyAssignment)\r
288         if (!expressionData.isExpression) {\r
289             checkPropertyValue(propertyName, propertyDefinition, propertyAssignment)\r
290         }\r
291     }\r
292 \r
293     @Throws(BluePrintException::class)\r
294     open fun validateCapabilityAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {\r
295         val capabilities = nodeTemplate.capabilities\r
296         paths.add("capabilities")\r
297         capabilities?.forEach { capabilityName, capabilityAssignment ->\r
298             paths.add(capabilityName)\r
299 \r
300             val capabilityDefinition = nodeType.capabilities?.get(capabilityName)\r
301                     ?: throw BluePrintException(format("Failed to get NodeTemplate({}) capability definition ({}) " +\r
302                             "from NodeType({}) ", nodeTemplateName, capabilityName, nodeTemplate.type))\r
303 \r
304             validateCapabilityAssignment(nodeTemplateName, capabilityName, capabilityDefinition, capabilityAssignment)\r
305 \r
306             paths.removeAt(paths.lastIndex)\r
307         }\r
308         paths.removeAt(paths.lastIndex)\r
309     }\r
310 \r
311     @Throws(BluePrintException::class)\r
312     open fun validateCapabilityAssignment(nodeTemplateName: String, capabilityName: String,\r
313                                           capabilityDefinition: CapabilityDefinition, capabilityAssignment: CapabilityAssignment) {\r
314 \r
315         capabilityAssignment.properties?.let { validatePropertyAssignments(capabilityDefinition.properties!!, capabilityAssignment.properties!!) }\r
316 \r
317     }\r
318 \r
319     @Throws(BluePrintException::class)\r
320     open fun validateRequirementAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {\r
321         val requirements = nodeTemplate.requirements\r
322         paths.add("requirements")\r
323         requirements?.forEach { requirementName, requirementAssignment ->\r
324             paths.add(requirementName)\r
325             val requirementDefinition = nodeType.requirements?.get(requirementName)\r
326                     ?: throw BluePrintException(format("Failed to get NodeTemplate({}) requirement definition ({}) from" +\r
327                             " NodeType({}) ", nodeTemplateName, requirementName, nodeTemplate.type))\r
328             // Validate Requirement Assignment\r
329             validateRequirementAssignment(nodeTemplateName, requirementName, requirementDefinition, requirementAssignment)\r
330             paths.removeAt(paths.lastIndex)\r
331         }\r
332         paths.removeAt(paths.lastIndex)\r
333 \r
334     }\r
335 \r
336     @Throws(BluePrintException::class)\r
337     open fun validateRequirementAssignment(nodeTemplateName: String, requirementAssignmentName: String,\r
338                                            requirementDefinition: RequirementDefinition, requirementAssignment: RequirementAssignment) {\r
339         log.info("Validating NodeTemplate({}) requirement assignment ({}) ", nodeTemplateName, requirementAssignmentName)\r
340         val requirementNodeTemplateName = requirementAssignment.node!!\r
341         val capabilityName = requirementAssignment.capability\r
342         val relationship = requirementAssignment.relationship!!\r
343 \r
344         check(BluePrintTypes.validRelationShipDerivedFroms.contains(relationship)) {\r
345             throw BluePrintException(format("Failed to get relationship type ({}) for NodeTemplate({})'s requirement({}) ",\r
346                     relationship, nodeTemplateName, requirementAssignmentName))\r
347         }\r
348 \r
349         val relationShipNodeTemplate = serviceTemplate.topologyTemplate?.nodeTemplates?.get(requirementNodeTemplateName)\r
350                 ?: throw BluePrintException(format("Failed to get requirement NodeTemplate({})'s for NodeTemplate({}) requirement({}) ",\r
351                         requirementNodeTemplateName, nodeTemplateName, requirementAssignmentName))\r
352 \r
353         relationShipNodeTemplate.capabilities?.get(capabilityName)\r
354                 ?: throw BluePrintException(format("Failed to get requirement NodeTemplate({})'s capability({}) for NodeTemplate ({})'s requirement({}) ",\r
355                         requirementNodeTemplateName, capabilityName, nodeTemplateName, requirementAssignmentName))\r
356 \r
357 \r
358     }\r
359 \r
360     @Throws(BluePrintException::class)\r
361     open fun validateInterfaceAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {\r
362 \r
363         val interfaces = nodeTemplate.interfaces\r
364         paths.add("interfaces")\r
365         interfaces?.forEach { interfaceAssignmentName, interfaceAssignment ->\r
366             paths.add(interfaceAssignmentName)\r
367             val interfaceDefinition = nodeType.interfaces?.get(interfaceAssignmentName)\r
368                     ?: throw BluePrintException(format("Failed to get NodeTemplate({}) interface definition ({}) from" +\r
369                             " NodeType({}) ", nodeTemplateName, interfaceAssignmentName, nodeTemplate.type))\r
370 \r
371             validateInterfaceAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,\r
372                     interfaceAssignment)\r
373             paths.removeAt(paths.lastIndex)\r
374         }\r
375         paths.removeAt(paths.lastIndex)\r
376 \r
377 \r
378     }\r
379 \r
380     @Throws(BluePrintException::class)\r
381     open fun validateInterfaceAssignment(nodeTemplateName: String, interfaceAssignmentName: String,\r
382                                          interfaceDefinition: InterfaceDefinition,\r
383                                          interfaceAssignment: InterfaceAssignment) {\r
384 \r
385         val operations = interfaceAssignment.operations\r
386         operations?.let {\r
387             validateInterfaceOperationsAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,\r
388                     interfaceAssignment)\r
389         }\r
390 \r
391     }\r
392 \r
393     @Throws(BluePrintException::class)\r
394     open fun validateInterfaceOperationsAssignment(nodeTemplateName: String, interfaceAssignmentName: String,\r
395                                                    interfaceDefinition: InterfaceDefinition,\r
396                                                    interfaceAssignment: InterfaceAssignment) {\r
397 \r
398         val operations = interfaceAssignment.operations\r
399         operations?.let {\r
400             it.forEach { operationAssignmentName, operationAssignments ->\r
401 \r
402                 val operationDefinition = interfaceDefinition.operations?.get(operationAssignmentName)\r
403                         ?: throw BluePrintException(format("Failed to get NodeTemplate({}) operation definition ({}) ",\r
404                                 nodeTemplateName, operationAssignmentName))\r
405 \r
406                 log.info("Validation NodeTemplate({}) Interface({}) Operation ({})", nodeTemplateName,\r
407                         interfaceAssignmentName, operationAssignmentName)\r
408 \r
409                 val inputs = operationAssignments.inputs\r
410                 val outputs = operationAssignments.outputs\r
411 \r
412                 inputs?.forEach { propertyName, propertyAssignment ->\r
413                     val propertyDefinition = operationDefinition.inputs?.get(propertyName)\r
414                             ?: throw BluePrintException(format("Failed to get NodeTemplate({}) operation definition ({}) " +\r
415                                     "property definition({})", nodeTemplateName, operationAssignmentName, propertyName))\r
416                     // Check the property values with property definition\r
417                     validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)\r
418                 }\r
419 \r
420                 outputs?.forEach { propertyName, propertyAssignment ->\r
421                     val propertyDefinition = operationDefinition.outputs?.get(propertyName)\r
422                             ?: throw BluePrintException(format("Failed to get NodeTemplate({}) operation definition ({}) " +\r
423                                     "output property definition({})", nodeTemplateName, operationAssignmentName,\r
424                                     propertyName))\r
425                     // Check the property values with property definition\r
426                     validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)\r
427                 }\r
428 \r
429             }\r
430         }\r
431 \r
432     }\r
433 \r
434     @Throws(BluePrintException::class)\r
435     open fun validateRequirementDefinitions(nodeName: String, nodeType: NodeType) {\r
436         paths.add("requirements")\r
437         val requirements = nodeType.requirements\r
438 \r
439         requirements?.forEach { requirementDefinitionName, requirementDefinition ->\r
440             paths.add(requirementDefinitionName)\r
441             message.appendln("Validating : " + paths.joinToString(separator))\r
442             validateRequirementDefinition(nodeName, nodeType, requirementDefinitionName, requirementDefinition)\r
443             paths.removeAt(paths.lastIndex)\r
444         }\r
445         paths.removeAt(paths.lastIndex)\r
446     }\r
447 \r
448     @Throws(BluePrintException::class)\r
449     open fun validateRequirementDefinition(nodeTypeName: String, nodeType: NodeType, requirementDefinitionName: String,\r
450                                            requirementDefinition: RequirementDefinition) {\r
451 \r
452         log.info("Validating NodeType({}) RequirementDefinition ({}) ", nodeTypeName, requirementDefinitionName)\r
453         val requirementNodeTypeName = requirementDefinition.node!!\r
454         val capabilityName = requirementDefinition.capability\r
455         val relationship = requirementDefinition.relationship!!\r
456 \r
457         check(BluePrintTypes.validRelationShipDerivedFroms.contains(relationship)) {\r
458             throw BluePrintException(format("Failed to get relationship({}) for NodeType({})'s requirement({}) ",\r
459                     relationship, nodeTypeName, requirementDefinitionName))\r
460         }\r
461 \r
462         val relationShipNodeType = serviceTemplate.nodeTypes?.get(requirementNodeTypeName)\r
463                 ?: throw BluePrintException(format("Failed to get requirement NodeType({})'s for requirement({}) ",\r
464                         requirementNodeTypeName, requirementDefinitionName))\r
465 \r
466         relationShipNodeType.capabilities?.get(capabilityName)\r
467                 ?: throw BluePrintException(format("Failed to get requirement NodeType({})'s capability({}) for NodeType ({})'s requirement({}) ",\r
468                         requirementNodeTypeName, capabilityName, nodeTypeName, requirementDefinitionName))\r
469 \r
470     }\r
471 \r
472 \r
473     @Throws(BluePrintException::class)\r
474     open fun validateInterfaceDefinitions(interfaces: MutableMap<String, InterfaceDefinition>) {\r
475         paths.add("interfaces")\r
476         interfaces.forEach { interfaceName, interfaceDefinition ->\r
477             paths.add(interfaceName)\r
478             message.appendln("Validating : " + paths.joinToString(separator))\r
479             interfaceDefinition.operations?.let { validateOperationDefinitions(interfaceDefinition.operations!!) }\r
480             paths.removeAt(paths.lastIndex)\r
481         }\r
482         paths.removeAt(paths.lastIndex)\r
483     }\r
484 \r
485     @Throws(BluePrintException::class)\r
486     open fun validateOperationDefinitions(operations: MutableMap<String, OperationDefinition>) {\r
487         paths.add("operations")\r
488         operations.forEach { opertaionName, operationDefinition ->\r
489             paths.add(opertaionName)\r
490             message.appendln("Validating : " + paths.joinToString(separator))\r
491             operationDefinition.implementation?.let { validateImplementation(operationDefinition.implementation!!) }\r
492             operationDefinition.inputs?.let { validatePropertyDefinitions(operationDefinition.inputs!!) }\r
493             operationDefinition.outputs?.let { validatePropertyDefinitions(operationDefinition.outputs!!) }\r
494             paths.removeAt(paths.lastIndex)\r
495         }\r
496         paths.removeAt(paths.lastIndex)\r
497     }\r
498 \r
499     @Throws(BluePrintException::class)\r
500     open fun validateImplementation(implementation: Implementation) {\r
501         checkNotEmptyNThrow(implementation.primary)\r
502     }\r
503 \r
504     @Throws(BluePrintException::class)\r
505     open fun checkValidArtifactType(artifactDefinitionName: String, artifactTypeName: String) {\r
506 \r
507         val artifactType = serviceTemplate.artifactTypes?.get(artifactTypeName)\r
508                 ?: throw BluePrintException(format("Failed to ArtifactType for ArtifactDefinition : {}", artifactDefinitionName))\r
509 \r
510         checkValidArtifactTypeDerivedFrom(artifactTypeName, artifactType.derivedFrom)\r
511     }\r
512 \r
513     @Throws(BluePrintException::class)\r
514     open fun checkValidArtifactTypeDerivedFrom(artifactTypeName: String, derivedFrom: String) {\r
515         check(BluePrintTypes.validArtifactTypeDerivedFroms.contains(derivedFrom)) {\r
516             throw BluePrintException(format("Failed to get ArtifactType ({})'s  derivedFrom({}) definition ", artifactTypeName, derivedFrom))\r
517         }\r
518     }\r
519 \r
520     @Throws(BluePrintException::class)\r
521     open fun checkValidDataTypeDerivedFrom(dataTypeName: String, derivedFrom: String) {\r
522         check(BluePrintTypes.validDataTypeDerivedFroms.contains(derivedFrom)) {\r
523             throw BluePrintException(format("Failed to get DataType ({})'s  derivedFrom({}) definition ", dataTypeName, derivedFrom))\r
524         }\r
525     }\r
526 \r
527     @Throws(BluePrintException::class)\r
528     open fun checkValidRelationshipTypeDerivedFrom(relationshipTypeName: String, derivedFrom: String) {\r
529         check(BluePrintTypes.validRelationShipDerivedFroms.contains(derivedFrom)) {\r
530             throw BluePrintException(format("Failed to get relationship type ({})'s  derivedFrom({}) definition ", relationshipTypeName, derivedFrom))\r
531         }\r
532     }\r
533 \r
534     open fun checkPropertyValue(propertyName: String, propertyDefinition: PropertyDefinition, propertyAssignment: JsonNode) {\r
535         val propertyType = propertyDefinition.type\r
536         val isValid: Boolean\r
537 \r
538         if (BluePrintTypes.validPrimitiveTypes().contains(propertyType)) {\r
539             isValid = JacksonUtils.checkJsonNodeValueOfPrimitiveType(propertyType, propertyAssignment)\r
540 \r
541         } else if (BluePrintTypes.validCollectionTypes().contains(propertyType)) {\r
542 \r
543             val entrySchemaType = propertyDefinition.entrySchema?.type\r
544                     ?: throw BluePrintException(format("Failed to get EntrySchema type for the collection property ({})", propertyName))\r
545 \r
546             if (!BluePrintTypes.validPropertyTypes().contains(entrySchemaType)) {\r
547                 checkPropertyDataType(entrySchemaType, propertyName)\r
548             }\r
549             isValid = JacksonUtils.checkJsonNodeValueOfCollectionType(propertyType, propertyAssignment)\r
550         } else {\r
551             checkPropertyDataType(propertyType, propertyName)\r
552             isValid = true\r
553         }\r
554 \r
555         check(isValid) {\r
556             throw BluePrintException(format("property({}) defined of type({}) is not comptable with the value ({})",\r
557                     propertyName, propertyType, propertyAssignment))\r
558         }\r
559     }\r
560 \r
561     private fun checkPropertyDataType(dataType: String, propertyName: String) {\r
562 \r
563         val dataType = serviceTemplate.dataTypes?.get(dataType)\r
564                 ?: throw BluePrintException(format("DataType ({}) for the property ({}) not found", dataType, propertyName))\r
565 \r
566         checkValidDataTypeDerivedFrom(propertyName, dataType.derivedFrom)\r
567 \r
568     }\r
569 \r
570     private fun checkPrimitiveOrComplex(dataType: String, propertyName: String): Boolean {\r
571         if (BluePrintTypes.validPrimitiveTypes().contains(dataType) || checkDataType(dataType)) {\r
572             return true\r
573         } else {\r
574             throw BluePrintException(format("DataType ({}) for the property ({}) is not valid", dataType))\r
575         }\r
576     }\r
577 \r
578     private fun checkDataType(key: String): Boolean {\r
579         return serviceTemplate.dataTypes?.containsKey(key) ?: false\r
580     }\r
581 \r
582 }