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.VNF_NODE_TEMPLATE_ID_SUFFIX;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.List;
38 import java.util.Objects;
39 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 (nodeTemplate != null && toscaAnalyzerService.isTypeOf(nodeTemplate, VFC_ABSTRACT_SUBSTITUTE,
96 serviceTemplate, toscaModel)) {
98 String componentDisplayName = getComponentDisplayName(nodeTemplateId, nodeTemplate);
100 enrichProperties(nodeTemplate, componentDisplayName, componentProperties);
102 enrichRequirements(sourceToTargetDependencies, componentDisplayName, nodeTemplate,
103 componentDisplayNameToNodeTemplateIds, serviceTemplate, toscaModel);
109 private void enrichProperties(NodeTemplate nodeTemplate, String componentDisplayName,
110 Map<String, Map<String, Object>> componentProperties) {
111 setProperty(nodeTemplate, VM_TYPE_TAG, componentDisplayName);
113 if (componentProperties != null && componentProperties.containsKey(componentDisplayName)) {
114 final String mandatory =
115 getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, MANDATORY);
117 boolean isServiceTemplateFilterNotExists = false;
118 if (!StringUtils.isEmpty(mandatory)) {
119 Map<String, Object> innerProps = (Map<String, Object>) nodeTemplate.getProperties()
120 .get(SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
122 if (innerProps == null) {
123 innerProps = new HashMap<>();
124 isServiceTemplateFilterNotExists = true;
126 Optional<Boolean> mandatoryValue = getValue(mandatory);
127 if (mandatoryValue.isPresent()) {
128 innerProps.put(MANDATORY, mandatoryValue.get());
131 if (isServiceTemplateFilterNotExists) {
132 nodeTemplate.getProperties().put(SERVICE_TEMPLATE_FILTER_PROPERTY_NAME, innerProps);
136 setProperty(nodeTemplate, HIGH_AVAIL_MODE,
137 getValueFromQuestionnaireDetails(componentProperties, componentDisplayName,
140 setProperty(nodeTemplate, NFC_NAMING_CODE,
141 getValueFromQuestionnaireDetails(componentProperties, componentDisplayName,
144 setProperty(nodeTemplate, VFC_CODE,
145 getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, VFC_CODE));
147 setProperty(nodeTemplate, NFC_FUNCTION,
148 getValueFromQuestionnaireDetails(componentProperties, componentDisplayName, NFC_FUNCTION));
150 if (componentProperties.get(componentDisplayName).get(MIN_INSTANCES) != null) {
151 nodeTemplate.getProperties().put(MIN_INSTANCES,
152 componentProperties.get(componentDisplayName).get(MIN_INSTANCES));
155 if (componentProperties.get(componentDisplayName).get(MAX_INSTANCES) != null) {
156 nodeTemplate.getProperties().put(MAX_INSTANCES,
157 componentProperties.get(componentDisplayName).get(MAX_INSTANCES));
162 private Map<String, List<String>> populateAllNodeTemplateIdForComponent(Map<String, NodeTemplate> nodeTemplates,
163 ServiceTemplate serviceTemplate,
164 ToscaServiceModel toscaModel) {
167 Map<String, List<String>> componentDisplayNameToNodeTempalteIds = new HashMap<>();
169 //set dependency target
170 nodeTemplates.keySet().forEach(nodeTemplateId -> {
171 final NodeTemplate nodeTemplate =
172 toscaAnalyzerService.getNodeTemplateById(serviceTemplate, nodeTemplateId).orElse(null);
174 if (nodeTemplate != null &&
175 toscaAnalyzerService.isTypeOf(nodeTemplate, VFC_ABSTRACT_SUBSTITUTE, serviceTemplate, toscaModel)) {
177 String componentDisplayName = getComponentDisplayName(nodeTemplateId, nodeTemplate);
179 if (componentDisplayNameToNodeTempalteIds.containsKey(componentDisplayName)) {
180 componentDisplayNameToNodeTempalteIds.get(componentDisplayName).add(nodeTemplateId);
182 List<String> nodeTemplateIds = new ArrayList<>();
183 nodeTemplateIds.add(nodeTemplateId);
184 componentDisplayNameToNodeTempalteIds.put(componentDisplayName, nodeTemplateIds);
190 return componentDisplayNameToNodeTempalteIds;
193 private void enrichRequirements(Map<String, List<String>> sourceToTargetDependencies, String componentDisplayName,
194 NodeTemplate nodeTemplate,
195 Map<String, List<String>> componentDisplayNameToNodeTempalteIds,
196 ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
197 final List<String> targets = sourceToTargetDependencies.get(componentDisplayName);
198 if (CollectionUtils.isEmpty(targets)) {
202 for (String target : targets) {
203 List<String> targetNodeTemplateIds = componentDisplayNameToNodeTempalteIds.get(target);
204 if (CollectionUtils.isEmpty(targetNodeTemplateIds)) {
207 for (String targetNodeTemplateId : targetNodeTemplateIds) {
208 Optional<String> dependencyRequirementKey =
209 getDependencyRequirementKey(serviceTemplate, componentDisplayName, nodeTemplate,
211 if (dependencyRequirementKey.isPresent()) {
212 RequirementAssignment requirementAssignment = new RequirementAssignment();
213 requirementAssignment.setCapability(NATIVE_NODE);
214 requirementAssignment.setRelationship(NATIVE_DEPENDS_ON);
215 requirementAssignment.setNode(targetNodeTemplateId);
216 DataModelUtil.addRequirementAssignment(nodeTemplate, dependencyRequirementKey.get(),
217 requirementAssignment);
223 private Optional<String> getDependencyRequirementKey(ServiceTemplate serviceTemplate, String componentDisplayName,
224 NodeTemplate nodeTemplate,
225 ToscaServiceModel toscaServiceModel) {
226 String nodeType = nodeTemplate.getType();
227 NodeType flatNodeType = (NodeType) toscaAnalyzerService.getFlatEntity(ToscaElementTypes.NODE_TYPE, nodeType,
228 serviceTemplate, toscaServiceModel).getFlatEntity();
229 List<Map<String, RequirementDefinition>> flatNodeTypeRequirements = flatNodeType.getRequirements();
230 if (Objects.isNull(flatNodeTypeRequirements)) {
231 return Optional.empty();
233 for (Map<String, RequirementDefinition> requirementDefinitionMap : flatNodeTypeRequirements) {
234 String requirementKey = requirementDefinitionMap.keySet().iterator().next();
235 String expectedKey = ToscaConstants.DEPENDS_ON_REQUIREMENT_ID + "_" + componentDisplayName;
236 if (requirementKey.equals(expectedKey)) {
237 return Optional.of(requirementKey);
240 return Optional.empty();
243 private String getComponentDisplayName(String nodeTemplateId, NodeTemplate nodeTemplate) {
244 String componentDisplayName;
245 final String type = nodeTemplate.getType();
246 if (MULTIDEPLOYMENTFLAVOR_NODE_TYPE.equals(type)) {
247 componentDisplayName = nodeTemplateId.substring(0, nodeTemplateId.lastIndexOf(VNF_NODE_TEMPLATE_ID_SUFFIX));
249 String vmType = DataModelUtil.getNamespaceSuffix(type);
250 final String[] removedSuffix = vmType.split("_\\d+");
251 componentDisplayName = removedSuffix[0];
253 return componentDisplayName;
256 private String getValueFromQuestionnaireDetails(Map<String, Map<String, Object>> componentTypetoParams,
257 String componentDisplayName, String propertyName) {
258 return (String) componentTypetoParams.get(componentDisplayName).get(propertyName);
261 private void setProperty(NodeTemplate nodeTemplate, String key, String value) {
262 if (!StringUtils.isEmpty(value)) {
263 //YamlUtil throws IllegalStateException("duplicate key: " + key) if key is already present.
264 // So first removing and then populating same key with new updated value
265 nodeTemplate.getProperties().remove(key);
266 nodeTemplate.getProperties().put(key, value);
270 private Optional<Boolean> getValue(String value) {
273 return Optional.of(Boolean.TRUE);
275 return Optional.of(Boolean.FALSE);
277 return Optional.empty();
281 private ComponentQuestionnaireData getComponentQuestionnaireData() {
282 if (componentQuestionnaireData == null) {
283 componentQuestionnaireData = new ComponentQuestionnaireData();
285 return componentQuestionnaireData;