cebabc0df1f2b05a1f285c34cf8cb2cd6b93716a
[sdc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.sdc.translator.services.heattotosca.impl.resourcetranslation;
22
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.openecomp.sdc.common.errors.CoreException;
25 import org.openecomp.sdc.datatypes.error.ErrorLevel;
26 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
27 import org.openecomp.sdc.heat.datatypes.model.Resource;
28 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
29 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
30 import org.openecomp.sdc.logging.types.LoggerConstants;
31 import org.openecomp.sdc.logging.types.LoggerErrorCode;
32 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
33 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
34 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
35 import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
36 import org.openecomp.sdc.tosca.datatypes.ToscaTopologyTemplateElements;
37 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
38 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
39 import org.openecomp.sdc.tosca.services.DataModelUtil;
40 import org.openecomp.sdc.tosca.services.ToscaConstants;
41 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
42 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
43 import org.openecomp.sdc.translator.services.heattotosca.ConsolidationDataUtil;
44 import org.openecomp.sdc.translator.services.heattotosca.ConsolidationEntityType;
45 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
46 import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslationFactory;
47 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import java.util.ArrayList;
52 import java.util.HashMap;
53 import java.util.HashSet;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Objects;
57 import java.util.Optional;
58 import java.util.function.Predicate;
59 import java.util.stream.Collectors;
60
61 public abstract class ResourceTranslationBase {
62
63   protected static Logger logger = (Logger) LoggerFactory.getLogger(ResourceTranslationBase.class);
64   protected static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
65
66   protected abstract void translate(TranslateTo translateTo);
67
68   /**
69    * Translate resource.
70    *
71    * @param heatFileName              the heat file name
72    * @param serviceTemplate           the service template
73    * @param heatOrchestrationTemplate the heat orchestration template
74    * @param resource                  the resource
75    * @param resourceId                the resource id
76    * @param context                   the context
77    * @return the translated id if this resource is supported, or empty value if not supported
78    */
79   public Optional<String> translateResource(String heatFileName, ServiceTemplate serviceTemplate,
80                                             HeatOrchestrationTemplate heatOrchestrationTemplate,
81                                             Resource resource, String resourceId,
82                                             TranslationContext context) {
83
84     mdcDataDebugMessage.debugEntryMessage("file, resource", heatFileName, resourceId);
85     Optional<String> translatedId =
86         getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, resourceId, context);
87     context.getTranslatedResources().putIfAbsent(heatFileName, new HashSet<>());
88     if (context.getTranslatedResources().get(heatFileName).contains(resourceId)) {
89       return translatedId;
90     }
91     if (!translatedId.isPresent()) {
92       return Optional.empty();
93     }
94     logger.debug("Translate- file:" + heatFileName + " resource Id:" + resourceId
95         + " translated resource id:" + translatedId.get());
96     TranslateTo translateTo = new TranslateTo(heatFileName, serviceTemplate,
97         heatOrchestrationTemplate, resource, resourceId, translatedId.get(), context);
98     translate(translateTo);
99     context.getTranslatedResources().get(heatFileName).add(resourceId);
100
101     if (DataModelUtil.isNodeTemplate(translatedId.get(), serviceTemplate)) {
102       if (!context.getHeatStackGroupMembers().containsKey(heatFileName)) {
103         context.getHeatStackGroupMembers().put(heatFileName, new HashSet<>());
104       }
105       context.getHeatStackGroupMembers().get(heatFileName).add(translatedId.get());
106       updateResourceDependency(translateTo);
107     }
108
109     mdcDataDebugMessage.debugExitMessage("file, resource", heatFileName, resourceId);
110     return translatedId;
111   }
112
113   /**
114    * Gets resource translated id.
115    *
116    * @param heatFileName              the heat file name
117    * @param heatOrchestrationTemplate the heat orchestration template
118    * @param resourceId                the resource id
119    * @param context                   the context
120    * @return the resource translated id
121    */
122   public static Optional<String> getResourceTranslatedId(String heatFileName,
123                                                          HeatOrchestrationTemplate
124                                                              heatOrchestrationTemplate,
125                                                          String resourceId,
126                                                          TranslationContext context) {
127
128
129     mdcDataDebugMessage.debugEntryMessage(null, null);
130
131     if (!context.getTranslatedIds().containsKey(heatFileName)) {
132       context.getTranslatedIds().put(heatFileName, new HashMap<>());
133     }
134
135     Map<String, String> translatedIdsPerFile = context.getTranslatedIds().get(heatFileName);
136     String translatedId = translatedIdsPerFile.get(resourceId);
137     if (translatedId != null) {
138       return Optional.of(translatedId);
139     }
140
141     Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
142     if (resource == null) {
143       MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
144           LoggerTragetServiceName.GET_RESOURCE, ErrorLevel.ERROR.name(),
145           LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.TRANSLATE_HEAT);
146       throw new CoreException(
147           new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
148     }
149
150     mdcDataDebugMessage.debugExitMessage(null, null);
151     return getTranslatedResourceId(resourceId, heatFileName, resource, heatOrchestrationTemplate,
152         context
153     );
154   }
155
156   private static Optional<String> getTranslatedResourceId(String resourceId,
157                                                           String heatFileName,
158                                                           Resource resource,
159                                                           HeatOrchestrationTemplate heatOrchestrationTemplate,
160                                                           TranslationContext context) {
161     TranslateTo translateTo =
162         generateTranslationTo(heatFileName, null, heatOrchestrationTemplate, resource, resourceId,
163             null, context);
164
165     String translatedId =
166         ResourceTranslationFactory.getInstance(resource).generateTranslatedId(translateTo);
167
168     if (ConsolidationDataUtil.isNodeTemplatePointsToServiceTemplateWithoutNodeTemplates
169         (translatedId, heatFileName, context)) {
170       return Optional.empty();
171     }
172
173     if (translatedId != null) {
174       context.getTranslatedIds().get(heatFileName).put(resourceId, translatedId);
175     }
176
177     return Optional.ofNullable(translatedId);
178   }
179
180
181   /**
182    * Gets resource translated element template.
183    *
184    * @param heatFileName              the heat file name
185    * @param heatOrchestrationTemplate the heat orchestration template
186    * @param resourceId                the resource id
187    * @param context                   the context
188    * @return the resource translated element template
189    */
190   public static Optional<ToscaTopologyTemplateElements> getResourceTranslatedElementTemplate(
191       String heatFileName,
192       HeatOrchestrationTemplate heatOrchestrationTemplate,
193       String resourceId, TranslationContext context) {
194
195     mdcDataDebugMessage.debugEntryMessage(null, null);
196
197     Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
198     if (resource == null) {
199       MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
200           LoggerTragetServiceName.GET_RESOURCE, ErrorLevel.ERROR.name(),
201           LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.TRANSLATE_HEAT);
202       throw new CoreException(
203           new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
204     }
205     TranslateTo translateTo =
206         generateTranslationTo(heatFileName, null, heatOrchestrationTemplate, resource, resourceId,
207             null, context);
208
209     Optional<ToscaTopologyTemplateElements> translatedElementTemplate =
210         ResourceTranslationFactory.getInstance(resource)
211             .getTranslatedToscaTopologyElement(translateTo);
212
213     mdcDataDebugMessage.debugExitMessage(null, null);
214     return translatedElementTemplate;
215   }
216
217   protected String generateTranslatedId(TranslateTo translateTo) {
218     if (isEssentialRequirementsValid(translateTo)) {
219       return translateTo.getResourceId();
220     } else {
221       return null;
222     }
223
224   }
225
226   protected Optional<ToscaTopologyTemplateElements> getTranslatedToscaTopologyElement(
227       TranslateTo translateTo) {
228     if (isEssentialRequirementsValid(translateTo)) {
229       return Optional.of(ToscaTopologyTemplateElements.NODE_TEMPLATE);
230     } else {
231       return Optional.empty();
232     }
233   }
234
235   protected boolean isEssentialRequirementsValid(TranslateTo translateTo) {
236     return true;
237   }
238
239   private static TranslateTo generateTranslationTo(String heatFileName,
240                                                    ServiceTemplate serviceTemplate,
241                                                    HeatOrchestrationTemplate
242                                                        heatOrchestrationTemplate,
243                                                    Resource resource, String resourceId,
244                                                    String translatedId,
245                                                    TranslationContext context) {
246     TranslateTo to = new TranslateTo();
247     to.setHeatFileName(heatFileName);
248     to.setServiceTemplate(serviceTemplate);
249     to.setHeatOrchestrationTemplate(heatOrchestrationTemplate);
250     to.setResource(resource);
251     to.setResourceId(resourceId);
252     to.setTranslatedId(translatedId);
253     to.setContext(context);
254     return to;
255   }
256
257   private void updateResourceDependency(TranslateTo translateTo) {
258
259     String heatFileName = translateTo.getHeatFileName();
260     mdcDataDebugMessage.debugEntryMessage("file", heatFileName);
261
262     Resource resource = translateTo.getResource();
263     HeatOrchestrationTemplate heatOrchestrationTemplate = translateTo
264         .getHeatOrchestrationTemplate();
265     String translatedId = translateTo.getTranslatedId();
266     ServiceTemplate serviceTemplate = translateTo.getServiceTemplate();
267     TranslationContext context = translateTo.getContext();
268     if (resource.getDepends_on() == null) {
269       return;
270     }
271
272     if (resource.getDepends_on() instanceof List) {
273       List<String> dependsOnList = (List<String>) resource.getDepends_on();
274       for (String dependsOnResourceId : dependsOnList) {
275         addDependOnRequirement(dependsOnResourceId, translateTo);
276       }
277     } else {
278       String dependsOnResourceId = (String) resource.getDepends_on();
279       addDependOnRequirement(dependsOnResourceId, translateTo);
280     }
281
282     mdcDataDebugMessage.debugExitMessage("file", heatFileName);
283   }
284
285   private void addDependOnRequirement(String dependsOnResourceId, TranslateTo translateTo) {
286
287     mdcDataDebugMessage.debugEntryMessage(null, null);
288     String nodeTemplateId = translateTo.getTranslatedId();
289     ServiceTemplate serviceTemplate = translateTo.getServiceTemplate();
290     String heatFileName = translateTo.getHeatFileName();
291     HeatOrchestrationTemplate heatOrchestrationTemplate = translateTo
292         .getHeatOrchestrationTemplate();
293     TranslationContext context = translateTo.getContext();
294     RequirementAssignment requirementAssignment = new RequirementAssignment();
295     Optional<String> resourceTranslatedId =
296         getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, dependsOnResourceId,
297             context);
298
299     Optional<ToscaTopologyTemplateElements> resourceTranslatedElementTemplate =
300         getResourceTranslatedElementTemplate(heatFileName, heatOrchestrationTemplate,
301             dependsOnResourceId, context);
302
303     if (resourceTranslatedId.isPresent()
304         && (resourceTranslatedElementTemplate.isPresent() && resourceTranslatedElementTemplate
305         .get() == ToscaTopologyTemplateElements.NODE_TEMPLATE)) {
306       Resource sourceResource = translateTo.getResource();
307       Resource targetResource = HeatToToscaUtil
308           .getResource(heatOrchestrationTemplate, dependsOnResourceId,
309               translateTo.getHeatFileName());
310       if (HeatToToscaUtil
311           .isValidDependsOnCandidate(heatOrchestrationTemplate, sourceResource, targetResource,
312               ConsolidationEntityType.OTHER, translateTo.getContext())) {
313         requirementAssignment.setNode(resourceTranslatedId.get());
314         requirementAssignment.setCapability(ToscaCapabilityType.NATIVE_NODE);
315         requirementAssignment.setRelationship(ToscaRelationshipType.NATIVE_DEPENDS_ON);
316         DataModelUtil.addRequirementAssignment(
317             serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId),
318             ToscaConstants.DEPENDS_ON_REQUIREMENT_ID, requirementAssignment);
319         Resource dependsOnResource = targetResource;
320         ConsolidationDataUtil
321             .updateNodesConnectedData(translateTo, dependsOnResourceId, dependsOnResource,
322                 sourceResource, nodeTemplateId, ToscaConstants.DEPENDS_ON_REQUIREMENT_ID,
323                 requirementAssignment);
324       }
325     }
326     mdcDataDebugMessage.debugExitMessage(null, null);
327   }
328
329   Optional<List<Map.Entry<String, Resource>>> getResourceByTranslatedResourceId(
330       String heatFileName,
331       HeatOrchestrationTemplate heatOrchestrationTemplate,
332       String translatedResourceId,
333       TranslateTo translateTo,
334       String heatResourceType) {
335     mdcDataDebugMessage.debugEntryMessage(null, null);
336     List<Map.Entry<String, Resource>> list = heatOrchestrationTemplate.getResources().entrySet()
337         .stream()
338         .filter(entry -> getPredicatesForTranslatedIdToResourceId(heatFileName,
339             heatOrchestrationTemplate, translatedResourceId, translateTo.getContext(),
340             heatResourceType)
341             .stream()
342             .allMatch(p -> p.test(entry)))
343         .collect(Collectors.toList());
344     if (CollectionUtils.isEmpty(list)) {
345       mdcDataDebugMessage.debugExitMessage(null, null);
346       return Optional.empty();
347     } else {
348       mdcDataDebugMessage.debugExitMessage(null, null);
349       return Optional.of(list);
350     }
351   }
352
353   private List<Predicate<Map.Entry<String, Resource>>> getPredicatesForTranslatedIdToResourceId(
354       String heatFileName, HeatOrchestrationTemplate heatOrchestrationTemplate,
355       String translatedResourceId, TranslationContext context, String heatResourceType) {
356     List<Predicate<Map.Entry<String, Resource>>> list = new ArrayList<>();
357     list.add(entry ->
358         entry.getValue().getType().equals(heatResourceType));
359     list.add(entry -> {
360       Optional<String> resourceTranslatedId =
361           getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, entry.getKey(), context);
362       return resourceTranslatedId.isPresent()
363           && resourceTranslatedId.get().equals(translatedResourceId);
364     });
365     return list;
366   }
367
368   boolean isResourceTypeSupported(Resource resource, List<String> supporteTypes) {
369     return Objects.nonNull(resource) && supporteTypes.contains(resource.getType());
370   }
371
372 }