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