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