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