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