Provide input name when declaring service property as input
[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                 if (resource.getTenant() != null) {
587                     toscaMetadata.put(JsonPresentationFields.TENANT.getPresentation(), resource.getTenant());
588                 }
589                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
590                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
591                 break;
592             case SERVICE:
593                 Service service = (Service) component;
594                 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
595                 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
596                 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
597                 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
598                 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
599                 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
600                     service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
601                 if (!isInstance) {
602                     // DE268546
603                     toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
604                     toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
605                     toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
606                 }
607                 break;
608             default:
609                 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
610         }
611         for (final String key : component.getCategorySpecificMetadata().keySet()) {
612             if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
613                 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
614             }
615         }
616         return toscaMetadata;
617     }
618
619     private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
620         if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
621             return INVARIANT_UUID;
622         }
623         return jsonPresentationField.getPresentation();
624     }
625
626     private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
627         final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
628         if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
629             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
630             return Either.right(ToscaError.GENERAL_ERROR);
631         }
632         Map<String, Component> componentCache = new HashMap<>();
633         if (!ModelConverter.isAtomicComponent(component)) {
634             final List<Map<String, Map<String, String>>> additionalImports =
635                 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
636             List<Triple<String, String, Component>> dependencies = new ArrayList<>();
637             Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
638             final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
639             if (!substituteTypeImportEntry.isEmpty()) {
640                 additionalImports.add(substituteTypeImportEntry);
641             }
642             List<ComponentInstance> componentInstances = component.getComponentInstances();
643             if (componentInstances != null && !componentInstances.isEmpty()) {
644                 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
645             }
646             toscaTemplate.setDependencies(dependencies);
647             toscaTemplate.setImports(additionalImports);
648         } else {
649             log.debug("currently imports supported for VF and service only");
650         }
651         return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
652     }
653
654     private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
655                                                                                    final Map<String, ArtifactDefinition> toscaArtifacts) {
656
657         if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
658             return Collections.emptyMap();
659         }
660         if (MapUtils.isEmpty(toscaArtifacts)) {
661             return Collections.emptyMap();
662         }
663         final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
664         if (artifactDefinition == null) {
665             return Collections.emptyMap();
666         }
667         final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
668         return Map.of(importEntryName,
669             Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
670         );
671     }
672
673     private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
674         return getConfiguration().getDefaultImports();
675     }
676
677     private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
678                                   final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
679         log.debug("createDependency componentCache {}", componentCache);
680         Component componentRI = componentCache.get(componentInstance.getComponentUid());
681         if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
682             // all resource must be only once!
683             final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
684             if ((resource.isRight()) && (log.isDebugEnabled())) {
685                 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
686                     componentInstance.getUniqueId());
687                 return;
688             }
689             final Component fetchedComponent = resource.left().value();
690             componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
691             addDependencies(imports, dependencies, componentRI);
692         }
693     }
694
695     /**
696      * Sets a componentCache from the given component/resource.
697      */
698     private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
699                                         final Component fetchedComponent) {
700         componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
701         if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
702             || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
703             final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
704                 .getToscaFullElement(componentInstance.getSourceModelUid());
705             if (sourceService.isRight() && (log.isDebugEnabled())) {
706                 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
707                     componentInstance.getUniqueId());
708             }
709             final Component fetchedSource = sourceService.left().value();
710             componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
711             return fetchedSource;
712         }
713         return fetchedComponent;
714     }
715
716     /**
717      * Retrieves all derived_from nodes and stores it in a predictable order.
718      */
719     private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
720                                  final Component fetchedComponent) {
721         final Set<Component> componentsList = new LinkedHashSet<>();
722         if (fetchedComponent instanceof Resource) {
723             log.debug("fetchedComponent is a resource {}", fetchedComponent);
724             final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
725             if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
726                 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
727                     log.debug("Started entry.getValue() : {}", entry.getValue());
728                     if (!NATIVE_ROOT.equals(entry.getValue())) {
729                         Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
730                         if (resourcefetched != null && resourcefetched.isLeft()) {
731                             componentsList.add(resourcefetched.left().value());
732                         }
733                     }
734                 });
735                 setImports(imports, dependencies, componentsList);
736             } else {
737                 setImports(imports, dependencies, fetchedComponent);
738             }
739         }
740     }
741
742     /**
743      * Returns all derived_from nodes found.
744      */
745     private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
746         final Resource parentResource = (Resource) fetchedComponent;
747         Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
748         if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
749             componentsList.add(fetchedComponent);
750             for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
751                 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
752                     .getToscaElement(componentInstance.getComponentUid());
753                 if (resourcefetched != null && resourcefetched.isLeft()) {
754                     final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
755                     if (MapUtils.isNotEmpty(derivedWithId)) {
756                         derivedFromMapOfIdToName.putAll(derivedWithId);
757                     }
758                 }
759             }
760         } else {
761             derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
762         }
763         log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
764         return Optional.ofNullable(derivedFromMapOfIdToName);
765     }
766
767     /**
768      * Creates a resource map and adds it to the import list.
769      */
770     private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
771                             final Set<Component> componentsList) {
772         componentsList.forEach(component -> setImports(imports, dependencies, component));
773     }
774
775     private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
776                             final Component component) {
777         final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
778         final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
779         if (artifactDefinition != null) {
780             final Map<String, String> files = new HashMap<>();
781             final String artifactName = artifactDefinition.getArtifactName();
782             files.put(IMPORTS_FILE_KEY, artifactName);
783             final StringBuilder keyNameBuilder = new StringBuilder();
784             keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
785             keyNameBuilder.append("-");
786             keyNameBuilder.append(component.getName());
787             addImports(imports, keyNameBuilder, files);
788             dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
789             if (!ModelConverter.isAtomicComponent(component)) {
790                 final Map<String, String> interfaceFiles = new HashMap<>();
791                 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
792                 keyNameBuilder.append("-interface");
793                 addImports(imports, keyNameBuilder, interfaceFiles);
794             }
795         }
796     }
797
798     /**
799      * Adds the found resource to the import definition list.
800      */
801     private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
802                             final Map<String, String> files) {
803         final String mapKey = keyNameBuilder.toString();
804         if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
805             final Map<String, Map<String, String>> importsListMember = new HashMap<>();
806             importsListMember.put(keyNameBuilder.toString(), files);
807             imports.add(importsListMember);
808         }
809     }
810
811     private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
812                                                               Map<String, ToscaNodeType> nodeTypes) {
813         return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
814     }
815
816     public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
817                                                                       ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
818                                                                       boolean isAssociatedComponent) {
819         log.debug("start convert node type for {}", component.getUniqueId());
820         ToscaNodeType toscaNodeType = createNodeType(component);
821         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
822             .getAllInterfaceLifecycleTypes(component.getModel());
823         if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
824             log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
825             return Either.right(ToscaError.GENERAL_ERROR);
826         }
827         if (lifecycleTypeEither.isLeft()) {
828             List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
829                 .collect(Collectors.toList());
830             toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
831         }
832         final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
833         if (dataTypesEither.isRight()) {
834             log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
835             return Either.right(ToscaError.GENERAL_ERROR);
836         }
837         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
838         List<InputDefinition> inputDef = component.getInputs();
839         interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
840         final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
841         if (!toscaAttributeMap.isEmpty()) {
842             toscaNodeType.setAttributes(toscaAttributeMap);
843         }
844         final var mergedProperties = convertInputsToProperties(dataTypes, inputDef, component.getUniqueId());
845         if (CollectionUtils.isNotEmpty(component.getProperties())) {
846             List<PropertyDefinition> properties = component.getProperties();
847             Map<String, ToscaProperty> convertedProperties = properties.stream()
848                 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
849                     .toMap(PropertyDataDefinition::getName,
850                         property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
851             // merge component properties and inputs properties
852             mergedProperties.putAll(convertedProperties);
853         }
854         if (MapUtils.isNotEmpty(mergedProperties)) {
855             toscaNodeType.setProperties(mergedProperties);
856         }
857         /* convert private data_types */
858         List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
859         if (CollectionUtils.isNotEmpty(privateDataTypes)) {
860             Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
861             for (DataTypeDefinition dataType : privateDataTypes) {
862                 log.debug("Emitting private data type: component.name={} dataType.name={}",
863                     component.getNormalizedName(), dataType.getName());
864                 ToscaDataType toscaDataType = new ToscaDataType();
865                 toscaDataType.setDerived_from(dataType.getDerivedFromName());
866                 toscaDataType.setDescription(dataType.getDescription());
867                 toscaDataType.setVersion(dataType.getVersion());
868                 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
869                     toscaDataType.setProperties(dataType.getProperties().stream()
870                         .collect(Collectors.toMap(
871                             PropertyDataDefinition::getName,
872                             s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
873                             (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
874                                 toscaProperty)
875                         )));
876                 }
877                 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
878             }
879             toscaNode.setData_types(toscaDataTypeMap);
880         }
881
882         // Extracted to method for code reuse
883         return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
884     }
885
886     private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
887                                                 final ToscaProperty toscaProperty) {
888         final Optional<DataTypeDefinition> match = privateDataTypes.stream()
889             .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
890         return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
891     }
892
893     private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
894                                                                  final Map<String, DataTypeDefinition> dataTypes) {
895         if (CollectionUtils.isEmpty(attributeList)) {
896             return Collections.emptyMap();
897         }
898         final AttributeConverter converter = new AttributeConverter(dataTypes);
899         final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
900         for (final AttributeDefinition attributeDefinition : attributeList) {
901             toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
902         }
903         return toscaAttributeMap;
904     }
905
906     private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
907                                                                        Component component, ToscaTemplate toscaNode,
908                                                                        Map<String, ToscaNodeType> nodeTypes,
909                                                                        ToscaNodeType toscaNodeType,
910                                                                        Map<String, DataTypeDefinition> dataTypes) {
911         Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
912             dataTypes);
913         if (capabilities.isRight()) {
914             return Either.right(capabilities.right().value());
915         }
916         toscaNodeType = capabilities.left().value();
917         log.debug("Capabilities converted for {}", component.getUniqueId());
918
919         Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
920             .convertRequirements(componentsCache, component, toscaNodeType);
921         if (requirements.isRight()) {
922             return Either.right(requirements.right().value());
923         }
924         toscaNodeType = requirements.left().value();
925         log.debug("Requirements converted for {}", component.getUniqueId());
926
927         String toscaResourceName;
928         switch (component.getComponentType()) {
929             case RESOURCE:
930                 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
931                     .getMetadataDataDefinition()).getToscaResourceName();
932                 break;
933             case SERVICE:
934                 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
935                     + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
936                 break;
937             default:
938                 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
939                 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
940         }
941
942         nodeTypes.put(toscaResourceName, toscaNodeType);
943         toscaNode.setNode_types(nodeTypes);
944         log.debug("finish convert node type for {}", component.getUniqueId());
945         return Either.left(toscaNode);
946     }
947
948     private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
949                                                                                     final Map<String, Component> componentCache,
950                                                                                     final Map<String, DataTypeDefinition> dataTypes,
951                                                                                     final ToscaTopolgyTemplate topologyTemplate) {
952
953         final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
954         final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
955         final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
956         final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
957         final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
958
959         Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
960         log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
961         final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
962
963         Map<String, ToscaGroupTemplate> groupsMap = null;
964         for (final ComponentInstance componentInstance : component.getComponentInstances()) {
965             ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
966             if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
967                 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
968             }
969             if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
970                 List<Object> occur = new ArrayList<>();
971                 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
972                 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
973                 nodeTemplate.setOccurrences(occur);
974             }
975             if (componentInstance.getInstanceCount() != null) {
976                 ObjectMapper objectMapper = new ObjectMapper();
977                 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
978                 if (obj != null) {
979                     Map<String, String> map = objectMapper.convertValue(obj, Map.class);
980                     nodeTemplate.setInstance_count(map);
981                 }
982             }
983             nodeTemplate.setType(componentInstance.getToscaComponentName());
984             nodeTemplate.setDirectives(componentInstance.getDirectives());
985             NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
986             if(nodeFilter != null && nodeFilter.hasData()){
987                 nodeTemplate.setNode_filter(nodeFilter);
988             }
989             final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
990                 .getOriginComponent(componentCache, componentInstance);
991             if (originComponentRes.isRight()) {
992                 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
993                 break;
994             }
995             final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
996                 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
997             if (requirements.isRight()) {
998                 convertNodeTemplatesRes = Either.right(requirements.right().value());
999                 break;
1000             }
1001             final String instanceUniqueId = componentInstance.getUniqueId();
1002             log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1003
1004             nodeTemplate = requirements.left().value();
1005
1006             final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1007
1008             if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1009                 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1010                 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1011             } else {
1012                 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1013             }
1014
1015             final Either<ToscaNodeTemplate, ToscaError> capabilities =
1016                 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1017             if (capabilities.isRight()) {
1018                 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1019                 break;
1020             }
1021             log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1022
1023             nodeTemplate = capabilities.left().value();
1024             final Map<String, Object> props = new HashMap<>();
1025             final Map<String, Object> attribs = new HashMap<>();
1026
1027             if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1028                 // Adds the properties of parent component to map
1029                 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1030                 addAttributesOfParentComponent(originalComponent, attribs);
1031             }
1032
1033             if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1034                 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1035             }
1036             if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1037                 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1038             }
1039
1040             if (componentInstancesInputs != null
1041                 && componentInstancesInputs.containsKey(instanceUniqueId)
1042                 && !isComponentOfTypeServiceProxy(componentInstance)) {
1043                 //For service proxy the inputs are already handled under instance properties above
1044                 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1045             }
1046
1047             //M3[00001] - NODE TEMPLATE INTERFACES  - START
1048             handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1049             //M3[00001] - NODE TEMPLATE INTERFACES  - END
1050             if (MapUtils.isNotEmpty(props)) {
1051                 nodeTemplate.setProperties(props);
1052             }
1053             if (MapUtils.isNotEmpty(attribs)) {
1054                 nodeTemplate.setAttributes(attribs);
1055             }
1056
1057             final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1058             if (CollectionUtils.isNotEmpty(groupInstances)) {
1059                 if (groupsMap == null) {
1060                     groupsMap = new HashMap<>();
1061                 }
1062                 for (final GroupInstance groupInst : groupInstances) {
1063                     if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1064                         groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1065                     }
1066                 }
1067             }
1068
1069             nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1070         }
1071         if (groupsMap != null) {
1072             log.debug("instance groups added");
1073             topologyTemplate.addGroups(groupsMap);
1074         }
1075         if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1076             ((Service) component).getForwardingPaths())) {
1077             log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1078             ForwardingPathToscaUtil
1079                 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1080             log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1081         }
1082         if (convertNodeTemplatesRes == null) {
1083             convertNodeTemplatesRes = Either.left(nodeTemplates);
1084         }
1085         log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1086         return convertNodeTemplatesRes;
1087     }
1088
1089     private Object convertToToscaObject(String value) {
1090         try {
1091             ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1092             StringReader reader = new StringReader(value);
1093             JsonReader jsonReader = new JsonReader(reader);
1094             jsonReader.setLenient(true);
1095             JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1096             if (jsonElement.isJsonObject()) {
1097                 JsonObject jsonObj = jsonElement.getAsJsonObject();
1098                 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1099                     return mapConverterInst.handleComplexJsonValue(jsonElement);
1100                 }
1101             }
1102             return null;
1103         } catch (Exception e) {
1104             log.debug("convertToToscaValue failed to parse json value :", e);
1105             return null;
1106         }
1107     }
1108
1109     private Object parseToIntIfPossible(final String value) {
1110         final Integer intValue = Ints.tryParse(value);
1111         return intValue == null ? value : intValue;
1112     }
1113
1114     private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1115                                           ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1116                                           ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1117
1118         if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1119             nodeTemplate.setInterfaces(null);
1120             return;
1121         }
1122
1123         final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1124
1125         final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1126         currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1127
1128         final Map<String, Object> interfaceMap = interfacesOperationsConverter
1129             .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1130
1131         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1132         nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1133     }
1134
1135     private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1136         return Objects.nonNull(componentInstance.getOriginType())
1137             && componentInstance.getOriginType().getValue().equals("Service Proxy");
1138     }
1139
1140     private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1141                                             Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1142                                             String instanceUniqueId, Map<String, Object> props) {
1143
1144         List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1145         if (instanceInputsList != null) {
1146             instanceInputsList.forEach(input -> {
1147                 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1148                     : input.getDefaultValue();
1149                 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1150             });
1151         }
1152     }
1153
1154     private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1155                                                   final Map<String, DataTypeDefinition> dataTypes,
1156                                                   final String instanceUniqueId,
1157                                                   final Map<String, Object> props) {
1158
1159         if (isNotEmpty(componentInstancesProperties)) {
1160             componentInstancesProperties.get(instanceUniqueId)
1161                 // Converts and adds each value to property map
1162                 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1163         }
1164     }
1165
1166     private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1167                                                   final String instanceUniqueId,
1168                                                   final Map<String, Object> attribs) {
1169
1170         if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1171             componentInstancesAttributes.get(instanceUniqueId)
1172                 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1173         }
1174     }
1175
1176     private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1177                                                 Component componentOfInstance, Map<String, Object> props) {
1178
1179         List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1180         if (isNotEmpty(componentProperties)) {
1181             componentProperties.stream()
1182                 // Filters out properties with empty default values
1183                 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1184                 // Converts and adds each value to property map
1185                 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1186         }
1187     }
1188
1189     private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1190
1191         final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1192         if (isNotEmpty(componentAttributes)) {
1193             componentAttributes.stream()
1194                 // Filters out Attributes with empty default values
1195                 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1196                 // Converts and adds each value to attribute map
1197                 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1198         }
1199     }
1200
1201     private ToscaNodeType createNodeType(Component component) {
1202         ToscaNodeType toscaNodeType = new ToscaNodeType();
1203         if (ModelConverter.isAtomicComponent(component)) {
1204             if (((Resource) component).getDerivedFrom() != null) {
1205                 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1206             }
1207             toscaNodeType.setDescription(component.getDescription());
1208         } else {
1209             String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1210                 : NATIVE_ROOT;
1211             toscaNodeType.setDerived_from(derivedFrom);
1212         }
1213         return toscaNodeType;
1214     }
1215
1216     private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1217
1218         Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1219         Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1220         List<ComponentInstance> componentInstances = container.getComponentInstances();
1221         if (CollectionUtils.isEmpty(componentInstances)) {
1222             return res;
1223         }
1224         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1225         componentInstances.stream()
1226             .filter(this::isComponentOfTypeServiceProxy)
1227             .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1228         if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1229             return res;
1230         }
1231         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1232             Component serviceComponent;
1233             ComponentParametersView componentParametersView = new ComponentParametersView();
1234             componentParametersView.disableAll();
1235             componentParametersView.setIgnoreInterfaces(false);
1236             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1237                 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1238             if (service.isRight()) {
1239                 log.debug("Failed to fetch original service component with id {} for instance {}",
1240                     entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1241                 return Either.right(ToscaError.GENERAL_ERROR);
1242             } else {
1243                 serviceComponent = service.left().value();
1244             }
1245
1246             Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1247                 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1248             if (lifecycleTypeEither.isRight()) {
1249                 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1250                 return Either.right(ToscaError.GENERAL_ERROR);
1251             }
1252
1253             List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1254                 .map(InterfaceDataDefinition::getType)
1255                 .collect(Collectors.toList());
1256             //Add interface types for local interfaces in the original service component for proxy
1257             Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1258                 allGlobalInterfaceTypes);
1259             if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1260                 proxyInterfaceTypes.putAll(localInterfaceTypes);
1261             }
1262
1263         }
1264         return Either.left(proxyInterfaceTypes);
1265     }
1266
1267     private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1268                                                                                 Component container) {
1269
1270         Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1271         Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1272
1273         List<ComponentInstance> componentInstances = container.getComponentInstances();
1274
1275         if (componentInstances == null || componentInstances.isEmpty()) {
1276             return res;
1277         }
1278         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1279         List<ComponentInstance> proxyInst = componentInstances.stream()
1280             .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1281             .collect(Collectors.toList());
1282         if (proxyInst != null && !proxyInst.isEmpty()) {
1283             for (ComponentInstance inst : proxyInst) {
1284                 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1285             }
1286         }
1287
1288         if (serviceProxyInstanceList.isEmpty()) {
1289             return res;
1290         }
1291         Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1292             .getLatestByName("serviceProxy", null);
1293         if (serviceProxyOrigin.isRight()) {
1294             log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1295                 serviceProxyOrigin.right().value());
1296             return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1297         }
1298         Component origComponent = serviceProxyOrigin.left().value();
1299
1300         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1301             Component serviceComponent = null;
1302             ComponentParametersView componentParametersView = new ComponentParametersView();
1303             componentParametersView.disableAll();
1304             componentParametersView.setIgnoreCategories(false);
1305             componentParametersView.setIgnoreProperties(false);
1306             componentParametersView.setIgnoreInputs(false);
1307             componentParametersView.setIgnoreInterfaces(false);
1308             componentParametersView.setIgnoreRequirements(false);
1309             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1310                 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1311             if (service.isRight()) {
1312                 log.debug("Failed to fetch resource with id {} for instance {}",
1313                     entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1314             } else {
1315                 serviceComponent = service.left().value();
1316             }
1317
1318             ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1319                 entryProxy.getValue());
1320             nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1321         }
1322
1323         return Either.left(nodeTypesMap);
1324     }
1325
1326     private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1327                                                     final Component container, final ToscaTemplate toscaNode) {
1328         final List<ComponentInstance> componentInstances = container.getComponentInstances();
1329
1330         if (CollectionUtils.isEmpty(componentInstances)) {
1331             return;
1332         }
1333         final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1334             .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1335             .collect(Collectors.toList());
1336         if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1337             for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1338                 final Map<String, ToscaNodeType> nodeTypes =
1339                     toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1340                 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1341                     nodeTypes, true);
1342             }
1343         }
1344     }
1345
1346     private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1347                                               Component proxyComponent, ComponentInstance componentInstance) {
1348         ToscaNodeType toscaNodeType = new ToscaNodeType();
1349         String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1350
1351         toscaNodeType.setDerived_from(derivedFrom);
1352         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1353             origComponent.getModel());
1354         if (dataTypesEither.isRight()) {
1355             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1356         }
1357         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1358         Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1359             .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1360
1361         if (MapUtils.isNotEmpty(capabilities)) {
1362             toscaNodeType.setCapabilities(capabilities);
1363         }
1364         List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1365             .convertProxyRequirements(componentCache, componentInstance);
1366         if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1367             toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1368         }
1369         Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1370         proxyProperties.ifPresent(toscaNodeType::setProperties);
1371
1372         Map<String, Object> interfaceMap = new HashMap<>();
1373         if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1374             final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1375             if (proxyInterfaces.isPresent()) {
1376                 interfaceMap = proxyInterfaces.get();
1377             }
1378         } else {
1379             interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1380
1381         }
1382         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1383         toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1384
1385         return toscaNodeType;
1386     }
1387
1388     private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1389                                                                                        ComponentInstance componentInstance,
1390                                                                                        List<RequirementCapabilityRelDef> relations,
1391                                                                                        ToscaNodeTemplate nodeTypeTemplate,
1392                                                                                        Component originComponent,
1393                                                                                        Map<String, Component> componentCache) {
1394
1395         final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1396             relations);
1397         if (isNotEmpty(requirementDefinitionList)) {
1398             try {
1399                 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1400                     requirementDefinitionList, originComponent, componentCache);
1401                 if (!toscaRequirements.isEmpty()) {
1402                     nodeTypeTemplate.setRequirements(toscaRequirements);
1403                 }
1404             } catch (final Exception e) {
1405                 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1406                     componentInstance.getName(), e);
1407                 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1408             }
1409         }
1410         log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1411         return Either.left(nodeTypeTemplate);
1412     }
1413
1414     private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1415                                                                           final ComponentInstance componentInstance,
1416                                                                           final List<RequirementCapabilityRelDef> filteredRelations,
1417                                                                           final Component originComponent,
1418                                                                           final Map<String, Component> componentCache)
1419         throws ToscaExportException {
1420
1421         final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1422         for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1423             final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1424                 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1425             toscaRequirements.add(toscaTemplateRequirementMap);
1426         }
1427
1428         return toscaRequirements;
1429     }
1430
1431     private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1432                                                                  List<RequirementCapabilityRelDef> relations) {
1433         return relations.stream()
1434             .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1435     }
1436
1437     private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1438                                                                    final Component fromOriginComponent,
1439                                                                    final List<ComponentInstance> instancesList,
1440                                                                    final RequirementCapabilityRelDef relationshipDefinition,
1441                                                                    final Map<String, Component> componentCache)
1442         throws ToscaExportException {
1443
1444         final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1445         final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1446             .getRelationships().get(0);
1447         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1448
1449         final ComponentInstance toInstance = instancesList.stream()
1450             .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1451             .findFirst().orElse(null);
1452         if (toInstance == null) {
1453             final String errorMsg = String
1454                 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1455                     relationshipDefinition.getToNode());
1456             log.debug(errorMsg);
1457             throw new ToscaExportException(errorMsg);
1458         }
1459         final Optional<RequirementDefinition> reqOpt =
1460             findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1461         if (reqOpt.isEmpty()) {
1462             final String errorMsg = String
1463                 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1464                     relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1465             log.debug(errorMsg);
1466             throw new ToscaExportException(errorMsg);
1467         }
1468         final ComponentParametersView filter = new ComponentParametersView(true);
1469         filter.setIgnoreComponentInstances(false);
1470         filter.setIgnoreCapabilities(false);
1471         filter.setIgnoreGroups(false);
1472         final Either<Component, StorageOperationStatus> getOriginRes =
1473             toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1474         if (getOriginRes.isRight()) {
1475             final String errorMsg = String.format(
1476                 "Failed to build substituted name for the requirement %s. "
1477                     + "Failed to get an origin component with uniqueId %s",
1478                 reqOpt.get().getName(), toInstance.getActualComponentUid());
1479             log.debug(errorMsg);
1480             throw new ToscaExportException(errorMsg);
1481         }
1482         final Component toOriginComponent = getOriginRes.left().value();
1483         Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1484             .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1485         if (capOpt.isEmpty()) {
1486             capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1487             if (capOpt.isEmpty()) {
1488                 final String errorMsg = String
1489                     .format("Failed to find a capability with name %s on a component with uniqueId %s",
1490                         relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1491                 log.debug(errorMsg);
1492                 throw new ToscaExportException(errorMsg);
1493             }
1494         }
1495         return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1496             capabilityRequirementRelationship, toInstance, componentCache);
1497     }
1498
1499     private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1500                                                  CapabilityDefinition capability) {
1501         return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1502             && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1503     }
1504
1505     private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1506                                                           Component toOriginComponent, Component fromOriginComponent,
1507                                                           RequirementDefinition requirement) {
1508         Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1509             .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1510         if (!cap.isPresent()) {
1511             log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1512                 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1513         }
1514         return cap;
1515     }
1516
1517     private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1518                                                                    final Component toOriginComponent,
1519                                                                    final CapabilityDefinition capability,
1520                                                                    final RequirementDefinition requirement,
1521                                                                    final CapabilityRequirementRelationship capabilityRequirementRelationship,
1522                                                                    final ComponentInstance toInstance,
1523                                                                    final Map<String, Component> componentCache)
1524         throws ToscaExportException {
1525
1526         List<String> reducedPath = capability.getPath();
1527         if (capability.getOwnerId() != null) {
1528             reducedPath = capabilityRequirementConverter
1529                 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1530         }
1531         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1532         final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1533             toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1534         if (capabilityNameEither.isRight()) {
1535             final String errorMsg = String.format(
1536                 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1537                 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1538             log.debug(
1539                 errorMsg);
1540             throw new ToscaExportException(errorMsg);
1541         }
1542         final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1543             .buildSubstitutedName(componentCache, fromOriginComponent,
1544                 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1545         if (requirementNameEither.isRight()) {
1546             final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1547                     + "with name %s on a component with uniqueId %s",
1548                 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1549             log.debug(errorMsg);
1550             throw new ToscaExportException(errorMsg);
1551         }
1552         final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1553         final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1554         toscaRequirement.setNode(toInstance.getName());
1555         toscaRequirement.setCapability(capabilityNameEither.left().value());
1556         if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1557             toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1558         }
1559         toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1560         return toscaReqMap;
1561     }
1562
1563     private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1564                                                             Map<String, List<RequirementDefinition>> reqMap,
1565                                                             RelationshipInfo reqAndRelationshipPair,
1566                                                             String fromInstanceId) {
1567         for (List<RequirementDefinition> reqList : reqMap.values()) {
1568             Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1569                     r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1570                 .findFirst();
1571             if (reqOpt.isPresent()) {
1572                 return reqOpt;
1573             }
1574         }
1575         return Optional.empty();
1576     }
1577
1578     /**
1579      * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1580      * 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
1581      * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1582      */
1583     private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1584                                                   RequirementDefinition requirement, String fromInstanceId) {
1585         if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1586             log.debug("Failed to find a requirement with name {} and  reqAndRelationshipPair {}", requirement.getName(),
1587                 reqAndRelationshipPair.getRequirement());
1588             return false;
1589         }
1590         return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1591             originComponent);
1592     }
1593
1594     private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1595                                                Component originComponent) {
1596         return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1597             isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1598                 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1599     }
1600
1601     private boolean isCvfc(Component component) {
1602         return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1603     }
1604
1605     private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1606                                                                                              final Map<String, Component> componentCache) {
1607         Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1608             capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1609         if (toscaCapabilitiesRes.isRight()) {
1610             log.debug("Failed convert capabilities for the component {}. ", component.getName());
1611             return Either.right(toscaCapabilitiesRes.right().value());
1612         }
1613         if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1614             log.debug("Finish convert capabilities for the component {}. ", component.getName());
1615             return Either.left(toscaCapabilitiesRes.left().value());
1616         }
1617         log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1618
1619         return Either.left(Collections.emptyMap());
1620     }
1621
1622     private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1623                                                                   Map<String, DataTypeDefinition> dataTypes) {
1624         Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1625         if (!toscaCapabilities.isEmpty()) {
1626             nodeType.setCapabilities(toscaCapabilities);
1627         }
1628         log.debug("Finish convert Capabilities for node type");
1629         return Either.left(nodeType);
1630     }
1631
1632     private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1633         if (artifacts == null) {
1634             return null;
1635         }
1636         Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1637         for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1638             ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1639             artifact.setFile(entry.getValue().getFile());
1640             artifact.setType(entry.getValue().getType());
1641             artifact.setProperties(entry.getValue().getProperties());
1642             arts.put(entry.getKey(), artifact);
1643         }
1644         return arts;
1645     }
1646
1647     private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1648         if (inNodeFilter == null) {
1649             return null;
1650         }
1651         NodeFilter nodeFilter = new NodeFilter();
1652         ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1653         ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1654         List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1655         copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1656         if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1657             nodeFilter.setCapabilities(capabilitiesCopy);
1658         }
1659         final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1660         if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1661             nodeFilter.setProperties(propertiesCopy);
1662         }
1663         nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1664         nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1665         return nodeFilter;
1666     }
1667
1668     private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1669         if (substitutionFilterDataDefinition == null) {
1670             return null;
1671         }
1672         NodeFilter nodeFilter = new NodeFilter();
1673         final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1674         if (!propertiesCopy.isEmpty()) {
1675             nodeFilter.setProperties(propertiesCopy);
1676         }
1677         nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1678         return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1679     }
1680
1681     private Object cloneToscaId(Object toscaId) {
1682         return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1683     }
1684
1685     private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1686         String objectAsYml = yamlUtil.objectToYaml(objToClone);
1687         return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1688     }
1689
1690     private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1691                                                     List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1692         if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1693             .isEmpty()) {
1694             return;
1695         }
1696         for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1697             Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1698             final var capabilityFilter = new CapabilityFilter();
1699             capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1700             capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1701             capabilitiesCopy.add(capabilityFilterCopyMap);
1702         }
1703     }
1704
1705     private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1706         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1707             return Collections.emptyList();
1708         }
1709         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1710         Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1711         for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1712             final String propertyName = propertyFilter.getName();
1713             for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1714                 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1715                     if (constraints == null) {
1716                         constraints = new ArrayList<>();
1717                     }
1718                     constraints.add(buildNodeFilterValue(filterConstraint));
1719                     return constraints;
1720                 });
1721             }
1722         }
1723         propertyFilterDefinitionMap.entrySet().stream()
1724             .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1725             .forEach(propertiesCopy::add);
1726         return propertiesCopy;
1727     }
1728
1729     private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1730         final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1731
1732         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1733             return Collections.emptyList();
1734         }
1735         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1736         Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1737         for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1738             final String propertyName = propertyFilter.getName();
1739             for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1740                 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1741                     if (constraints == null) {
1742                         constraints = new ArrayList<>();
1743                     }
1744                     constraints.add(buildNodeFilterValue(filterConstraint));
1745                     return constraints;
1746                 });
1747             }
1748         }
1749         propertyFilterDefinitionMap.entrySet().stream()
1750             .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1751             .forEach(propertiesCopy::add);
1752         return propertiesCopy;
1753     }
1754
1755     private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1756         if (filterConstraint.getValue() instanceof ToscaFunction) {
1757             return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1758         } else {
1759             return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1760         }
1761     }
1762
1763     private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1764         if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1765             return Collections.emptyMap();
1766         }
1767         Map<String, String[]> propertyMapping = new HashMap<>();
1768         List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect(
1769             Collectors.toList());
1770
1771         if (CollectionUtils.isNotEmpty(propertyMappedInputList)) {
1772             propertyMappedInputList.forEach(inputDefinition -> {
1773                 if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) {
1774                     Optional<PropertyDefinition> property = component.getProperties().stream()
1775                         .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst();
1776                     if (property.isPresent()) {
1777                         propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()});
1778                     }
1779                 } else {
1780                     propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()});
1781                 }
1782             });
1783         }
1784         return propertyMapping;
1785     }
1786
1787     private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1788         if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1789             return Collections.emptyMap();
1790         }
1791         return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1792             .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1793     }
1794
1795     private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1796         if (Objects.isNull(proxyComponent)) {
1797             return Optional.empty();
1798         }
1799         final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1800         if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1801             proxyProperties.putAll(proxyComponent.getProperties().stream()
1802                 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1803                     .toMap(PropertyDataDefinition::getName,
1804                         property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1805         }
1806         return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1807     }
1808
1809     private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1810                                                              String componentUniqueId) {
1811         if (CollectionUtils.isEmpty(componentInputs)) {
1812             return new HashMap<>();
1813         }
1814         return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1815             .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1816     }
1817
1818     private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1819         if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1820             return Optional.empty();
1821         }
1822         Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1823         //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1824
1825         // always available in the proxy node template
1826         removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1827         return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1828     }
1829
1830     private static class CustomRepresenter extends Representer {
1831
1832         CustomRepresenter() {
1833             super();
1834             this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1835             this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1836             // null representer is exceptional and it is stored as an instance
1837
1838             // variable.
1839             this.nullRepresenter = new RepresentNull();
1840         }
1841
1842         public boolean validateGetInputValue(final Object valueObj) {
1843             if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1844                 return false;
1845             }
1846             if (valueObj instanceof List) {
1847                 return ((List) valueObj).size() > 1;
1848             }
1849             return true;
1850         }
1851
1852         public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1853             if (valueObj instanceof List) {
1854                 return ((List) valueObj).size() > 1;
1855             }
1856             return false;
1857         }
1858
1859         @Override
1860         protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1861             if (propertyValue == null) {
1862                 return null;
1863             }
1864             // skip not relevant for Tosca property
1865             if ("dependencies".equals(property.getName())) {
1866                 return null;
1867             }
1868             if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1869                 return null;
1870             }
1871             if (javaBean instanceof ToscaPropertyConstraint) {
1872                 return handleToscaPropertyConstraint((ToscaPropertyConstraint)javaBean, property, propertyValue, customTag);
1873             }
1874             removeDefaultP(propertyValue);
1875             NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1876             if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1877                 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1878             }
1879             return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1880         }
1881         
1882         private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1883                 final Tag customTag) {
1884             final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1885             final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1886             return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1887         }
1888
1889         private void removeDefaultP(final Object propertyValue) {
1890             if (propertyValue instanceof Map) {
1891                 final Map mapPropertyValue = ((Map) propertyValue);
1892                 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1893                 Object defaultValue = null;
1894                 while (iter.hasNext()) {
1895                     final Map.Entry entry = iter.next();
1896                     if ("_defaultp_".equals(entry.getKey())) {
1897                         defaultValue = entry.getValue();
1898                         iter.remove();
1899                     } else if (entry.getValue() instanceof Map) {
1900                         removeDefaultP(entry.getValue());
1901                     }
1902                 }
1903                 if (defaultValue != null) {
1904                     mapPropertyValue.putIfAbsent("default", defaultValue);
1905                 }
1906             }
1907         }
1908
1909         @Override
1910         protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1911             // remove the bean type from the output yaml (!! ...)
1912             if (!classTags.containsKey(javaBean.getClass())) {
1913                 addClassTag(javaBean.getClass(), Tag.MAP);
1914             }
1915             return super.representJavaBean(properties, javaBean);
1916         }
1917
1918         private class RepresentToscaAttribute implements Represent {
1919
1920             @Override
1921             public Node representData(Object data) {
1922                 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1923                 return represent(toscaAttribute.asToscaMap());
1924             }
1925         }
1926
1927         private class RepresentToscaPropertyAssignment implements Represent {
1928
1929             public Node representData(Object data) {
1930                 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1931                 if (toscaOperationAssignment.getValue() instanceof String) {
1932                     final String stringValue = (String) toscaOperationAssignment.getValue();
1933                     if (isPropertyOrAttributeFunction(stringValue)) {
1934                         return representGetAttribute(stringValue);
1935                     }
1936                     return representScalar(Tag.STR, stringValue);
1937                 }
1938                 return represent(null);
1939             }
1940
1941             public Node representGetAttribute(final String getAttributeFunction) {
1942                 return represent(new Yaml().load(getAttributeFunction));
1943             }
1944
1945             public boolean isPropertyOrAttributeFunction(final String value) {
1946                 try {
1947                     final Yaml yaml = new Yaml();
1948                     final Object yamlObj = yaml.load(value);
1949                     if (!(yamlObj instanceof Map)) {
1950                         return false;
1951                     }
1952                     final Map<String, Object> getAttributeMap = (Map) yamlObj;
1953                     if (getAttributeMap.size() != 1) {
1954                         return false;
1955                     }
1956                     final List<String> functionList = Arrays
1957                         .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1958                     final Optional<String> function = getAttributeMap.keySet().stream()
1959                         .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1960                     if (function.isEmpty()) {
1961                         return false;
1962                     }
1963                     final String functionName = function.get();
1964                     final Object getAttributeValueObj = getAttributeMap.get(functionName);
1965                     if (GET_INPUT.getFunctionName().equals(functionName)) {
1966                         return validateGetInputValue(getAttributeValueObj);
1967                     } else {
1968                         return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1969                     }
1970                 } catch (final Exception ignored) {
1971                     return false;
1972                 }
1973             }
1974         }
1975
1976         private class RepresentNull implements Represent {
1977
1978             @Override
1979             public Node representData(Object data) {
1980                 // possible values are here http://yaml.org/type/null.html
1981                 return representScalar(Tag.NULL, "");
1982             }
1983         }
1984     }
1985
1986     private static class UnsortedPropertyUtils extends PropertyUtils {
1987
1988         @Override
1989         protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1990             Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1991             return new LinkedHashSet<>(fields);
1992         }
1993     }
1994
1995     private Configuration getConfiguration() {
1996         return ConfigurationManager.getConfigurationManager().getConfiguration();
1997     }
1998
1999 }