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