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