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