Add NodeTemplate Interface & Operation Validation. 26/73726/3
authorMuthuramalingam, Brinda Santh(bs2796) <bs2796@att.com>
Tue, 27 Nov 2018 20:29:57 +0000 (15:29 -0500)
committerDan Timoney <dtimoney@att.com>
Fri, 30 Nov 2018 21:09:28 +0000 (21:09 +0000)
Change-Id: I0a694512c6eaaf9190b0137f63b7ad4dbddaf1e6
Issue-ID: CCSDK-757
Signed-off-by: Muthuramalingam, Brinda Santh(bs2796) <bs2796@att.com>
components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/validation/BluePrintNodeTemplateValidatorImpl.kt [new file with mode: 0644]

diff --git a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/validation/BluePrintNodeTemplateValidatorImpl.kt b/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/validation/BluePrintNodeTemplateValidatorImpl.kt
new file mode 100644 (file)
index 0000000..bf29546
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * Copyright © 2017-2018 AT&T Intellectual Property.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.ccsdk.apps.controllerblueprints.core.validation
+
+import com.att.eelf.configuration.EELFLogger
+import com.att.eelf.configuration.EELFManager
+import com.fasterxml.jackson.databind.JsonNode
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintValidationError
+import org.onap.ccsdk.apps.controllerblueprints.core.data.*
+import org.onap.ccsdk.apps.controllerblueprints.core.format
+import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BluePrintNodeTemplateValidator
+import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BluePrintTypeValidatorService
+import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintContext
+import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintExpressionService
+import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils
+
+
+open class BluePrintNodeTemplateValidatorImpl(private val bluePrintTypeValidatorService: BluePrintTypeValidatorService) : BluePrintNodeTemplateValidator {
+
+    private val log: EELFLogger = EELFManager.getInstance().getLogger(BluePrintNodeTemplateValidatorImpl::class.toString())
+
+    var bluePrintContext: BluePrintContext? = null
+    var error: BluePrintValidationError? = null
+    var paths: MutableList<String> = arrayListOf()
+
+    override fun validate(bluePrintContext: BluePrintContext, error: BluePrintValidationError, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
+
+        paths.add(nodeTemplateName)
+
+        val type: String = nodeTemplate.type
+
+        val nodeType: NodeType = bluePrintContext.serviceTemplate.nodeTypes?.get(type)
+                ?: throw BluePrintException("Failed to get NodeType($type) definition for NodeTemplate($nodeTemplateName)")
+
+        nodeTemplate.artifacts?.let { validateArtifactDefinitions(nodeTemplate.artifacts!!) }
+        nodeTemplate.properties?.let { validatePropertyAssignments(nodeType.properties!!, nodeTemplate.properties!!) }
+        nodeTemplate.capabilities?.let { validateCapabilityAssignments(nodeType, nodeTemplateName, nodeTemplate) }
+        nodeTemplate.requirements?.let { validateRequirementAssignments(nodeType, nodeTemplateName, nodeTemplate) }
+        nodeTemplate.interfaces?.let { validateInterfaceAssignments(nodeType, nodeTemplateName, nodeTemplate) }
+
+        paths.removeAt(paths.lastIndex)
+    }
+
+    @Throws(BluePrintException::class)
+    open fun validateArtifactDefinitions(artifacts: MutableMap<String, ArtifactDefinition>) {
+        paths.add("artifacts")
+        artifacts.forEach { artifactDefinitionName, artifactDefinition ->
+            paths.add(artifactDefinitionName)
+            val type: String = artifactDefinition.type
+                    ?: throw BluePrintException("type is missing for ArtifactDefinition$artifactDefinitionName)")
+            // Check Artifact Type
+            checkValidArtifactType(artifactDefinitionName, type)
+
+            val file: String = artifactDefinition.file
+                    ?: throw BluePrintException("file is missing for ArtifactDefinition($artifactDefinitionName)")
+
+            paths.removeAt(paths.lastIndex)
+        }
+        paths.removeAt(paths.lastIndex)
+    }
+
+
+    @Throws(BluePrintException::class)
+    open fun validatePropertyAssignments(nodeTypeProperties: MutableMap<String, PropertyDefinition>,
+                                         properties: MutableMap<String, JsonNode>) {
+        properties.forEach { propertyName, propertyAssignment ->
+            val propertyDefinition: PropertyDefinition = nodeTypeProperties[propertyName]
+                    ?: throw BluePrintException("failed to get definition for the property ($propertyName)")
+
+            validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
+
+        }
+    }
+
+    @Throws(BluePrintException::class)
+    open fun validatePropertyAssignment(propertyName: String, propertyDefinition: PropertyDefinition,
+                                        propertyAssignment: JsonNode) {
+        // Check and Validate if Expression Node
+        val expressionData = BluePrintExpressionService.getExpressionData(propertyAssignment)
+        if (!expressionData.isExpression) {
+            checkPropertyValue(propertyName, propertyDefinition, propertyAssignment)
+        }
+    }
+
+    @Throws(BluePrintException::class)
+    open fun validateCapabilityAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
+        val capabilities = nodeTemplate.capabilities
+        paths.add("capabilities")
+        capabilities?.forEach { capabilityName, capabilityAssignment ->
+            paths.add(capabilityName)
+
+            val capabilityDefinition = nodeType.capabilities?.get(capabilityName)
+                    ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) capability definition ($capabilityName) " +
+                            "from NodeType(${nodeTemplate.type})")
+
+            validateCapabilityAssignment(nodeTemplateName, capabilityName, capabilityDefinition, capabilityAssignment)
+
+            paths.removeAt(paths.lastIndex)
+        }
+        paths.removeAt(paths.lastIndex)
+    }
+
+    @Throws(BluePrintException::class)
+    open fun validateCapabilityAssignment(nodeTemplateName: String, capabilityName: String,
+                                          capabilityDefinition: CapabilityDefinition, capabilityAssignment: CapabilityAssignment) {
+
+        capabilityAssignment.properties?.let { validatePropertyAssignments(capabilityDefinition.properties!!, capabilityAssignment.properties!!) }
+
+    }
+
+    @Throws(BluePrintException::class)
+    open fun validateRequirementAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
+        val requirements = nodeTemplate.requirements
+        paths.add("requirements")
+        requirements?.forEach { requirementName, requirementAssignment ->
+            paths.add(requirementName)
+            val requirementDefinition = nodeType.requirements?.get(requirementName)
+                    ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) requirement definition ($requirementName) from" +
+                            " NodeType(${nodeTemplate.type})")
+            // Validate Requirement Assignment
+            validateRequirementAssignment(nodeTemplateName, requirementName, requirementDefinition, requirementAssignment)
+            paths.removeAt(paths.lastIndex)
+        }
+        paths.removeAt(paths.lastIndex)
+
+    }
+
+    @Throws(BluePrintException::class)
+    open fun validateRequirementAssignment(nodeTemplateName: String, requirementAssignmentName: String,
+                                           requirementDefinition: RequirementDefinition, requirementAssignment: RequirementAssignment) {
+        log.info("Validating NodeTemplate({}) requirement assignment ({}) ", nodeTemplateName, requirementAssignmentName)
+        val requirementNodeTemplateName = requirementAssignment.node!!
+        val capabilityName = requirementAssignment.capability
+        val relationship = requirementAssignment.relationship!!
+
+        check(BluePrintTypes.validRelationShipDerivedFroms.contains(relationship)) {
+            throw BluePrintException("Failed to get relationship type ($relationship) for NodeTemplate($nodeTemplateName)'s requirement($requirementAssignmentName)")
+        }
+
+        val relationShipNodeTemplate = bluePrintContext!!.serviceTemplate.topologyTemplate?.nodeTemplates?.get(requirementNodeTemplateName)
+                ?: throw BluePrintException("Failed to get requirement NodeTemplate($requirementNodeTemplateName)'s " +
+                        "for NodeTemplate($nodeTemplateName) requirement($requirementAssignmentName)")
+
+        relationShipNodeTemplate.capabilities?.get(capabilityName)
+                ?: throw BluePrintException("Failed to get requirement NodeTemplate($requirementNodeTemplateName)'s " +
+                        "capability($capabilityName) for NodeTemplate ($nodeTemplateName)'s requirement($requirementAssignmentName)")
+
+
+    }
+
+    @Throws(BluePrintException::class)
+    open fun validateInterfaceAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
+
+        val interfaces = nodeTemplate.interfaces
+        paths.add("interfaces")
+        interfaces?.forEach { interfaceAssignmentName, interfaceAssignment ->
+            paths.add(interfaceAssignmentName)
+            val interfaceDefinition = nodeType.interfaces?.get(interfaceAssignmentName)
+                    ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) interface definition ($interfaceAssignmentName) from" +
+                            " NodeType(${nodeTemplate.type})")
+
+            validateInterfaceAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,
+                    interfaceAssignment)
+            paths.removeAt(paths.lastIndex)
+        }
+        paths.removeAt(paths.lastIndex)
+
+
+    }
+
+    @Throws(BluePrintException::class)
+    open fun validateInterfaceAssignment(nodeTemplateName: String, interfaceAssignmentName: String,
+                                         interfaceDefinition: InterfaceDefinition,
+                                         interfaceAssignment: InterfaceAssignment) {
+
+        val operations = interfaceAssignment.operations
+        operations?.let {
+            validateInterfaceOperationsAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,
+                    interfaceAssignment)
+        }
+
+    }
+
+    @Throws(BluePrintException::class)
+    open fun validateInterfaceOperationsAssignment(nodeTemplateName: String, interfaceAssignmentName: String,
+                                                   interfaceDefinition: InterfaceDefinition,
+                                                   interfaceAssignment: InterfaceAssignment) {
+
+        val operations = interfaceAssignment.operations
+        operations?.let {
+            it.forEach { operationAssignmentName, operationAssignments ->
+
+                val operationDefinition = interfaceDefinition.operations?.get(operationAssignmentName)
+                        ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) operation definition ($operationAssignmentName)")
+
+                log.info("Validation NodeTemplate({}) Interface({}) Operation ({})", nodeTemplateName,
+                        interfaceAssignmentName, operationAssignmentName)
+
+                val inputs = operationAssignments.inputs
+                val outputs = operationAssignments.outputs
+
+                inputs?.forEach { propertyName, propertyAssignment ->
+                    val propertyDefinition = operationDefinition.inputs?.get(propertyName)
+                            ?: throw BluePrintException("Failed to get NodeTemplate(nodeTemplateName) operation " +
+                                    "definition (operationAssignmentName) property definition(propertyName)")
+                    // Check the property values with property definition
+                    validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
+                }
+
+                outputs?.forEach { propertyName, propertyAssignment ->
+                    val propertyDefinition = operationDefinition.outputs?.get(propertyName)
+                            ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) operation definition ($operationAssignmentName) " +
+                                    "output property definition($propertyName)")
+                    // Check the property values with property definition
+                    validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
+                }
+
+            }
+        }
+
+    }
+
+    open fun checkValidArtifactType(artifactDefinitionName: String, artifactTypeName: String) {
+
+        val artifactType = bluePrintContext!!.serviceTemplate.artifactTypes?.get(artifactTypeName)
+                ?: throw BluePrintException("failed to artifactType($artifactTypeName) for ArtifactDefinition($artifactDefinitionName)")
+
+        checkValidArtifactTypeDerivedFrom(artifactTypeName, artifactType.derivedFrom)
+    }
+
+    @Throws(BluePrintException::class)
+    open fun checkValidArtifactTypeDerivedFrom(artifactTypeName: String, derivedFrom: String) {
+        check(BluePrintTypes.validArtifactTypeDerivedFroms.contains(derivedFrom)) {
+            throw BluePrintException("failed to get artifactType($artifactTypeName)'s derivedFrom($derivedFrom) definition")
+        }
+    }
+
+    open fun checkPropertyValue(propertyName: String, propertyDefinition: PropertyDefinition, propertyAssignment: JsonNode) {
+        val propertyType = propertyDefinition.type
+        val isValid: Boolean
+
+        if (BluePrintTypes.validPrimitiveTypes().contains(propertyType)) {
+            isValid = JacksonUtils.checkJsonNodeValueOfPrimitiveType(propertyType, propertyAssignment)
+
+        } else if (BluePrintTypes.validCollectionTypes().contains(propertyType)) {
+
+            val entrySchemaType = propertyDefinition.entrySchema?.type
+                    ?: throw BluePrintException(format("Failed to get EntrySchema type for the collection property ({})", propertyName))
+
+            if (!BluePrintTypes.validPropertyTypes().contains(entrySchemaType)) {
+                checkPropertyDataType(entrySchemaType, propertyName)
+            }
+            isValid = JacksonUtils.checkJsonNodeValueOfCollectionType(propertyType, propertyAssignment)
+        } else {
+            checkPropertyDataType(propertyType, propertyName)
+            isValid = true
+        }
+
+        check(isValid) {
+            throw BluePrintException("property(propertyName) defined of type(propertyType) is not comptable with the value (propertyAssignment)")
+        }
+    }
+
+    private fun checkPropertyDataType(dataTypeName: String, propertyName: String) {
+
+        val dataType = bluePrintContext!!.serviceTemplate.dataTypes?.get(dataTypeName)
+                ?: throw BluePrintException("DataType ($dataTypeName) for the property ($propertyName) not found")
+
+        checkValidDataTypeDerivedFrom(propertyName, dataType.derivedFrom)
+
+    }
+
+    private fun checkValidDataTypeDerivedFrom(dataTypeName: String, derivedFrom: String) {
+        check(BluePrintTypes.validDataTypeDerivedFroms.contains(derivedFrom)) {
+            throw BluePrintException("Failed to get DataType($dataTypeName)'s  derivedFrom($derivedFrom) definition ")
+        }
+    }
+
+}
\ No newline at end of file