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