Service Import - Input appearing as a property
[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).stream()
1132                 // Filters out Attributes with empty default values
1133                 .filter(attributeDefinition -> StringUtils.isNotEmpty(attributeDefinition.getDefaultValue()))
1134                 // Converts and adds each value to attribute map
1135                 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1136         }
1137     }
1138
1139     private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1140                                                 Component componentOfInstance, Map<String, Object> props) {
1141
1142         List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1143         if (isNotEmpty(componentProperties)) {
1144             componentProperties.stream()
1145                 // Filters out properties with empty default values
1146                 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1147                 // Converts and adds each value to property map
1148                 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1149         }
1150     }
1151
1152     private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1153
1154         final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1155         if (isNotEmpty(componentAttributes)) {
1156             componentAttributes.stream()
1157                 // Filters out Attributes with empty default values
1158                 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1159                 // Converts and adds each value to attribute map
1160                 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1161         }
1162     }
1163
1164     private ToscaNodeType createNodeType(Component component) {
1165         ToscaNodeType toscaNodeType = new ToscaNodeType();
1166         if (ModelConverter.isAtomicComponent(component)) {
1167             if (((Resource) component).getDerivedFrom() != null) {
1168                 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1169             }
1170             toscaNodeType.setDescription(component.getDescription());
1171         } else {
1172             String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1173                 : NATIVE_ROOT;
1174             toscaNodeType.setDerived_from(derivedFrom);
1175         }
1176         return toscaNodeType;
1177     }
1178
1179     private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1180
1181         Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1182         Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1183         List<ComponentInstance> componentInstances = container.getComponentInstances();
1184         if (CollectionUtils.isEmpty(componentInstances)) {
1185             return res;
1186         }
1187         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1188         componentInstances.stream()
1189             .filter(this::isComponentOfTypeServiceProxy)
1190             .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1191         if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1192             return res;
1193         }
1194         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1195             Component serviceComponent;
1196             ComponentParametersView componentParametersView = new ComponentParametersView();
1197             componentParametersView.disableAll();
1198             componentParametersView.setIgnoreInterfaces(false);
1199             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1200                 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1201             if (service.isRight()) {
1202                 log.debug("Failed to fetch original service component with id {} for instance {}",
1203                     entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1204                 return Either.right(ToscaError.GENERAL_ERROR);
1205             } else {
1206                 serviceComponent = service.left().value();
1207             }
1208
1209             Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1210                 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1211             if (lifecycleTypeEither.isRight()) {
1212                 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1213                 return Either.right(ToscaError.GENERAL_ERROR);
1214             }
1215
1216             List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1217                 .map(InterfaceDataDefinition::getType)
1218                 .collect(Collectors.toList());
1219             //Add interface types for local interfaces in the original service component for proxy
1220             Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1221                 allGlobalInterfaceTypes);
1222             if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1223                 proxyInterfaceTypes.putAll(localInterfaceTypes);
1224             }
1225
1226         }
1227         return Either.left(proxyInterfaceTypes);
1228     }
1229
1230     private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1231                                                                                 Component container) {
1232
1233         Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1234         Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1235
1236         List<ComponentInstance> componentInstances = container.getComponentInstances();
1237
1238         if (componentInstances == null || componentInstances.isEmpty()) {
1239             return res;
1240         }
1241         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1242         List<ComponentInstance> proxyInst = componentInstances.stream()
1243             .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1244             .collect(Collectors.toList());
1245         if (proxyInst != null && !proxyInst.isEmpty()) {
1246             for (ComponentInstance inst : proxyInst) {
1247                 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1248             }
1249         }
1250
1251         if (serviceProxyInstanceList.isEmpty()) {
1252             return res;
1253         }
1254         Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1255             .getLatestByName("serviceProxy", null);
1256         if (serviceProxyOrigin.isRight()) {
1257             log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1258                 serviceProxyOrigin.right().value());
1259             return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1260         }
1261         Component origComponent = serviceProxyOrigin.left().value();
1262
1263         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1264             Component serviceComponent = null;
1265             ComponentParametersView componentParametersView = new ComponentParametersView();
1266             componentParametersView.disableAll();
1267             componentParametersView.setIgnoreCategories(false);
1268             componentParametersView.setIgnoreProperties(false);
1269             componentParametersView.setIgnoreInputs(false);
1270             componentParametersView.setIgnoreInterfaces(false);
1271             componentParametersView.setIgnoreRequirements(false);
1272             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1273                 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1274             if (service.isRight()) {
1275                 log.debug("Failed to fetch resource with id {} for instance {}",
1276                     entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1277             } else {
1278                 serviceComponent = service.left().value();
1279             }
1280
1281             ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1282                 entryProxy.getValue());
1283             nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1284         }
1285
1286         return Either.left(nodeTypesMap);
1287     }
1288
1289     private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1290                                                     final Component container, final ToscaTemplate toscaNode) {
1291         final List<ComponentInstance> componentInstances = container.getComponentInstances();
1292
1293         if (CollectionUtils.isEmpty(componentInstances)) {
1294             return;
1295         }
1296         final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1297             .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1298             .collect(Collectors.toList());
1299         if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1300             for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1301                 final Map<String, ToscaNodeType> nodeTypes =
1302                     toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1303                 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1304                     nodeTypes, true);
1305             }
1306         }
1307     }
1308
1309     private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1310                                               Component proxyComponent, ComponentInstance componentInstance) {
1311         ToscaNodeType toscaNodeType = new ToscaNodeType();
1312         String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1313
1314         toscaNodeType.setDerived_from(derivedFrom);
1315         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1316             origComponent.getModel());
1317         if (dataTypesEither.isRight()) {
1318             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1319         }
1320         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1321         Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1322             .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1323
1324         if (MapUtils.isNotEmpty(capabilities)) {
1325             toscaNodeType.setCapabilities(capabilities);
1326         }
1327         List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1328             .convertProxyRequirements(componentCache, componentInstance);
1329         if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1330             toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1331         }
1332         Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1333         proxyProperties.ifPresent(toscaNodeType::setProperties);
1334
1335         Map<String, Object> interfaceMap = new HashMap<>();
1336         if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1337             final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1338             if (proxyInterfaces.isPresent()) {
1339                 interfaceMap = proxyInterfaces.get();
1340             }
1341         } else {
1342             interfaceMap = interfacesOperationsConverter
1343                 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1344
1345         }
1346         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1347         toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1348
1349         return toscaNodeType;
1350     }
1351
1352     private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1353                                                                                        ComponentInstance componentInstance,
1354                                                                                        List<RequirementCapabilityRelDef> relations,
1355                                                                                        ToscaNodeTemplate nodeTypeTemplate,
1356                                                                                        Component originComponent,
1357                                                                                        Map<String, Component> componentCache) {
1358
1359         final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1360             relations);
1361         if (isNotEmpty(requirementDefinitionList)) {
1362             try {
1363                 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1364                     requirementDefinitionList, originComponent, componentCache);
1365                 if (!toscaRequirements.isEmpty()) {
1366                     nodeTypeTemplate.setRequirements(toscaRequirements);
1367                 }
1368             } catch (final Exception e) {
1369                 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1370                     componentInstance.getName(), e);
1371                 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1372             }
1373         }
1374         log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1375         return Either.left(nodeTypeTemplate);
1376     }
1377
1378     private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1379                                                                           final ComponentInstance componentInstance,
1380                                                                           final List<RequirementCapabilityRelDef> filteredRelations,
1381                                                                           final Component originComponent,
1382                                                                           final Map<String, Component> componentCache)
1383         throws ToscaExportException {
1384
1385         final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1386         for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1387             final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1388                 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1389             toscaRequirements.add(toscaTemplateRequirementMap);
1390         }
1391
1392         return toscaRequirements;
1393     }
1394
1395     private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1396                                                                  List<RequirementCapabilityRelDef> relations) {
1397         return relations.stream()
1398             .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1399     }
1400
1401     private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1402                                                                    final Component fromOriginComponent,
1403                                                                    final List<ComponentInstance> instancesList,
1404                                                                    final RequirementCapabilityRelDef relationshipDefinition,
1405                                                                    final Map<String, Component> componentCache)
1406         throws ToscaExportException {
1407
1408         final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1409         final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1410             .getRelationships().get(0);
1411         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1412
1413         final ComponentInstance toInstance = instancesList.stream()
1414             .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1415             .findFirst().orElse(null);
1416         if (toInstance == null) {
1417             final String errorMsg = String
1418                 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1419                     relationshipDefinition.getToNode());
1420             log.debug(errorMsg);
1421             throw new ToscaExportException(errorMsg);
1422         }
1423         final Optional<RequirementDefinition> reqOpt =
1424             findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1425         if (reqOpt.isEmpty()) {
1426             final String errorMsg = String
1427                 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1428                     relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1429             log.debug(errorMsg);
1430             throw new ToscaExportException(errorMsg);
1431         }
1432         final ComponentParametersView filter = new ComponentParametersView(true);
1433         filter.setIgnoreComponentInstances(false);
1434         filter.setIgnoreCapabilities(false);
1435         filter.setIgnoreGroups(false);
1436         final Either<Component, StorageOperationStatus> getOriginRes =
1437             toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1438         if (getOriginRes.isRight()) {
1439             final String errorMsg = String.format(
1440                 "Failed to build substituted name for the requirement %s. "
1441                     + "Failed to get an origin component with uniqueId %s",
1442                 reqOpt.get().getName(), toInstance.getActualComponentUid());
1443             log.debug(errorMsg);
1444             throw new ToscaExportException(errorMsg);
1445         }
1446         final Component toOriginComponent = getOriginRes.left().value();
1447         Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1448             .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1449         if (capOpt.isEmpty()) {
1450             capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1451             if (capOpt.isEmpty()) {
1452                 final String errorMsg = String
1453                     .format("Failed to find a capability with name %s on a component with uniqueId %s",
1454                         relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1455                 log.debug(errorMsg);
1456                 throw new ToscaExportException(errorMsg);
1457             }
1458         }
1459         return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1460             capabilityRequirementRelationship, toInstance, componentCache);
1461     }
1462
1463     private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1464                                                  CapabilityDefinition capability) {
1465         return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1466             && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1467     }
1468
1469     private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1470                                                           Component toOriginComponent, Component fromOriginComponent,
1471                                                           RequirementDefinition requirement) {
1472         Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1473             .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1474         if (!cap.isPresent()) {
1475             log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1476                 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1477         }
1478         return cap;
1479     }
1480
1481     private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1482                                                                    final Component toOriginComponent,
1483                                                                    final CapabilityDefinition capability,
1484                                                                    final RequirementDefinition requirement,
1485                                                                    final CapabilityRequirementRelationship capabilityRequirementRelationship,
1486                                                                    final ComponentInstance toInstance,
1487                                                                    final Map<String, Component> componentCache)
1488         throws ToscaExportException {
1489
1490         List<String> reducedPath = capability.getPath();
1491         if (capability.getOwnerId() != null) {
1492             reducedPath = capabilityRequirementConverter
1493                 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1494         }
1495         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1496         final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1497             toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1498         if (capabilityNameEither.isRight()) {
1499             final String errorMsg = String.format(
1500                 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1501                 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1502             log.debug(
1503                 errorMsg);
1504             throw new ToscaExportException(errorMsg);
1505         }
1506         final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1507             .buildSubstitutedName(componentCache, fromOriginComponent,
1508                 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1509         if (requirementNameEither.isRight()) {
1510             final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1511                     + "with name %s on a component with uniqueId %s",
1512                 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1513             log.debug(errorMsg);
1514             throw new ToscaExportException(errorMsg);
1515         }
1516         final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1517         final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1518         toscaRequirement.setNode(toInstance.getName());
1519         toscaRequirement.setCapability(capabilityNameEither.left().value());
1520         if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1521             toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1522         }
1523         toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1524         return toscaReqMap;
1525     }
1526
1527     private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1528                                                             Map<String, List<RequirementDefinition>> reqMap,
1529                                                             RelationshipInfo reqAndRelationshipPair,
1530                                                             String fromInstanceId) {
1531         for (List<RequirementDefinition> reqList : reqMap.values()) {
1532             Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1533                     r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1534                 .findFirst();
1535             if (reqOpt.isPresent()) {
1536                 return reqOpt;
1537             }
1538         }
1539         return Optional.empty();
1540     }
1541
1542     /**
1543      * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1544      * 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
1545      * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1546      */
1547     private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1548                                                   RequirementDefinition requirement, String fromInstanceId) {
1549         if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1550             log.debug("Failed to find a requirement with name {} and  reqAndRelationshipPair {}", requirement.getName(),
1551                 reqAndRelationshipPair.getRequirement());
1552             return false;
1553         }
1554         return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1555             originComponent);
1556     }
1557
1558     private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1559                                                Component originComponent) {
1560         return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1561             isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1562                 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1563     }
1564
1565     private boolean isCvfc(Component component) {
1566         return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1567     }
1568
1569     private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1570                                                                                              final Map<String, Component> componentCache) {
1571         Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1572             capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1573         if (toscaCapabilitiesRes.isRight()) {
1574             log.debug("Failed convert capabilities for the component {}. ", component.getName());
1575             return Either.right(toscaCapabilitiesRes.right().value());
1576         }
1577         if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1578             log.debug("Finish convert capabilities for the component {}. ", component.getName());
1579             return Either.left(toscaCapabilitiesRes.left().value());
1580         }
1581         log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1582
1583         return Either.left(Collections.emptyMap());
1584     }
1585
1586     private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1587                                                                   Map<String, DataTypeDefinition> dataTypes) {
1588         Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1589         if (!toscaCapabilities.isEmpty()) {
1590             nodeType.setCapabilities(toscaCapabilities);
1591         }
1592         log.debug("Finish convert Capabilities for node type");
1593         return Either.left(nodeType);
1594     }
1595
1596     private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1597         if (artifacts == null) {
1598             return null;
1599         }
1600         Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1601         for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1602             ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1603             artifact.setFile(entry.getValue().getFile());
1604             artifact.setType(entry.getValue().getType());
1605             artifact.setProperties(entry.getValue().getProperties());
1606             arts.put(entry.getKey(), artifact);
1607         }
1608         return arts;
1609     }
1610
1611     private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1612         if (inNodeFilter == null) {
1613             return null;
1614         }
1615         NodeFilter nodeFilter = new NodeFilter();
1616         ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1617         ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1618         List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1619         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1620         copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1621         copyNodeFilterProperties(origProperties, propertiesCopy);
1622         if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1623             nodeFilter.setCapabilities(capabilitiesCopy);
1624         }
1625         if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1626             nodeFilter.setProperties(propertiesCopy);
1627         }
1628         nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1629         nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1630         return nodeFilter;
1631     }
1632
1633     private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1634         if (substitutionFilterDataDefinition == null) {
1635             return null;
1636         }
1637         NodeFilter nodeFilter = new NodeFilter();
1638         ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1639         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1640         copySubstitutionFilterProperties(origProperties, propertiesCopy);
1641         if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1642             nodeFilter.setProperties(propertiesCopy);
1643         }
1644         nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1645         return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1646     }
1647
1648     private Object cloneToscaId(Object toscaId) {
1649         return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1650     }
1651
1652     private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1653         String objectAsYml = yamlUtil.objectToYaml(objToClone);
1654         return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1655     }
1656
1657     private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1658                                                     List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1659         if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1660             .isEmpty()) {
1661             return;
1662         }
1663         for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1664             Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1665             CapabilityFilter capabilityFilter = new CapabilityFilter();
1666             List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1667             copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1668             capabilityFilter.setProperties(propertiesCopy);
1669             capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1670             capabilitiesCopy.add(capabilityFilterCopyMap);
1671         }
1672     }
1673
1674     private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1675                                           List<Map<String, List<Object>>> propertiesCopy) {
1676         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1677             return;
1678         }
1679         Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1680         for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1681             for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1682                 Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1683                 String propertyName = propertyDataDefinition.getName();
1684                 if (propertyMapCopy.containsKey(propertyName)) {
1685                     addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1686                 } else {
1687                     if (propertyName != null) {
1688                         List<Object> propsList = new ArrayList<>();
1689                         addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1690                         propertyMapCopy.put(propertyName, propsList);
1691                     } else {
1692                         propertyMapCopy.putAll(propertyValObj);
1693                     }
1694                 }
1695             }
1696         }
1697         propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1698     }
1699
1700     private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1701                                                   final List<Map<String, List<Object>>> propertiesCopy) {
1702         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1703             return;
1704         }
1705         final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1706         for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1707             for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1708                 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1709                 final String propertyName = propertyDataDefinition.getName();
1710                 if (propertyMapCopy.containsKey(propertyName)) {
1711                     addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1712                 } else {
1713                     if (propertyName != null) {
1714                         final List<Object> propsList = new ArrayList<>();
1715                         addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1716                         propertyMapCopy.put(propertyName, propsList);
1717                     } else {
1718                         propertyMapCopy.putAll(propertyValObj);
1719                     }
1720                 }
1721             }
1722         }
1723         propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1724     }
1725
1726     private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1727         if (propertyValObj.containsKey(propertyName)) {
1728             propsList.add(propertyValObj.get(propertyName));
1729         } else {
1730             propsList.add(propertyValObj);
1731         }
1732     }
1733
1734     private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1735         Map<String, List<Object>> tempMap = new HashMap<>();
1736         tempMap.put(entry.getKey(), entry.getValue());
1737         propertiesCopy.add(tempMap);
1738     }
1739
1740     private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1741         if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1742             return Collections.emptyMap();
1743         }
1744         return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName)
1745             .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1746     }
1747
1748     private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1749         if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1750             return Collections.emptyMap();
1751         }
1752         return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1753             .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1754     }
1755
1756     private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1757         if (Objects.isNull(proxyComponent)) {
1758             return Optional.empty();
1759         }
1760         final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1761         if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1762             proxyProperties.putAll(proxyComponent.getProperties().stream()
1763                 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1764                     .toMap(PropertyDataDefinition::getName,
1765                         property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1766         }
1767         return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1768     }
1769
1770     private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1771                                                              String componentUniqueId) {
1772         if (CollectionUtils.isEmpty(componentInputs)) {
1773             return new HashMap<>();
1774         }
1775         return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1776             .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1777     }
1778
1779     private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1780         if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1781             return Optional.empty();
1782         }
1783         Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1784         //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1785
1786         // always available in the proxy node template
1787         removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1788         return Optional
1789             .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1790     }
1791
1792     private static class CustomRepresenter extends Representer {
1793
1794         CustomRepresenter() {
1795             super();
1796             this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1797             this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1798             // null representer is exceptional and it is stored as an instance
1799
1800             // variable.
1801             this.nullRepresenter = new RepresentNull();
1802         }
1803
1804         public boolean validateGetInputValue(final Object valueObj) {
1805             if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1806                 return false;
1807             }
1808             if (valueObj instanceof List) {
1809                 return ((List) valueObj).size() > 1;
1810             }
1811             return true;
1812         }
1813
1814         public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1815             if (valueObj instanceof List) {
1816                 return ((List) valueObj).size() > 1;
1817             }
1818             return false;
1819         }
1820
1821         @Override
1822         protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1823             if (propertyValue == null) {
1824                 return null;
1825             }
1826             // skip not relevant for Tosca property
1827             if ("dependencies".equals(property.getName())) {
1828                 return null;
1829             }
1830             if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1831                 return null;
1832             }
1833             removeDefaultP(propertyValue);
1834             NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1835             if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1836                 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1837             }
1838             return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1839         }
1840
1841         private void removeDefaultP(final Object propertyValue) {
1842             if (propertyValue instanceof Map) {
1843                 final Map mapPropertyValue = ((Map) propertyValue);
1844                 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1845                 Object defaultValue = null;
1846                 while (iter.hasNext()) {
1847                     final Map.Entry entry = iter.next();
1848                     if ("_defaultp_".equals(entry.getKey())) {
1849                         defaultValue = entry.getValue();
1850                         iter.remove();
1851                     } else if (entry.getValue() instanceof Map) {
1852                         removeDefaultP(entry.getValue());
1853                     }
1854                 }
1855                 if (defaultValue != null) {
1856                     mapPropertyValue.putIfAbsent("default", defaultValue);
1857                 }
1858             }
1859         }
1860
1861         @Override
1862         protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1863             // remove the bean type from the output yaml (!! ...)
1864             if (!classTags.containsKey(javaBean.getClass())) {
1865                 addClassTag(javaBean.getClass(), Tag.MAP);
1866             }
1867             return super.representJavaBean(properties, javaBean);
1868         }
1869
1870         private class RepresentToscaAttribute implements Represent {
1871
1872             @Override
1873             public Node representData(Object data) {
1874                 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1875                 return represent(toscaAttribute.asToscaMap());
1876             }
1877         }
1878
1879         private class RepresentToscaPropertyAssignment implements Represent {
1880
1881             public Node representData(Object data) {
1882                 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1883                 if (toscaOperationAssignment.getValue() instanceof String) {
1884                     final String stringValue = (String) toscaOperationAssignment.getValue();
1885                     if (isPropertyOrAttributeFunction(stringValue)) {
1886                         return representGetAttribute(stringValue);
1887                     }
1888                     return representScalar(Tag.STR, stringValue);
1889                 }
1890                 return represent(null);
1891             }
1892
1893             public Node representGetAttribute(final String getAttributeFunction) {
1894                 return represent(new Yaml().load(getAttributeFunction));
1895             }
1896
1897             public boolean isPropertyOrAttributeFunction(final String value) {
1898                 try {
1899                     final Yaml yaml = new Yaml();
1900                     final Object yamlObj = yaml.load(value);
1901                     if (!(yamlObj instanceof Map)) {
1902                         return false;
1903                     }
1904                     final Map<String, Object> getAttributeMap = (Map) yamlObj;
1905                     if (getAttributeMap.size() != 1) {
1906                         return false;
1907                     }
1908                     final List<String> functionList = Arrays
1909                         .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1910                     final Optional<String> function = getAttributeMap.keySet().stream()
1911                         .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1912                     if (function.isEmpty()) {
1913                         return false;
1914                     }
1915                     final String functionName = function.get();
1916                     final Object getAttributeValueObj = getAttributeMap.get(functionName);
1917                     if (GET_INPUT.getFunctionName().equals(functionName)) {
1918                         return validateGetInputValue(getAttributeValueObj);
1919                     } else {
1920                         return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1921                     }
1922                 } catch (final Exception ignored) {
1923                     return false;
1924                 }
1925             }
1926         }
1927
1928         private class RepresentNull implements Represent {
1929
1930             @Override
1931             public Node representData(Object data) {
1932                 // possible values are here http://yaml.org/type/null.html
1933                 return representScalar(Tag.NULL, "");
1934             }
1935         }
1936     }
1937
1938     private static class UnsortedPropertyUtils extends PropertyUtils {
1939
1940         @Override
1941         protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1942             Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1943             return new LinkedHashSet<>(fields);
1944         }
1945     }
1946
1947     private Configuration getConfiguration() {
1948         return ConfigurationManager.getConfigurationManager().getConfiguration();
1949     }
1950
1951 }