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