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