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