dafd8e620781d0d3703f75d02b3484903c0cd825
[sdc.git] /
1 /*
2  * Copyright © 2016-2017 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;
18
19 import org.apache.commons.collections4.CollectionUtils;
20 import org.apache.commons.collections4.MapUtils;
21 import org.apache.commons.io.FilenameUtils;
22 import org.openecomp.core.translator.api.HeatToToscaTranslator;
23 import org.openecomp.core.translator.datatypes.TranslatorOutput;
24 import org.openecomp.core.translator.factory.HeatToToscaTranslatorFactory;
25 import org.openecomp.core.utilities.file.FileContentHandler;
26 import org.openecomp.core.utilities.file.FileUtils;
27 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
28 import org.openecomp.core.validation.util.MessageContainerUtil;
29 import org.openecomp.sdc.common.errors.CoreException;
30 import org.openecomp.sdc.common.togglz.ToggleableFeature;
31 import org.openecomp.sdc.common.utils.SdcCommon;
32 import org.openecomp.sdc.datatypes.error.ErrorLevel;
33 import org.openecomp.sdc.datatypes.error.ErrorMessage;
34 import org.openecomp.sdc.heat.datatypes.HeatBoolean;
35 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
36 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
37 import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes;
38 import org.openecomp.sdc.heat.datatypes.model.Resource;
39 import org.openecomp.sdc.heat.datatypes.structure.HeatStructureTree;
40 import org.openecomp.sdc.heat.datatypes.structure.ValidationStructureList;
41 import org.openecomp.sdc.heat.services.HeatConstants;
42 import org.openecomp.sdc.heat.services.tree.HeatTreeManager;
43 import org.openecomp.sdc.heat.services.tree.HeatTreeManagerUtil;
44 import org.openecomp.sdc.logging.api.Logger;
45 import org.openecomp.sdc.logging.api.LoggerFactory;
46 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
47 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
48 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
49 import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
50 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
51 import org.openecomp.sdc.tosca.datatypes.model.AttributeDefinition;
52 import org.openecomp.sdc.tosca.datatypes.model.CapabilityDefinition;
53 import org.openecomp.sdc.tosca.datatypes.model.Import;
54 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
55 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
56 import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
57 import org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition;
58 import org.openecomp.sdc.tosca.datatypes.model.PropertyType;
59 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
60 import org.openecomp.sdc.tosca.datatypes.model.RequirementDefinition;
61 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
62 import org.openecomp.sdc.tosca.datatypes.model.Template;
63 import org.openecomp.sdc.tosca.datatypes.model.TopologyTemplate;
64 import org.openecomp.sdc.tosca.services.DataModelUtil;
65 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
66 import org.openecomp.sdc.tosca.services.ToscaConstants;
67 import org.openecomp.sdc.tosca.services.ToscaExtensionYamlUtil;
68 import org.openecomp.sdc.tosca.services.ToscaUtil;
69 import org.openecomp.sdc.tosca.services.YamlUtil;
70 import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
71 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedPropertyVal;
72 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
73 import org.openecomp.sdc.translator.datatypes.heattotosca.ReferenceType;
74 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
75 import org.openecomp.sdc.translator.datatypes.heattotosca.to.FileDataCollection;
76 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
77 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
78 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
79 import org.openecomp.sdc.translator.services.heattotosca.helper.FunctionTranslationHelper;
80 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaPropertyConverter;
81
82 import java.io.IOException;
83 import java.io.InputStream;
84 import java.util.ArrayList;
85 import java.util.Collection;
86 import java.util.HashMap;
87 import java.util.HashSet;
88 import java.util.List;
89 import java.util.Map;
90 import java.util.Objects;
91 import java.util.Optional;
92 import java.util.Set;
93 import java.util.stream.Collectors;
94
95 /**
96  * The type Heat to tosca util.
97  */
98 public class HeatToToscaUtil {
99
100   private static final Logger LOGGER = LoggerFactory.getLogger(HeatToToscaUtil.class);
101   public static final String FQ_NAME = "fq_name";
102   public static final String GET_PARAM = "get_param";
103   private static final String FORWARDER = "forwarder";
104   private static final String GET_ATTR = "get_attr";
105   private static final String GET_RESOURCE = "get_resource";
106
107   /**
108    * Load and translate template data translator output.
109    *
110    * @param fileNameContentMap the file name content map
111    * @return the translator output
112    */
113   public static TranslatorOutput loadAndTranslateTemplateData(
114       FileContentHandler fileNameContentMap) {
115     HeatToToscaTranslator heatToToscaTranslator =
116         HeatToToscaTranslatorFactory.getInstance().createInterface();
117
118     try (InputStream fileContent = fileNameContentMap.getFileContent(SdcCommon.MANIFEST_NAME)) {
119       heatToToscaTranslator.addManifest(SdcCommon.MANIFEST_NAME, FileUtils.toByteArray(fileContent));
120     } catch (IOException e) {
121       throw new RuntimeException("Failed to read manifest", e);
122     }
123
124     fileNameContentMap.getFileList().stream()
125         .filter(fileName -> !(fileName.equals(SdcCommon.MANIFEST_NAME))).forEach(
126             fileName -> heatToToscaTranslator
127                 .addFile(fileName, FileUtils.toByteArray
128                     (fileNameContentMap.getFileContent(fileName))));
129
130     Map<String, List<ErrorMessage>> errors = heatToToscaTranslator.validate();
131     if (MapUtils.isNotEmpty(MessageContainerUtil.getMessageByLevel(ErrorLevel.ERROR, errors))) {
132       TranslatorOutput translatorOutput = new TranslatorOutput();
133       translatorOutput.setErrorMessages(errors);
134       return translatorOutput;
135     }
136
137     try (InputStream structureFile = getHeatStructureTreeFile(fileNameContentMap)) {
138       heatToToscaTranslator.addExternalArtifacts(SdcCommon.HEAT_META, structureFile);
139       return heatToToscaTranslator.translate();
140     } catch (IOException e) {
141       // rethrow as a RuntimeException to keep the signature backward compatible
142       throw new RuntimeException("Failed to read Heat template tree", e);
143     }
144   }
145
146
147   private static InputStream getHeatStructureTreeFile(FileContentHandler fileNameContentMap) {
148     HeatTreeManager heatTreeManager = HeatTreeManagerUtil.initHeatTreeManager(fileNameContentMap);
149     heatTreeManager.createTree();
150     HeatStructureTree tree = heatTreeManager.getTree();
151     ValidationStructureList validationStructureList = new ValidationStructureList(tree);
152     return FileUtils.convertToInputStream(validationStructureList, FileUtils.FileExtension.JSON);
153   }
154
155   /**
156    * Build list of files to search optional.
157    *
158    * @param heatFileName  the heat file name
159    * @param filesDataList the files data list
160    * @param types         the types
161    * @return the optional
162    */
163   public static Optional<List<FileData>> buildListOfFilesToSearch(String heatFileName,
164                                                                   List<FileData> filesDataList,
165                                                                   FileData.Type... types) {
166     List<FileData> list = new ArrayList<>(filesDataList);
167     Optional<FileData> resourceFileData = HeatToToscaUtil.getFileData(heatFileName, filesDataList);
168     if (resourceFileData.isPresent() && Objects.nonNull(resourceFileData.get().getData())) {
169       list.addAll(resourceFileData.get().getData());
170     }
171     return Optional.ofNullable(HeatToToscaUtil.getFilteredListOfFileDataByTypes(list, types));
172   }
173
174   /**
175    * Gets filtered list of file data by types.
176    *
177    * @param filesToSearch the files to search
178    * @param types         the types
179    * @return the filtered list of file data by types
180    */
181   public static List<FileData> getFilteredListOfFileDataByTypes(List<FileData> filesToSearch,
182                                                                 FileData.Type... types) {
183     return filesToSearch.stream().filter(FileData.buildFileDataPredicateByType(types))
184         .collect(Collectors.toList());
185   }
186
187   /**
188    * Gets file data from the list according to the input heat file name.
189    *
190    * @param heatFileName the heat file name
191    * @param fileDataList the file data list
192    * @return the file data
193    */
194   public static Optional<FileData> getFileData(String heatFileName,
195                                                Collection<FileData> fileDataList) {
196     for (FileData file : fileDataList) {
197       if (file.getFile().equals(heatFileName)) {
198         return Optional.of(file);
199       }
200     }
201     return Optional.empty();
202   }
203
204   /**
205    * Gets file data which is supported by the translator, from the context according the input heat
206    * file name.
207    *
208    * @param heatFileName the heat file name
209    * @param context      the translation context
210    * @return the file data
211    */
212   public static FileData getFileData(String heatFileName, TranslationContext context) {
213
214     List<FileData> fileDataList = context.getManifest().getContent().getData();
215     for (FileData fileData : fileDataList) {
216       if (TranslationService.getTypesToProcessByTranslator().contains(fileData.getType())
217           && fileData.getFile().equals(heatFileName)) {
218         return fileData;
219       }
220     }
221     return null;
222   }
223
224   static FileDataCollection getFileCollectionsByFilter(List<FileData> fileDataList,
225                                                        Set<FileData.Type> typeFilter,
226                                                        TranslationContext translationContext) {
227     FileDataCollection fileDataCollection = new FileDataCollection();
228     Map<String, FileData> filteredFiles = filterFileDataListByType(fileDataList, typeFilter);
229     Set<String> referenced = new HashSet<>();
230
231     for (FileData fileData : filteredFiles.values()) {
232       String fileName = fileData.getFile();
233
234       if (FileData.isHeatFile(fileData.getType())) {
235         if (fileData.getBase() != null && fileData.getBase()) {
236           fileDataCollection.addBaseFiles(fileData);
237         }
238         HeatOrchestrationTemplate heatOrchestrationTemplate = new YamlUtil()
239             .yamlToObject(translationContext.getFileContent(fileName),
240                 HeatOrchestrationTemplate.class);
241         if (MapUtils.isNotEmpty(heatOrchestrationTemplate.getResources())) {
242           applyFilterOnFileCollection(heatOrchestrationTemplate, translationContext,
243               fileDataCollection, filteredFiles, referenced);
244         }
245
246       } else {
247         fileDataCollection.addArtifactFiles(fileData);
248         filteredFiles.remove(fileData.getFile());
249       }
250     }
251
252     referenced.forEach(filteredFiles::remove);
253     if (!CollectionUtils.isEmpty(fileDataCollection.getBaseFile())) {
254       for (FileData fileData : fileDataCollection.getBaseFile()) {
255         filteredFiles.remove(fileData.getFile());
256       }
257     }
258     fileDataCollection.setAddOnFiles(filteredFiles.values());
259     return fileDataCollection;
260   }
261
262   private static void applyFilterOnFileCollection(
263       HeatOrchestrationTemplate heatOrchestrationTemplate,
264       TranslationContext translationContext,
265       FileDataCollection fileDataCollection, Map<String, FileData> filteredFiles,
266       Set<String> referenced) {
267     List<String> filenames = extractFilenamesFromFileDataList(filteredFiles.values());
268
269     for (Resource resource : heatOrchestrationTemplate.getResources().values()) {
270       if (filenames.contains(resource.getType())) {
271         handleNestedFile(translationContext, fileDataCollection, filteredFiles, referenced,
272             resource.getType());
273       } else if (resource.getType()
274           .equals(HeatResourcesTypes.RESOURCE_GROUP_RESOURCE_TYPE.getHeatResource())) {
275         handleResourceGrpNestedFile(resource, translationContext, fileDataCollection,
276             filteredFiles, filenames, referenced);
277       }
278     }
279   }
280
281   private static void handleResourceGrpNestedFile(Resource resource,
282                                                   TranslationContext translationContext,
283                                                   FileDataCollection fileDataCollection,
284                                                   Map<String, FileData> filteredFiles,
285                                                   List<String> filenames,
286                                                   Set<String> referenced) {
287     Object resourceDef = resource.getProperties().get(HeatConstants.RESOURCE_DEF_PROPERTY_NAME);
288     Object innerTypeDef = ((Map) resourceDef).get("type");
289     if (innerTypeDef instanceof String) {
290       String internalResourceType = (String) innerTypeDef;
291       if (filenames.contains(internalResourceType)) {
292         handleNestedFile(translationContext, fileDataCollection, filteredFiles,
293             referenced, internalResourceType);
294       }
295     }
296   }
297
298   private static void handleNestedFile(TranslationContext translationContext,
299                                        FileDataCollection fileDataCollection,
300                                        Map<String, FileData> filteredFiles, Set<String> referenced,
301                                        String nestedFileName) {
302     referenced.add(nestedFileName);
303     fileDataCollection.addNestedFiles(filteredFiles.get(nestedFileName));
304     translationContext.getNestedHeatsFiles().add(nestedFileName);
305   }
306
307   private static Map<String, FileData> filterFileDataListByType(List<FileData> fileDataList,
308                                                                 Set<FileData.Type> typesToGet) {
309     Map<String, FileData> filtered = new HashMap<>();
310     fileDataList.stream().filter(file -> typesToGet.contains(file.getType()))
311         .forEach(file -> filtered.put(file.getFile(), file));
312     return filtered;
313   }
314
315   private static List<String> extractFilenamesFromFileDataList(Collection<FileData> fileDataList) {
316     return fileDataList.stream().map(FileData::getFile).collect(Collectors.toList());
317   }
318
319   /**
320    * Extract attached resource id optional.
321    *
322    * @param translateTo  the translate to
323    * @param propertyName the property name
324    * @return the optional
325    */
326   public static Optional<AttachedResourceId> extractAttachedResourceId(TranslateTo translateTo,
327                                                                        String propertyName) {
328     Object propertyValue = translateTo.getResource().getProperties().get(propertyName);
329     if (propertyValue == null) {
330       return Optional.empty();
331     }
332     return extractAttachedResourceId(translateTo.getHeatFileName(),
333         translateTo.getHeatOrchestrationTemplate(), translateTo.getContext(), propertyValue);
334   }
335
336   /**
337    * Extract attached resource id optional.
338    *
339    * @param heatFileName              the heat file name
340    * @param heatOrchestrationTemplate the heat orchestration template
341    * @param context                   the context
342    * @param propertyValue             the property value
343    * @return the optional
344    */
345   public static Optional<AttachedResourceId> extractAttachedResourceId(
346       String heatFileName,
347       HeatOrchestrationTemplate heatOrchestrationTemplate,
348       TranslationContext context,
349       Object propertyValue) {
350
351     Object entity;
352     Object translatedId;
353
354     if (Objects.isNull(propertyValue)) {
355       return Optional.empty();
356     }
357
358     ReferenceType referenceType = ReferenceType.OTHER;
359     if (propertyValue instanceof Map && !((Map) propertyValue).isEmpty()) {
360       Map<String, Object> propMap = (Map) propertyValue;
361       Map.Entry<String, Object> entry = propMap.entrySet().iterator().next();
362       entity = entry.getValue();
363       String key = entry.getKey();
364       referenceType = getReferenceTypeFromAttachedResouce(key);
365
366       if (!FunctionTranslationFactory.getInstance(entry.getKey()).isPresent()) {
367         translatedId = null;
368       } else {
369         translatedId = FunctionTranslationFactory.getInstance(entry.getKey()).get()
370             .translateFunction(null, null, null, entry.getKey(), entry.getValue(), heatFileName,
371                 heatOrchestrationTemplate, null, context);
372       }
373       if (translatedId instanceof String
374           && !FunctionTranslationHelper.isResourceSupported((String) translatedId)) {
375         translatedId = null;
376       }
377
378     } else {
379       translatedId = propertyValue;
380       entity = propertyValue;
381     }
382
383     return Optional.of(new AttachedResourceId(translatedId, entity, referenceType));
384   }
385
386   private static ReferenceType getReferenceTypeFromAttachedResouce(String key) {
387     ReferenceType referenceType;
388     switch (key) {
389       case GET_RESOURCE:
390         referenceType = ReferenceType.GET_RESOURCE;
391         break;
392       case GET_PARAM:
393         referenceType = ReferenceType.GET_PARAM;
394         break;
395       case GET_ATTR:
396         referenceType = ReferenceType.GET_ATTR;
397         break;
398       default:
399         referenceType = ReferenceType.OTHER;
400         break;
401     }
402
403     return referenceType;
404   }
405
406   /**
407    * Gets contrail attached heat resource id.
408    *
409    * @param attachedResource the attached resource
410    * @return the contrail attached heat resource id
411    */
412   public static Optional<String> getContrailAttachedHeatResourceId(
413       AttachedResourceId attachedResource) {
414     if (attachedResource == null) {
415       return Optional.empty();
416     }
417
418     if (attachedResource.isGetResource()) {
419       return Optional.of((String) attachedResource.getEntityId());
420     }
421
422     if (attachedResource.isGetAttr()) {
423       return getResourceId(attachedResource.getEntityId());
424     }
425     return Optional.empty();
426   }
427
428   /**
429    * Extract property optional.
430    *
431    * @param propertyValue the property value
432    * @return the optional
433    */
434   public static Optional<AttachedPropertyVal> extractProperty(Object propertyValue) {
435     Object attachedPropertyVal;
436     if (Objects.isNull(propertyValue)) {
437       return Optional.empty();
438     }
439
440     ReferenceType referenceType = ReferenceType.OTHER;
441     if (propertyValue instanceof Map && !((Map) propertyValue).isEmpty()) {
442       Map<String, Object> propMap = (Map) propertyValue;
443       Map.Entry<String, Object> entry = propMap.entrySet().iterator().next();
444       attachedPropertyVal = entry.getValue();
445       String key = entry.getKey();
446       switch (key) {
447         case GET_RESOURCE:
448           referenceType = ReferenceType.GET_RESOURCE;
449           break;
450         case GET_PARAM:
451           referenceType = ReferenceType.GET_PARAM;
452           break;
453         case GET_ATTR:
454           referenceType = ReferenceType.GET_ATTR;
455           break;
456         default:
457           break;
458       }
459
460     } else {
461       attachedPropertyVal = propertyValue;
462     }
463     return Optional.of(new AttachedPropertyVal(attachedPropertyVal, referenceType));
464   }
465
466   /**
467    * Map boolean.
468    *
469    * @param nodeTemplate the node template
470    * @param propertyKey  the property key
471    */
472   public static void mapBoolean(NodeTemplate nodeTemplate, String propertyKey) {
473     Object value = nodeTemplate.getProperties().get(propertyKey);
474     if (value != null && !(value instanceof Map)) {
475       nodeTemplate.getProperties().put(propertyKey, HeatBoolean.eval(value));
476     }
477   }
478
479   /**
480    * Map boolean list.
481    *
482    * @param nodeTemplate    the node template
483    * @param propertyListKey the property list key
484    */
485   public static void mapBooleanList(NodeTemplate nodeTemplate, String propertyListKey) {
486     Object listValue = nodeTemplate.getProperties().get(propertyListKey);
487     if (listValue instanceof List) {
488       List booleanList = (List) listValue;
489       for (int i = 0; i < booleanList.size(); i++) {
490         Object value = booleanList.get(i);
491         if (value != null && !(value instanceof Map)) {
492           booleanList.set(i, HeatBoolean.eval(value));
493         }
494       }
495     }
496   }
497
498
499   /**
500    * Is yml file type boolean.
501    *
502    * @param filename the filename
503    * @return the boolean
504    */
505   public static boolean isYmlFileType(String filename) {
506     String extension = FilenameUtils.getExtension(filename);
507     return "yaml".equalsIgnoreCase(extension)
508         || "yml".equalsIgnoreCase(extension);
509   }
510
511   /**
512    * Is nested resource boolean.
513    *
514    * @param resource the resource
515    * @return the boolean
516    */
517   public static boolean isNestedResource(Resource resource) {
518     String resourceType = resource.getType();
519
520     if (resourceType.equals(HeatResourcesTypes.RESOURCE_GROUP_RESOURCE_TYPE.getHeatResource())) {
521       Object resourceDef = resource.getProperties().get(HeatConstants.RESOURCE_DEF_PROPERTY_NAME);
522       if (!(((Map) resourceDef).get("type") instanceof String)) {
523         //currently only resource group which is poinitng to nested heat file is supported
524         //dynamic type is currently not supported
525         return false;
526       }
527       String internalResourceType = (String) ((Map) resourceDef).get("type");
528       if (isYamlFile(internalResourceType)) {
529         return true;
530       }
531     } else if (isYamlFile(resourceType)) {
532       return true;
533     }
534     return false;
535   }
536
537   /**
538    * Checks if the nested resource represents a VFC or a complex VFC (Heat file should contain at
539    * least one or more compute nodes).
540    *
541    * @param resource the resource
542    * @param context the context
543    * @return true if the resource represents a VFC and false otherwise.
544    */
545   public static boolean isNestedVfcResource(Resource resource, TranslationContext context) {
546     Optional<String> nestedHeatFileName = HeatToToscaUtil.getNestedHeatFileName(resource);
547     HeatOrchestrationTemplate nestedHeatOrchestrationTemplate = new YamlUtil()
548         .yamlToObject(context.getFileContent(nestedHeatFileName.get()),
549             HeatOrchestrationTemplate.class);
550     if (Objects.nonNull(nestedHeatOrchestrationTemplate.getResources())) {
551       for (String innerResourceId : nestedHeatOrchestrationTemplate.getResources().keySet()) {
552         if (ConsolidationDataUtil
553             .isComputeResource(nestedHeatOrchestrationTemplate, innerResourceId)) {
554           return true;
555         }
556       }
557     }
558     return false;
559   }
560
561   /**
562    * Get nested heat file name in case of nested resource.
563    *
564    * @param resource the resource
565    * @return the nested heat file name
566    */
567   public static Optional<String> getNestedHeatFileName(Resource resource) {
568     if (!isNestedResource(resource)) {
569       return Optional.empty();
570     }
571
572     String resourceType = resource.getType();
573
574     if (resourceType.equals(HeatResourcesTypes.RESOURCE_GROUP_RESOURCE_TYPE.getHeatResource())) {
575       Object resourceDef = resource.getProperties().get(HeatConstants.RESOURCE_DEF_PROPERTY_NAME);
576       String internalResourceType = (String) ((Map) resourceDef).get("type");
577       return Optional.of(internalResourceType);
578     }
579     return Optional.of(resourceType);
580   }
581
582   /**
583    * Gets nested file.
584    *
585    * @param resource the resource
586    * @return the nested file
587    */
588   public static Optional<String> getNestedFile(Resource resource) {
589     if (!isNestedResource(resource)) {
590       return Optional.empty();
591     }
592     String resourceType = resource.getType();
593     if (resourceType.equals(HeatResourcesTypes.RESOURCE_GROUP_RESOURCE_TYPE.getHeatResource())) {
594       Object resourceDef = resource.getProperties().get(HeatConstants.RESOURCE_DEF_PROPERTY_NAME);
595       String internalResourceType = (String) ((Map) resourceDef).get("type");
596       return Optional.of(internalResourceType);
597     } else {
598       return Optional.of(resourceType);
599     }
600   }
601
602   private static boolean isYamlFile(String fileName) {
603     return fileName.endsWith(".yaml") || fileName.endsWith(".yml");
604   }
605
606   /**
607    * Gets resource.
608    *
609    * @param heatOrchestrationTemplate the heat orchestration template
610    * @param resourceId                the resource id
611    * @param heatFileName              the heat file name
612    * @return the resource
613    */
614   public static Resource getResource(HeatOrchestrationTemplate heatOrchestrationTemplate,
615                                      String resourceId, String heatFileName) {
616     Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
617     if (resource == null) {
618       throw new CoreException(
619           new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
620     }
621     return resource;
622   }
623
624
625   /**
626    * Get resource type.
627    *
628    * @param resourceId                the resource id
629    * @param heatOrchestrationTemplate heat orchestration template
630    * @param heatFileName              heat file name
631    * @return resource type
632    */
633   public static String getResourceType(String resourceId,
634                                        HeatOrchestrationTemplate heatOrchestrationTemplate,
635                                        String heatFileName) {
636     return HeatToToscaUtil.getResource(heatOrchestrationTemplate, resourceId, heatFileName)
637         .getType();
638   }
639
640   /**
641    * Is heat file nested boolean.
642    *
643    * @param translateTo  the translate to
644    * @param heatFileName the heat file name
645    * @return the boolean
646    */
647   public static boolean isHeatFileNested(TranslateTo translateTo, String heatFileName) {
648     return isHeatFileNested(translateTo.getContext(), heatFileName);
649   }
650
651   public static boolean isHeatFileNested(TranslationContext context, String heatFileName) {
652     return context.getNestedHeatsFiles().contains(heatFileName);
653   }
654
655   /**
656    * Extract contrail get resource attached heat resource id optional.
657    *
658    * @param propertyValue the property value
659    * @return the optional
660    */
661   public static Optional<String> extractContrailGetResourceAttachedHeatResourceId(
662       Object propertyValue) {
663     if (propertyValue instanceof Map) {
664       if (((Map) propertyValue).containsKey(GET_ATTR)) {
665         return getResourceId(((Map) propertyValue).get(GET_ATTR));
666       } else if (((Map) propertyValue).containsKey(GET_RESOURCE)) {
667         return getHeatResourceIdFromResource((Map) propertyValue);
668       } else {
669         Collection valCollection = ((Map) propertyValue).values();
670         return evaluateHeatResourceId(valCollection);
671       }
672     } else if (propertyValue instanceof List) {
673       return evaluateHeatResourceId((List) propertyValue);
674     }
675     return Optional.empty();
676   }
677
678   private static Optional<String> getResourceId(Object data) {
679     if (data instanceof List && CollectionUtils.size(data) > 1
680         && FQ_NAME.equals(((List) data).get(1))
681         && ((List) data).get(0) instanceof String) {
682       return Optional.of((String) ((List) data).get(0));
683     } else {
684       LOGGER.warn("invalid format of 'get_attr' function - " + data.toString());
685       return Optional.empty();
686     }
687   }
688
689   private static Optional<String> getHeatResourceIdFromResource(Map propertyValue) {
690     Object value = propertyValue.get(GET_RESOURCE);
691     if (value instanceof String) {
692       return Optional.of((String) value);
693     } else {
694       LOGGER.warn("invalid format of 'get_resource' function - " + propertyValue.toString());
695       return Optional.empty();
696     }
697   }
698
699   private static Optional<String> evaluateHeatResourceId(Collection propertyValue) {
700     for (Object prop : propertyValue) {
701       Optional<String> ret = extractContrailGetResourceAttachedHeatResourceId(prop);
702       if (ret.isPresent()) {
703         return ret;
704       }
705     }
706     return Optional.empty();
707   }
708   /**
709    * Gets tosca service model.
710    *
711    * @param context translation context
712    * @return the tosca service model
713    */
714   public static ToscaServiceModel getToscaServiceModel(TranslationContext context) {
715     Map<String, String> metadata = new HashMap<>();
716     metadata.put(ToscaConstants.ST_METADATA_TEMPLATE_NAME, Constants.MAIN_TEMPLATE_NAME);
717     return getToscaServiceModel(context, metadata);
718   }
719
720   /**
721    * Gets tosca service model.
722    *
723    * @param context                 translation context
724    * @param entryDefinitionMetadata template name of the entry definition servie template
725    * @return the tosca service model
726    */
727   public static ToscaServiceModel getToscaServiceModel(
728       TranslationContext context,
729       Map<String, String> entryDefinitionMetadata) {
730     Map<String, ServiceTemplate> serviceTemplates =
731         new HashMap<>(context.getGlobalServiceTemplates());
732     Collection<ServiceTemplate> tmpServiceTemplates =
733         context.getTranslatedServiceTemplates().values();
734     for (ServiceTemplate serviceTemplate : tmpServiceTemplates) {
735       ToscaUtil.addServiceTemplateToMapWithKeyFileName(serviceTemplates, serviceTemplate);
736     }
737     return new ToscaServiceModel(null, serviceTemplates,
738         ToscaUtil.getServiceTemplateFileName(entryDefinitionMetadata));
739   }
740
741   /**
742    * Gets service template from context.
743    *
744    * @param serviceTemplateFileName the service template file name
745    * @param context                 the context
746    * @return the service template from context
747    */
748   public static Optional<ServiceTemplate> getServiceTemplateFromContext(
749       String serviceTemplateFileName, TranslationContext context) {
750     for (ServiceTemplate serviceTemplate : context.getTranslatedServiceTemplates().values()) {
751       if (ToscaUtil.getServiceTemplateFileName(serviceTemplate).equals(serviceTemplateFileName)) {
752         return Optional.of(serviceTemplate);
753       }
754     }
755     return Optional.empty();
756   }
757
758   /**
759    * Adding link requerment from port node template to network node template.
760    *
761    * @param portNodeTemplate    port node template
762    * @param networkTranslatedId network node template id
763    */
764   public static RequirementAssignment addLinkReqFromPortToNetwork(NodeTemplate portNodeTemplate,
765                                                                   String networkTranslatedId) {
766     RequirementAssignment requirement = new RequirementAssignment();
767     requirement.setCapability(ToscaCapabilityType.NATIVE_NETWORK_LINKABLE);
768     requirement.setRelationship(ToscaRelationshipType.NATIVE_NETWORK_LINK_TO);
769     requirement.setNode(networkTranslatedId);
770     DataModelUtil.addRequirementAssignment(portNodeTemplate,
771         ToscaConstants.LINK_REQUIREMENT_ID, requirement);
772     return requirement;
773   }
774
775   /**
776    * Adding binding requerment from sub interface node template to interface (port) node template.
777    *
778    * @param subInterfaceNodeTemplate sub interface template
779    * @param interfaceTranslatedId    interface node template id
780    */
781   public static void addBindingReqFromSubInterfaceToInterface(
782       NodeTemplate subInterfaceNodeTemplate, String interfaceTranslatedId) {
783     RequirementAssignment requirement = new RequirementAssignment();
784     requirement.setCapability(ToscaCapabilityType.NATIVE_NETWORK_BINDABLE);
785     requirement.setRelationship(ToscaRelationshipType.NATIVE_NETWORK_BINDS_TO);
786     requirement.setNode(interfaceTranslatedId);
787     DataModelUtil
788         .addRequirementAssignment(subInterfaceNodeTemplate,
789             ToscaConstants.BINDING_REQUIREMENT_ID, requirement);
790   }
791
792   /**
793    * Get property Parameter Name Value.
794    *
795    * @param property property
796    * @return Parameter name in case the property include "get_param" function
797    */
798   public static Optional<String> getPropertyParameterNameValue(Object property) {
799     if (Objects.isNull(property)) {
800       return Optional.empty();
801     }
802     Optional<AttachedPropertyVal> extractedProperty = extractProperty(property);
803     return extractedProperty.flatMap(HeatToToscaUtil::getParameterName);
804   }
805
806   private static Optional<String> getParameterName(AttachedPropertyVal extractedProperty) {
807     if (!extractedProperty.isGetParam()) {
808       return Optional.empty();
809     }
810     Object getParamFuncValue = extractedProperty.getPropertyValue();
811     if (getParamFuncValue instanceof String) {
812       return Optional.of((String) getParamFuncValue);
813     } else {
814       return Optional.of((String) ((List) getParamFuncValue).get(0));
815     }
816   }
817
818   public static String getToscaPropertyName(TranslationContext context, String heatResourceType,
819                                             String heatPropertyName) {
820     return context.getElementMapping(heatResourceType, Constants.PROP, heatPropertyName);
821   }
822
823   /**
824    * Gets tosca property name.
825    *
826    * @param translateTo      the translate to
827    * @param heatPropertyName the heat property name
828    * @return the tosca property name
829    */
830   public static String getToscaPropertyName(TranslateTo translateTo, String heatPropertyName) {
831     return translateTo.getContext()
832         .getElementMapping(translateTo.getResource().getType(), Constants.PROP, heatPropertyName);
833   }
834
835   /**
836    * Gets tosca attribute name.
837    *
838    * @param context          the context
839    * @param heatResourceType the heat resource type
840    * @param heatAttrName     the heat attr name
841    * @return the tosca attribute name
842    */
843   public static String getToscaAttributeName(TranslationContext context, String heatResourceType,
844                                              String heatAttrName) {
845     return context.getElementMapping(heatResourceType, Constants.ATTR, heatAttrName);
846   }
847
848   /**
849    * Gets tosca attribute name.
850    *
851    * @param translateTo  the translate to
852    * @param heatAttrName the heat attr name
853    * @return the tosca attribute name
854    */
855   public static String getToscaAttributeName(TranslateTo translateTo, String heatAttrName) {
856     return translateTo.getContext()
857         .getElementMapping(translateTo.getResource().getType(), Constants.ATTR, heatAttrName);
858   }
859
860   /**
861    * Create init substitution service template service template.
862    *
863    * @param templateName the template name
864    * @return the service template
865    */
866   public static ServiceTemplate createInitSubstitutionServiceTemplate(String templateName) {
867     ServiceTemplate nestedSubstitutionServiceTemplate = new ServiceTemplate();
868     Map<String, String> templateMetadata = new HashMap<>();
869     templateMetadata.put(ToscaConstants.ST_METADATA_TEMPLATE_NAME, templateName);
870     nestedSubstitutionServiceTemplate.setMetadata(templateMetadata);
871     nestedSubstitutionServiceTemplate
872         .setTosca_definitions_version(ToscaConstants.TOSCA_DEFINITIONS_VERSION);
873     nestedSubstitutionServiceTemplate.setTopology_template(new TopologyTemplate());
874     List<Map<String, Import>> globalTypesImportList =
875         GlobalTypesGenerator.getGlobalTypesImportList();
876     globalTypesImportList.addAll(
877         HeatToToscaUtil.createImportList(Constants.GLOBAL_SUBSTITUTION_TYPES_TEMPLATE_NAME));
878     nestedSubstitutionServiceTemplate.setImports(globalTypesImportList);
879     return nestedSubstitutionServiceTemplate;
880   }
881
882   /**
883    * Create init global substitution service template service template.
884    *
885    * @return the service template
886    */
887   public static ServiceTemplate createInitGlobalSubstitutionServiceTemplate() {
888     ServiceTemplate globalSubstitutionServiceTemplate = new ServiceTemplate();
889     Map<String, String> templateMetadata = new HashMap<>();
890     templateMetadata.put(ToscaConstants.ST_METADATA_TEMPLATE_NAME,
891         Constants.GLOBAL_SUBSTITUTION_TYPES_TEMPLATE_NAME);
892     globalSubstitutionServiceTemplate.setMetadata(templateMetadata);
893     globalSubstitutionServiceTemplate
894         .setImports(GlobalTypesGenerator.getGlobalTypesImportList());
895     globalSubstitutionServiceTemplate
896         .setTosca_definitions_version(ToscaConstants.TOSCA_DEFINITIONS_VERSION);
897     return globalSubstitutionServiceTemplate;
898   }
899
900   /**
901    * Create substitution node type node type.
902    *
903    * @param substitutionServiceTemplate the substitution service template
904    * @return the node type
905    */
906   public NodeType createSubstitutionNodeType(ServiceTemplate substitutionServiceTemplate) {
907     NodeType substitutionNodeType = new NodeType();
908     substitutionNodeType.setDerived_from(ToscaNodeType.ABSTRACT_SUBSTITUTE);
909     substitutionNodeType.setDescription(substitutionServiceTemplate.getDescription());
910     substitutionNodeType
911         .setProperties(manageSubstitutionNodeTypeProperties(substitutionServiceTemplate));
912     substitutionNodeType
913         .setAttributes(manageSubstitutionNodeTypeAttributes(substitutionServiceTemplate));
914     return substitutionNodeType;
915   }
916
917   private Map<String, PropertyDefinition> manageSubstitutionNodeTypeProperties(
918       ServiceTemplate substitutionServiceTemplate) {
919     Map<String, PropertyDefinition> substitutionNodeTypeProperties = new HashMap<>();
920     Map<String, ParameterDefinition> properties =
921         substitutionServiceTemplate.getTopology_template().getInputs();
922     if (properties == null) {
923       return null;
924     }
925
926     PropertyDefinition propertyDefinition;
927     String toscaPropertyName;
928     for (Map.Entry<String, ParameterDefinition> entry : properties.entrySet()) {
929       toscaPropertyName = entry.getKey();
930       propertyDefinition = new PropertyDefinition();
931       ParameterDefinition parameterDefinition =
932           substitutionServiceTemplate.getTopology_template().getInputs().get(toscaPropertyName);
933       propertyDefinition.setType(parameterDefinition.getType());
934       propertyDefinition.setDescription(parameterDefinition.getDescription());
935       propertyDefinition.setRequired(parameterDefinition.getRequired());
936       propertyDefinition.set_default(parameterDefinition.get_default());
937       propertyDefinition.setConstraints(parameterDefinition.getConstraints());
938       propertyDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
939       propertyDefinition.setStatus(parameterDefinition.getStatus());
940       substitutionNodeTypeProperties.put(toscaPropertyName, propertyDefinition);
941     }
942     return substitutionNodeTypeProperties;
943   }
944
945   private Map<String, AttributeDefinition> manageSubstitutionNodeTypeAttributes(
946       ServiceTemplate substitutionServiceTemplate) {
947     Map<String, AttributeDefinition> substitutionNodeTypeAttributes = new HashMap<>();
948     Map<String, ParameterDefinition> attributes =
949         substitutionServiceTemplate.getTopology_template().getOutputs();
950     if (attributes == null) {
951       return null;
952     }
953     AttributeDefinition attributeDefinition;
954     String toscaAttributeName;
955
956     for (Map.Entry<String, ParameterDefinition> entry : attributes.entrySet()) {
957       attributeDefinition = new AttributeDefinition();
958       toscaAttributeName = entry.getKey();
959       ParameterDefinition parameterDefinition =
960           substitutionServiceTemplate.getTopology_template().getOutputs().get(toscaAttributeName);
961       if (parameterDefinition.getType() != null && !parameterDefinition.getType().isEmpty()) {
962         attributeDefinition.setType(parameterDefinition.getType());
963       } else {
964         attributeDefinition.setType(PropertyType.STRING.getDisplayName());
965       }
966       attributeDefinition.setDescription(parameterDefinition.getDescription());
967       attributeDefinition.set_default(parameterDefinition.get_default());
968       attributeDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
969       attributeDefinition.setStatus(parameterDefinition.getStatus());
970       substitutionNodeTypeAttributes.put(toscaAttributeName, attributeDefinition);
971     }
972     return substitutionNodeTypeAttributes;
973   }
974
975   /**
976    * .
977    * Create and add substitution mapping to the nested substitution service template, and update
978    * the subtitution node type accordingly with the exposed requerments and capabilities
979    *
980    * @param context                           the translation context
981    * @param substitutionNodeTypeKey           the substitution node type key
982    * @param nestedSubstitutionServiceTemplate the nested substitution service template
983    * @param substitutionNodeType              the substitution node type
984    */
985   public static void handleSubstitutionMapping(
986       TranslationContext context,
987       String substitutionNodeTypeKey,
988       ServiceTemplate nestedSubstitutionServiceTemplate,
989       NodeType substitutionNodeType) {
990     Map<String, Map<String, List<String>>> substitutionMapping =
991         getSubstitutionNodeTypeExposedConnectionPoints(substitutionNodeType,
992             nestedSubstitutionServiceTemplate, context);
993     //add substitution mapping after capability and requirement expose calculation
994     nestedSubstitutionServiceTemplate.getTopology_template().setSubstitution_mappings(
995         DataModelUtil.createSubstitutionTemplateSubMapping(substitutionNodeTypeKey,
996             substitutionNodeType, substitutionMapping));
997   }
998
999   /**
1000    * Gets node type with flat hierarchy.
1001    *
1002    * @param nodeTypeId      the node type id
1003    * @param serviceTemplate the service template
1004    * @param context         the context
1005    * @return the node type with flat hierarchy
1006    */
1007   public static NodeType getNodeTypeWithFlatHierarchy(String nodeTypeId,
1008                                                       ServiceTemplate serviceTemplate,
1009                                                       TranslationContext context) {
1010     ToscaAnalyzerService toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
1011     ToscaServiceModel toscaServiceModel = HeatToToscaUtil
1012         .getToscaServiceModel(context, serviceTemplate.getMetadata());
1013     return (NodeType) toscaAnalyzerService
1014         .getFlatEntity(ToscaElementTypes.NODE_TYPE, nodeTypeId, serviceTemplate, toscaServiceModel);
1015   }
1016
1017   /**
1018    * Create substitution node template node template.
1019    *
1020    * @param translateTo             the translate to
1021    * @param templateName            the template name
1022    * @param substitutionNodeTypeKey the substitution node type key
1023    * @return the node template
1024    */
1025   public NodeTemplate createSubstitutionNodeTemplate(TranslateTo translateTo, String templateName,
1026                                                      String substitutionNodeTypeKey) {
1027     NodeTemplate substitutionNodeTemplate = new NodeTemplate();
1028     List<String> directiveList = new ArrayList<>();
1029     directiveList.add(ToscaConstants.NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
1030     substitutionNodeTemplate.setDirectives(directiveList);
1031     substitutionNodeTemplate.setType(substitutionNodeTypeKey);
1032     substitutionNodeTemplate.setProperties(
1033         managerSubstitutionNodeTemplateProperties(translateTo, substitutionNodeTemplate,
1034             templateName));
1035     return substitutionNodeTemplate;
1036   }
1037
1038   /**
1039    * Create abstract substitution node template.
1040    *
1041    * @param translateTo             the translate to
1042    * @param templateName            the template name
1043    * @param substitutionNodeTypeKey the substitution node type key
1044    * @return the abstract substitute node template
1045    */
1046   public static NodeTemplate createAbstractSubstitutionNodeTemplate(
1047       TranslateTo translateTo,
1048       String templateName,
1049       String substitutionNodeTypeKey) {
1050     NodeTemplate substitutionNodeTemplate = new NodeTemplate();
1051     List<String> directiveList = new ArrayList<>();
1052     directiveList.add(ToscaConstants.NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
1053     substitutionNodeTemplate.setDirectives(directiveList);
1054     substitutionNodeTemplate.setType(substitutionNodeTypeKey);
1055     substitutionNodeTemplate.setProperties(
1056         managerSubstitutionNodeTemplateProperties(translateTo, substitutionNodeTemplate,
1057             templateName));
1058     return substitutionNodeTemplate;
1059   }
1060
1061
1062   /**
1063    * Checks if the source and target resource is a valid candidate for adding tosca dependency
1064    * relationship.
1065    *
1066    * @param heatOrchestrationTemplate the heat orchestration template
1067    * @param sourceResource          the source resource
1068    * @param targetResource          the target resource
1069    * @param dependencyEntity        the dependency entity
1070    * @return true if the candidate resources are a valid combination for the dependency relationship
1071    * and false otherwise
1072    */
1073   public static boolean isValidDependsOnCandidate(HeatOrchestrationTemplate
1074                                                       heatOrchestrationTemplate,
1075                                                   Resource sourceResource,
1076                                                   Resource targetResource,
1077                                                   ConsolidationEntityType dependencyEntity,
1078                                                   TranslationContext context) {
1079     dependencyEntity
1080         .setEntityType(heatOrchestrationTemplate, sourceResource, targetResource, context);
1081     ConsolidationEntityType sourceEntityType = dependencyEntity.getSourceEntityType();
1082     ConsolidationEntityType targetEntityType = dependencyEntity.getTargetEntityType();
1083
1084     return ConsolidationTypesConnectivity.isDependsOnRelationshipValid(sourceEntityType, targetEntityType);
1085   }
1086
1087   private static Map<String, Object> managerSubstitutionNodeTemplateProperties(
1088       TranslateTo translateTo,
1089       Template template,
1090       String templateName) {
1091     Map<String, Object> substitutionProperties = new HashMap<>();
1092     Map<String, Object> heatProperties = translateTo.getResource().getProperties();
1093     if (Objects.nonNull(heatProperties)) {
1094       for (Map.Entry<String, Object> entry : heatProperties.entrySet()) {
1095         Object property = TranslatorHeatToToscaPropertyConverter
1096             .getToscaPropertyValue(translateTo.getServiceTemplate(),
1097                 translateTo.getTranslatedId(), entry.getKey(),
1098                 entry.getValue(), null, translateTo.getHeatFileName(),
1099                 translateTo.getHeatOrchestrationTemplate(), template, translateTo.getContext());
1100         substitutionProperties.put(entry.getKey(), property);
1101       }
1102     }
1103     return addAbstractSubstitutionProperty(templateName, substitutionProperties);
1104   }
1105
1106   private static Map<String, Object> addAbstractSubstitutionProperty(String templateName,
1107                                                                      Map<String, Object>
1108                                                                          substitutionProperties) {
1109     Map<String, Object> innerProps = new HashMap<>();
1110     innerProps.put(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME,
1111         ToscaUtil.getServiceTemplateFileName(templateName));
1112     substitutionProperties.put(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME, innerProps);
1113     return substitutionProperties;
1114   }
1115
1116   private static Map<String, Map<String, List<String>>>
1117   getSubstitutionNodeTypeExposedConnectionPoints(NodeType substitutionNodeType,
1118                                                  ServiceTemplate substitutionServiceTemplate,
1119                                                  TranslationContext context) {
1120     Map<String, NodeTemplate> nodeTemplates =
1121         substitutionServiceTemplate.getTopology_template().getNode_templates();
1122     String nodeTemplateId;
1123     NodeTemplate nodeTemplate;
1124     String nodeType;
1125     Map<String, Map<String, List<String>>> substitutionMapping = new HashMap<>();
1126     if (nodeTemplates == null) {
1127       return substitutionMapping;
1128     }
1129
1130     Map<String, List<String>> capabilitySubstitutionMapping = new HashMap<>();
1131     Map<String, List<String>> requirementSubstitutionMapping = new HashMap<>();
1132     substitutionMapping.put("capability", capabilitySubstitutionMapping);
1133     substitutionMapping.put("requirement", requirementSubstitutionMapping);
1134     List<Map<String, RequirementDefinition>> nodeTypeRequirementsDefinition;
1135     Map<String, RequirementAssignment> nodeTemplateRequirementsAssignment;
1136     List<Map<String, RequirementDefinition>> exposedRequirementsDefinition;
1137     Map<String, Map<String, RequirementAssignment>> fullFilledRequirementsDefinition =
1138         new HashMap<>();
1139     Map<String, CapabilityDefinition> nodeTypeCapabilitiesDefinition = new HashMap<>();
1140     Map<String, CapabilityDefinition> exposedCapabilitiesDefinition;
1141     ToscaAnalyzerService toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
1142
1143     for (Map.Entry<String, NodeTemplate> entry : nodeTemplates.entrySet()) {
1144       nodeTemplateId = entry.getKey();
1145       nodeTemplate = entry.getValue();
1146       nodeType = nodeTemplate.getType();
1147
1148       // get requirements
1149       nodeTypeRequirementsDefinition =
1150           getNodeTypeReqs(nodeType, nodeTemplateId, substitutionServiceTemplate,
1151               requirementSubstitutionMapping, context);
1152       nodeTemplateRequirementsAssignment = DataModelUtil.getNodeTemplateRequirements(nodeTemplate);
1153       fullFilledRequirementsDefinition.put(nodeTemplateId, nodeTemplateRequirementsAssignment);
1154       //set substitution node type requirements
1155       exposedRequirementsDefinition =
1156           toscaAnalyzerService.calculateExposedRequirements(nodeTypeRequirementsDefinition,
1157           nodeTemplateRequirementsAssignment);
1158       DataModelUtil
1159           .addSubstitutionNodeTypeRequirements(substitutionNodeType, exposedRequirementsDefinition,
1160           nodeTemplateId);
1161
1162       //get capabilities
1163       addNodeTypeCapabilitiesToSubMapping(nodeTypeCapabilitiesDefinition,
1164           capabilitySubstitutionMapping, nodeType,
1165           nodeTemplateId, substitutionServiceTemplate, context);
1166     }
1167
1168     exposedCapabilitiesDefinition =
1169         toscaAnalyzerService.calculateExposedCapabilities(nodeTypeCapabilitiesDefinition,
1170         fullFilledRequirementsDefinition);
1171     DataModelUtil.addNodeTypeCapabilitiesDef(substitutionNodeType, exposedCapabilitiesDefinition);
1172     return substitutionMapping;
1173   }
1174
1175   private static void addNodeTypeCapabilitiesToSubMapping(
1176       Map<String, CapabilityDefinition> nodeTypeCapabilitiesDefinition,
1177       Map<String, List<String>> capabilitySubstitutionMapping, String type, String templateName,
1178       ServiceTemplate serviceTemplate, TranslationContext context) {
1179     NodeType flatNodeType =
1180         getNodeTypeWithFlatHierarchy(type, serviceTemplate, context);
1181
1182     if (flatNodeType.getCapabilities() != null) {
1183       flatNodeType.getCapabilities()
1184           .entrySet()
1185           .stream()
1186           .filter(capabilityNodeEntry -> shouldCapabilityNeedsToBeAdded(capabilityNodeEntry.getKey()))
1187           .forEach(capabilityNodeEntry ->
1188               addCapabilityToSubMapping(
1189               templateName, capabilityNodeEntry, nodeTypeCapabilitiesDefinition, capabilitySubstitutionMapping));
1190     }
1191   }
1192
1193   private static boolean shouldCapabilityNeedsToBeAdded(String capabilityKey) {
1194     return !capabilityKey.contains(FORWARDER) || ToggleableFeature.FORWARDER_CAPABILITY.isActive();
1195   }
1196
1197   public static boolean shouldAnnotationsToBeAdded() {
1198     return ToggleableFeature.ANNOTATIONS.isActive();
1199   }
1200
1201   private static void addCapabilityToSubMapping(String templateName,
1202                                                 Map.Entry<String, CapabilityDefinition> capabilityNodeEntry,
1203                                                 Map<String, CapabilityDefinition> nodeTypeCapabilitiesDefinition,
1204                                                 Map<String, List<String>> capabilitySubstitutionMapping) {
1205     String capabilityKey;
1206     List<String> capabilityMapping;
1207     capabilityKey = capabilityNodeEntry.getKey() + "_" + templateName;
1208     nodeTypeCapabilitiesDefinition.put(capabilityKey, capabilityNodeEntry.getValue().clone());
1209     capabilityMapping = new ArrayList<>();
1210     capabilityMapping.add(templateName);
1211     capabilityMapping.add(capabilityNodeEntry.getKey());
1212     capabilitySubstitutionMapping.put(capabilityKey, capabilityMapping);
1213   }
1214
1215   private static List<Map<String, RequirementDefinition>> getNodeTypeReqs(
1216       String type,
1217       String templateName,
1218       ServiceTemplate serviceTemplate,
1219       Map<String, List<String>> requirementSubstitutionMapping,
1220       TranslationContext context) {
1221     List<Map<String, RequirementDefinition>> requirementList = new ArrayList<>();
1222     NodeType flatNodeType = getNodeTypeWithFlatHierarchy(type, serviceTemplate, context);
1223     List<String> requirementMapping;
1224
1225     if (flatNodeType.getRequirements() == null) {
1226       return requirementList;
1227     }
1228
1229     for (Map<String, RequirementDefinition> requirementMap : flatNodeType.getRequirements()) {
1230       for (Map.Entry<String, RequirementDefinition> requirementNodeEntry : requirementMap
1231           .entrySet()) {
1232         ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
1233         RequirementDefinition requirementNodeEntryValue = toscaExtensionYamlUtil
1234             .yamlToObject(toscaExtensionYamlUtil.objectToYaml(requirementNodeEntry.getValue()),
1235                 RequirementDefinition.class);
1236         if (Objects.isNull(requirementNodeEntryValue.getOccurrences())) {
1237           requirementNodeEntryValue.setOccurrences(new Object[]{1, 1});
1238         }
1239         Map<String, RequirementDefinition> requirementDef = new HashMap<>();
1240         requirementDef.put(requirementNodeEntry.getKey(), requirementNodeEntryValue);
1241         DataModelUtil.addRequirementToList(requirementList, requirementDef);
1242         requirementMapping = new ArrayList<>();
1243         requirementMapping.add(templateName);
1244         requirementMapping.add(requirementNodeEntry.getKey());
1245         requirementSubstitutionMapping
1246             .put(requirementNodeEntry.getKey() + "_" + templateName, requirementMapping);
1247         if (Objects.isNull(requirementNodeEntryValue.getNode())) {
1248           requirementNodeEntryValue.setOccurrences(new Object[]{1, 1});
1249         }
1250       }
1251     }
1252     return requirementList;
1253   }
1254
1255   /**
1256    * Fetch global substitution service template service template.
1257    *
1258    * @param serviceTemplate the service template
1259    * @param context         the context
1260    * @return the service template
1261    */
1262   public static ServiceTemplate fetchGlobalSubstitutionServiceTemplate(
1263       ServiceTemplate serviceTemplate,
1264       TranslationContext context) {
1265     ServiceTemplate globalSubstitutionServiceTemplate =
1266         context.getTranslatedServiceTemplates()
1267             .get(Constants.GLOBAL_SUBSTITUTION_TYPES_TEMPLATE_NAME);
1268     if (globalSubstitutionServiceTemplate == null) {
1269       globalSubstitutionServiceTemplate =
1270           HeatToToscaUtil.createInitGlobalSubstitutionServiceTemplate();
1271       context.getTranslatedServiceTemplates()
1272           .put(Constants.GLOBAL_SUBSTITUTION_TYPES_TEMPLATE_NAME,
1273               globalSubstitutionServiceTemplate);
1274     }
1275     boolean isImportAddedToServiceTemplate =
1276         DataModelUtil.isImportAddedToServiceTemplate(serviceTemplate.getImports(), Constants
1277             .GLOBAL_SUBSTITUTION_TYPES_TEMPLATE_NAME);
1278     if (!isImportAddedToServiceTemplate) {
1279       serviceTemplate.getImports()
1280           .addAll(
1281               HeatToToscaUtil.createImportList(Constants.GLOBAL_SUBSTITUTION_TYPES_TEMPLATE_NAME));
1282     }
1283     return globalSubstitutionServiceTemplate;
1284   }
1285
1286   public static List<Map<String, Import>> createImportList(String templateName) {
1287     List<Map<String, Import>> imports = new ArrayList<>();
1288     Map<String, Import> importsMap = new HashMap<>();
1289     importsMap.put(templateName, HeatToToscaUtil.createServiceTemplateImport(templateName));
1290     imports.add(importsMap);
1291     return imports;
1292   }
1293
1294   /**
1295    * Create service template import import.
1296    *
1297    * @param serviceTemplate the service template
1298    * @return the import
1299    */
1300   public static Import createServiceTemplateImport(ServiceTemplate serviceTemplate) {
1301     Import serviceTemplateImport = new Import();
1302     serviceTemplateImport.setFile(ToscaUtil.getServiceTemplateFileName(serviceTemplate));
1303     return serviceTemplateImport;
1304   }
1305
1306   /**
1307    * Create service template import import.
1308    *
1309    * @param metadataTemplateName the service template name
1310    * @return the import
1311    */
1312   public static Import createServiceTemplateImport(String metadataTemplateName) {
1313     Import serviceTemplateImport = new Import();
1314     serviceTemplateImport.setFile(ToscaUtil.getServiceTemplateFileName(metadataTemplateName));
1315     return serviceTemplateImport;
1316   }
1317
1318   public static ToscaServiceModel createToscaServiceModel(ServiceTemplate
1319                                                               entryDefinitionServiceTemplate,
1320                                                           TranslationContext translationContext) {
1321     return new ToscaServiceModel(getCsarArtifactFiles(translationContext),
1322         getServiceTemplates(translationContext),
1323         ToscaUtil.getServiceTemplateFileName(entryDefinitionServiceTemplate));
1324   }
1325
1326   private static FileContentHandler getCsarArtifactFiles(TranslationContext translationContext) {
1327     FileContentHandler artifactFiles = new FileContentHandler();
1328     artifactFiles.setFiles(translationContext.getFiles());
1329     artifactFiles.setFiles(translationContext.getExternalArtifacts());
1330
1331     HeatTreeManager heatTreeManager =
1332         HeatTreeManagerUtil.initHeatTreeManager(translationContext.getFiles());
1333     heatTreeManager.createTree();
1334     ValidationStructureList validationStructureList =
1335         new ValidationStructureList(heatTreeManager.getTree());
1336     byte[] validationStructureFile =
1337         FileUtils.convertToBytes(validationStructureList, FileUtils.FileExtension.JSON);
1338     artifactFiles.addFile("HEAT.meta", validationStructureFile);
1339     return artifactFiles;
1340   }
1341
1342
1343   private static Map<String, ServiceTemplate> getServiceTemplates(TranslationContext
1344                                                                       translationContext) {
1345     List<ServiceTemplate> serviceTemplates = new ArrayList<>();
1346     serviceTemplates.addAll(GlobalTypesGenerator
1347         .getGlobalTypesServiceTemplate(OnboardingTypesEnum.ZIP).values());
1348     serviceTemplates.addAll(translationContext.getTranslatedServiceTemplates().values());
1349     Map<String, ServiceTemplate> serviceTemplatesMap = new HashMap<>();
1350
1351     for (ServiceTemplate template : serviceTemplates) {
1352       serviceTemplatesMap.put(ToscaUtil.getServiceTemplateFileName(template), template);
1353     }
1354     return serviceTemplatesMap;
1355   }
1356
1357 }