2 * Copyright © 2016-2018 European Support Limited
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.openecomp.sdc.enrichment.impl.tosca;
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.NFC_FUNCTION;
24 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.NFC_NAMING_CODE;
25 import static org.openecomp.sdc.enrichment.impl.util.EnrichmentConstants.VFC_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.MULTIDEPLOYMENTFLAVOR_NODE_TYPE;
29 import static org.openecomp.sdc.tosca.datatypes.ToscaNodeType.VFC_ABSTRACT_SUBSTITUTE;
30 import static org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType.NATIVE_DEPENDS_ON;
31 import static org.openecomp.sdc.tosca.services.ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME;
32 import static org.openecomp.sdc.translator.services.heattotosca.Constants.ABSTRACT_NODE_TEMPLATE_ID_PREFIX;
33 import static org.openecomp.sdc.translator.services.heattotosca.Constants.VNF_NODE_TEMPLATE_ID_SUFFIX;
35 import java.util.ArrayList;
36 import java.util.HashMap;
37 import java.util.List;
39 import java.util.Objects;
40 import java.util.Optional;
41 import org.apache.commons.collections4.CollectionUtils;
42 import org.apache.commons.lang3.StringUtils;
43 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
44 import org.onap.sdc.tosca.datatypes.model.NodeType;
45 import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
46 import org.onap.sdc.tosca.datatypes.model.RequirementDefinition;
47 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
48 import org.openecomp.sdc.datatypes.error.ErrorMessage;
49 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
50 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
51 import org.openecomp.sdc.tosca.services.DataModelUtil;
52 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
53 import org.openecomp.sdc.tosca.services.ToscaConstants;
54 import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
55 import org.openecomp.sdc.versioning.dao.types.Version;
57 public class AbstractSubstituteToscaEnricher {
59 private ToscaAnalyzerService toscaAnalyzerService;
60 private ComponentQuestionnaireData componentQuestionnaireData;
63 public Map<String, List<ErrorMessage>> enrich(ToscaServiceModel toscaModel, String vspId, Version version) {
64 componentQuestionnaireData = getComponentQuestionnaireData();
65 toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
67 Map<String, Map<String, Object>> componentProperties =
68 componentQuestionnaireData.getPropertiesfromCompQuestionnaire(vspId, version);
70 final Map<String, List<String>> sourceToTargetDependencies = componentQuestionnaireData
71 .populateDependencies(vspId, version,
72 componentQuestionnaireData
73 .getSourceToTargetComponent());
74 Map<String, List<ErrorMessage>> errors = new HashMap<>();
76 final ServiceTemplate serviceTemplate =
77 toscaModel.getServiceTemplates().get(toscaModel.getEntryDefinitionServiceTemplate());
79 if (serviceTemplate == null) {
83 final Map<String, NodeTemplate> nodeTemplates = serviceTemplate.getTopology_template().getNode_templates();
84 if (nodeTemplates == null) {
88 final Map<String, List<String>> componentDisplayNameToNodeTemplateIds =
89 populateAllNodeTemplateIdForComponent(nodeTemplates, serviceTemplate, toscaModel);
91 nodeTemplates.keySet().forEach(nodeTemplateId -> {
92 final NodeTemplate nodeTemplate =
93 toscaAnalyzerService.getNodeTemplateById(serviceTemplate, nodeTemplateId).orElse(null);
95 if (toscaAnalyzerService.isTypeOf(nodeTemplate, VFC_ABSTRACT_SUBSTITUTE, serviceTemplate, toscaModel)) {
97 String componentDisplayName = getComponentDisplayName(nodeTemplateId, nodeTemplate);
99 enrichProperties(nodeTemplate, componentDisplayName, componentProperties);
101 enrichRequirements(sourceToTargetDependencies, componentDisplayName, nodeTemplate,
102 componentDisplayNameToNodeTemplateIds, serviceTemplate, toscaModel);
108 private void enrichProperties(NodeTemplate nodeTemplate, String componentDisplayName,
109 Map<String, Map<String, Object>> componentProperties) {
110 setProperty(nodeTemplate, VM_TYPE_TAG, componentDisplayName);
112 if (componentProperties != null && componentProperties.containsKey(componentDisplayName)) {
113 final String mandatory =
114 getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, MANDATORY);
116 boolean isServiceTemplateFilterNotExists = false;
117 if (!StringUtils.isEmpty(mandatory)) {
118 Map innerProps = (Map<String, Object>) nodeTemplate.getProperties()
119 .get(SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
121 if (innerProps == null) {
122 innerProps = new HashMap<String, Object>();
123 isServiceTemplateFilterNotExists = true;
126 innerProps.put(MANDATORY, getValue(mandatory));
128 if (isServiceTemplateFilterNotExists) {
129 nodeTemplate.getProperties().put(SERVICE_TEMPLATE_FILTER_PROPERTY_NAME, innerProps);
133 setProperty(nodeTemplate, HIGH_AVAIL_MODE,
134 getValueFromQuestionnaireDetails(componentProperties, componentDisplayName,
137 setProperty(nodeTemplate, NFC_NAMING_CODE,
138 getValueFromQuestionnaireDetails(componentProperties, componentDisplayName,
141 setProperty(nodeTemplate, VFC_CODE,
142 getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, VFC_CODE));
144 setProperty(nodeTemplate, NFC_FUNCTION,
145 getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, NFC_FUNCTION));
147 if (componentProperties.get(componentDisplayName).get(MIN_INSTANCES) != null) {
148 nodeTemplate.getProperties().put(MIN_INSTANCES,
149 componentProperties.get(componentDisplayName).get(MIN_INSTANCES));
152 if (componentProperties.get(componentDisplayName).get(MAX_INSTANCES) != null) {
153 nodeTemplate.getProperties().put(MAX_INSTANCES,
154 componentProperties.get(componentDisplayName).get(MAX_INSTANCES));
159 private Map<String, List<String>> populateAllNodeTemplateIdForComponent(Map<String, NodeTemplate> nodeTemplates,
160 ServiceTemplate serviceTemplate,
161 ToscaServiceModel toscaModel) {
164 Map<String, List<String>> componentDisplayNameToNodeTempalteIds = new HashMap<>();
166 //set dependency target
167 nodeTemplates.keySet().forEach(nodeTemplateId -> {
168 final NodeTemplate nodeTemplate =
169 toscaAnalyzerService.getNodeTemplateById(serviceTemplate, nodeTemplateId).orElse(null);
171 if (toscaAnalyzerService.isTypeOf(nodeTemplate, VFC_ABSTRACT_SUBSTITUTE, serviceTemplate, toscaModel)) {
173 String componentDisplayName = getComponentDisplayName(nodeTemplateId, nodeTemplate);
175 if (componentDisplayNameToNodeTempalteIds.containsKey(componentDisplayName)) {
176 componentDisplayNameToNodeTempalteIds.get(componentDisplayName).add(nodeTemplateId);
178 List<String> nodeTemplateIds = new ArrayList<>();
179 nodeTemplateIds.add(nodeTemplateId);
180 componentDisplayNameToNodeTempalteIds.put(componentDisplayName, nodeTemplateIds);
186 return componentDisplayNameToNodeTempalteIds;
189 private void enrichRequirements(Map<String, List<String>> sourceToTargetDependencies, String componentDisplayName,
190 NodeTemplate nodeTemplate,
191 Map<String, List<String>> componentDisplayNameToNodeTempalteIds,
192 ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
193 final List<String> targets = sourceToTargetDependencies.get(componentDisplayName);
194 if (CollectionUtils.isEmpty(targets)) {
198 for (String target : targets) {
199 List<String> targetNodeTemplateIds = componentDisplayNameToNodeTempalteIds.get(target);
200 if (CollectionUtils.isEmpty(targetNodeTemplateIds)) {
203 for (String targetNodeTemplateId : targetNodeTemplateIds) {
204 Optional<String> dependencyRequirementKey =
205 getDependencyRequirementKey(serviceTemplate, componentDisplayName, nodeTemplate,
207 if (dependencyRequirementKey.isPresent()) {
208 RequirementAssignment requirementAssignment = new RequirementAssignment();
209 requirementAssignment.setCapability(NATIVE_NODE);
210 requirementAssignment.setRelationship(NATIVE_DEPENDS_ON);
211 requirementAssignment.setNode(targetNodeTemplateId);
212 DataModelUtil.addRequirementAssignment(nodeTemplate, dependencyRequirementKey.get(),
213 requirementAssignment);
219 private Optional<String> getDependencyRequirementKey(ServiceTemplate serviceTemplate, String componentDisplayName,
220 NodeTemplate nodeTemplate,
221 ToscaServiceModel toscaServiceModel) {
222 String nodeType = nodeTemplate.getType();
223 NodeType flatNodeType = (NodeType) toscaAnalyzerService.getFlatEntity(ToscaElementTypes.NODE_TYPE, nodeType,
224 serviceTemplate, toscaServiceModel).getFlatEntity();
225 List<Map<String, RequirementDefinition>> flatNodeTypeRequirements = flatNodeType.getRequirements();
226 if (Objects.isNull(flatNodeTypeRequirements)) {
227 return Optional.empty();
229 for (Map<String, RequirementDefinition> requirementDefinitionMap : flatNodeTypeRequirements) {
230 String requirementKey = requirementDefinitionMap.keySet().iterator().next();
231 String expectedKey = ToscaConstants.DEPENDS_ON_REQUIREMENT_ID + "_" + componentDisplayName;
232 if (requirementKey.equals(expectedKey)) {
233 return Optional.of(requirementKey);
236 return Optional.empty();
239 private String getComponentDisplayName(String nodeTemplateId, NodeTemplate nodeTemplate) {
240 String componentDisplayName;
241 if (nodeTemplateId.contains(ABSTRACT_NODE_TEMPLATE_ID_PREFIX)) {
242 String removedPrefix = nodeTemplateId.split(ABSTRACT_NODE_TEMPLATE_ID_PREFIX)[1];
243 final String[] removedSuffix = removedPrefix.split("_\\d");
244 componentDisplayName = removedSuffix[0];
246 final String type = nodeTemplate.getType();
247 componentDisplayName = MULTIDEPLOYMENTFLAVOR_NODE_TYPE.equals(type)
248 ? nodeTemplateId.substring(0, nodeTemplateId.lastIndexOf(VNF_NODE_TEMPLATE_ID_SUFFIX))
249 : type.substring(type.lastIndexOf('.') + 1);
251 return componentDisplayName;
254 private String getValueFromQuestionnaireDetails(Map<String, Map<String, Object>> componentTypetoParams,
255 String componentDisplayName, String propertyName) {
256 return (String) componentTypetoParams.get(componentDisplayName).get(propertyName);
259 private void setProperty(NodeTemplate nodeTemplate, String key, String value) {
260 if (!StringUtils.isEmpty(value)) {
261 //YamlUtil throws IllegalStateException("duplicate key: " + key) if key is already present.
262 // So first removing and then populating same key with new updated value
263 nodeTemplate.getProperties().remove(key);
264 nodeTemplate.getProperties().put(key, value);
268 private Boolean getValue(String value) {
279 private ComponentQuestionnaireData getComponentQuestionnaireData() {
280 if (componentQuestionnaireData == null) {
281 componentQuestionnaireData = new ComponentQuestionnaireData();
283 return componentQuestionnaireData;