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