8c802bc43ec01e11f02583e8fa1900c7ab106680
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / tosca / ToscaExportHandler.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.openecomp.sdc.be.tosca;
21
22 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
23 import static org.apache.commons.collections.MapUtils.isNotEmpty;
24 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput;
25 import static org.openecomp.sdc.common.api.Constants.ADDITIONAL_TYPE_DEFINITIONS;
26 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
27 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
28 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
29
30 import com.fasterxml.jackson.databind.ObjectMapper;
31 import com.google.common.primitives.Ints;
32 import com.google.gson.JsonElement;
33 import com.google.gson.JsonObject;
34 import com.google.gson.JsonParser;
35 import com.google.gson.stream.JsonReader;
36 import fj.data.Either;
37
38 import java.io.StringReader;
39 import java.nio.file.Path;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.Collection;
43 import java.util.Collections;
44 import java.util.HashMap;
45 import java.util.HashSet;
46 import java.util.Iterator;
47 import java.util.LinkedHashMap;
48 import java.util.LinkedHashSet;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.Map.Entry;
52 import java.util.Objects;
53 import java.util.Optional;
54 import java.util.Set;
55 import java.util.function.Supplier;
56 import java.util.stream.Collectors;
57
58 import org.apache.commons.collections.CollectionUtils;
59 import org.apache.commons.collections.MapUtils;
60 import org.apache.commons.io.FilenameUtils;
61 import org.apache.commons.lang3.StringUtils;
62 import org.apache.commons.lang3.tuple.ImmutablePair;
63 import org.apache.commons.lang3.tuple.ImmutableTriple;
64 import org.apache.commons.lang3.tuple.Triple;
65 import org.onap.sdc.tosca.services.YamlUtil;
66 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
67 import org.openecomp.sdc.be.config.CategoryBaseTypeConfig;
68 import org.openecomp.sdc.be.config.Configuration;
69 import org.openecomp.sdc.be.config.ConfigurationManager;
70 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
71 import org.openecomp.sdc.be.data.model.ToscaImportByModel;
72 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
73 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
74 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
75 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
76 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
77 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
78 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition;
79 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition;
80 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
81 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
82 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition;
83 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
84 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
85 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
86 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
87 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
88 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
89 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
90 import org.openecomp.sdc.be.exception.ToscaExportException;
91 import org.openecomp.sdc.be.model.ArtifactDefinition;
92 import org.openecomp.sdc.be.model.AttributeDefinition;
93 import org.openecomp.sdc.be.model.CapabilityDefinition;
94 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
95 import org.openecomp.sdc.be.model.Component;
96 import org.openecomp.sdc.be.model.ComponentInstance;
97 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
98 import org.openecomp.sdc.be.model.ComponentInstanceInput;
99 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
100 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
101 import org.openecomp.sdc.be.model.ComponentParametersView;
102 import org.openecomp.sdc.be.model.DataTypeDefinition;
103 import org.openecomp.sdc.be.model.GroupInstance;
104 import org.openecomp.sdc.be.model.InputDefinition;
105 import org.openecomp.sdc.be.model.InterfaceDefinition;
106 import org.openecomp.sdc.be.model.PropertyDefinition;
107 import org.openecomp.sdc.be.model.RelationshipInfo;
108 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
109 import org.openecomp.sdc.be.model.RequirementDefinition;
110 import org.openecomp.sdc.be.model.Resource;
111 import org.openecomp.sdc.be.model.Service;
112 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
113 import org.openecomp.sdc.be.model.category.CategoryDefinition;
114 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
115 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
116 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
117 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
118 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
119 import org.openecomp.sdc.be.model.tosca.ToscaType;
120 import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
121 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
122 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
123 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
124 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
125 import org.openecomp.sdc.be.tosca.model.NodeFilter;
126 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
127 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
128 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
129 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
130 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
131 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
132 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
133 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
134 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
135 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
136 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraint;
137 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
138 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
139 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
140 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
141 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
142 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
143 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
144 import org.openecomp.sdc.be.tosca.utils.InputConverter;
145 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
146 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
147 import org.openecomp.sdc.common.log.wrappers.Logger;
148 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
149 import org.springframework.beans.factory.annotation.Autowired;
150 import org.yaml.snakeyaml.DumperOptions;
151 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
152 import org.yaml.snakeyaml.Yaml;
153 import org.yaml.snakeyaml.introspector.BeanAccess;
154 import org.yaml.snakeyaml.introspector.Property;
155 import org.yaml.snakeyaml.introspector.PropertyUtils;
156 import org.yaml.snakeyaml.nodes.MappingNode;
157 import org.yaml.snakeyaml.nodes.Node;
158 import org.yaml.snakeyaml.nodes.NodeTuple;
159 import org.yaml.snakeyaml.nodes.Tag;
160 import org.yaml.snakeyaml.representer.Represent;
161 import org.yaml.snakeyaml.representer.Representer;
162
163 @org.springframework.stereotype.Component("tosca-export-handler")
164 public class ToscaExportHandler {
165
166     public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
167     private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
168     private static final String INVARIANT_UUID = "invariantUUID";
169     private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
170     private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
171     private static final String IMPORTS_FILE_KEY = "file";
172     private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
173     private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
174     private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
175     private static final String NATIVE_ROOT = "tosca.nodes.Root";
176     private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
177             .of("Service Function", "Service Role", "Naming Policy", "Service Type");
178     private static final YamlUtil yamlUtil = new YamlUtil();
179     private final ApplicationDataTypeCache applicationDataTypeCache;
180     private final ToscaOperationFacade toscaOperationFacade;
181     private final CapabilityRequirementConverter capabilityRequirementConverter;
182     private final PolicyExportParser policyExportParser;
183     private final GroupExportParser groupExportParser;
184     private final PropertyConvertor propertyConvertor;
185     private final AttributeConverter attributeConverter;
186     private final InputConverter inputConverter;
187     private final OutputConverter outputConverter;
188     private final InterfaceLifecycleOperation interfaceLifecycleOperation;
189     private final InterfacesOperationsConverter interfacesOperationsConverter;
190     private final ModelOperation modelOperation;
191
192     @Autowired
193     public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
194                               final ToscaOperationFacade toscaOperationFacade,
195                               final CapabilityRequirementConverter capabilityRequirementConverter,
196                               final PolicyExportParser policyExportParser,
197                               final GroupExportParser groupExportParser,
198                               final PropertyConvertor propertyConvertor,
199                               final AttributeConverter attributeConverter,
200                               final InputConverter inputConverter,
201                               final OutputConverter outputConverter,
202                               final InterfaceLifecycleOperation interfaceLifecycleOperation,
203                               final InterfacesOperationsConverter interfacesOperationsConverter,
204                               final ModelOperation modelOperation) {
205         this.applicationDataTypeCache = applicationDataTypeCache;
206         this.toscaOperationFacade = toscaOperationFacade;
207         this.capabilityRequirementConverter = capabilityRequirementConverter;
208         this.policyExportParser = policyExportParser;
209         this.groupExportParser = groupExportParser;
210         this.propertyConvertor = propertyConvertor;
211         this.attributeConverter = attributeConverter;
212         this.inputConverter = inputConverter;
213         this.outputConverter = outputConverter;
214         this.interfaceLifecycleOperation = interfaceLifecycleOperation;
215         this.interfacesOperationsConverter = interfacesOperationsConverter;
216         this.modelOperation = modelOperation;
217     }
218
219     public static String getInterfaceFilename(String artifactName) {
220         return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
221     }
222
223     private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
224         if (MapUtils.isEmpty(proxyComponentInterfaces)) {
225             return;
226         }
227         proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
228                 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
229     }
230
231     public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
232         return convertToToscaTemplate(component, false).left().map(this::createToscaRepresentation);
233     }
234
235     public Either<ToscaRepresentation, ToscaError> exportComponent(Component component, Boolean isSkipImports) {
236         return convertToToscaTemplate(component, isSkipImports).left().map(this::createToscaRepresentation);
237     }
238
239     public Either<ToscaRepresentation, ToscaError> exportDataType(DataTypeDefinition dataTypeDefinition) {
240         return convertDataTypeToToscaTemplate(dataTypeDefinition).left().map(this::createToscaRepresentation);
241     }
242
243     public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
244         final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel(), false));
245         if (CollectionUtils.isEmpty(imports)) {
246             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
247             return Either.right(ToscaError.GENERAL_ERROR);
248         }
249         List<Triple<String, String, Component>> dependencies = new ArrayList<>();
250         if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
251                 .startsWith("org.openecomp.resource.abstract.nodes.")) {
252             final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
253                     .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
254                             component.getModel());
255             if (baseType.isLeft() && baseType.left().value() != null) {
256                 addDependencies(imports, dependencies, baseType.left().value(), false);
257             } else {
258                 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
259             }
260         }
261
262         String toscaVersion = null;
263         if (component instanceof Resource) {
264             toscaVersion = ((Resource) component).getToscaVersion();
265         }
266         ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
267         toscaTemplate.setImports(imports);
268         final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
269         final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
270                 isAssociatedComponent);
271         if (toscaTemplateRes.isRight()) {
272             return Either.right(toscaTemplateRes.right().value());
273         }
274         toscaTemplate = toscaTemplateRes.left().value();
275         toscaTemplate.setDependencies(dependencies);
276         ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
277         return Either.left(toscaRepresentation);
278     }
279
280     public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent,
281                                                                             final boolean isSkipImports) {
282         final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel(), isSkipImports));
283         if (CollectionUtils.isEmpty(imports)) {
284             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
285             return Either.right(ToscaError.GENERAL_ERROR);
286         }
287         List<Triple<String, String, Component>> dependencies = new ArrayList<>();
288         if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
289             .startsWith("org.openecomp.resource.abstract.nodes.")) {
290             final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
291                 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
292                     component.getModel());
293             if (baseType.isLeft() && baseType.left().value() != null) {
294                 addDependencies(imports, dependencies, baseType.left().value(), isSkipImports);
295             } else {
296                 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
297             }
298         }
299
300         String toscaVersion = null;
301         if (component instanceof Resource) {
302             toscaVersion = ((Resource) component).getToscaVersion();
303         }
304         ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
305         toscaTemplate.setImports(imports);
306         final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
307         final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
308             isAssociatedComponent);
309         if (toscaTemplateRes.isRight()) {
310             return Either.right(toscaTemplateRes.right().value());
311         }
312         toscaTemplate = toscaTemplateRes.left().value();
313         toscaTemplate.setDependencies(dependencies);
314         ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
315         return Either.left(toscaRepresentation);
316     }
317
318     private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
319         CustomRepresenter representer = new CustomRepresenter();
320         DumperOptions options = new DumperOptions();
321         options.setAllowReadOnlyProperties(false);
322         options.setPrettyFlow(true);
323         options.setDefaultFlowStyle(FlowStyle.FLOW);
324         options.setCanonical(false);
325         representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
326         representer.setPropertyUtils(new UnsortedPropertyUtils());
327
328         Yaml yaml = new Yaml(representer, options);
329         String yamlAsString = yaml.dumpAsMap(toscaTemplate);
330         String sb = getConfiguration().getHeatEnvArtifactHeader()
331                 + yamlAsString
332                 + getConfiguration().getHeatEnvArtifactFooter();
333         return ToscaRepresentation.make(sb.getBytes(), toscaTemplate);
334     }
335
336     public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
337         ToscaTemplate toscaTemplate = new ToscaTemplate(null);
338         Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate, false);
339         if (fillImports.isRight()) {
340             return Either.right(fillImports.right().value());
341         }
342         return Either.left(fillImports.left().value().left);
343     }
344
345     public Either<ToscaTemplate, ToscaError> getDependencies(Component component, boolean isSkipImports) {
346         ToscaTemplate toscaTemplate = new ToscaTemplate(null);
347         Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate, isSkipImports);
348         if (fillImports.isRight()) {
349             return Either.right(fillImports.right().value());
350         }
351         return Either.left(fillImports.left().value().left);
352     }
353
354     public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component, final boolean isSkipImports) {
355         final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel(), isSkipImports);
356         if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
357             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
358             return Either.right(ToscaError.GENERAL_ERROR);
359         }
360         log.trace("start tosca export for {}", component.getUniqueId());
361         String toscaVersion = null;
362         if (component instanceof Resource) {
363             toscaVersion = ((Resource) component).getToscaVersion();
364         }
365         final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
366         toscaTemplate.setMetadata(convertMetadata(component));
367         toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
368         final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
369         if (ModelConverter.isAtomicComponent(component)) {
370             log.trace("convert component as node type");
371             return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
372         } else {
373             log.trace("convert component as topology template");
374             return convertToscaTemplate(component, toscaTemplate, isSkipImports);
375         }
376     }
377
378     private Either<ToscaTemplate, ToscaError> convertDataTypeToToscaTemplate(final DataTypeDefinition dataTypeDefinition) {
379         final ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION);
380         return convertDataTypeTosca(dataTypeDefinition, toscaTemplate);
381     }
382
383     private Either<ToscaTemplate, ToscaError> convertDataTypeTosca(final DataTypeDefinition dataTypeDefinition, final ToscaTemplate toscaTemplate) {
384         final var dataTypesEither = applicationDataTypeCache.getAll(dataTypeDefinition.getModel());
385         if (dataTypesEither.isRight()) {
386             log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
387             return Either.right(ToscaError.GENERAL_ERROR);
388         }
389         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
390         if (!dataTypeDefinition.isEmpty()) {
391             Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
392             ToscaDataType toscaDataType = new ToscaDataType();
393             toscaDataType.setDerived_from(dataTypeDefinition.getDerivedFromName());
394             toscaDataType.setDescription(dataTypeDefinition.getDescription());
395             toscaDataType.setVersion(dataTypeDefinition.getVersion());
396             if (CollectionUtils.isNotEmpty(dataTypeDefinition.getProperties())) {
397                 toscaDataType.setProperties(dataTypeDefinition.getProperties().stream()
398                         .collect(Collectors.toMap(
399                                 PropertyDataDefinition::getName,
400                                 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
401                                 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty((List<DataTypeDefinition>) dataTypeDefinition,
402                                         toscaPropertyTobeValidated,
403                                         toscaProperty)
404                         )));
405             }
406             toscaDataTypeMap.put(dataTypeDefinition.getName(), toscaDataType);
407             toscaTemplate.setData_types(toscaDataTypeMap);
408         }
409         return Either.left(toscaTemplate);
410     }
411
412     private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId, final boolean isSkipImports) {
413         if (StringUtils.isEmpty(modelId)) {
414             return getDefaultToscaImportConfig();
415         }
416
417         final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
418         final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
419         final Set<Path> addedPathList = new HashSet<>();
420         for (final ToscaImportByModel toscaImportByModel : allModelImports) {
421             var importPath = Path.of(toscaImportByModel.getFullPath());
422             if (!(isSkipImports && importPath.toString().equals(ADDITIONAL_TYPE_DEFINITIONS))) {
423                 if (addedPathList.contains(importPath)) {
424                     importPath =
425                         ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
426                 }
427                 final String fileName = FilenameUtils.getBaseName(importPath.toString());
428                 importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
429                 addedPathList.add(importPath);
430             }
431         }
432         return importList;
433     }
434
435     private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode, boolean isSkipImports) {
436         Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode, isSkipImports);
437         if (importsRes.isRight()) {
438             return Either.right(importsRes.right().value());
439         }
440         toscaNode = importsRes.left().value().left;
441         Map<String, Component> componentCache = importsRes.left().value().right;
442         Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
443         if (nodeTypesMapEither.isRight()) {
444             log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
445             return Either.right(nodeTypesMapEither.right().value());
446         }
447         Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
448         if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
449             toscaNode.setNode_types(nodeTypesMap);
450         }
451         createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
452         Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
453         if (proxyInterfaceTypesEither.isRight()) {
454             log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
455             return Either.right(proxyInterfaceTypesEither.right().value());
456         }
457         Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
458         if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
459             toscaNode.setInterface_types(proxyInterfaceTypes);
460         }
461         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
462         if (dataTypesEither.isRight()) {
463             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
464             return Either.right(ToscaError.GENERAL_ERROR);
465         }
466         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
467         ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
468         List<InputDefinition> inputDef = component.getInputs();
469         Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
470         if (!inputs.isEmpty()) {
471             topologyTemplate.setInputs(inputs);
472         }
473         final Map<String, ToscaProperty> outputs;
474         try {
475             outputs = outputConverter.convert(component.getOutputs(), dataTypes);
476         } catch (final ToscaConversionException e) {
477             log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
478                     "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
479             return Either.right(ToscaError.GENERAL_ERROR);
480         }
481         if (!outputs.isEmpty()) {
482             topologyTemplate.setOutputs(outputs);
483         }
484         if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
485             final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
486                     convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
487             if (nodeTemplates.isRight()) {
488                 return Either.right(nodeTemplates.right().value());
489             }
490             log.debug("node templates converted");
491             topologyTemplate.setNode_templates(nodeTemplates.left().value());
492         }
493         final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
494                 .createFrom(topologyTemplate.getNode_templates());
495         if (!relationshipTemplatesMap.isEmpty()) {
496             topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
497         }
498         addGroupsToTopologyTemplate(component, topologyTemplate);
499         try {
500             addPoliciesToTopologyTemplate(component, topologyTemplate);
501         } catch (SdcResourceNotFoundException e) {
502             log.debug("Fail to add policies to topology template:", e);
503             return Either.right(ToscaError.GENERAL_ERROR);
504         }
505         try {
506             createSubstitutionMapping(component, componentCache).ifPresent(topologyTemplate::setSubstitution_mappings);
507         } catch (final ToscaExportException e) {
508             log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ToscaExportHandler.class.getName(), e.getMessage());
509             return Either.right(e.getToscaError());
510         }
511         if (!topologyTemplate.isEmpty()) {
512             toscaNode.setTopology_template(topologyTemplate);
513         }
514         return Either.left(toscaNode);
515     }
516
517     private Either<String, ToscaError> createComponentToscaName(final Component component) {
518         switch (component.getComponentType()) {
519             case RESOURCE:
520                 final ResourceMetadataDataDefinition resourceMetadata =
521                         (ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition();
522                 return Either.left(resourceMetadata.getToscaResourceName());
523             case SERVICE:
524                 return Either.left(SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName());
525             default:
526                 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
527                 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
528         }
529     }
530
531     private Optional<SubstitutionMapping> createSubstitutionMapping(final Component component,
532                                                                     final Map<String, Component> componentCache) throws ToscaExportException {
533         if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
534             return Optional.empty();
535         }
536
537         final Either<String, ToscaError> toscaResourceNameEither = createComponentToscaName(component);
538         if (toscaResourceNameEither.isRight()) {
539             throw new ToscaExportException("Could not create component TOSCA name", toscaResourceNameEither.right().value());
540         }
541         final String toscaResourceName = toscaResourceNameEither.left().value();
542
543         final SubstitutionMapping substitutionMapping = new SubstitutionMapping();
544         if (doNotExtendBaseType(component)) {
545             substitutionMapping.setNode_type(component.getDerivedFromGenericType());
546         } else {
547             substitutionMapping.setNode_type(toscaResourceName);
548         }
549         convertSubstitutionMappingFilter(component).ifPresent(substitutionMapping::setSubstitution_filter);
550
551         final Either<Map<String, String[]>, ToscaError> capabilitiesEither = convertSubstitutionMappingCapabilities(component, componentCache);
552         if (capabilitiesEither.isRight()) {
553             throw new ToscaExportException("Could not convert substitution mapping capabilities", capabilitiesEither.right().value());
554         }
555         final Map<String, String[]> capabilityMap = capabilitiesEither.left().value();
556         if (!capabilityMap.isEmpty()) {
557             substitutionMapping.setCapabilities(capabilityMap);
558         }
559         final Either<Map<String, String[]>, ToscaError> requirements =
560                 capabilityRequirementConverter.convertSubstitutionMappingRequirements(component, componentCache);
561         if (requirements.isRight()) {
562             throw new ToscaExportException("Could not convert substitution mapping requirements", requirements.right().value());
563         }
564         final Map<String, String[]> requirementMap = requirements.left().value();
565         if (MapUtils.isNotEmpty(requirementMap)) {
566             substitutionMapping.setRequirements(requirementMap);
567         }
568
569         final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
570         if (MapUtils.isNotEmpty(propertyMappingMap)) {
571             substitutionMapping.setProperties(propertyMappingMap);
572         }
573
574         final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
575         if (MapUtils.isNotEmpty(attributesMappingMap)) {
576             substitutionMapping.setAttributes(attributesMappingMap);
577         }
578
579         return Optional.of(substitutionMapping);
580     }
581
582     private boolean doNotExtendBaseType(final Component component) {
583         final Map<String, CategoryBaseTypeConfig> serviceNodeTypesConfig = ConfigurationManager.getConfigurationManager().getConfiguration()
584                 .getServiceBaseNodeTypes();
585         List<CategoryDefinition> categories = component.getCategories();
586         if (CollectionUtils.isNotEmpty(categories) && MapUtils.isNotEmpty(serviceNodeTypesConfig)
587                 && serviceNodeTypesConfig.get(categories.get(0).getName()) != null) {
588             return serviceNodeTypesConfig.get(categories.get(0).getName()).isDoNotExtendBaseType();
589         }
590         return false;
591     }
592
593     private Optional<NodeFilter> convertSubstitutionMappingFilter(final Component component) {
594         if (component.getSubstitutionFilter() == null || (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() == null) {
595             return Optional.empty();
596         }
597
598         return Optional.ofNullable(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
599     }
600
601     private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
602         Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
603         if (groups != null) {
604             topologyTemplate.addGroups(groups);
605         }
606     }
607
608     private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
609         Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
610         if (policies != null) {
611             topologyTemplate.addPolicies(policies);
612         }
613     }
614
615     private Map<String, Object> convertMetadata(Component component) {
616         return convertMetadata(component, false, null);
617     }
618
619     private Map<String, Object> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
620         Map<String, Object> toscaMetadata = new LinkedHashMap<>();
621         toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
622         toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
623         toscaMetadata
624                 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
625         toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
626         List<CategoryDefinition> categories = component.getCategories();
627         CategoryDefinition categoryDefinition = categories.get(0);
628         toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), component.getModel());
629         toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
630         if (isInstance) {
631             toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
632             toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
633             if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
634                 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
635                 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
636                 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
637                 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
638                 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
639                     toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
640                             componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
641                 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
642                     toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
643                             componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
644                 }
645                 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
646             }
647         }
648         switch (component.getComponentType()) {
649             case RESOURCE:
650                 Resource resource = (Resource) component;
651                 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
652                         || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
653                     toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
654                 } else {
655                     toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
656                 }
657                 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
658                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
659                 if (resource.getTenant() != null) {
660                     toscaMetadata.put(JsonPresentationFields.TENANT.getPresentation(), resource.getTenant());
661                 }
662                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
663                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
664                 toscaMetadata.put(resource.isTopologyTemplate() ? JsonPresentationFields.TEMPLATE_VERSION.getPresentation() : JsonPresentationFields.VERSION.getPresentation(), resource.getVersion());
665                 break;
666             case SERVICE:
667                 Service service = (Service) component;
668                 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
669                 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
670                 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
671                 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
672                 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
673                 toscaMetadata.put(JsonPresentationFields.TEMPLATE_VERSION.getPresentation(), service.getVersion());
674                 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
675                         service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
676                 if (!isInstance) {
677                     toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
678                     toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
679                 }
680                 break;
681             default:
682                 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
683         }
684         for (final String key : component.getCategorySpecificMetadata().keySet()) {
685             if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
686                 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
687             }
688         }
689         return toscaMetadata;
690     }
691
692     private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
693         if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
694             return INVARIANT_UUID;
695         }
696         return jsonPresentationField.getPresentation();
697     }
698
699     private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate, boolean isSkipImports) {
700         final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel(), isSkipImports);
701         if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
702             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
703             return Either.right(ToscaError.GENERAL_ERROR);
704         }
705         Map<String, Component> componentCache = new HashMap<>();
706         if (!ModelConverter.isAtomicComponent(component)) {
707             final List<Map<String, Map<String, String>>> additionalImports =
708                     toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
709             List<Triple<String, String, Component>> dependencies = new ArrayList<>();
710             Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
711             final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
712             if (!substituteTypeImportEntry.isEmpty()) {
713                 additionalImports.add(substituteTypeImportEntry);
714             }
715             List<ComponentInstance> componentInstances = component.getComponentInstances();
716             if (componentInstances != null && !componentInstances.isEmpty()) {
717                 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci, isSkipImports));
718             }
719             toscaTemplate.setDependencies(dependencies);
720             toscaTemplate.setImports(additionalImports);
721         } else {
722             log.debug("currently imports supported for VF and service only");
723         }
724         return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
725     }
726
727     private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
728                                                                                    final Map<String, ArtifactDefinition> toscaArtifacts) {
729         if (doNotExtendBaseType(component)) {
730             return Collections.emptyMap();
731         }
732         if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
733             return Collections.emptyMap();
734         }
735         if (MapUtils.isEmpty(toscaArtifacts)) {
736             return Collections.emptyMap();
737         }
738         final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
739         if (artifactDefinition == null) {
740             return Collections.emptyMap();
741         }
742         final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
743         return Map.of(importEntryName,
744                 Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
745         );
746     }
747
748     private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
749         return getConfiguration().getDefaultImports();
750     }
751
752     private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
753                                   final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance,
754                                   final boolean isSkipImports) {
755         log.debug("createDependency componentCache {}", componentCache);
756         Component componentRI = componentCache.get(componentInstance.getComponentUid());
757         if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
758             // all resource must be only once!
759             final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
760             if ((resource.isRight()) && (log.isDebugEnabled())) {
761                 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
762                         componentInstance.getUniqueId());
763                 return;
764             }
765             final Component fetchedComponent = resource.left().value();
766             componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
767             addDependencies(imports, dependencies, componentRI, isSkipImports);
768         }
769     }
770
771     /**
772      * Sets a componentCache from the given component/resource.
773      */
774     private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
775                                         final Component fetchedComponent) {
776         componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
777         if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
778                 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
779             final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
780                     .getToscaFullElement(componentInstance.getSourceModelUid());
781             if (sourceService.isRight() && (log.isDebugEnabled())) {
782                 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
783                         componentInstance.getUniqueId());
784             }
785             final Component fetchedSource = sourceService.left().value();
786             componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
787             return fetchedSource;
788         }
789         return fetchedComponent;
790     }
791
792     /**
793      * Retrieves all derived_from nodes and stores it in a predictable order.
794      */
795     private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
796                                  final Component fetchedComponent, final boolean isSkipImports) {
797         final Set<Component> componentsList = new LinkedHashSet<>();
798         if (fetchedComponent instanceof Resource && !isSkipImports) {
799             log.debug("fetchedComponent is a resource {}", fetchedComponent);
800             final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
801             if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
802                 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
803                     log.debug("Started entry.getValue() : {}", entry.getValue());
804                     if (!NATIVE_ROOT.equals(entry.getValue())) {
805                         Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
806                         if (resourcefetched != null && resourcefetched.isLeft()) {
807                             componentsList.add(resourcefetched.left().value());
808                         }
809                     }
810                 });
811                 setImports(imports, dependencies, componentsList);
812             } else {
813                 setImports(imports, dependencies, fetchedComponent);
814             }
815         }
816     }
817
818     /**
819      * Returns all derived_from nodes found.
820      */
821     private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
822         final Resource parentResource = (Resource) fetchedComponent;
823         Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
824         if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
825             componentsList.add(fetchedComponent);
826             for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
827                 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
828                         .getToscaElement(componentInstance.getComponentUid());
829                 if (resourcefetched != null && resourcefetched.isLeft()) {
830                     final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
831                     if (MapUtils.isNotEmpty(derivedWithId)) {
832                         derivedFromMapOfIdToName.putAll(derivedWithId);
833                     }
834                 }
835             }
836         } else {
837             derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
838         }
839         log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
840         return Optional.ofNullable(derivedFromMapOfIdToName);
841     }
842
843     /**
844      * Creates a resource map and adds it to the import list.
845      */
846     private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
847                             final Set<Component> componentsList) {
848         componentsList.forEach(component ->  setImports(imports, dependencies, component));
849     }
850
851     private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
852                             final Component component) {
853         final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
854         final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
855         if (artifactDefinition != null) {
856             final Map<String, String> files = new HashMap<>();
857             final String artifactName = artifactDefinition.getArtifactName();
858             files.put(IMPORTS_FILE_KEY, artifactName);
859             final StringBuilder keyNameBuilder = new StringBuilder();
860             keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
861             keyNameBuilder.append("-");
862             keyNameBuilder.append(component.getName());
863             addImports(imports, keyNameBuilder, files);
864             dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
865             if (!ModelConverter.isAtomicComponent(component)) {
866                 final Map<String, String> interfaceFiles = new HashMap<>();
867                 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
868                 keyNameBuilder.append("-interface");
869                 addImports(imports, keyNameBuilder, interfaceFiles);
870             }
871         }
872     }
873
874     /**
875      * Adds the found resource to the import definition list.
876      */
877     private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
878                             final Map<String, String> files) {
879         final String mapKey = keyNameBuilder.toString();
880         if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
881             final Map<String, Map<String, String>> importsListMember = new HashMap<>();
882             importsListMember.put(keyNameBuilder.toString(), files);
883             imports.add(importsListMember);
884         }
885     }
886
887     private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
888                                                               Map<String, ToscaNodeType> nodeTypes) {
889         return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
890     }
891
892     public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
893                                                                       ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
894                                                                       boolean isAssociatedComponent) {
895         log.debug("start convert node type for {}", component.getUniqueId());
896         ToscaNodeType toscaNodeType = createNodeType(component);
897         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
898                 .getAllInterfaceLifecycleTypes(component.getModel());
899         if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
900             log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
901             return Either.right(ToscaError.GENERAL_ERROR);
902         }
903         if (lifecycleTypeEither.isLeft()) {
904             List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
905                     .collect(Collectors.toList());
906             toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
907         }
908         final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
909         if (dataTypesEither.isRight()) {
910             log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
911             return Either.right(ToscaError.GENERAL_ERROR);
912         }
913         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
914         interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
915         final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
916         if (!toscaAttributeMap.isEmpty()) {
917             toscaNodeType.setAttributes(toscaAttributeMap);
918         }
919         Map<String, ToscaProperty> convertedProperties = new HashMap();
920         if (CollectionUtils.isNotEmpty(component.getProperties())) {
921             List<PropertyDefinition> properties = component.getProperties();
922             convertedProperties = properties.stream()
923                     .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
924                             .toMap(PropertyDataDefinition::getName,
925                                     property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
926         }
927         if (MapUtils.isNotEmpty(convertedProperties)) {
928             toscaNodeType.setProperties(convertedProperties);
929         }
930         /* convert private data_types */
931         List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
932         if (CollectionUtils.isNotEmpty(privateDataTypes)) {
933             Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
934             for (DataTypeDefinition dataType : privateDataTypes) {
935                 log.debug("Emitting private data type: component.name={} dataType.name={}",
936                         component.getNormalizedName(), dataType.getName());
937                 ToscaDataType toscaDataType = new ToscaDataType();
938                 toscaDataType.setDerived_from(dataType.getDerivedFromName());
939                 toscaDataType.setDescription(dataType.getDescription());
940                 toscaDataType.setVersion(dataType.getVersion());
941                 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
942                     toscaDataType.setProperties(dataType.getProperties().stream()
943                             .collect(Collectors.toMap(
944                                     PropertyDataDefinition::getName,
945                                     s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
946                                     (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
947                                             toscaProperty)
948                             )));
949                 }
950                 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
951             }
952             toscaNode.setData_types(toscaDataTypeMap);
953         }
954
955         // Extracted to method for code reuse
956         return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
957     }
958
959     private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
960                                                 final ToscaProperty toscaProperty) {
961         final Optional<DataTypeDefinition> match = privateDataTypes.stream()
962                 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
963         return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
964     }
965
966     private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
967                                                                  final Map<String, DataTypeDefinition> dataTypes) {
968         if (CollectionUtils.isEmpty(attributeList)) {
969             return Collections.emptyMap();
970         }
971         final AttributeConverter converter = new AttributeConverter(dataTypes);
972         final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
973         for (final AttributeDefinition attributeDefinition : attributeList) {
974             toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
975         }
976         return toscaAttributeMap;
977     }
978
979     private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
980                                                                        Component component, ToscaTemplate toscaNode,
981                                                                        Map<String, ToscaNodeType> nodeTypes,
982                                                                        ToscaNodeType toscaNodeType,
983                                                                        Map<String, DataTypeDefinition> dataTypes) {
984         Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
985                 dataTypes);
986         if (capabilities.isRight()) {
987             return Either.right(capabilities.right().value());
988         }
989         toscaNodeType = capabilities.left().value();
990         log.debug("Capabilities converted for {}", component.getUniqueId());
991
992         Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
993                 .convertRequirements(componentsCache, component, toscaNodeType);
994         if (requirements.isRight()) {
995             return Either.right(requirements.right().value());
996         }
997         toscaNodeType = requirements.left().value();
998         log.debug("Requirements converted for {}", component.getUniqueId());
999
1000         String toscaResourceName;
1001         switch (component.getComponentType()) {
1002             case RESOURCE:
1003                 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
1004                         .getMetadataDataDefinition()).getToscaResourceName();
1005                 break;
1006             case SERVICE:
1007                 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
1008                         + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
1009                 break;
1010             default:
1011                 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
1012                 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1013         }
1014
1015         nodeTypes.put(toscaResourceName, toscaNodeType);
1016         toscaNode.setNode_types(nodeTypes);
1017         log.debug("finish convert node type for {}", component.getUniqueId());
1018         return Either.left(toscaNode);
1019     }
1020
1021     private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
1022                                                                                     final Map<String, Component> componentCache,
1023                                                                                     final Map<String, DataTypeDefinition> dataTypes,
1024                                                                                     final ToscaTopolgyTemplate topologyTemplate) {
1025
1026         final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
1027         final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
1028         final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
1029         final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
1030         final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
1031
1032         Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
1033         log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1034         final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
1035
1036         Map<String, ToscaGroupTemplate> groupsMap = null;
1037         for (final ComponentInstance componentInstance : component.getComponentInstances()) {
1038             ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
1039             if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
1040                 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
1041             }
1042             if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
1043                 List<Object> occur = new ArrayList<>();
1044                 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
1045                 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
1046                 nodeTemplate.setOccurrences(occur);
1047             }
1048             if (componentInstance.getInstanceCount() != null) {
1049                 ObjectMapper objectMapper = new ObjectMapper();
1050                 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
1051                 if (obj != null) {
1052                     Map<String, String> map = objectMapper.convertValue(obj, Map.class);
1053                     nodeTemplate.setInstance_count(map);
1054                 }
1055             }
1056             nodeTemplate.setType(componentInstance.getToscaComponentName());
1057             nodeTemplate.setDirectives(componentInstance.getDirectives());
1058             NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
1059             if (nodeFilter != null && nodeFilter.hasData()) {
1060                 nodeTemplate.setNode_filter(nodeFilter);
1061             }
1062             final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
1063                     .getOriginComponent(componentCache, componentInstance);
1064             if (originComponentRes.isRight()) {
1065                 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1066                 break;
1067             }
1068             final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
1069                     componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
1070             if (requirements.isRight()) {
1071                 convertNodeTemplatesRes = Either.right(requirements.right().value());
1072                 break;
1073             }
1074             final String instanceUniqueId = componentInstance.getUniqueId();
1075             log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1076
1077             nodeTemplate = requirements.left().value();
1078
1079             final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1080
1081             if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1082                 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1083                 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1084             } else {
1085                 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1086             }
1087
1088             final Either<ToscaNodeTemplate, ToscaError> capabilities =
1089                     capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1090             if (capabilities.isRight()) {
1091                 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1092                 break;
1093             }
1094             log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1095
1096             nodeTemplate = capabilities.left().value();
1097             final Map<String, Object> props = new HashMap<>();
1098             final Map<String, Object> attribs = new HashMap<>();
1099
1100             if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1101                 // Adds the properties of parent component to map
1102                 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1103                 addAttributesOfParentComponent(originalComponent, attribs);
1104             }
1105
1106             if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1107                 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1108             }
1109             if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1110                 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1111             }
1112
1113             if (componentInstancesInputs != null
1114                     && componentInstancesInputs.containsKey(instanceUniqueId)
1115                     && !isComponentOfTypeServiceProxy(componentInstance)) {
1116                 //For service proxy the inputs are already handled under instance properties above
1117                 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1118             }
1119
1120             //M3[00001] - NODE TEMPLATE INTERFACES  - START
1121             handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1122             //M3[00001] - NODE TEMPLATE INTERFACES  - END
1123             if (MapUtils.isNotEmpty(props)) {
1124                 nodeTemplate.setProperties(props);
1125             }
1126             if (MapUtils.isNotEmpty(attribs)) {
1127                 nodeTemplate.setAttributes(attribs);
1128             }
1129
1130             final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1131             if (CollectionUtils.isNotEmpty(groupInstances)) {
1132                 if (groupsMap == null) {
1133                     groupsMap = new HashMap<>();
1134                 }
1135                 for (final GroupInstance groupInst : groupInstances) {
1136                     if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1137                         groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1138                     }
1139                 }
1140             }
1141
1142             nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1143         }
1144         if (groupsMap != null) {
1145             log.debug("instance groups added");
1146             topologyTemplate.addGroups(groupsMap);
1147         }
1148         if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1149                 ((Service) component).getForwardingPaths())) {
1150             log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1151             ForwardingPathToscaUtil
1152                     .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1153             log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1154         }
1155         if (convertNodeTemplatesRes == null) {
1156             convertNodeTemplatesRes = Either.left(nodeTemplates);
1157         }
1158         log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1159         return convertNodeTemplatesRes;
1160     }
1161
1162     private Object convertToToscaObject(String value) {
1163         try {
1164             ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1165             StringReader reader = new StringReader(value);
1166             JsonReader jsonReader = new JsonReader(reader);
1167             jsonReader.setLenient(true);
1168             JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1169             if (jsonElement.isJsonObject()) {
1170                 JsonObject jsonObj = jsonElement.getAsJsonObject();
1171                 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1172                     return mapConverterInst.handleComplexJsonValue(jsonElement);
1173                 }
1174             }
1175             return null;
1176         } catch (Exception e) {
1177             log.debug("convertToToscaValue failed to parse json value :", e);
1178             return null;
1179         }
1180     }
1181
1182     private Object parseToIntIfPossible(final String value) {
1183         final Integer intValue = Ints.tryParse(value);
1184         return intValue == null ? value : intValue;
1185     }
1186
1187     private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1188                                           ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1189                                           ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1190
1191         if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1192             nodeTemplate.setInterfaces(null);
1193             return;
1194         }
1195
1196         final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1197
1198         final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1199         currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1200
1201         final Map<String, Object> interfaceMap = interfacesOperationsConverter
1202                 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1203
1204         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1205         nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1206     }
1207
1208     private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1209         return Objects.nonNull(componentInstance.getOriginType())
1210                 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1211     }
1212
1213     private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1214                                             Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1215                                             String instanceUniqueId, Map<String, Object> props) {
1216
1217         List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1218         if (instanceInputsList != null) {
1219             instanceInputsList.forEach(input -> {
1220                 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1221                         : input.getDefaultValue();
1222                 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1223             });
1224         }
1225     }
1226
1227     private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1228                                                   final Map<String, DataTypeDefinition> dataTypes,
1229                                                   final String instanceUniqueId,
1230                                                   final Map<String, Object> props) {
1231
1232         if (isNotEmpty(componentInstancesProperties)) {
1233             componentInstancesProperties.get(instanceUniqueId)
1234                     // Converts and adds each value to property map
1235                     .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1236         }
1237     }
1238
1239     private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1240                                                   final String instanceUniqueId,
1241                                                   final Map<String, Object> attribs) {
1242
1243         if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1244             componentInstancesAttributes.get(instanceUniqueId)
1245                     .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1246         }
1247     }
1248
1249     private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1250                                                 Component componentOfInstance, Map<String, Object> props) {
1251
1252         List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1253         if (isNotEmpty(componentProperties)) {
1254             componentProperties.stream()
1255                     // Filters out properties with empty default values
1256                     .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1257                     // Converts and adds each value to property map
1258                     .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1259         }
1260     }
1261
1262     private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1263
1264         final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1265         if (isNotEmpty(componentAttributes)) {
1266             componentAttributes.stream()
1267                     // Filters out Attributes with empty default values
1268                     .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1269                     // Converts and adds each value to attribute map
1270                     .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1271         }
1272     }
1273
1274     private ToscaNodeType createNodeType(Component component) {
1275         ToscaNodeType toscaNodeType = new ToscaNodeType();
1276         if (ModelConverter.isAtomicComponent(component)) {
1277             if (((Resource) component).getDerivedFrom() != null) {
1278                 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1279             }
1280             toscaNodeType.setDescription(component.getDescription());
1281         } else {
1282             String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1283                     : NATIVE_ROOT;
1284             toscaNodeType.setDerived_from(derivedFrom);
1285         }
1286         return toscaNodeType;
1287     }
1288
1289     private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1290
1291         Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1292         Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1293         List<ComponentInstance> componentInstances = container.getComponentInstances();
1294         if (CollectionUtils.isEmpty(componentInstances)) {
1295             return res;
1296         }
1297         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1298         componentInstances.stream()
1299                 .filter(this::isComponentOfTypeServiceProxy)
1300                 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1301         if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1302             return res;
1303         }
1304         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1305             Component serviceComponent;
1306             ComponentParametersView componentParametersView = new ComponentParametersView();
1307             componentParametersView.disableAll();
1308             componentParametersView.setIgnoreInterfaces(false);
1309             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1310                     .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1311             if (service.isRight()) {
1312                 log.debug("Failed to fetch original service component with id {} for instance {}",
1313                         entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1314                 return Either.right(ToscaError.GENERAL_ERROR);
1315             } else {
1316                 serviceComponent = service.left().value();
1317             }
1318
1319             Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1320                     interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1321             if (lifecycleTypeEither.isRight()) {
1322                 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1323                 return Either.right(ToscaError.GENERAL_ERROR);
1324             }
1325
1326             List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1327                     .map(InterfaceDataDefinition::getType)
1328                     .collect(Collectors.toList());
1329             //Add interface types for local interfaces in the original service component for proxy
1330             Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1331                     allGlobalInterfaceTypes);
1332             if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1333                 proxyInterfaceTypes.putAll(localInterfaceTypes);
1334             }
1335
1336         }
1337         return Either.left(proxyInterfaceTypes);
1338     }
1339
1340     private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1341                                                                                 Component container) {
1342
1343         Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1344         Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1345
1346         List<ComponentInstance> componentInstances = container.getComponentInstances();
1347
1348         if (componentInstances == null || componentInstances.isEmpty()) {
1349             return res;
1350         }
1351         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1352         List<ComponentInstance> proxyInst = componentInstances.stream()
1353                 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1354                 .collect(Collectors.toList());
1355         if (proxyInst != null && !proxyInst.isEmpty()) {
1356             for (ComponentInstance inst : proxyInst) {
1357                 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1358             }
1359         }
1360
1361         if (serviceProxyInstanceList.isEmpty()) {
1362             return res;
1363         }
1364         Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1365                 .getLatestByName("serviceProxy", null);
1366         if (serviceProxyOrigin.isRight()) {
1367             log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1368                     serviceProxyOrigin.right().value());
1369             return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1370         }
1371         Component origComponent = serviceProxyOrigin.left().value();
1372
1373         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1374             Component serviceComponent = null;
1375             ComponentParametersView componentParametersView = new ComponentParametersView();
1376             componentParametersView.disableAll();
1377             componentParametersView.setIgnoreCategories(false);
1378             componentParametersView.setIgnoreProperties(false);
1379             componentParametersView.setIgnoreInputs(false);
1380             componentParametersView.setIgnoreInterfaces(false);
1381             componentParametersView.setIgnoreRequirements(false);
1382             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1383                     .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1384             if (service.isRight()) {
1385                 log.debug("Failed to fetch resource with id {} for instance {}",
1386                         entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1387             } else {
1388                 serviceComponent = service.left().value();
1389             }
1390
1391             ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1392                     entryProxy.getValue());
1393             nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1394         }
1395
1396         return Either.left(nodeTypesMap);
1397     }
1398
1399     private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1400                                                     final Component container, final ToscaTemplate toscaNode) {
1401         final List<ComponentInstance> componentInstances = container.getComponentInstances();
1402
1403         if (CollectionUtils.isEmpty(componentInstances)) {
1404             return;
1405         }
1406         final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1407                 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1408                 .collect(Collectors.toList());
1409         if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1410             for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1411                 final Map<String, ToscaNodeType> nodeTypes =
1412                         toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1413                 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1414                         nodeTypes, true);
1415             }
1416         }
1417     }
1418
1419     private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1420                                               Component proxyComponent, ComponentInstance componentInstance) {
1421         ToscaNodeType toscaNodeType = new ToscaNodeType();
1422         String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1423
1424         toscaNodeType.setDerived_from(derivedFrom);
1425         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1426                 origComponent.getModel());
1427         if (dataTypesEither.isRight()) {
1428             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1429         }
1430         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1431         Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1432                 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1433
1434         if (MapUtils.isNotEmpty(capabilities)) {
1435             toscaNodeType.setCapabilities(capabilities);
1436         }
1437         List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1438                 .convertProxyRequirements(componentCache, componentInstance);
1439         if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1440             toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1441         }
1442         Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1443         proxyProperties.ifPresent(toscaNodeType::setProperties);
1444
1445         Map<String, Object> interfaceMap = new HashMap<>();
1446         if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1447             final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1448             if (proxyInterfaces.isPresent()) {
1449                 interfaceMap = proxyInterfaces.get();
1450             }
1451         } else {
1452             interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1453
1454         }
1455         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1456         toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1457
1458         return toscaNodeType;
1459     }
1460
1461     private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1462                                                                                        ComponentInstance componentInstance,
1463                                                                                        List<RequirementCapabilityRelDef> relations,
1464                                                                                        ToscaNodeTemplate nodeTypeTemplate,
1465                                                                                        Component originComponent,
1466                                                                                        Map<String, Component> componentCache) {
1467
1468         final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1469                 relations);
1470         if (isNotEmpty(requirementDefinitionList)) {
1471             try {
1472                 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1473                         requirementDefinitionList, originComponent, componentCache);
1474                 if (CollectionUtils.isNotEmpty(toscaRequirements)) {
1475                     nodeTypeTemplate.setRequirements(toscaRequirements);
1476                 }
1477             } catch (final Exception e) {
1478                 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1479                         componentInstance.getName(), e);
1480                 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1481             }
1482         }
1483         log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1484         return Either.left(nodeTypeTemplate);
1485     }
1486
1487     private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1488                                                                           final ComponentInstance componentInstance,
1489                                                                           final List<RequirementCapabilityRelDef> filteredRelations,
1490                                                                           final Component originComponent,
1491                                                                           final Map<String, Component> componentCache)
1492             throws ToscaExportException {
1493
1494         final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1495         for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1496             final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1497                     buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1498             if (MapUtils.isNotEmpty(toscaTemplateRequirementMap)) {
1499                 toscaRequirements.add(toscaTemplateRequirementMap);
1500             }
1501         }
1502
1503         return toscaRequirements;
1504     }
1505
1506     private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1507                                                                  List<RequirementCapabilityRelDef> relations) {
1508         return relations.stream()
1509                 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1510     }
1511
1512     private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1513                                                                    final Component fromOriginComponent,
1514                                                                    final List<ComponentInstance> instancesList,
1515                                                                    final RequirementCapabilityRelDef relationshipDefinition,
1516                                                                    final Map<String, Component> componentCache)
1517             throws ToscaExportException {
1518
1519         final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1520         if (MapUtils.isEmpty(reqMap)) {
1521             return new HashMap<>();
1522         }
1523         final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition.getRelationships().get(0);
1524         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1525
1526         final ComponentInstance toInstance = instancesList.stream().filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1527                 .findFirst().orElse(null);
1528         if (toInstance == null) {
1529             final String errorMsg = String
1530                     .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1531                             relationshipDefinition.getToNode());
1532             log.debug(errorMsg);
1533             throw new ToscaExportException(errorMsg);
1534         }
1535         final Optional<RequirementDefinition> reqOpt = findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1536         if (reqOpt.isEmpty()) {
1537             final String errorMsg = String.format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1538                     relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1539             log.debug(errorMsg);
1540             throw new ToscaExportException(errorMsg);
1541         }
1542         final ComponentParametersView filter = new ComponentParametersView(true);
1543         filter.setIgnoreComponentInstances(false);
1544         filter.setIgnoreCapabilities(false);
1545         filter.setIgnoreGroups(false);
1546         final Either<Component, StorageOperationStatus> getOriginRes =
1547                 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1548         if (getOriginRes.isRight()) {
1549             final String errorMsg = String.format(
1550                     "Failed to build substituted name for the requirement %s. Failed to get an origin component with uniqueId %s",
1551                     reqOpt.get().getName(), toInstance.getActualComponentUid());
1552             log.debug(errorMsg);
1553             throw new ToscaExportException(errorMsg);
1554         }
1555         final Component toOriginComponent = getOriginRes.left().value();
1556         Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1557                 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1558         if (capOpt.isEmpty()) {
1559             capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1560             if (capOpt.isEmpty()) {
1561                 final String errorMsg = String.format("Failed to find a capability with name %s on a component with uniqueId %s",
1562                         relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1563                 log.debug(errorMsg);
1564                 throw new ToscaExportException(errorMsg);
1565             }
1566         }
1567         return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1568                 capabilityRequirementRelationship, toInstance, componentCache);
1569     }
1570
1571     private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1572                                                  CapabilityDefinition capability) {
1573         return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1574                 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1575     }
1576
1577     private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1578                                                           Component toOriginComponent, Component fromOriginComponent,
1579                                                           RequirementDefinition requirement) {
1580         Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1581                 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1582         if (cap.isEmpty()) {
1583             log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1584                     reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1585         }
1586         return cap;
1587     }
1588
1589     private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1590                                                                    final Component toOriginComponent,
1591                                                                    final CapabilityDefinition capability,
1592                                                                    final RequirementDefinition requirement,
1593                                                                    final CapabilityRequirementRelationship capabilityRequirementRelationship,
1594                                                                    final ComponentInstance toInstance,
1595                                                                    final Map<String, Component> componentCache)
1596             throws ToscaExportException {
1597
1598         List<String> reducedPath = capability.getPath();
1599         if (capability.getOwnerId() != null) {
1600             reducedPath = capabilityRequirementConverter
1601                     .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1602         }
1603         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1604         final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1605                 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1606         if (capabilityNameEither.isRight()) {
1607             final String errorMsg = String.format(
1608                     "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1609                     capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1610             log.debug(
1611                     errorMsg);
1612             throw new ToscaExportException(errorMsg);
1613         }
1614         final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1615                 .buildSubstitutedName(componentCache, fromOriginComponent,
1616                         requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1617         if (requirementNameEither.isRight()) {
1618             final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1619                             + "with name %s on a component with uniqueId %s",
1620                     capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1621             log.debug(errorMsg);
1622             throw new ToscaExportException(errorMsg);
1623         }
1624         final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1625         final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1626         toscaRequirement.setNode(toInstance.getName());
1627         toscaRequirement.setCapability(capabilityNameEither.left().value());
1628         if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1629             toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1630         }
1631         toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1632         return toscaReqMap;
1633     }
1634
1635     private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1636                                                             Map<String, List<RequirementDefinition>> reqMap,
1637                                                             RelationshipInfo reqAndRelationshipPair,
1638                                                             String fromInstanceId) {
1639         for (final List<RequirementDefinition> reqList : reqMap.values()) {
1640             final Optional<RequirementDefinition> reqOpt = reqList.stream()
1641                     .filter(r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId)).findFirst();
1642             if (reqOpt.isPresent()) {
1643                 return reqOpt;
1644             }
1645         }
1646         return Optional.empty();
1647     }
1648
1649     /**
1650      * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1651      * 1.The name of the requirement equals to the "requirement" field of the relation; AND 2. In case of a non-atomic resource, OwnerId of the
1652      * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1653      */
1654     private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1655                                                   RequirementDefinition requirement, String fromInstanceId) {
1656         if (originComponent.isService() && requirement.getUniqueId().equals(reqAndRelationshipPair.getRequirementUid())) {
1657             return true;
1658         }
1659         if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1660             log.debug("Failed to find a requirement with name {} and  reqAndRelationshipPair {}", requirement.getName(),
1661                     reqAndRelationshipPair.getRequirement());
1662             return false;
1663         }
1664         return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1665                 originComponent);
1666     }
1667
1668     private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1669                                                Component originComponent) {
1670         return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1671                 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1672                         .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1673     }
1674
1675     private boolean isCvfc(Component component) {
1676         return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1677     }
1678
1679     private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1680                                                                                              final Map<String, Component> componentCache) {
1681         Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1682                 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1683         if (toscaCapabilitiesRes.isRight()) {
1684             log.debug("Failed convert capabilities for the component {}. ", component.getName());
1685             return Either.right(toscaCapabilitiesRes.right().value());
1686         }
1687         if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1688             log.debug("Finish convert capabilities for the component {}. ", component.getName());
1689             return Either.left(toscaCapabilitiesRes.left().value());
1690         }
1691         log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1692
1693         return Either.left(Collections.emptyMap());
1694     }
1695
1696     private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1697                                                                   Map<String, DataTypeDefinition> dataTypes) {
1698         Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1699         if (!toscaCapabilities.isEmpty()) {
1700             nodeType.setCapabilities(toscaCapabilities);
1701         }
1702         log.debug("Finish convert Capabilities for node type");
1703         return Either.left(nodeType);
1704     }
1705
1706     private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1707         if (artifacts == null) {
1708             return null;
1709         }
1710         Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1711         for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1712             ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1713             artifact.setFile(entry.getValue().getFile());
1714             artifact.setType(entry.getValue().getType());
1715             artifact.setProperties(entry.getValue().getProperties());
1716             arts.put(entry.getKey(), artifact);
1717         }
1718         return arts;
1719     }
1720
1721     private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1722         if (inNodeFilter == null) {
1723             return null;
1724         }
1725         NodeFilter nodeFilter = new NodeFilter();
1726         ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1727         ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1728         List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1729         copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1730         if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1731             nodeFilter.setCapabilities(capabilitiesCopy);
1732         }
1733         final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1734         if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1735             nodeFilter.setProperties(propertiesCopy);
1736         }
1737         nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1738         return cloneObjectFromYml(nodeFilter, NodeFilter.class);
1739     }
1740
1741     private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1742         if (substitutionFilterDataDefinition == null) {
1743             return null;
1744         }
1745         NodeFilter nodeFilter = new NodeFilter();
1746         final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1747         if (!propertiesCopy.isEmpty()) {
1748             nodeFilter.setProperties(propertiesCopy);
1749         }
1750         nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1751         return cloneObjectFromYml(nodeFilter, NodeFilter.class);
1752     }
1753
1754     private Object cloneToscaId(Object toscaId) {
1755         return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1756     }
1757
1758     private <T> T cloneObjectFromYml(Object objToClone, Class<T> classOfObj) {
1759         String objectAsYml = yamlUtil.objectToYaml(objToClone);
1760         return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1761     }
1762
1763     private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1764                                                     List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1765         if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1766                 .isEmpty()) {
1767             return;
1768         }
1769         for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1770             Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1771             final var capabilityFilter = new CapabilityFilter();
1772             capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1773             capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1774             capabilitiesCopy.add(capabilityFilterCopyMap);
1775         }
1776     }
1777
1778     private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1779         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1780             return Collections.emptyList();
1781         }
1782         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1783         Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1784         for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1785             final String propertyName = propertyFilter.getName();
1786             for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1787                 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1788                     if (constraints == null) {
1789                         constraints = new ArrayList<>();
1790                     }
1791                     constraints.add(buildNodeFilterValue(filterConstraint));
1792                     return constraints;
1793                 });
1794             }
1795         }
1796         propertyFilterDefinitionMap.entrySet().stream()
1797                 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1798                 .forEach(propertiesCopy::add);
1799         return propertiesCopy;
1800     }
1801
1802     private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1803             final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1804
1805         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1806             return Collections.emptyList();
1807         }
1808         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1809         Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1810         for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1811             final String propertyName = propertyFilter.getName();
1812             for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1813                 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1814                     if (constraints == null) {
1815                         constraints = new ArrayList<>();
1816                     }
1817                     constraints.add(buildNodeFilterValue(filterConstraint));
1818                     return constraints;
1819                 });
1820             }
1821         }
1822         propertyFilterDefinitionMap.entrySet().stream()
1823                 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1824                 .forEach(propertiesCopy::add);
1825         return propertiesCopy;
1826     }
1827
1828     private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1829         if (filterConstraint.getValue() instanceof ToscaFunction) {
1830             return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1831         }
1832         if (filterConstraint.getValue() instanceof List) {
1833             if (((List<?>) filterConstraint.getValue()).get(0) instanceof ToscaFunction) {
1834                 List<Object> toscaFunctionList = new ArrayList<>();
1835                 ((List<?>) filterConstraint.getValue()).forEach(toscaFunctionValue -> toscaFunctionList.add(
1836                         ((ToscaFunction) toscaFunctionValue).getJsonObjectValue()));
1837                 return Map.of(filterConstraint.getOperator().getType(), toscaFunctionList);
1838             }
1839         }
1840         if (doesTypeNeedConvertingToIntOrFloat(filterConstraint.getOriginalType(), filterConstraint.getValue())) {
1841             ToscaType toscaType = ToscaType.getToscaType(
1842                     filterConstraint.getValue() instanceof List ? ToscaType.LIST.getType() : filterConstraint.getOriginalType());
1843             filterConstraint.setValue(toscaType.convert(String.valueOf(filterConstraint.getValue())));
1844         } else if (ConstraintType.LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1845                 ConstraintType.MIN_LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1846                 ConstraintType.MAX_LENGTH.getType().equals(filterConstraint.getOperator().getType())) {
1847             filterConstraint.setValue(Integer.valueOf(String.valueOf(filterConstraint.getValue())));
1848         }
1849         if (doesTypeNeedConvertingToBoolean(filterConstraint.getOriginalType())) {
1850             filterConstraint.setValue(ToscaType.getToscaType(filterConstraint.getOriginalType()).convert(
1851                 String.valueOf(filterConstraint.getValue())));
1852         }
1853         return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1854     }
1855
1856     private static boolean doesTypeNeedConvertingToIntOrFloat(String propertyType, Object value) {
1857         if (value instanceof List && ((List<?>) value).get(0) instanceof LinkedHashMap
1858                 && ((LinkedHashMap) ((List<?>) value).get(0)).get("type") != null) {
1859             return false;
1860         }
1861         return ToscaType.INTEGER.getType().equals(propertyType) || ToscaType.FLOAT.getType().equals(propertyType);
1862     }
1863
1864     private static boolean doesTypeNeedConvertingToBoolean(String propertyType) {
1865         return ToscaType.BOOLEAN.getType().equals(propertyType);
1866     }
1867
1868     private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1869         if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1870             return Collections.emptyMap();
1871         }
1872         Map<String, String[]> propertyMapping = new HashMap<>();
1873         List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect(
1874                 Collectors.toList());
1875
1876         if (CollectionUtils.isNotEmpty(propertyMappedInputList)) {
1877             propertyMappedInputList.forEach(inputDefinition -> {
1878                 if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) {
1879                     Optional<PropertyDefinition> property = component.getProperties().stream()
1880                             .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst();
1881                     if (property.isPresent()) {
1882                         propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()});
1883                     }
1884                 } else {
1885                     propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()});
1886                 }
1887             });
1888         }
1889         return propertyMapping;
1890     }
1891
1892     private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1893         if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1894             return Collections.emptyMap();
1895         }
1896         return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1897                 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1898     }
1899
1900     private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1901         if (Objects.isNull(proxyComponent)) {
1902             return Optional.empty();
1903         }
1904         final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1905         if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1906             proxyProperties.putAll(proxyComponent.getProperties().stream()
1907                     .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1908                             .toMap(PropertyDataDefinition::getName,
1909                                     property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1910         }
1911         return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1912     }
1913
1914     private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1915                                                                  String componentUniqueId) {
1916         if (CollectionUtils.isEmpty(componentInputs)) {
1917             return new HashMap<>();
1918         }
1919         return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1920                 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1921     }
1922
1923     private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1924         if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1925             return Optional.empty();
1926         }
1927         Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1928         //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1929
1930         // always available in the proxy node template
1931         removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1932         return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1933     }
1934
1935     private Configuration getConfiguration() {
1936         return ConfigurationManager.getConfigurationManager().getConfiguration();
1937     }
1938
1939     private static class CustomRepresenter extends Representer {
1940
1941         CustomRepresenter() {
1942             this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1943             this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1944             // null representer is exceptional and it is stored as an instance
1945
1946             // variable.
1947             this.nullRepresenter = new RepresentNull();
1948         }
1949
1950         public boolean validateGetInputValue(final Object valueObj) {
1951             if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1952                 return false;
1953             }
1954             if (valueObj instanceof List) {
1955                 return ((List) valueObj).size() > 1;
1956             }
1957             return true;
1958         }
1959
1960         public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1961             if (valueObj instanceof List) {
1962                 return ((List) valueObj).size() > 1;
1963             }
1964             return false;
1965         }
1966
1967         @Override
1968         protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1969             if (propertyValue == null) {
1970                 return null;
1971             }
1972             // skip not relevant for Tosca property
1973             if ("dependencies".equals(property.getName())) {
1974                 return null;
1975             }
1976             if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1977                 return null;
1978             }
1979             if (javaBean instanceof ToscaPropertyConstraint) {
1980                 return handleToscaPropertyConstraint((ToscaPropertyConstraint) javaBean, property, propertyValue, customTag);
1981             }
1982             removeDefaultP(propertyValue);
1983             NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1984             if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1985                 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1986             }
1987             return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1988         }
1989
1990         private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1991                                                         final Tag customTag) {
1992             final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1993             final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1994             return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1995         }
1996
1997         private void removeDefaultP(final Object propertyValue) {
1998             if (propertyValue instanceof Map) {
1999                 final Map mapPropertyValue = ((Map) propertyValue);
2000                 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
2001                 Object defaultValue = null;
2002                 while (iter.hasNext()) {
2003                     final Map.Entry entry = iter.next();
2004                     if ("_defaultp_".equals(entry.getKey())) {
2005                         defaultValue = entry.getValue();
2006                         iter.remove();
2007                     } else if (entry.getValue() instanceof Map) {
2008                         removeDefaultP(entry.getValue());
2009                     }
2010                 }
2011                 if (defaultValue != null) {
2012                     mapPropertyValue.putIfAbsent("default", defaultValue);
2013                 }
2014             }
2015         }
2016
2017         @Override
2018         protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
2019             // remove the bean type from the output yaml (!! ...)
2020             if (!classTags.containsKey(javaBean.getClass())) {
2021                 addClassTag(javaBean.getClass(), Tag.MAP);
2022             }
2023             return super.representJavaBean(properties, javaBean);
2024         }
2025
2026         private class RepresentToscaAttribute implements Represent {
2027
2028             @Override
2029             public Node representData(Object data) {
2030                 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
2031                 return represent(toscaAttribute.asToscaMap());
2032             }
2033         }
2034
2035         private class RepresentToscaPropertyAssignment implements Represent {
2036
2037             public Node representData(Object data) {
2038                 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
2039                 if (toscaOperationAssignment.getValue() instanceof String) {
2040                     final String stringValue = (String) toscaOperationAssignment.getValue();
2041                     if (isPropertyOrAttributeFunction(stringValue)) {
2042                         return representGetAttribute(stringValue);
2043                     }
2044                     return representScalar(Tag.STR, stringValue);
2045                 }
2046                 return represent(null);
2047             }
2048
2049             public Node representGetAttribute(final String getAttributeFunction) {
2050                 return represent(new Yaml().load(getAttributeFunction));
2051             }
2052
2053             public boolean isPropertyOrAttributeFunction(final String value) {
2054                 try {
2055                     final Yaml yaml = new Yaml();
2056                     final Object yamlObj = yaml.load(value);
2057                     if (!(yamlObj instanceof Map)) {
2058                         return false;
2059                     }
2060                     final Map<String, Object> getAttributeMap = (Map) yamlObj;
2061                     if (getAttributeMap.size() != 1) {
2062                         return false;
2063                     }
2064                     final List<String> functionList = Arrays
2065                             .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
2066                     final Optional<String> function = getAttributeMap.keySet().stream()
2067                             .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
2068                     if (function.isEmpty()) {
2069                         return false;
2070                     }
2071                     final String functionName = function.get();
2072                     final Object getAttributeValueObj = getAttributeMap.get(functionName);
2073                     if (GET_INPUT.getFunctionName().equals(functionName)) {
2074                         return validateGetInputValue(getAttributeValueObj);
2075                     } else {
2076                         return validateGetPropertyOrAttributeValue(getAttributeValueObj);
2077                     }
2078                 } catch (final Exception ignored) {
2079                     return false;
2080                 }
2081             }
2082         }
2083
2084         private class RepresentNull implements Represent {
2085
2086             @Override
2087             public Node representData(Object data) {
2088                 // possible values are here http://yaml.org/type/null.html
2089                 return representScalar(Tag.NULL, "");
2090             }
2091         }
2092     }
2093
2094     private static class UnsortedPropertyUtils extends PropertyUtils {
2095
2096         @Override
2097         protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
2098             Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
2099             return new LinkedHashSet<>(fields);
2100         }
2101     }
2102
2103 }