Fix 'missing properties after service import'-bug
[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) {
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, isSkipImports);
812             } else {
813                 setImports(imports, dependencies, fetchedComponent, isSkipImports);
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, boolean isSkipImports) {
848         componentsList.forEach(component ->  setImports(imports, dependencies, component, isSkipImports));
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, boolean isSkipImports) {
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             if (!isSkipImports) {
864                 addImports(imports, keyNameBuilder, files);
865             }
866             dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
867             if (!ModelConverter.isAtomicComponent(component) && !isSkipImports) {
868                 final Map<String, String> interfaceFiles = new HashMap<>();
869                 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
870                 keyNameBuilder.append("-interface");
871                 addImports(imports, keyNameBuilder, interfaceFiles);
872             }
873         }
874     }
875
876     /**
877      * Adds the found resource to the import definition list.
878      */
879     private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
880                             final Map<String, String> files) {
881         final String mapKey = keyNameBuilder.toString();
882         if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
883             final Map<String, Map<String, String>> importsListMember = new HashMap<>();
884             importsListMember.put(keyNameBuilder.toString(), files);
885             imports.add(importsListMember);
886         }
887     }
888
889     private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
890                                                               Map<String, ToscaNodeType> nodeTypes) {
891         return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
892     }
893
894     public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
895                                                                       ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
896                                                                       boolean isAssociatedComponent) {
897         log.debug("start convert node type for {}", component.getUniqueId());
898         ToscaNodeType toscaNodeType = createNodeType(component);
899         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
900                 .getAllInterfaceLifecycleTypes(component.getModel());
901         if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
902             log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
903             return Either.right(ToscaError.GENERAL_ERROR);
904         }
905         if (lifecycleTypeEither.isLeft()) {
906             List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
907                     .collect(Collectors.toList());
908             toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
909         }
910         final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
911         if (dataTypesEither.isRight()) {
912             log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
913             return Either.right(ToscaError.GENERAL_ERROR);
914         }
915         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
916         interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
917         final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
918         if (!toscaAttributeMap.isEmpty()) {
919             toscaNodeType.setAttributes(toscaAttributeMap);
920         }
921         Map<String, ToscaProperty> convertedProperties = new HashMap();
922         if (CollectionUtils.isNotEmpty(component.getProperties())) {
923             List<PropertyDefinition> properties = component.getProperties();
924             convertedProperties = properties.stream()
925                     .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
926                             .toMap(PropertyDataDefinition::getName,
927                                     property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
928         }
929         if (MapUtils.isNotEmpty(convertedProperties)) {
930             toscaNodeType.setProperties(convertedProperties);
931         }
932         /* convert private data_types */
933         List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
934         if (CollectionUtils.isNotEmpty(privateDataTypes)) {
935             Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
936             for (DataTypeDefinition dataType : privateDataTypes) {
937                 log.debug("Emitting private data type: component.name={} dataType.name={}",
938                         component.getNormalizedName(), dataType.getName());
939                 ToscaDataType toscaDataType = new ToscaDataType();
940                 toscaDataType.setDerived_from(dataType.getDerivedFromName());
941                 toscaDataType.setDescription(dataType.getDescription());
942                 toscaDataType.setVersion(dataType.getVersion());
943                 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
944                     toscaDataType.setProperties(dataType.getProperties().stream()
945                             .collect(Collectors.toMap(
946                                     PropertyDataDefinition::getName,
947                                     s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
948                                     (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
949                                             toscaProperty)
950                             )));
951                 }
952                 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
953             }
954             toscaNode.setData_types(toscaDataTypeMap);
955         }
956
957         // Extracted to method for code reuse
958         return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
959     }
960
961     private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
962                                                 final ToscaProperty toscaProperty) {
963         final Optional<DataTypeDefinition> match = privateDataTypes.stream()
964                 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
965         return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
966     }
967
968     private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
969                                                                  final Map<String, DataTypeDefinition> dataTypes) {
970         if (CollectionUtils.isEmpty(attributeList)) {
971             return Collections.emptyMap();
972         }
973         final AttributeConverter converter = new AttributeConverter(dataTypes);
974         final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
975         for (final AttributeDefinition attributeDefinition : attributeList) {
976             toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
977         }
978         return toscaAttributeMap;
979     }
980
981     private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
982                                                                        Component component, ToscaTemplate toscaNode,
983                                                                        Map<String, ToscaNodeType> nodeTypes,
984                                                                        ToscaNodeType toscaNodeType,
985                                                                        Map<String, DataTypeDefinition> dataTypes) {
986         Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
987                 dataTypes);
988         if (capabilities.isRight()) {
989             return Either.right(capabilities.right().value());
990         }
991         toscaNodeType = capabilities.left().value();
992         log.debug("Capabilities converted for {}", component.getUniqueId());
993
994         Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
995                 .convertRequirements(componentsCache, component, toscaNodeType);
996         if (requirements.isRight()) {
997             return Either.right(requirements.right().value());
998         }
999         toscaNodeType = requirements.left().value();
1000         log.debug("Requirements converted for {}", component.getUniqueId());
1001
1002         String toscaResourceName;
1003         switch (component.getComponentType()) {
1004             case RESOURCE:
1005                 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
1006                         .getMetadataDataDefinition()).getToscaResourceName();
1007                 break;
1008             case SERVICE:
1009                 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
1010                         + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
1011                 break;
1012             default:
1013                 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
1014                 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1015         }
1016
1017         nodeTypes.put(toscaResourceName, toscaNodeType);
1018         toscaNode.setNode_types(nodeTypes);
1019         log.debug("finish convert node type for {}", component.getUniqueId());
1020         return Either.left(toscaNode);
1021     }
1022
1023     private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
1024                                                                                     final Map<String, Component> componentCache,
1025                                                                                     final Map<String, DataTypeDefinition> dataTypes,
1026                                                                                     final ToscaTopolgyTemplate topologyTemplate) {
1027
1028         final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
1029         final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
1030         final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
1031         final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
1032         final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
1033
1034         Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
1035         log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1036         final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
1037
1038         Map<String, ToscaGroupTemplate> groupsMap = null;
1039         for (final ComponentInstance componentInstance : component.getComponentInstances()) {
1040             ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
1041             if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
1042                 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
1043             }
1044             if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
1045                 List<Object> occur = new ArrayList<>();
1046                 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
1047                 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
1048                 nodeTemplate.setOccurrences(occur);
1049             }
1050             if (componentInstance.getInstanceCount() != null) {
1051                 ObjectMapper objectMapper = new ObjectMapper();
1052                 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
1053                 if (obj != null) {
1054                     Map<String, String> map = objectMapper.convertValue(obj, Map.class);
1055                     nodeTemplate.setInstance_count(map);
1056                 }
1057             }
1058             nodeTemplate.setType(componentInstance.getToscaComponentName());
1059             nodeTemplate.setDirectives(componentInstance.getDirectives());
1060             NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
1061             if (nodeFilter != null && nodeFilter.hasData()) {
1062                 nodeTemplate.setNode_filter(nodeFilter);
1063             }
1064             final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
1065                     .getOriginComponent(componentCache, componentInstance);
1066             if (originComponentRes.isRight()) {
1067                 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1068                 break;
1069             }
1070             final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
1071                     componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
1072             if (requirements.isRight()) {
1073                 convertNodeTemplatesRes = Either.right(requirements.right().value());
1074                 break;
1075             }
1076             final String instanceUniqueId = componentInstance.getUniqueId();
1077             log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1078
1079             nodeTemplate = requirements.left().value();
1080
1081             final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1082
1083             if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1084                 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1085                 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1086             } else {
1087                 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1088             }
1089
1090             final Either<ToscaNodeTemplate, ToscaError> capabilities =
1091                     capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1092             if (capabilities.isRight()) {
1093                 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1094                 break;
1095             }
1096             log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1097
1098             nodeTemplate = capabilities.left().value();
1099             final Map<String, Object> props = new HashMap<>();
1100             final Map<String, Object> attribs = new HashMap<>();
1101
1102             if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1103                 // Adds the properties of parent component to map
1104                 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1105                 addAttributesOfParentComponent(originalComponent, attribs);
1106             }
1107
1108             if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1109                 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1110             }
1111             if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1112                 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1113             }
1114
1115             if (componentInstancesInputs != null
1116                     && componentInstancesInputs.containsKey(instanceUniqueId)
1117                     && !isComponentOfTypeServiceProxy(componentInstance)) {
1118                 //For service proxy the inputs are already handled under instance properties above
1119                 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1120             }
1121
1122             //M3[00001] - NODE TEMPLATE INTERFACES  - START
1123             handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1124             //M3[00001] - NODE TEMPLATE INTERFACES  - END
1125             if (MapUtils.isNotEmpty(props)) {
1126                 nodeTemplate.setProperties(props);
1127             }
1128             if (MapUtils.isNotEmpty(attribs)) {
1129                 nodeTemplate.setAttributes(attribs);
1130             }
1131
1132             final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1133             if (CollectionUtils.isNotEmpty(groupInstances)) {
1134                 if (groupsMap == null) {
1135                     groupsMap = new HashMap<>();
1136                 }
1137                 for (final GroupInstance groupInst : groupInstances) {
1138                     if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1139                         groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1140                     }
1141                 }
1142             }
1143
1144             nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1145         }
1146         if (groupsMap != null) {
1147             log.debug("instance groups added");
1148             topologyTemplate.addGroups(groupsMap);
1149         }
1150         if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1151                 ((Service) component).getForwardingPaths())) {
1152             log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1153             ForwardingPathToscaUtil
1154                     .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1155             log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1156         }
1157         if (convertNodeTemplatesRes == null) {
1158             convertNodeTemplatesRes = Either.left(nodeTemplates);
1159         }
1160         log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1161         return convertNodeTemplatesRes;
1162     }
1163
1164     private Object convertToToscaObject(String value) {
1165         try {
1166             ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1167             StringReader reader = new StringReader(value);
1168             JsonReader jsonReader = new JsonReader(reader);
1169             jsonReader.setLenient(true);
1170             JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1171             if (jsonElement.isJsonObject()) {
1172                 JsonObject jsonObj = jsonElement.getAsJsonObject();
1173                 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1174                     return mapConverterInst.handleComplexJsonValue(jsonElement);
1175                 }
1176             }
1177             return null;
1178         } catch (Exception e) {
1179             log.debug("convertToToscaValue failed to parse json value :", e);
1180             return null;
1181         }
1182     }
1183
1184     private Object parseToIntIfPossible(final String value) {
1185         final Integer intValue = Ints.tryParse(value);
1186         return intValue == null ? value : intValue;
1187     }
1188
1189     private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1190                                           ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1191                                           ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1192
1193         if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1194             nodeTemplate.setInterfaces(null);
1195             return;
1196         }
1197
1198         final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1199
1200         final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1201         currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1202
1203         final Map<String, Object> interfaceMap = interfacesOperationsConverter
1204                 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1205
1206         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1207         nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1208     }
1209
1210     private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1211         return Objects.nonNull(componentInstance.getOriginType())
1212                 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1213     }
1214
1215     private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1216                                             Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1217                                             String instanceUniqueId, Map<String, Object> props) {
1218
1219         List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1220         if (instanceInputsList != null) {
1221             instanceInputsList.forEach(input -> {
1222                 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1223                         : input.getDefaultValue();
1224                 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1225             });
1226         }
1227     }
1228
1229     private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1230                                                   final Map<String, DataTypeDefinition> dataTypes,
1231                                                   final String instanceUniqueId,
1232                                                   final Map<String, Object> props) {
1233
1234         if (isNotEmpty(componentInstancesProperties)) {
1235             componentInstancesProperties.get(instanceUniqueId)
1236                     // Converts and adds each value to property map
1237                     .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1238         }
1239     }
1240
1241     private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1242                                                   final String instanceUniqueId,
1243                                                   final Map<String, Object> attribs) {
1244
1245         if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1246             componentInstancesAttributes.get(instanceUniqueId)
1247                     .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1248         }
1249     }
1250
1251     private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1252                                                 Component componentOfInstance, Map<String, Object> props) {
1253
1254         List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1255         if (isNotEmpty(componentProperties)) {
1256             componentProperties.stream()
1257                     // Filters out properties with empty default values
1258                     .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1259                     // Converts and adds each value to property map
1260                     .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1261         }
1262     }
1263
1264     private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1265
1266         final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1267         if (isNotEmpty(componentAttributes)) {
1268             componentAttributes.stream()
1269                     // Filters out Attributes with empty default values
1270                     .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1271                     // Converts and adds each value to attribute map
1272                     .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1273         }
1274     }
1275
1276     private ToscaNodeType createNodeType(Component component) {
1277         ToscaNodeType toscaNodeType = new ToscaNodeType();
1278         if (ModelConverter.isAtomicComponent(component)) {
1279             if (((Resource) component).getDerivedFrom() != null) {
1280                 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1281             }
1282             toscaNodeType.setDescription(component.getDescription());
1283         } else {
1284             String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1285                     : NATIVE_ROOT;
1286             toscaNodeType.setDerived_from(derivedFrom);
1287         }
1288         return toscaNodeType;
1289     }
1290
1291     private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1292
1293         Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1294         Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1295         List<ComponentInstance> componentInstances = container.getComponentInstances();
1296         if (CollectionUtils.isEmpty(componentInstances)) {
1297             return res;
1298         }
1299         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1300         componentInstances.stream()
1301                 .filter(this::isComponentOfTypeServiceProxy)
1302                 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1303         if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1304             return res;
1305         }
1306         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1307             Component serviceComponent;
1308             ComponentParametersView componentParametersView = new ComponentParametersView();
1309             componentParametersView.disableAll();
1310             componentParametersView.setIgnoreInterfaces(false);
1311             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1312                     .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1313             if (service.isRight()) {
1314                 log.debug("Failed to fetch original service component with id {} for instance {}",
1315                         entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1316                 return Either.right(ToscaError.GENERAL_ERROR);
1317             } else {
1318                 serviceComponent = service.left().value();
1319             }
1320
1321             Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1322                     interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1323             if (lifecycleTypeEither.isRight()) {
1324                 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1325                 return Either.right(ToscaError.GENERAL_ERROR);
1326             }
1327
1328             List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1329                     .map(InterfaceDataDefinition::getType)
1330                     .collect(Collectors.toList());
1331             //Add interface types for local interfaces in the original service component for proxy
1332             Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1333                     allGlobalInterfaceTypes);
1334             if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1335                 proxyInterfaceTypes.putAll(localInterfaceTypes);
1336             }
1337
1338         }
1339         return Either.left(proxyInterfaceTypes);
1340     }
1341
1342     private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1343                                                                                 Component container) {
1344
1345         Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1346         Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1347
1348         List<ComponentInstance> componentInstances = container.getComponentInstances();
1349
1350         if (componentInstances == null || componentInstances.isEmpty()) {
1351             return res;
1352         }
1353         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1354         List<ComponentInstance> proxyInst = componentInstances.stream()
1355                 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1356                 .collect(Collectors.toList());
1357         if (proxyInst != null && !proxyInst.isEmpty()) {
1358             for (ComponentInstance inst : proxyInst) {
1359                 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1360             }
1361         }
1362
1363         if (serviceProxyInstanceList.isEmpty()) {
1364             return res;
1365         }
1366         Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1367                 .getLatestByName("serviceProxy", null);
1368         if (serviceProxyOrigin.isRight()) {
1369             log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1370                     serviceProxyOrigin.right().value());
1371             return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1372         }
1373         Component origComponent = serviceProxyOrigin.left().value();
1374
1375         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1376             Component serviceComponent = null;
1377             ComponentParametersView componentParametersView = new ComponentParametersView();
1378             componentParametersView.disableAll();
1379             componentParametersView.setIgnoreCategories(false);
1380             componentParametersView.setIgnoreProperties(false);
1381             componentParametersView.setIgnoreInputs(false);
1382             componentParametersView.setIgnoreInterfaces(false);
1383             componentParametersView.setIgnoreRequirements(false);
1384             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1385                     .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1386             if (service.isRight()) {
1387                 log.debug("Failed to fetch resource with id {} for instance {}",
1388                         entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1389             } else {
1390                 serviceComponent = service.left().value();
1391             }
1392
1393             ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1394                     entryProxy.getValue());
1395             nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1396         }
1397
1398         return Either.left(nodeTypesMap);
1399     }
1400
1401     private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1402                                                     final Component container, final ToscaTemplate toscaNode) {
1403         final List<ComponentInstance> componentInstances = container.getComponentInstances();
1404
1405         if (CollectionUtils.isEmpty(componentInstances)) {
1406             return;
1407         }
1408         final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1409                 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1410                 .collect(Collectors.toList());
1411         if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1412             for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1413                 final Map<String, ToscaNodeType> nodeTypes =
1414                         toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1415                 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1416                         nodeTypes, true);
1417             }
1418         }
1419     }
1420
1421     private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1422                                               Component proxyComponent, ComponentInstance componentInstance) {
1423         ToscaNodeType toscaNodeType = new ToscaNodeType();
1424         String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1425
1426         toscaNodeType.setDerived_from(derivedFrom);
1427         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1428                 origComponent.getModel());
1429         if (dataTypesEither.isRight()) {
1430             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1431         }
1432         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1433         Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1434                 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1435
1436         if (MapUtils.isNotEmpty(capabilities)) {
1437             toscaNodeType.setCapabilities(capabilities);
1438         }
1439         List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1440                 .convertProxyRequirements(componentCache, componentInstance);
1441         if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1442             toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1443         }
1444         Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1445         proxyProperties.ifPresent(toscaNodeType::setProperties);
1446
1447         Map<String, Object> interfaceMap = new HashMap<>();
1448         if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1449             final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1450             if (proxyInterfaces.isPresent()) {
1451                 interfaceMap = proxyInterfaces.get();
1452             }
1453         } else {
1454             interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1455
1456         }
1457         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1458         toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1459
1460         return toscaNodeType;
1461     }
1462
1463     private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1464                                                                                        ComponentInstance componentInstance,
1465                                                                                        List<RequirementCapabilityRelDef> relations,
1466                                                                                        ToscaNodeTemplate nodeTypeTemplate,
1467                                                                                        Component originComponent,
1468                                                                                        Map<String, Component> componentCache) {
1469
1470         final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1471                 relations);
1472         if (isNotEmpty(requirementDefinitionList)) {
1473             try {
1474                 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1475                         requirementDefinitionList, originComponent, componentCache);
1476                 if (CollectionUtils.isNotEmpty(toscaRequirements)) {
1477                     nodeTypeTemplate.setRequirements(toscaRequirements);
1478                 }
1479             } catch (final Exception e) {
1480                 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1481                         componentInstance.getName(), e);
1482                 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1483             }
1484         }
1485         log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1486         return Either.left(nodeTypeTemplate);
1487     }
1488
1489     private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1490                                                                           final ComponentInstance componentInstance,
1491                                                                           final List<RequirementCapabilityRelDef> filteredRelations,
1492                                                                           final Component originComponent,
1493                                                                           final Map<String, Component> componentCache)
1494             throws ToscaExportException {
1495
1496         final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1497         for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1498             final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1499                     buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1500             if (MapUtils.isNotEmpty(toscaTemplateRequirementMap)) {
1501                 toscaRequirements.add(toscaTemplateRequirementMap);
1502             }
1503         }
1504
1505         return toscaRequirements;
1506     }
1507
1508     private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1509                                                                  List<RequirementCapabilityRelDef> relations) {
1510         return relations.stream()
1511                 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1512     }
1513
1514     private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1515                                                                    final Component fromOriginComponent,
1516                                                                    final List<ComponentInstance> instancesList,
1517                                                                    final RequirementCapabilityRelDef relationshipDefinition,
1518                                                                    final Map<String, Component> componentCache)
1519             throws ToscaExportException {
1520
1521         final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1522         if (MapUtils.isEmpty(reqMap)) {
1523             return new HashMap<>();
1524         }
1525         final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition.getRelationships().get(0);
1526         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1527
1528         final ComponentInstance toInstance = instancesList.stream().filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1529                 .findFirst().orElse(null);
1530         if (toInstance == null) {
1531             final String errorMsg = String
1532                     .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1533                             relationshipDefinition.getToNode());
1534             log.debug(errorMsg);
1535             throw new ToscaExportException(errorMsg);
1536         }
1537         final Optional<RequirementDefinition> reqOpt = findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1538         if (reqOpt.isEmpty()) {
1539             final String errorMsg = String.format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1540                     relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1541             log.debug(errorMsg);
1542             throw new ToscaExportException(errorMsg);
1543         }
1544         final ComponentParametersView filter = new ComponentParametersView(true);
1545         filter.setIgnoreComponentInstances(false);
1546         filter.setIgnoreCapabilities(false);
1547         filter.setIgnoreGroups(false);
1548         final Either<Component, StorageOperationStatus> getOriginRes =
1549                 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1550         if (getOriginRes.isRight()) {
1551             final String errorMsg = String.format(
1552                     "Failed to build substituted name for the requirement %s. Failed to get an origin component with uniqueId %s",
1553                     reqOpt.get().getName(), toInstance.getActualComponentUid());
1554             log.debug(errorMsg);
1555             throw new ToscaExportException(errorMsg);
1556         }
1557         final Component toOriginComponent = getOriginRes.left().value();
1558         Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1559                 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1560         if (capOpt.isEmpty()) {
1561             capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1562             if (capOpt.isEmpty()) {
1563                 final String errorMsg = String.format("Failed to find a capability with name %s on a component with uniqueId %s",
1564                         relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1565                 log.debug(errorMsg);
1566                 throw new ToscaExportException(errorMsg);
1567             }
1568         }
1569         return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1570                 capabilityRequirementRelationship, toInstance, componentCache);
1571     }
1572
1573     private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1574                                                  CapabilityDefinition capability) {
1575         return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1576                 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1577     }
1578
1579     private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1580                                                           Component toOriginComponent, Component fromOriginComponent,
1581                                                           RequirementDefinition requirement) {
1582         Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1583                 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1584         if (cap.isEmpty()) {
1585             log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1586                     reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1587         }
1588         return cap;
1589     }
1590
1591     private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1592                                                                    final Component toOriginComponent,
1593                                                                    final CapabilityDefinition capability,
1594                                                                    final RequirementDefinition requirement,
1595                                                                    final CapabilityRequirementRelationship capabilityRequirementRelationship,
1596                                                                    final ComponentInstance toInstance,
1597                                                                    final Map<String, Component> componentCache)
1598             throws ToscaExportException {
1599
1600         List<String> reducedPath = capability.getPath();
1601         if (capability.getOwnerId() != null) {
1602             reducedPath = capabilityRequirementConverter
1603                     .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1604         }
1605         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1606         final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1607                 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1608         if (capabilityNameEither.isRight()) {
1609             final String errorMsg = String.format(
1610                     "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1611                     capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1612             log.debug(
1613                     errorMsg);
1614             throw new ToscaExportException(errorMsg);
1615         }
1616         final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1617                 .buildSubstitutedName(componentCache, fromOriginComponent,
1618                         requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1619         if (requirementNameEither.isRight()) {
1620             final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1621                             + "with name %s on a component with uniqueId %s",
1622                     capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1623             log.debug(errorMsg);
1624             throw new ToscaExportException(errorMsg);
1625         }
1626         final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1627         final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1628         toscaRequirement.setNode(toInstance.getName());
1629         toscaRequirement.setCapability(capabilityNameEither.left().value());
1630         if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1631             toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1632         }
1633         toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1634         return toscaReqMap;
1635     }
1636
1637     private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1638                                                             Map<String, List<RequirementDefinition>> reqMap,
1639                                                             RelationshipInfo reqAndRelationshipPair,
1640                                                             String fromInstanceId) {
1641         for (final List<RequirementDefinition> reqList : reqMap.values()) {
1642             final Optional<RequirementDefinition> reqOpt = reqList.stream()
1643                     .filter(r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId)).findFirst();
1644             if (reqOpt.isPresent()) {
1645                 return reqOpt;
1646             }
1647         }
1648         return Optional.empty();
1649     }
1650
1651     /**
1652      * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1653      * 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
1654      * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1655      */
1656     private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1657                                                   RequirementDefinition requirement, String fromInstanceId) {
1658         if (originComponent.isService() && requirement.getUniqueId().equals(reqAndRelationshipPair.getRequirementUid())) {
1659             return true;
1660         }
1661         if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1662             log.debug("Failed to find a requirement with name {} and  reqAndRelationshipPair {}", requirement.getName(),
1663                     reqAndRelationshipPair.getRequirement());
1664             return false;
1665         }
1666         return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1667                 originComponent);
1668     }
1669
1670     private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1671                                                Component originComponent) {
1672         return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1673                 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1674                         .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1675     }
1676
1677     private boolean isCvfc(Component component) {
1678         return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1679     }
1680
1681     private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1682                                                                                              final Map<String, Component> componentCache) {
1683         Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1684                 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1685         if (toscaCapabilitiesRes.isRight()) {
1686             log.debug("Failed convert capabilities for the component {}. ", component.getName());
1687             return Either.right(toscaCapabilitiesRes.right().value());
1688         }
1689         if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1690             log.debug("Finish convert capabilities for the component {}. ", component.getName());
1691             return Either.left(toscaCapabilitiesRes.left().value());
1692         }
1693         log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1694
1695         return Either.left(Collections.emptyMap());
1696     }
1697
1698     private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1699                                                                   Map<String, DataTypeDefinition> dataTypes) {
1700         Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1701         if (!toscaCapabilities.isEmpty()) {
1702             nodeType.setCapabilities(toscaCapabilities);
1703         }
1704         log.debug("Finish convert Capabilities for node type");
1705         return Either.left(nodeType);
1706     }
1707
1708     private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1709         if (artifacts == null) {
1710             return null;
1711         }
1712         Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1713         for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1714             ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1715             artifact.setFile(entry.getValue().getFile());
1716             artifact.setType(entry.getValue().getType());
1717             artifact.setProperties(entry.getValue().getProperties());
1718             arts.put(entry.getKey(), artifact);
1719         }
1720         return arts;
1721     }
1722
1723     private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1724         if (inNodeFilter == null) {
1725             return null;
1726         }
1727         NodeFilter nodeFilter = new NodeFilter();
1728         ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1729         ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1730         List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1731         copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1732         if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1733             nodeFilter.setCapabilities(capabilitiesCopy);
1734         }
1735         final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1736         if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1737             nodeFilter.setProperties(propertiesCopy);
1738         }
1739         nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1740         return cloneObjectFromYml(nodeFilter, NodeFilter.class);
1741     }
1742
1743     private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1744         if (substitutionFilterDataDefinition == null) {
1745             return null;
1746         }
1747         NodeFilter nodeFilter = new NodeFilter();
1748         final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1749         if (!propertiesCopy.isEmpty()) {
1750             nodeFilter.setProperties(propertiesCopy);
1751         }
1752         nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1753         return cloneObjectFromYml(nodeFilter, NodeFilter.class);
1754     }
1755
1756     private Object cloneToscaId(Object toscaId) {
1757         return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1758     }
1759
1760     private <T> T cloneObjectFromYml(Object objToClone, Class<T> classOfObj) {
1761         String objectAsYml = yamlUtil.objectToYaml(objToClone);
1762         return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1763     }
1764
1765     private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1766                                                     List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1767         if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1768                 .isEmpty()) {
1769             return;
1770         }
1771         for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1772             Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1773             final var capabilityFilter = new CapabilityFilter();
1774             capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1775             capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1776             capabilitiesCopy.add(capabilityFilterCopyMap);
1777         }
1778     }
1779
1780     private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1781         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1782             return Collections.emptyList();
1783         }
1784         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1785         Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1786         for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1787             final String propertyName = propertyFilter.getName();
1788             for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1789                 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1790                     if (constraints == null) {
1791                         constraints = new ArrayList<>();
1792                     }
1793                     constraints.add(buildNodeFilterValue(filterConstraint));
1794                     return constraints;
1795                 });
1796             }
1797         }
1798         propertyFilterDefinitionMap.entrySet().stream()
1799                 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1800                 .forEach(propertiesCopy::add);
1801         return propertiesCopy;
1802     }
1803
1804     private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1805             final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1806
1807         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1808             return Collections.emptyList();
1809         }
1810         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1811         Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1812         for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1813             final String propertyName = propertyFilter.getName();
1814             for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1815                 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1816                     if (constraints == null) {
1817                         constraints = new ArrayList<>();
1818                     }
1819                     constraints.add(buildNodeFilterValue(filterConstraint));
1820                     return constraints;
1821                 });
1822             }
1823         }
1824         propertyFilterDefinitionMap.entrySet().stream()
1825                 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1826                 .forEach(propertiesCopy::add);
1827         return propertiesCopy;
1828     }
1829
1830     private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1831         if (filterConstraint.getValue() instanceof ToscaFunction) {
1832             return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1833         }
1834         if (filterConstraint.getValue() instanceof List) {
1835             if (((List<?>) filterConstraint.getValue()).get(0) instanceof ToscaFunction) {
1836                 List<Object> toscaFunctionList = new ArrayList<>();
1837                 ((List<?>) filterConstraint.getValue()).forEach(toscaFunctionValue -> toscaFunctionList.add(
1838                         ((ToscaFunction) toscaFunctionValue).getJsonObjectValue()));
1839                 return Map.of(filterConstraint.getOperator().getType(), toscaFunctionList);
1840             }
1841         }
1842         if (doesTypeNeedConvertingToIntOrFloat(filterConstraint.getOriginalType(), filterConstraint.getValue())) {
1843             ToscaType toscaType = ToscaType.getToscaType(
1844                     filterConstraint.getValue() instanceof List ? ToscaType.LIST.getType() : filterConstraint.getOriginalType());
1845             filterConstraint.setValue(toscaType.convert(String.valueOf(filterConstraint.getValue())));
1846         } else if (ConstraintType.LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1847                 ConstraintType.MIN_LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1848                 ConstraintType.MAX_LENGTH.getType().equals(filterConstraint.getOperator().getType())) {
1849             filterConstraint.setValue(Integer.valueOf(String.valueOf(filterConstraint.getValue())));
1850         }
1851         if (doesTypeNeedConvertingToBoolean(filterConstraint.getOriginalType())) {
1852             filterConstraint.setValue(ToscaType.getToscaType(filterConstraint.getOriginalType()).convert(
1853                 String.valueOf(filterConstraint.getValue())));
1854         }
1855         return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1856     }
1857
1858     private static boolean doesTypeNeedConvertingToIntOrFloat(String propertyType, Object value) {
1859         if (value instanceof List && ((List<?>) value).get(0) instanceof LinkedHashMap
1860                 && ((LinkedHashMap) ((List<?>) value).get(0)).get("type") != null) {
1861             return false;
1862         }
1863         return ToscaType.INTEGER.getType().equals(propertyType) || ToscaType.FLOAT.getType().equals(propertyType);
1864     }
1865
1866     private static boolean doesTypeNeedConvertingToBoolean(String propertyType) {
1867         return ToscaType.BOOLEAN.getType().equals(propertyType);
1868     }
1869
1870     private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1871         if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1872             return Collections.emptyMap();
1873         }
1874         Map<String, String[]> propertyMapping = new HashMap<>();
1875         List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect(
1876                 Collectors.toList());
1877
1878         if (CollectionUtils.isNotEmpty(propertyMappedInputList)) {
1879             propertyMappedInputList.forEach(inputDefinition -> {
1880                 if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) {
1881                     Optional<PropertyDefinition> property = component.getProperties().stream()
1882                             .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst();
1883                     if (property.isPresent()) {
1884                         propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()});
1885                     }
1886                 } else {
1887                     propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()});
1888                 }
1889             });
1890         }
1891         return propertyMapping;
1892     }
1893
1894     private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1895         if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1896             return Collections.emptyMap();
1897         }
1898         return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1899                 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1900     }
1901
1902     private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1903         if (Objects.isNull(proxyComponent)) {
1904             return Optional.empty();
1905         }
1906         final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1907         if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1908             proxyProperties.putAll(proxyComponent.getProperties().stream()
1909                     .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1910                             .toMap(PropertyDataDefinition::getName,
1911                                     property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1912         }
1913         return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1914     }
1915
1916     private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1917                                                                  String componentUniqueId) {
1918         if (CollectionUtils.isEmpty(componentInputs)) {
1919             return new HashMap<>();
1920         }
1921         return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1922                 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1923     }
1924
1925     private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1926         if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1927             return Optional.empty();
1928         }
1929         Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1930         //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1931
1932         // always available in the proxy node template
1933         removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1934         return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1935     }
1936
1937     private Configuration getConfiguration() {
1938         return ConfigurationManager.getConfigurationManager().getConfiguration();
1939     }
1940
1941     private static class CustomRepresenter extends Representer {
1942
1943         CustomRepresenter() {
1944             this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1945             this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1946             // null representer is exceptional and it is stored as an instance
1947
1948             // variable.
1949             this.nullRepresenter = new RepresentNull();
1950         }
1951
1952         public boolean validateGetInputValue(final Object valueObj) {
1953             if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1954                 return false;
1955             }
1956             if (valueObj instanceof List) {
1957                 return ((List) valueObj).size() > 1;
1958             }
1959             return true;
1960         }
1961
1962         public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1963             if (valueObj instanceof List) {
1964                 return ((List) valueObj).size() > 1;
1965             }
1966             return false;
1967         }
1968
1969         @Override
1970         protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1971             if (propertyValue == null) {
1972                 return null;
1973             }
1974             // skip not relevant for Tosca property
1975             if ("dependencies".equals(property.getName())) {
1976                 return null;
1977             }
1978             if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1979                 return null;
1980             }
1981             if (javaBean instanceof ToscaPropertyConstraint) {
1982                 return handleToscaPropertyConstraint((ToscaPropertyConstraint) javaBean, property, propertyValue, customTag);
1983             }
1984             removeDefaultP(propertyValue);
1985             NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1986             if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1987                 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1988             }
1989             return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1990         }
1991
1992         private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1993                                                         final Tag customTag) {
1994             final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1995             final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1996             return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1997         }
1998
1999         private void removeDefaultP(final Object propertyValue) {
2000             if (propertyValue instanceof Map) {
2001                 final Map mapPropertyValue = ((Map) propertyValue);
2002                 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
2003                 Object defaultValue = null;
2004                 while (iter.hasNext()) {
2005                     final Map.Entry entry = iter.next();
2006                     if ("_defaultp_".equals(entry.getKey())) {
2007                         defaultValue = entry.getValue();
2008                         iter.remove();
2009                     } else if (entry.getValue() instanceof Map) {
2010                         removeDefaultP(entry.getValue());
2011                     }
2012                 }
2013                 if (defaultValue != null) {
2014                     mapPropertyValue.putIfAbsent("default", defaultValue);
2015                 }
2016             }
2017         }
2018
2019         @Override
2020         protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
2021             // remove the bean type from the output yaml (!! ...)
2022             if (!classTags.containsKey(javaBean.getClass())) {
2023                 addClassTag(javaBean.getClass(), Tag.MAP);
2024             }
2025             return super.representJavaBean(properties, javaBean);
2026         }
2027
2028         private class RepresentToscaAttribute implements Represent {
2029
2030             @Override
2031             public Node representData(Object data) {
2032                 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
2033                 return represent(toscaAttribute.asToscaMap());
2034             }
2035         }
2036
2037         private class RepresentToscaPropertyAssignment implements Represent {
2038
2039             public Node representData(Object data) {
2040                 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
2041                 if (toscaOperationAssignment.getValue() instanceof String) {
2042                     final String stringValue = (String) toscaOperationAssignment.getValue();
2043                     if (isPropertyOrAttributeFunction(stringValue)) {
2044                         return representGetAttribute(stringValue);
2045                     }
2046                     return representScalar(Tag.STR, stringValue);
2047                 }
2048                 return represent(null);
2049             }
2050
2051             public Node representGetAttribute(final String getAttributeFunction) {
2052                 return represent(new Yaml().load(getAttributeFunction));
2053             }
2054
2055             public boolean isPropertyOrAttributeFunction(final String value) {
2056                 try {
2057                     final Yaml yaml = new Yaml();
2058                     final Object yamlObj = yaml.load(value);
2059                     if (!(yamlObj instanceof Map)) {
2060                         return false;
2061                     }
2062                     final Map<String, Object> getAttributeMap = (Map) yamlObj;
2063                     if (getAttributeMap.size() != 1) {
2064                         return false;
2065                     }
2066                     final List<String> functionList = Arrays
2067                             .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
2068                     final Optional<String> function = getAttributeMap.keySet().stream()
2069                             .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
2070                     if (function.isEmpty()) {
2071                         return false;
2072                     }
2073                     final String functionName = function.get();
2074                     final Object getAttributeValueObj = getAttributeMap.get(functionName);
2075                     if (GET_INPUT.getFunctionName().equals(functionName)) {
2076                         return validateGetInputValue(getAttributeValueObj);
2077                     } else {
2078                         return validateGetPropertyOrAttributeValue(getAttributeValueObj);
2079                     }
2080                 } catch (final Exception ignored) {
2081                     return false;
2082                 }
2083             }
2084         }
2085
2086         private class RepresentNull implements Represent {
2087
2088             @Override
2089             public Node representData(Object data) {
2090                 // possible values are here http://yaml.org/type/null.html
2091                 return representScalar(Tag.NULL, "");
2092             }
2093         }
2094     }
2095
2096     private static class UnsortedPropertyUtils extends PropertyUtils {
2097
2098         @Override
2099         protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
2100             Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
2101             return new LinkedHashSet<>(fields);
2102         }
2103     }
2104
2105 }