92ce4c19aeeb5450ec24a337606077b32bfbaa4b
[sdc.git] / openecomp-be / lib / openecomp-sdc-translator-lib / openecomp-sdc-translator-core / src / main / java / org / openecomp / sdc / translator / services / heattotosca / impl / resourcetranslation / ResourceTranslationBase.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.translator.services.heattotosca.impl.resourcetranslation;
18
19 import org.apache.commons.collections4.CollectionUtils;
20 import org.openecomp.sdc.common.errors.CoreException;
21 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
22 import org.openecomp.sdc.heat.datatypes.model.Resource;
23 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
24 import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
25 import org.openecomp.sdc.tosca.datatypes.ToscaTopologyTemplateElements;
26 import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
27 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
28 import org.openecomp.sdc.tosca.services.DataModelUtil;
29 import org.openecomp.sdc.tosca.services.ToscaConstants;
30 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
31 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
32 import org.openecomp.sdc.translator.services.heattotosca.ConsolidationDataUtil;
33 import org.openecomp.sdc.translator.services.heattotosca.ConsolidationEntityType;
34 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
35 import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslationFactory;
36 import org.openecomp.sdc.translator.services.heattotosca.errors.DuplicateResourceIdsInDifferentFilesErrorBuilder;
37 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.Objects;
47 import java.util.Optional;
48 import java.util.Set;
49 import java.util.function.Predicate;
50 import java.util.stream.Collectors;
51
52 public abstract class ResourceTranslationBase {
53
54   protected static Logger logger = LoggerFactory.getLogger(ResourceTranslationBase.class);
55   protected abstract void translate(TranslateTo translateTo);
56
57   /**
58    * Translate resource.
59    *
60    * @param heatFileName              the heat file name
61    * @param serviceTemplate           the service template
62    * @param heatOrchestrationTemplate the heat orchestration template
63    * @param resource                  the resource
64    * @param resourceId                the resource id
65    * @param context                   the context
66    * @return the translated id if this resource is supported, or empty value if not supported
67    */
68   public Optional<String> translateResource(String heatFileName, ServiceTemplate serviceTemplate,
69                                             HeatOrchestrationTemplate heatOrchestrationTemplate,
70                                             Resource resource, String resourceId,
71                                             TranslationContext context) {
72     Optional<String> translatedId =
73         getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, resourceId, context);
74     context.getTranslatedResources().putIfAbsent(heatFileName, new HashSet<>());
75
76     if (isResourceWithSameIdAppearsInOtherFiles(heatFileName, resourceId, context)) {
77       throw new CoreException(
78           new DuplicateResourceIdsInDifferentFilesErrorBuilder(resourceId).build());
79     }
80     if (context.getTranslatedResources().get(heatFileName).contains(resourceId)) {
81       return translatedId;
82     }
83     if (!translatedId.isPresent()) {
84       return Optional.empty();
85     }
86     logger.debug("Translate- file: {}  resource Id: {} translated resource id: {}",
87             heatFileName, resourceId, translatedId.get());
88     TranslateTo translateTo = new TranslateTo(heatFileName, serviceTemplate,
89         heatOrchestrationTemplate, resource, resourceId, translatedId.get(), context);
90     translate(translateTo);
91     context.getTranslatedResources().get(heatFileName).add(resourceId);
92
93     if (DataModelUtil.isNodeTemplate(translatedId.get(), serviceTemplate)) {
94       if (!context.getHeatStackGroupMembers().containsKey(heatFileName)) {
95         context.getHeatStackGroupMembers().put(heatFileName, new HashSet<>());
96       }
97       context.getHeatStackGroupMembers().get(heatFileName).add(translatedId.get());
98       updateResourceDependency(translateTo);
99     }
100     return translatedId;
101   }
102
103   private boolean isResourceWithSameIdAppearsInOtherFiles(String heatFileName,
104                                                           String resourceId,
105                                                           TranslationContext context) {
106     Set<String> translatedResourceIdsFromOtherFiles =
107         context.getTranslatedResourceIdsFromOtherFiles(heatFileName);
108
109     return CollectionUtils.isNotEmpty(translatedResourceIdsFromOtherFiles)
110         && translatedResourceIdsFromOtherFiles.contains(resourceId);
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     if (!context.getTranslatedIds().containsKey(heatFileName)) {
128       context.getTranslatedIds().put(heatFileName, new HashMap<>());
129     }
130
131     Map<String, String> translatedIdsPerFile = context.getTranslatedIds().get(heatFileName);
132     String translatedId = translatedIdsPerFile.get(resourceId);
133     if (translatedId != null) {
134       return Optional.of(translatedId);
135     }
136
137     Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
138     if (resource == null) {
139       throw new CoreException(
140           new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
141     }
142     return getTranslatedResourceId(resourceId, heatFileName, resource, heatOrchestrationTemplate,
143         context
144     );
145   }
146
147   private static Optional<String> getTranslatedResourceId(String resourceId,
148                                                           String heatFileName,
149                                                           Resource resource,
150                                                           HeatOrchestrationTemplate heatOrchestrationTemplate,
151                                                           TranslationContext context) {
152     TranslateTo translateTo =
153         generateTranslationTo(heatFileName, null, heatOrchestrationTemplate, resource, resourceId,
154             null, context);
155
156     String translatedId =
157         ResourceTranslationFactory.getInstance(resource).generateTranslatedId(translateTo);
158
159     if (ConsolidationDataUtil.isNodeTemplatePointsToServiceTemplateWithoutNodeTemplates
160         (translatedId, heatFileName, context)) {
161       return Optional.empty();
162     }
163
164     if (translatedId != null) {
165       context.getTranslatedIds().get(heatFileName).put(resourceId, translatedId);
166     }
167
168     return Optional.ofNullable(translatedId);
169   }
170
171
172   /**
173    * Gets resource translated element template.
174    *
175    * @param heatFileName              the heat file name
176    * @param heatOrchestrationTemplate the heat orchestration template
177    * @param resourceId                the resource id
178    * @param context                   the context
179    * @return the resource translated element template
180    */
181   public static Optional<ToscaTopologyTemplateElements> getResourceTranslatedElementTemplate(
182       String heatFileName,
183       HeatOrchestrationTemplate heatOrchestrationTemplate,
184       String resourceId, TranslationContext context) {
185     Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
186     if (resource == null) {
187       throw new CoreException(
188           new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
189     }
190     TranslateTo translateTo =
191         generateTranslationTo(heatFileName, null, heatOrchestrationTemplate, resource, resourceId,
192             null, context);
193
194     return ResourceTranslationFactory.getInstance(resource)
195         .getTranslatedToscaTopologyElement(translateTo);
196   }
197
198   protected String generateTranslatedId(TranslateTo translateTo) {
199     if (isEssentialRequirementsValid(translateTo)) {
200       return translateTo.getResourceId();
201     } else {
202       return null;
203     }
204
205   }
206
207   protected Optional<ToscaTopologyTemplateElements> getTranslatedToscaTopologyElement(
208       TranslateTo translateTo) {
209     if (isEssentialRequirementsValid(translateTo)) {
210       return Optional.of(ToscaTopologyTemplateElements.NODE_TEMPLATE);
211     } else {
212       return Optional.empty();
213     }
214   }
215
216   protected boolean isEssentialRequirementsValid(TranslateTo translateTo) {
217     return true;
218   }
219
220   private static TranslateTo generateTranslationTo(String heatFileName,
221                                                    ServiceTemplate serviceTemplate,
222                                                    HeatOrchestrationTemplate
223                                                        heatOrchestrationTemplate,
224                                                    Resource resource, String resourceId,
225                                                    String translatedId,
226                                                    TranslationContext context) {
227     TranslateTo to = new TranslateTo();
228     to.setHeatFileName(heatFileName);
229     to.setServiceTemplate(serviceTemplate);
230     to.setHeatOrchestrationTemplate(heatOrchestrationTemplate);
231     to.setResource(resource);
232     to.setResourceId(resourceId);
233     to.setTranslatedId(translatedId);
234     to.setContext(context);
235     return to;
236   }
237
238   private void updateResourceDependency(TranslateTo translateTo) {
239
240     Resource resource = translateTo.getResource();
241     if (resource.getDepends_on() == null) {
242       return;
243     }
244
245     if (resource.getDepends_on() instanceof List) {
246       List<String> dependsOnList = (List<String>) resource.getDepends_on();
247       for (String dependsOnResourceId : dependsOnList) {
248         addDependOnRequirement(dependsOnResourceId, translateTo);
249       }
250     } else {
251       String dependsOnResourceId = (String) resource.getDepends_on();
252       addDependOnRequirement(dependsOnResourceId, translateTo);
253     }
254   }
255
256   private void addDependOnRequirement(String dependsOnResourceId, TranslateTo translateTo) {
257     String nodeTemplateId = translateTo.getTranslatedId();
258     ServiceTemplate serviceTemplate = translateTo.getServiceTemplate();
259     String heatFileName = translateTo.getHeatFileName();
260     HeatOrchestrationTemplate heatOrchestrationTemplate = translateTo
261         .getHeatOrchestrationTemplate();
262     TranslationContext context = translateTo.getContext();
263     RequirementAssignment requirementAssignment = new RequirementAssignment();
264     Optional<String> resourceTranslatedId =
265         getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, dependsOnResourceId,
266             context);
267
268     Optional<ToscaTopologyTemplateElements> resourceTranslatedElementTemplate =
269         getResourceTranslatedElementTemplate(heatFileName, heatOrchestrationTemplate,
270             dependsOnResourceId, context);
271
272     if (resourceTranslatedId.isPresent()
273         && (resourceTranslatedElementTemplate.isPresent() && resourceTranslatedElementTemplate
274         .get() == ToscaTopologyTemplateElements.NODE_TEMPLATE)) {
275       Resource sourceResource = translateTo.getResource();
276       Resource targetResource = HeatToToscaUtil
277           .getResource(heatOrchestrationTemplate, dependsOnResourceId,
278               translateTo.getHeatFileName());
279       if (HeatToToscaUtil
280           .isValidDependsOnCandidate(sourceResource, targetResource,
281               ConsolidationEntityType.OTHER, translateTo.getContext())) {
282         requirementAssignment.setNode(resourceTranslatedId.get());
283         requirementAssignment.setCapability(ToscaCapabilityType.NATIVE_NODE);
284         requirementAssignment.setRelationship(ToscaRelationshipType.NATIVE_DEPENDS_ON);
285         DataModelUtil.addRequirementAssignment(
286             serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId),
287             ToscaConstants.DEPENDS_ON_REQUIREMENT_ID, requirementAssignment);
288         ConsolidationDataUtil
289             .updateNodesConnectedData(translateTo, dependsOnResourceId, targetResource,
290                 sourceResource, nodeTemplateId, ToscaConstants.DEPENDS_ON_REQUIREMENT_ID,
291                 requirementAssignment);
292       }
293     }
294   }
295
296   Optional<List<Map.Entry<String, Resource>>> getResourceByTranslatedResourceId(
297       String heatFileName,
298       HeatOrchestrationTemplate heatOrchestrationTemplate,
299       String translatedResourceId,
300       TranslateTo translateTo,
301       String heatResourceType) {
302     List<Map.Entry<String, Resource>> list = heatOrchestrationTemplate.getResources().entrySet()
303         .stream()
304         .filter(entry -> getPredicatesForTranslatedIdToResourceId(heatFileName,
305             heatOrchestrationTemplate, translatedResourceId, translateTo.getContext(),
306             heatResourceType)
307             .stream()
308             .allMatch(p -> p.test(entry)))
309         .collect(Collectors.toList());
310     if (CollectionUtils.isEmpty(list)) {
311       return Optional.empty();
312     } else {
313       return Optional.of(list);
314     }
315   }
316
317   private List<Predicate<Map.Entry<String, Resource>>> getPredicatesForTranslatedIdToResourceId(
318       String heatFileName, HeatOrchestrationTemplate heatOrchestrationTemplate,
319       String translatedResourceId, TranslationContext context, String heatResourceType) {
320     List<Predicate<Map.Entry<String, Resource>>> list = new ArrayList<>();
321     list.add(entry ->
322         entry.getValue().getType().equals(heatResourceType));
323     list.add(entry -> {
324       Optional<String> resourceTranslatedId =
325           getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, entry.getKey(), context);
326       return resourceTranslatedId.isPresent()
327           && resourceTranslatedId.get().equals(translatedResourceId);
328     });
329     return list;
330   }
331
332   boolean isResourceTypeSupported(Resource resource, List<String> supporteTypes) {
333     return Objects.nonNull(resource) && supporteTypes.contains(resource.getType());
334   }
335
336 }