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