2  * Copyright © 2017-2018 AT&T Intellectual Property.
\r 
   3  * Modifications Copyright © 2018 IBM.
\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 
   9  *     http://www.apache.org/licenses/LICENSE-2.0
\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 
  18 package org.onap.ccsdk.apps.controllerblueprints.core.service
\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 
  33  * @author Brinda Santh
\r 
  35 interface BluePrintValidatorService : Serializable {
\r 
  37     @Throws(BluePrintException::class)
\r 
  38     fun validateBlueprint(bluePrintContext: BluePrintContext, properties: MutableMap<String, Any>)
\r 
  40     @Throws(BluePrintException::class)
\r 
  41     fun validateBlueprint(serviceTemplate: ServiceTemplate, properties: MutableMap<String, Any>)
\r 
  44 open class BluePrintValidatorDefaultService : BluePrintValidatorService {
\r 
  46     val log: EELFLogger = EELFManager.getInstance().getLogger(BluePrintValidatorDefaultService::class.toString())
\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 
  55     @Throws(BluePrintException::class)
\r 
  56     override fun validateBlueprint(bluePrintContext: BluePrintContext, properties: MutableMap<String, Any>) {
\r 
  57         validateBlueprint(bluePrintContext.serviceTemplate, properties)
\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 
  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 
  81     @Throws(BluePrintException::class)
\r 
  82     open fun validateMetadata(metaDataMap: MutableMap<String, String>) {
\r 
  83         paths.add("metadata")
\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 
  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 
  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 
 106         paths.removeAt(paths.lastIndex)
\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 
 118         paths.removeAt(paths.lastIndex)
\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 
 128         paths.removeAt(paths.lastIndex)
\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 
 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 
 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 
 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 
 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 
 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 
 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 
 183         paths.removeAt(paths.lastIndex)
\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 
 192         val nodeType: NodeType = serviceTemplate.nodeTypes?.get(type)
\r 
 193                 ?: throw BluePrintException(format("Failed to get NodeType({}) definition for NodeTemplate({})", type, nodeTemplateName))
\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 
 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 
 214             val file: String = artifactDefinition.file
\r 
 215                     ?: throw BluePrintException(format("file is missing for ArtifactDefinition({})", artifactDefinitionName))
\r 
 217             paths.removeAt(paths.lastIndex)
\r 
 219         paths.removeAt(paths.lastIndex)
\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 
 227             // Validate Single workflow
\r 
 228             validateWorkFlow(workflowName, workflow)
\r 
 230         paths.removeAt(paths.lastIndex)
\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 
 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 
 244         paths.removeAt(paths.lastIndex)
\r 
 245         // Step Validation Ends
\r 
 246         paths.removeAt(paths.lastIndex)
\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 
 256                 BluePrintTypes.validPrimitiveTypes().contains(dataType) -> {
\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 
 264                 else -> checkPropertyDataType(dataType, propertyName)
\r 
 266             message.appendln("property " + paths.joinToString(separator) + " of type " + dataType)
\r 
 267             paths.removeAt(paths.lastIndex)
\r 
 269         paths.removeAt(paths.lastIndex)
\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 
 279             validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
\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 
 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 
 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 
 305             validateCapabilityAssignment(nodeTemplateName, capabilityName, capabilityDefinition, capabilityAssignment)
\r 
 307             paths.removeAt(paths.lastIndex)
\r 
 309         paths.removeAt(paths.lastIndex)
\r 
 312     @Throws(BluePrintException::class)
\r 
 313     open fun validateCapabilityAssignment(nodeTemplateName: String, capabilityName: String,
\r 
 314                                           capabilityDefinition: CapabilityDefinition, capabilityAssignment: CapabilityAssignment) {
\r 
 316         capabilityAssignment.properties?.let { validatePropertyAssignments(capabilityDefinition.properties!!, capabilityAssignment.properties!!) }
\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 
 333         paths.removeAt(paths.lastIndex)
\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 
 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 
 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 
 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 
 361     @Throws(BluePrintException::class)
\r 
 362     open fun validateInterfaceAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
\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 
 372             validateInterfaceAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,
\r 
 373                     interfaceAssignment)
\r 
 374             paths.removeAt(paths.lastIndex)
\r 
 376         paths.removeAt(paths.lastIndex)
\r 
 381     @Throws(BluePrintException::class)
\r 
 382     open fun validateInterfaceAssignment(nodeTemplateName: String, interfaceAssignmentName: String,
\r 
 383                                          interfaceDefinition: InterfaceDefinition,
\r 
 384                                          interfaceAssignment: InterfaceAssignment) {
\r 
 386         val operations = interfaceAssignment.operations
\r 
 388             validateInterfaceOperationsAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,
\r 
 389                     interfaceAssignment)
\r 
 394     @Throws(BluePrintException::class)
\r 
 395     open fun validateInterfaceOperationsAssignment(nodeTemplateName: String, interfaceAssignmentName: String,
\r 
 396                                                    interfaceDefinition: InterfaceDefinition,
\r 
 397                                                    interfaceAssignment: InterfaceAssignment) {
\r 
 399         val operations = interfaceAssignment.operations
\r 
 401             it.forEach { operationAssignmentName, operationAssignments ->
\r 
 403                 val operationDefinition = interfaceDefinition.operations?.get(operationAssignmentName)
\r 
 404                         ?: throw BluePrintException(format("Failed to get NodeTemplate({}) operation definition ({}) ",
\r 
 405                                 nodeTemplateName, operationAssignmentName))
\r 
 407                 log.info("Validation NodeTemplate({}) Interface({}) Operation ({})", nodeTemplateName,
\r 
 408                         interfaceAssignmentName, operationAssignmentName)
\r 
 410                 val inputs = operationAssignments.inputs
\r 
 411                 val outputs = operationAssignments.outputs
\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 
 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 
 426                     // Check the property values with property definition
\r 
 427                     validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
\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 
 442             validateCapabilityDefinition(nodeTypeName, nodeType, capabilityName, capabilityDefinition)
\r 
 444             paths.removeAt(paths.lastIndex)
\r 
 446         paths.removeAt(paths.lastIndex)
\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 
 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 
 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 
 470         paths.removeAt(paths.lastIndex)
\r 
 473     @Throws(BluePrintException::class)
\r 
 474     open fun validateRequirementDefinition(nodeTypeName: String, nodeType: NodeType, requirementDefinitionName: String,
\r 
 475                                            requirementDefinition: RequirementDefinition) {
\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 
 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 
 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 
 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 
 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 
 507         paths.removeAt(paths.lastIndex)
\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 
 521         paths.removeAt(paths.lastIndex)
\r 
 524     @Throws(BluePrintException::class)
\r 
 525     open fun validateImplementation(implementation: Implementation) {
\r 
 526         checkNotEmptyNThrow(implementation.primary)
\r 
 529     @Throws(BluePrintException::class)
\r 
 530     open fun checkValidArtifactType(artifactDefinitionName: String, artifactTypeName: String) {
\r 
 532         val artifactType = serviceTemplate.artifactTypes?.get(artifactTypeName)
\r 
 533                 ?: throw BluePrintException("failed to artifactType($artifactTypeName) for ArtifactDefinition($artifactDefinitionName)")
\r 
 535         checkValidArtifactTypeDerivedFrom(artifactTypeName, artifactType.derivedFrom)
\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 
 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 
 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 
 559     open fun checkPropertyValue(propertyName: String, propertyDefinition: PropertyDefinition, propertyAssignment: JsonNode) {
\r 
 560         val propertyType = propertyDefinition.type
\r 
 561         val isValid: Boolean
\r 
 563         if (BluePrintTypes.validPrimitiveTypes().contains(propertyType)) {
\r 
 564             isValid = JacksonUtils.checkJsonNodeValueOfPrimitiveType(propertyType, propertyAssignment)
\r 
 566         } else if (BluePrintTypes.validCollectionTypes().contains(propertyType)) {
\r 
 568             val entrySchemaType = propertyDefinition.entrySchema?.type
\r 
 569                     ?: throw BluePrintException(format("Failed to get EntrySchema type for the collection property ({})", propertyName))
\r 
 571             if (!BluePrintTypes.validPropertyTypes().contains(entrySchemaType)) {
\r 
 572                 checkPropertyDataType(entrySchemaType, propertyName)
\r 
 574             isValid = JacksonUtils.checkJsonNodeValueOfCollectionType(propertyType, propertyAssignment)
\r 
 576             checkPropertyDataType(propertyType, propertyName)
\r 
 581             throw BluePrintException(format("property({}) defined of type({}) is not comptable with the value ({})",
\r 
 582                     propertyName, propertyType, propertyAssignment))
\r 
 586     private fun checkPropertyDataType(dataTypeName: String, propertyName: String) {
\r 
 588         val dataType = serviceTemplate.dataTypes?.get(dataTypeName)
\r 
 589                 ?: throw BluePrintException(format("DataType ({}) for the property ({}) not found", dataTypeName, propertyName))
\r 
 591         checkValidDataTypeDerivedFrom(propertyName, dataType.derivedFrom)
\r 
 595     private fun checkPrimitiveOrComplex(dataType: String, propertyName: String): Boolean {
\r 
 596         if (BluePrintTypes.validPrimitiveTypes().contains(dataType) || checkDataType(dataType)) {
\r 
 599             throw BluePrintException(format("DataType({}) for the property({}) is not valid", dataType, propertyName))
\r 
 603     private fun checkDataType(key: String): Boolean {
\r 
 604         return serviceTemplate.dataTypes?.containsKey(key) ?: false
\r