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