Add output enrichment validation
[ccsdk/cds.git] / ms / controllerblueprints / modules / blueprint-validation / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / validation / utils / PropertyAssignmentValidationUtils.kt
1 /*
2  *  Copyright © 2019 IBM.
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */
16
17 package org.onap.ccsdk.cds.controllerblueprints.validation.utils
18
19 import com.fasterxml.jackson.databind.JsonNode
20 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
21 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
22 import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
23 import org.onap.ccsdk.cds.controllerblueprints.core.format
24 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
25 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintExpressionService
26 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
27
28 open class PropertyAssignmentValidationUtils(private val bluePrintContext: BluePrintContext) {
29
30     // Property Definition holds both Definitons and Expression in same construct
31     open fun validatePropertyDefinitionNAssignments(propertyDefinitions: MutableMap<String, PropertyDefinition>) {
32         propertyDefinitions.forEach { propertyName, propertyDefinition ->
33             validatePropertyDefinitionNAssignment(propertyName, propertyDefinition)
34         }
35     }
36
37     // Property Definition holds both Definitons and Expression in same construct
38     open fun validatePropertyDefinitionNAssignment(propertyName: String, propertyDefinition: PropertyDefinition) {
39         // Check and Validate if Expression Node
40         checkNotNull(propertyDefinition.value) {
41             throw BluePrintException("couldn't get 'value' property from PropertyDefinition($propertyName)")
42         }
43         val propertyAssignment = propertyDefinition.value!!
44         val expressionData = BluePrintExpressionService.getExpressionData(propertyAssignment)
45         if (!expressionData.isExpression) {
46             checkPropertyValue(propertyName, propertyDefinition, propertyAssignment)
47         }
48     }
49
50     open fun validatePropertyAssignments(nodeTypeProperties: MutableMap<String, PropertyDefinition>,
51                                          properties: MutableMap<String, JsonNode>) {
52         properties.forEach { propertyName, propertyAssignment ->
53             val propertyDefinition: PropertyDefinition = nodeTypeProperties[propertyName]
54                     ?: throw BluePrintException("failed to get definition for the property ($propertyName)")
55
56             validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
57
58         }
59     }
60
61     open fun validatePropertyAssignment(propertyName: String, propertyDefinition: PropertyDefinition,
62                                         propertyAssignment: JsonNode) {
63         // Check and Validate if Expression Node
64         val expressionData = BluePrintExpressionService.getExpressionData(propertyAssignment)
65         if (!expressionData.isExpression) {
66             checkPropertyValue(propertyName, propertyDefinition, propertyAssignment)
67         }
68     }
69
70     open fun checkPropertyValue(propertyName: String, propertyDefinition: PropertyDefinition, propertyAssignment: JsonNode) {
71         val propertyType = propertyDefinition.type
72         val isValid: Boolean
73
74         if (BluePrintTypes.validPrimitiveTypes().contains(propertyType)) {
75             isValid = JacksonUtils.checkJsonNodeValueOfPrimitiveType(propertyType, propertyAssignment)
76
77         } else if (BluePrintTypes.validComplexTypes().contains(propertyType)) {
78             isValid = true
79         } else if (BluePrintTypes.validCollectionTypes().contains(propertyType)) {
80
81             val entrySchemaType = propertyDefinition.entrySchema?.type
82                     ?: throw BluePrintException(format("Failed to get EntrySchema type for the collection property ({})", propertyName))
83
84             if (!BluePrintTypes.validPropertyTypes().contains(entrySchemaType)) {
85                 checkPropertyDataType(entrySchemaType, propertyName)
86             }
87             isValid = JacksonUtils.checkJsonNodeValueOfCollectionType(propertyType, propertyAssignment)
88         } else {
89             checkPropertyDataType(propertyType, propertyName)
90             isValid = true
91         }
92
93         check(isValid) {
94             throw BluePrintException("property(propertyName) defined of type(propertyType) is not comptable with the value (propertyAssignment)")
95         }
96     }
97
98     open fun checkPropertyDataType(dataTypeName: String, propertyName: String) {
99
100         val dataType = bluePrintContext.serviceTemplate.dataTypes?.get(dataTypeName)
101                 ?: throw BluePrintException("DataType ($dataTypeName) for the property ($propertyName) not found")
102
103         checkValidDataTypeDerivedFrom(propertyName, dataType.derivedFrom)
104
105     }
106
107     open fun checkValidDataTypeDerivedFrom(dataTypeName: String, derivedFrom: String) {
108         check(BluePrintTypes.validDataTypeDerivedFroms.contains(derivedFrom)) {
109             throw BluePrintException("Failed to get DataType($dataTypeName)'s  derivedFrom($derivedFrom) definition ")
110         }
111     }
112 }