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