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