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