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