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