Controller Blueprints Microservice
[ccsdk/apps.git] / ms / controllerblueprints / modules / service / src / main / java / org / onap / ccsdk / apps / controllerblueprints / service / BluePrintEnhancerService.java
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.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.collections.MapUtils;\r
23 import org.apache.commons.lang3.StringUtils;\r
24 import org.jetbrains.annotations.NotNull;\r
25 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException;\r
26 import org.onap.ccsdk.apps.controllerblueprints.core.ConfigModelConstant;\r
27 import org.onap.ccsdk.apps.controllerblueprints.core.data.*;\r
28 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintEnhancerDefaultService;\r
29 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintRepoService;\r
30 import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils;\r
31 import org.onap.ccsdk.apps.controllerblueprints.resource.dict.ResourceAssignment;\r
32 import org.slf4j.Logger;\r
33 import org.slf4j.LoggerFactory;\r
34 import org.springframework.stereotype.Service;\r
35 \r
36 import java.util.HashMap;\r
37 import java.util.List;\r
38 import java.util.Map;\r
39 \r
40 /**\r
41  * BluePrintEnhancerService\r
42  *\r
43  * @author Brinda Santh DATE : 8/8/2018\r
44  */\r
45 \r
46 @Service\r
47 public class BluePrintEnhancerService extends BluePrintEnhancerDefaultService {\r
48 \r
49     private static Logger log = LoggerFactory.getLogger(BluePrintEnhancerService.class);\r
50 \r
51     private Map<String, DataType> recipeDataTypes = new HashMap<>();\r
52 \r
53     public BluePrintEnhancerService(BluePrintRepoService bluePrintEnhancerRepoDBService) {\r
54         super(bluePrintEnhancerRepoDBService);\r
55     }\r
56 \r
57     @Override\r
58     public void enrichTopologyTemplate(@NotNull ServiceTemplate serviceTemplate) {\r
59         super.enrichTopologyTemplate(serviceTemplate);\r
60 \r
61         // Update the Recipe Inputs and DataTypes\r
62         populateRecipeInputs(serviceTemplate);\r
63     }\r
64 \r
65 \r
66     @Override\r
67     public void enrichNodeTemplate(@NotNull String nodeTemplateName, @NotNull NodeTemplate nodeTemplate) throws BluePrintException {\r
68         super.enrichNodeTemplate(nodeTemplateName, nodeTemplate);\r
69 \r
70         String nodeTypeName = nodeTemplate.getType();\r
71         log.info("*** Enriching NodeType: {}", nodeTypeName);\r
72         // Get NodeType from Repo and Update Service Template\r
73         NodeType nodeType = super.populateNodeType(nodeTypeName);\r
74 \r
75         // Enrich NodeType\r
76         super.enrichNodeType(nodeTypeName, nodeType);\r
77 \r
78         // Custom for Artifact Population\r
79         if (StringUtils.isNotBlank(nodeType.getDerivedFrom())\r
80                 && ConfigModelConstant.MODEL_TYPE_NODE_ARTIFACT.equalsIgnoreCase(nodeType.getDerivedFrom())) {\r
81             populateArtifactTemplateMappingDataType(nodeTemplateName, nodeTemplate);\r
82         }\r
83 \r
84         //Enrich Node Template Artifacts\r
85         super.enrichNodeTemplateArtifactDefinition(nodeTemplateName, nodeTemplate);\r
86 \r
87     }\r
88 \r
89 \r
90     private void populateArtifactTemplateMappingDataType(@NotNull String nodeTemplateName, @NotNull NodeTemplate nodeTemplate)\r
91             throws BluePrintException {\r
92         log.info("****** Processing Artifact Node Template : {}", nodeTemplateName);\r
93 \r
94         if (nodeTemplate.getProperties() != null) {\r
95 \r
96             if (!nodeTemplate.getProperties().containsKey(ConfigModelConstant.PROPERTY_RECIPE_NAMES)) {\r
97                 throw new BluePrintException("Node Template (" + nodeTemplateName + ") doesn't have "\r
98                         + ConfigModelConstant.PROPERTY_RECIPE_NAMES + " property.");\r
99             }\r
100 \r
101             // Modified for ONAP converted Object to JsonNode\r
102             JsonNode recipeNames = nodeTemplate.getProperties().get(ConfigModelConstant.PROPERTY_RECIPE_NAMES);\r
103 \r
104             log.info("Processing Receipe Names : {} ", recipeNames);\r
105 \r
106             if (recipeNames != null && recipeNames.isArray() && recipeNames.size() > 0) {\r
107 \r
108                 Map<String, PropertyDefinition> mappingProperties =\r
109                         getCapabilityMappingProperties(nodeTemplateName, nodeTemplate);\r
110 \r
111                 for (JsonNode recipeNameNode : recipeNames) {\r
112                     String recipeName = recipeNameNode.textValue();\r
113                     processRecipe(nodeTemplateName, mappingProperties, recipeName);\r
114                 }\r
115             }\r
116         }\r
117     }\r
118 \r
119     private void processRecipe(@NotNull String nodeTemplateName, Map<String, PropertyDefinition> mappingProperties, String recipeName) {\r
120         if (StringUtils.isNotBlank(recipeName)) {\r
121             DataType recipeDataType = this.recipeDataTypes.get(recipeName);\r
122             if (recipeDataType == null) {\r
123                 log.info("DataType not present for the recipe({})", recipeName);\r
124                 recipeDataType = new DataType();\r
125                 recipeDataType.setVersion("1.0.0");\r
126                 recipeDataType.setDescription(\r
127                         "This is Dynamic Data type definition generated from resource mapping for the config template name "\r
128                                 + nodeTemplateName + ".");\r
129                 recipeDataType.setDerivedFrom(ConfigModelConstant.MODEL_TYPE_DATA_TYPE_DYNAMIC);\r
130                 Map<String, PropertyDefinition> dataTypeProperties = new HashMap<>();\r
131                 recipeDataType.setProperties(dataTypeProperties);\r
132             } else {\r
133                 log.info("DataType Already present for the recipe({})", recipeName);\r
134             }\r
135 \r
136             // Merge all the Recipe Properties\r
137             mergeDataTypeProperties(recipeDataType, mappingProperties);\r
138 \r
139             // Overwrite Recipe DataType\r
140             this.recipeDataTypes.put(recipeName, recipeDataType);\r
141 \r
142         }\r
143     }\r
144 \r
145     private Map<String, PropertyDefinition> getCapabilityMappingProperties(String nodeTemplateName,\r
146                                                                            NodeTemplate nodeTemplate) {\r
147 \r
148         Map<String, PropertyDefinition> dataTypeProperties = null;\r
149         if (nodeTemplate != null && MapUtils.isNotEmpty(nodeTemplate.getCapabilities())) {\r
150             CapabilityAssignment capability =\r
151                     nodeTemplate.getCapabilities().get(ConfigModelConstant.CAPABILITY_PROPERTY_MAPPING);\r
152 \r
153             if (capability != null && capability.getProperties() != null) {\r
154 \r
155                 String resourceAssignmentContent = JacksonUtils\r
156                         .getJson(capability.getProperties().get(ConfigModelConstant.CAPABILITY_PROPERTY_MAPPING));\r
157 \r
158                 List<ResourceAssignment> resourceAssignments =\r
159                         JacksonUtils.getListFromJson(resourceAssignmentContent, ResourceAssignment.class);\r
160 \r
161                 Preconditions.checkNotNull(resourceAssignments, "Failed to Processing Resource Mapping " + resourceAssignmentContent);\r
162                 dataTypeProperties = new HashMap<>();\r
163 \r
164                 for (ResourceAssignment resourceAssignment : resourceAssignments) {\r
165                     if (resourceAssignment != null\r
166                             // && Boolean.valueOf(resourceAssignment.getInputParameter())\r
167                             && resourceAssignment.getProperty() != null\r
168                             && StringUtils.isNotBlank(resourceAssignment.getName())) {\r
169 \r
170                         // Enrich the Property Definition\r
171                         super.enrichPropertyDefinition(resourceAssignment.getName(), resourceAssignment.getProperty());\r
172 \r
173                         dataTypeProperties.put(resourceAssignment.getName(), resourceAssignment.getProperty());\r
174 \r
175                     }\r
176                 }\r
177 \r
178             }\r
179         }\r
180         return dataTypeProperties;\r
181     }\r
182 \r
183     private void mergeDataTypeProperties(DataType dataType, Map<String, PropertyDefinition> mergeProperties) {\r
184         if (dataType != null && dataType.getProperties() != null && mergeProperties != null) {\r
185             // Add the Other Template Properties\r
186             mergeProperties.forEach((mappingKey, propertyDefinition) -> dataType.getProperties().put(mappingKey, propertyDefinition));\r
187         }\r
188     }\r
189 \r
190     private void populateRecipeInputs(ServiceTemplate serviceTemplate) {\r
191         if (serviceTemplate.getTopologyTemplate() != null\r
192                 && MapUtils.isNotEmpty(serviceTemplate.getTopologyTemplate().getInputs())\r
193                 && MapUtils.isNotEmpty(this.recipeDataTypes)\r
194                 && MapUtils.isNotEmpty(serviceTemplate.getDataTypes())) {\r
195             this.recipeDataTypes.forEach((recipeName, recipeDataType) -> {\r
196                 String dataTypePrefix = recipeName.replace("-action", "") + "-request";\r
197                 String dataTypeName = "dt-" + dataTypePrefix;\r
198 \r
199                 serviceTemplate.getDataTypes().put(dataTypeName, recipeDataType);\r
200 \r
201                 PropertyDefinition customInputProperty = new PropertyDefinition();\r
202                 customInputProperty.setDescription("This is Dynamic Data type for the receipe " + recipeName + ".");\r
203                 customInputProperty.setRequired(Boolean.FALSE);\r
204                 customInputProperty.setType(dataTypeName);\r
205                 serviceTemplate.getTopologyTemplate().getInputs().put(dataTypePrefix, customInputProperty);\r
206 \r
207             });\r
208         }\r
209     }\r
210 }\r