80e469771df548ef4335d710e11795dce867e7bd
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
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.openecomp.sdc.enrichment.impl.tosca;
18
19 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.HIGH_AVAIL_MODE;
20 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.MANDATORY;
21 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.MAX_INSTANCES;
22 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.MIN_INSTANCES;
23 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.VFC_CODE;
24 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.NFC_FUNCTION;
25 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.NFC_NAMING_CODE;
26 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.VM_TYPE_TAG;
27 import static org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType.NATIVE_NODE;
28 import static org.openecomp.sdc.tosca.datatypes.ToscaNodeType.VFC_ABSTRACT_SUBSTITUTE;
29 import static org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType.NATIVE_DEPENDS_ON;
30 import static org.openecomp.sdc.tosca.services.ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME;
31 import static org.openecomp.sdc.translator.services.heattotosca.Constants.ABSTRACT_NODE_TEMPLATE_ID_PREFIX;
32
33 import org.apache.commons.collections4.CollectionUtils;
34 import org.apache.commons.lang3.StringUtils;
35 import org.openecomp.sdc.datatypes.error.ErrorMessage;
36 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
37 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
38 import org.onap.sdc.tosca.datatypes.model.NodeType;
39 import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
40 import org.onap.sdc.tosca.datatypes.model.RequirementDefinition;
41 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
42 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
43 import org.openecomp.sdc.tosca.services.DataModelUtil;
44 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
45 import org.openecomp.sdc.tosca.services.ToscaConstants;
46 import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
47
48 import java.util.ArrayList;
49 import java.util.HashMap;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.Objects;
53 import java.util.Optional;
54
55 import org.openecomp.sdc.versioning.dao.types.Version;
56
57 public class AbstractSubstituteToscaEnricher {
58
59     private ToscaAnalyzerService toscaAnalyzerService;
60     private ComponentQuestionnaireData componentQuestionnaireData;
61
62
63     public Map<String, List<ErrorMessage>> enrich(ToscaServiceModel toscaModel, String vspId, Version version) {
64         componentQuestionnaireData = getComponentQuestionnaireData();
65         toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
66
67         Map<String, Map<String, Object>> componentProperties =
68                 componentQuestionnaireData.getPropertiesfromCompQuestionnaire(vspId, version);
69
70         final Map<String, List<String>> sourceToTargetDependencies = componentQuestionnaireData
71                                                                              .populateDependencies(vspId, version,
72                                                                                      componentQuestionnaireData
73                                                                                       .getSourceToTargetComponent());
74         Map<String, List<ErrorMessage>> errors = new HashMap<>();
75
76         final ServiceTemplate serviceTemplate =
77                 toscaModel.getServiceTemplates().get(toscaModel.getEntryDefinitionServiceTemplate());
78
79         if (serviceTemplate == null) {
80             return errors;
81         }
82
83         final Map<String, NodeTemplate> node_templates = serviceTemplate.getTopology_template().getNode_templates();
84         if (node_templates == null) {
85             return errors;
86         }
87
88         final Map<String, List<String>> componentDisplayNameToNodeTempalteIds =
89                 populateAllNodeTemplateIdForComponent(node_templates, serviceTemplate, toscaModel);
90
91         node_templates.keySet().stream().forEach(nodeTemplateId -> {
92             final Optional<NodeTemplate> nodeTemplateById =
93                     toscaAnalyzerService.getNodeTemplateById(serviceTemplate, nodeTemplateId);
94             final NodeTemplate nodeTemplate = nodeTemplateById.isPresent() ? nodeTemplateById.get() : null;
95
96             if (toscaAnalyzerService.isTypeOf(nodeTemplate, VFC_ABSTRACT_SUBSTITUTE, serviceTemplate, toscaModel)) {
97
98                 String componentDisplayName = getComponentDisplayName(nodeTemplateId, nodeTemplate);
99
100                 setProperty(nodeTemplate, VM_TYPE_TAG, componentDisplayName);
101
102                 if (componentProperties != null && componentProperties.containsKey(componentDisplayName)) {
103                     final String mandatory =
104                             getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, MANDATORY);
105
106                     boolean isServiceTemplateFilterNotExists = false;
107                     if (!StringUtils.isEmpty(mandatory)) {
108                         Map innerProps = (Map<String, Object>) nodeTemplate.getProperties()
109                                                                            .get(SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
110
111                         if (innerProps == null) {
112                             innerProps = new HashMap<String, Object>();
113                             isServiceTemplateFilterNotExists = true;
114                         }
115
116                         innerProps.put(MANDATORY, getValue(mandatory));
117
118                         if (isServiceTemplateFilterNotExists) {
119                             nodeTemplate.getProperties().put(SERVICE_TEMPLATE_FILTER_PROPERTY_NAME, innerProps);
120                         }
121                     }
122
123                     setProperty(nodeTemplate, HIGH_AVAIL_MODE,
124                             getValueFromQuestionnaireDetails(componentProperties, componentDisplayName,
125                                     HIGH_AVAIL_MODE));
126
127                     setProperty(nodeTemplate, NFC_NAMING_CODE,
128                             getValueFromQuestionnaireDetails(componentProperties, componentDisplayName,
129                                     NFC_NAMING_CODE));
130
131                     setProperty(nodeTemplate, VFC_CODE,
132                             getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, VFC_CODE));
133
134                     setProperty(nodeTemplate, NFC_FUNCTION,
135                             getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, NFC_FUNCTION));
136
137                     if (componentProperties.get(componentDisplayName).get(MIN_INSTANCES) != null) {
138                         nodeTemplate.getProperties().put(MIN_INSTANCES,
139                                 componentProperties.get(componentDisplayName).get(MIN_INSTANCES));
140                     }
141
142                     if (componentProperties.get(componentDisplayName).get(MAX_INSTANCES) != null) {
143                         nodeTemplate.getProperties().put(MAX_INSTANCES,
144                                 componentProperties.get(componentDisplayName).get(MAX_INSTANCES));
145                     }
146                 }
147
148                 enrichRequirements(sourceToTargetDependencies, componentDisplayName, nodeTemplate,
149                         componentDisplayNameToNodeTempalteIds, serviceTemplate, toscaModel);
150             }
151         });
152         return errors;
153     }
154
155     private Map<String, List<String>> populateAllNodeTemplateIdForComponent(Map<String, NodeTemplate> node_templates,
156                                                                                    ServiceTemplate serviceTemplate,
157                                                                                    ToscaServiceModel toscaModel) {
158
159
160         Map<String, List<String>> componentDisplayNameToNodeTempalteIds = new HashMap<>();
161
162         //set dependency target
163         node_templates.keySet().stream().forEach(nodeTemplateId -> {
164
165             final Optional<NodeTemplate> nodeTemplateById =
166                     toscaAnalyzerService.getNodeTemplateById(serviceTemplate, nodeTemplateId);
167             final NodeTemplate nodeTemplate = nodeTemplateById.isPresent() ? nodeTemplateById.get() : null;
168
169             if (toscaAnalyzerService.isTypeOf(nodeTemplate, VFC_ABSTRACT_SUBSTITUTE, serviceTemplate, toscaModel)) {
170
171                 String componentDisplayName = getComponentDisplayName(nodeTemplateId, nodeTemplate);
172
173                 if (componentDisplayNameToNodeTempalteIds.containsKey(componentDisplayName)) {
174                     componentDisplayNameToNodeTempalteIds.get(componentDisplayName).add(nodeTemplateId);
175                 } else {
176                     List<String> nodeTemplateIds = new ArrayList<>();
177                     nodeTemplateIds.add(nodeTemplateId);
178                     componentDisplayNameToNodeTempalteIds.put(componentDisplayName, nodeTemplateIds);
179                 }
180
181             }
182         });
183
184         return componentDisplayNameToNodeTempalteIds;
185     }
186
187     private void enrichRequirements(Map<String, List<String>> sourceToTargetDependencies, String componentDisplayName,
188                                            NodeTemplate nodeTemplate,
189                                            Map<String, List<String>> componentDisplayNameToNodeTempalteIds,
190                                            ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
191         final List<String> targets = sourceToTargetDependencies.get(componentDisplayName);
192         if (CollectionUtils.isEmpty(targets)) {
193             return;
194         }
195
196         for (String target : targets) {
197             List<String> targetNodeTemplateIds = componentDisplayNameToNodeTempalteIds.get(target);
198             if (CollectionUtils.isEmpty(targetNodeTemplateIds)) {
199                 continue;
200             }
201             for (String targetNodeTemplateId : targetNodeTemplateIds) {
202                 Optional<String> dependencyRequirementKey =
203                         getDependencyRequirementKey(serviceTemplate, componentDisplayName, nodeTemplate,
204                                 toscaServiceModel);
205                 if (dependencyRequirementKey.isPresent()) {
206                     RequirementAssignment requirementAssignment = new RequirementAssignment();
207                     requirementAssignment.setCapability(NATIVE_NODE);
208                     requirementAssignment.setRelationship(NATIVE_DEPENDS_ON);
209                     requirementAssignment.setNode(targetNodeTemplateId);
210                     DataModelUtil.addRequirementAssignment(nodeTemplate, dependencyRequirementKey.get(),
211                             requirementAssignment);
212                 }
213             }
214         }
215     }
216
217     private Optional<String> getDependencyRequirementKey(ServiceTemplate serviceTemplate, String componentDisplayName,
218                                                                 NodeTemplate nodeTemplate,
219                                                                 ToscaServiceModel toscaServiceModel) {
220         String nodeType = nodeTemplate.getType();
221         NodeType flatNodeType = (NodeType) toscaAnalyzerService.getFlatEntity(ToscaElementTypes.NODE_TYPE, nodeType,
222                 serviceTemplate, toscaServiceModel).getFlatEntity();
223         List<Map<String, RequirementDefinition>> flatNodeTypeRequirements = flatNodeType.getRequirements();
224         if (Objects.isNull(flatNodeTypeRequirements)) {
225             return Optional.empty();
226         }
227         for (Map<String, RequirementDefinition> requirementDefinitionMap : flatNodeTypeRequirements) {
228             String requirementKey = requirementDefinitionMap.keySet().iterator().next();
229             String expectedKey = ToscaConstants.DEPENDS_ON_REQUIREMENT_ID + "_" + componentDisplayName;
230             if (requirementKey.equals(expectedKey)) {
231                 return Optional.of(requirementKey);
232             }
233         }
234         return Optional.empty();
235     }
236
237     private String getComponentDisplayName(String nodeTemplateId, NodeTemplate nodeTemplate) {
238         String componentDisplayName;
239         if (nodeTemplateId.contains(ABSTRACT_NODE_TEMPLATE_ID_PREFIX)) {
240             String removedPrefix = nodeTemplateId.split(ABSTRACT_NODE_TEMPLATE_ID_PREFIX)[1];
241             final String[] removedSuffix = removedPrefix.split("_\\d");
242             componentDisplayName = removedSuffix[0];
243         } else {
244             final String type = nodeTemplate.getType();
245             final String[] splitted = type.split("\\.");
246             componentDisplayName = splitted[splitted.length - 1];
247
248         }
249         return componentDisplayName;
250     }
251
252     private String getValueFromQuestionnaireDetails(Map<String, Map<String, Object>> componentTypetoParams,
253                                                            String componentDisplayName, String propertyName) {
254         return (String) componentTypetoParams.get(componentDisplayName).get(propertyName);
255     }
256
257     private void setProperty(NodeTemplate nodeTemplate, String key, String value) {
258         if (!StringUtils.isEmpty(value)) {
259             //YamlUtil throws IllegalStateException("duplicate key: " + key) if key is already present.
260             // So first removing and then populating same key with new updated value
261             nodeTemplate.getProperties().remove(key);
262             nodeTemplate.getProperties().put(key, value);
263         }
264     }
265
266     private Boolean getValue(String value) {
267         String returnValue = null;
268         switch (value) {
269             case "YES":
270                 return true;
271             case "NO":
272                 return false;
273             default:
274                 return null;
275         }
276     }
277
278     private ComponentQuestionnaireData getComponentQuestionnaireData() {
279         if (componentQuestionnaireData == null) {
280             componentQuestionnaireData = new ComponentQuestionnaireData();
281         }
282         return componentQuestionnaireData;
283     }
284 }