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