2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.translator.services.heattotosca.impl;
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.apache.commons.lang3.StringUtils;
26 import org.openecomp.core.utilities.yaml.YamlUtil;
27 import org.openecomp.sdc.common.errors.CoreException;
28 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
29 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
30 import org.openecomp.sdc.heat.datatypes.model.Output;
31 import org.openecomp.sdc.heat.datatypes.model.Resource;
32 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
33 import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
34 import org.openecomp.sdc.tosca.datatypes.model.ArtifactDefinition;
35 import org.openecomp.sdc.tosca.datatypes.model.AttributeDefinition;
36 import org.openecomp.sdc.tosca.datatypes.model.CapabilityDefinition;
37 import org.openecomp.sdc.tosca.datatypes.model.Import;
38 import org.openecomp.sdc.tosca.datatypes.model.InterfaceDefinition;
39 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
40 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
41 import org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition;
42 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
43 import org.openecomp.sdc.tosca.datatypes.model.RequirementDefinition;
44 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
45 import org.openecomp.sdc.tosca.services.DataModelUtil;
46 import org.openecomp.sdc.tosca.services.ToscaConstants;
47 import org.openecomp.sdc.tosca.services.ToscaNativeTypesServiceTemplate;
48 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
49 import org.openecomp.sdc.translator.datatypes.heattotosca.to.ResourceFileDataAndIDs;
50 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
51 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
52 import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslation;
53 import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslationFactory;
54 import org.openecomp.sdc.translator.services.heattotosca.TranslationContext;
55 import org.openecomp.sdc.translator.services.heattotosca.TranslationService;
56 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
57 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
61 import java.util.ArrayList;
62 import java.util.Collection;
63 import java.util.HashMap;
64 import java.util.HashSet;
65 import java.util.List;
67 import java.util.Objects;
68 import java.util.Optional;
69 import java.util.function.Predicate;
70 import java.util.stream.Collectors;
72 public abstract class ResourceTranslationBase implements ResourceTranslation {
74 protected static Logger logger = LoggerFactory.getLogger(ResourceTranslationBase.class);
76 static Optional<ResourceFileDataAndIDs> getFileDataContainingResource(
77 List<FileData> filesToSearch, String resourceId, TranslationContext context,
78 FileData.Type... types) {
79 if (CollectionUtils.isEmpty(filesToSearch)) {
80 return Optional.empty();
83 List<FileData> fileDatas = Objects.isNull(types) ? filesToSearch
84 : HeatToToscaUtil.getFilteredListOfFileDataByTypes(filesToSearch, types);
85 for (FileData data : fileDatas) {
86 HeatOrchestrationTemplate heatOrchestrationTemplate = new YamlUtil()
87 .yamlToObject(context.getFiles().getFileContent(data.getFile()),
88 HeatOrchestrationTemplate.class);
89 Map<String, Output> outputs = heatOrchestrationTemplate.getOutputs();
90 if (Objects.isNull(outputs)) {
93 Output output = outputs.get(resourceId);
94 if (Objects.nonNull(output)) {
95 Optional<AttachedResourceId> attachedOutputId = HeatToToscaUtil
96 .extractAttachedResourceId(data.getFile(), heatOrchestrationTemplate, context,
98 if (attachedOutputId.isPresent()) {
99 AttachedResourceId attachedResourceId = attachedOutputId.get();
100 if (!attachedResourceId.isGetResource()) {
101 logger.warn("output: '" + resourceId + "' in file '" + data.getFile()
102 + "' is not defined as get_resource and therefor not supported.");
105 ResourceFileDataAndIDs fileDataAndIDs =
106 new ResourceFileDataAndIDs((String) attachedResourceId.getEntityId(),
107 (String) attachedResourceId.getTranslatedId(),
109 return Optional.of(fileDataAndIDs);
113 return Optional.empty();
117 * Gets resource translated id.
119 * @param heatFileName the heat file name
120 * @param heatOrchestrationTemplate the heat orchestration template
121 * @param resourceId the resource id
122 * @param context the context
123 * @return the resource translated id
125 public static Optional<String> getResourceTranslatedId(String heatFileName,
126 HeatOrchestrationTemplate
127 heatOrchestrationTemplate,
129 TranslationContext context) {
130 if (!context.getTranslatedIds().containsKey(heatFileName)) {
131 context.getTranslatedIds().put(heatFileName, new HashMap<>());
134 Map<String, String> translatedIdsPerFile = context.getTranslatedIds().get(heatFileName);
135 String translatedId = translatedIdsPerFile.get(resourceId);
136 if (translatedId != null) {
137 return Optional.of(translatedId);
140 Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
141 if (resource == null) {
142 throw new CoreException(
143 new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
145 TranslateTo translateTo =
146 generateTranslationTo(heatFileName, null, heatOrchestrationTemplate, resource, resourceId,
149 ResourceTranslationFactory.getInstance(resource).generateTranslatedId(translateTo);
150 if (translatedId != null) {
151 context.getTranslatedIds().get(heatFileName).put(resourceId, translatedId);
153 return Optional.ofNullable(translatedId);
156 private static TranslateTo generateTranslationTo(String heatFileName,
157 ServiceTemplate serviceTemplate,
158 HeatOrchestrationTemplate
159 heatOrchestrationTemplate,
160 Resource resource, String resourceId,
162 TranslationContext context) {
163 TranslateTo to = new TranslateTo();
164 to.setHeatFileName(heatFileName);
165 to.setServiceTemplate(serviceTemplate);
166 to.setHeatOrchestrationTemplate(heatOrchestrationTemplate);
167 to.setResource(resource);
168 to.setResourceId(resourceId);
169 to.setTranslatedId(translatedId);
170 to.setContext(context);
174 protected abstract void translate(TranslateTo translateTo);
176 protected String generateTranslatedId(TranslateTo translateTo) {
177 isEssentialRequirementsValid(translateTo);
178 return translateTo.getResourceId();
181 protected boolean isEssentialRequirementsValid(TranslateTo translateTo) {
186 public Optional<String> translateResource(String heatFileName, ServiceTemplate serviceTemplate,
187 HeatOrchestrationTemplate heatOrchestrationTemplate,
188 Resource resource, String resourceId,
189 TranslationContext context) {
190 Optional<String> translatedId =
191 getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, resourceId, context);
192 context.getTranslatedResources().putIfAbsent(heatFileName, new HashSet<>());
193 if (context.getTranslatedResources().get(heatFileName).contains(resourceId)) {
196 if (!translatedId.isPresent()) {
197 return Optional.empty();
199 logger.debug("Translate- file:" + heatFileName + " resource Id:" + resourceId
200 + " translated resource id:" + translatedId.get());
201 translate(new TranslateTo(heatFileName, serviceTemplate, heatOrchestrationTemplate, resource,
202 resourceId, translatedId.get(), context));
203 context.getTranslatedResources().get(heatFileName).add(resourceId);
205 if (isNodeTemplate(translatedId.get(), serviceTemplate)) {
206 if (!context.getHeatStackGroupMembers().containsKey(heatFileName)) {
207 context.getHeatStackGroupMembers().put(heatFileName, new HashSet<>());
209 context.getHeatStackGroupMembers().get(heatFileName).add(translatedId.get());
210 updateResourceDependency(heatFileName, resource, heatOrchestrationTemplate,
211 translatedId.get(), serviceTemplate, context);
217 private void updateResourceDependency(String heatFileName, Resource resource,
218 HeatOrchestrationTemplate heatOrchestrationTemplate,
219 String translatedId, ServiceTemplate serviceTemplate,
220 TranslationContext context) {
221 if (resource.getDepends_on() == null) {
225 if (resource.getDepends_on() instanceof List) {
226 List<String> dependsOnList = (List<String>) resource.getDepends_on();
227 for (String dependsOnResourceId : dependsOnList) {
228 addDependOnRequirement(dependsOnResourceId, translatedId, serviceTemplate, heatFileName,
229 heatOrchestrationTemplate, context);
232 String dependsOnResourceId = (String) resource.getDepends_on();
233 addDependOnRequirement(dependsOnResourceId, translatedId, serviceTemplate, heatFileName,
234 heatOrchestrationTemplate, context);
239 private void addDependOnRequirement(String dependsOnResourceId, String nodeTemplateId,
240 ServiceTemplate serviceTemplate, String heatFileName,
241 HeatOrchestrationTemplate heatOrchestrationTemplate,
242 TranslationContext context) {
243 RequirementAssignment requirementAssignment = new RequirementAssignment();
244 Optional<String> resourceTranslatedId =
245 getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, dependsOnResourceId,
248 if (resourceTranslatedId.isPresent()
249 && isNodeTemplate(resourceTranslatedId.get(), serviceTemplate)) {
250 requirementAssignment.setNode(resourceTranslatedId.get());
251 requirementAssignment.setCapability(ToscaCapabilityType.NODE.getDisplayName());
252 requirementAssignment.setRelationship(ToscaRelationshipType.DEPENDS_ON.getDisplayName());
253 DataModelUtil.addRequirementAssignment(
254 serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId),
255 ToscaConstants.DEPENDS_ON_REQUIREMENT_ID, requirementAssignment);
259 private boolean isNodeTemplate(String entryId, ServiceTemplate serviceTemplate) {
260 return serviceTemplate.getTopology_template().getNode_templates() != null
261 && serviceTemplate.getTopology_template().getNode_templates().get(entryId) != null;
264 FileData getFileData(String fileName, TranslationContext context) {
266 List<FileData> fileDataList = context.getManifest().getContent().getData();
267 for (FileData fileData : fileDataList) {
268 if (TranslationService.getTypesToProcessByTranslator().contains(fileData.getType())
269 && fileData.getFile().equals(fileName)) {
276 NodeType getNodeTypeWithFlatHierarchy(String nodeTypeId, ServiceTemplate serviceTemplate,
277 TranslationContext context) {
279 if (serviceTemplate != null && serviceTemplate.getNode_types() != null) {
280 nodeType = serviceTemplate.getNode_types().get(nodeTypeId);
282 if (nodeType != null) {
283 return enrichNodeType(nodeType, serviceTemplate, context);
286 Map<String, Map<String, NodeType>> globalNodeTypesMap = new HashMap<>();
287 Collection<ServiceTemplate> globalNodeTypes =
288 GlobalTypesGenerator.getGlobalTypesServiceTemplate().values();
289 ServiceTemplate nativeNodeTypeServiceTemplate =
290 ToscaNativeTypesServiceTemplate.createServiceTemplate();
291 for (ServiceTemplate globalNodeType : globalNodeTypes) {
293 .put(globalNodeType.getMetadata().getTemplate_name(), globalNodeType.getNode_types());
295 if (Objects.nonNull(serviceTemplate) && MapUtils.isNotEmpty(serviceTemplate.getImports())) {
296 for (Map.Entry<String, Import> entry : serviceTemplate.getImports().entrySet()) {
297 if (globalNodeTypesMap.containsKey(entry.getKey())) {
298 Map<String, NodeType> nodeTypes = globalNodeTypesMap.get(entry.getKey());
299 if (nodeTypes != null && nodeTypes.containsKey(nodeTypeId)) {
300 return enrichNodeType(nodeTypes.get(nodeTypeId), serviceTemplate, context);
303 if (context.getGlobalSubstitutionServiceTemplate() != null
304 && context.getGlobalSubstitutionServiceTemplate().getNode_types() != null
305 && context.getGlobalSubstitutionServiceTemplate().getNode_types()
306 .containsKey(nodeTypeId)) {
307 return enrichNodeType(
308 context.getGlobalSubstitutionServiceTemplate().getNode_types().get(nodeTypeId),
309 serviceTemplate, context);
311 if (nativeNodeTypeServiceTemplate.getNode_types().containsKey(nodeTypeId)) {
312 return enrichNodeType(nativeNodeTypeServiceTemplate.getNode_types().get(nodeTypeId),
313 serviceTemplate, context);
317 return new NodeType();
321 private NodeType enrichNodeType(NodeType nodeType, ServiceTemplate serviceTemplate,
322 TranslationContext context) {
323 NodeType clonedNodeType;
325 if (StringUtils.isEmpty(nodeType.getDerived_from())) {
326 return nodeType.clone();
329 clonedNodeType = enrichNodeType(
330 getNodeTypeWithFlatHierarchy(nodeType.getDerived_from(), serviceTemplate, context),
331 serviceTemplate, context);
332 mergeNodeTypes(clonedNodeType, nodeType);
333 return clonedNodeType;
337 private void mergeNodeTypes(NodeType target, NodeType source) {
338 target.setDerived_from(source.getDerived_from());
339 target.setDescription(source.getDescription());
340 target.setVersion(source.getVersion());
341 target.setProperties(
342 mergeMaps(target.getProperties(), source.getProperties(), PropertyDefinition.class));
343 target.setInterfaces(
344 mergeMaps(target.getInterfaces(), source.getInterfaces(), InterfaceDefinition.class));
346 mergeMaps(target.getArtifacts(), source.getArtifacts(), ArtifactDefinition.class));
347 target.setAttributes(
348 mergeMaps(target.getAttributes(), source.getAttributes(), AttributeDefinition.class));
349 target.setCapabilities(
350 mergeMaps(target.getCapabilities(), source.getCapabilities(), CapabilityDefinition.class));
351 target.setRequirements(mergeLists(target.getRequirements(), source.getRequirements(),
352 RequirementDefinition.class));
355 private <T, S> List<Map<T, S>> mergeLists(List<Map<T, S>> target, List<Map<T, S>> source,
357 List<Map<T, S>> retList = new ArrayList<>();
358 if (Objects.nonNull(target)) {
359 retList.addAll(target);
362 if (Objects.nonNull(source)) {
363 for (Map<T, S> sourceMap : source) {
364 for (Map.Entry<T, S> entry : sourceMap.entrySet()) {
365 mergeEntryInList(entry.getKey(), entry.getValue(), retList);
372 <T, S> void mergeEntryInList(T key, S value, List<Map<T, S>> target) {
373 boolean found = false;
374 for (Map<T, S> map : target) {
375 if (map.containsKey(key)) {
382 Map<T, S> newMap = new HashMap<>();
383 newMap.put(key, value);
389 private <T, S> Map<T, S> mergeMaps(Map<T, S> target, Map<T, S> source, Class<S> value) {
390 Map<T, S> retMap = new HashMap<>();
391 if (MapUtils.isNotEmpty(target)) {
392 retMap.putAll(target);
395 if (MapUtils.isNotEmpty(source)) {
396 retMap.putAll(source);
401 Optional<List<Map.Entry<String, Resource>>> getResourceByTranslatedResourceId(
403 HeatOrchestrationTemplate heatOrchestrationTemplate,
404 String translatedResourceId,TranslateTo translateTo,String heatResourceType) {
405 List<Map.Entry<String, Resource>> list = heatOrchestrationTemplate.getResources().entrySet()
408 entry -> getPredicatesForTranslatedIdToResourceId(fileName, heatOrchestrationTemplate,
409 translatedResourceId, translateTo.getContext(), heatResourceType)
411 .allMatch(p -> p.test(entry)))
412 .collect(Collectors.toList());
413 if (CollectionUtils.isEmpty(list)) {
414 return Optional.empty();
416 return Optional.of(list);
420 private List<Predicate<Map.Entry<String, Resource>>> getPredicatesForTranslatedIdToResourceId(
421 String fileName, HeatOrchestrationTemplate heatOrchestrationTemplate,
422 String translatedResourceId, TranslationContext context, String heatResourceType) {
423 List<Predicate<Map.Entry<String, Resource>>> list = new ArrayList<>();
425 entry.getValue().getType().equals(heatResourceType));
427 Optional<String> resourceTranslatedId =
428 getResourceTranslatedId(fileName, heatOrchestrationTemplate, entry.getKey(), context);
429 return resourceTranslatedId.isPresent()
430 && resourceTranslatedId.get().equals(translatedResourceId);
435 void addBindingReqFromPortToCompute(String computeNodeTemplateId, NodeTemplate portNodeTemplate) {
436 RequirementAssignment requirementAssignment = new RequirementAssignment();
437 requirementAssignment.setCapability(ToscaCapabilityType.NETWORK_BINDABLE.getDisplayName());
438 requirementAssignment.setRelationship(ToscaRelationshipType.NETWORK_BINDS_TO.getDisplayName());
439 requirementAssignment.setNode(computeNodeTemplateId);
440 DataModelUtil.addRequirementAssignment(portNodeTemplate, ToscaConstants.BINDING_REQUIREMENT_ID,
441 requirementAssignment);
444 void addLinkReqFromPortToNetwork(NodeTemplate nodeTemplate, String translatedId) {
445 RequirementAssignment requirement = new RequirementAssignment();
446 requirement.setCapability(ToscaCapabilityType.NETWORK_LINKABLE.getDisplayName());
447 requirement.setRelationship(ToscaRelationshipType.NETWORK_LINK_TO.getDisplayName());
448 requirement.setNode(translatedId);
450 .addRequirementAssignment(nodeTemplate, ToscaConstants.LINK_REQUIREMENT_ID, requirement);
453 boolean isResourceTypeSupported(Resource resource, List<String> supportedTypes) {
454 return Objects.nonNull(resource) && supportedTypes.contains(resource.getType());