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