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