Make Service base type optional
[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
818                                 .convertProperty(dataTypes, s, PropertyType.PROPERTY)
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 Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
831                                                                  final Map<String, DataTypeDefinition> dataTypes) {
832         if (CollectionUtils.isEmpty(attributeList)) {
833             return Collections.emptyMap();
834         }
835         final AttributeConverter converter = new AttributeConverter(dataTypes);
836         final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
837         for (final AttributeDefinition attributeDefinition : attributeList) {
838             toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
839         }
840         return toscaAttributeMap;
841     }
842
843     private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
844                                                                        Component component, ToscaTemplate toscaNode,
845                                                                        Map<String, ToscaNodeType> nodeTypes,
846                                                                        ToscaNodeType toscaNodeType,
847                                                                        Map<String, DataTypeDefinition> dataTypes) {
848         Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
849             dataTypes);
850         if (capabilities.isRight()) {
851             return Either.right(capabilities.right().value());
852         }
853         toscaNodeType = capabilities.left().value();
854         log.debug("Capabilities converted for {}", component.getUniqueId());
855
856         Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
857             .convertRequirements(componentsCache, component, toscaNodeType);
858         if (requirements.isRight()) {
859             return Either.right(requirements.right().value());
860         }
861         toscaNodeType = requirements.left().value();
862         log.debug("Requirements converted for {}", component.getUniqueId());
863
864         String toscaResourceName;
865         switch (component.getComponentType()) {
866             case RESOURCE:
867                 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
868                     .getMetadataDataDefinition()).getToscaResourceName();
869                 break;
870             case SERVICE:
871                 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
872                     + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
873                 break;
874             default:
875                 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
876                 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
877         }
878
879         nodeTypes.put(toscaResourceName, toscaNodeType);
880         toscaNode.setNode_types(nodeTypes);
881         log.debug("finish convert node type for {}", component.getUniqueId());
882         return Either.left(toscaNode);
883     }
884
885     private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
886                                                                                     final Map<String, Component> componentCache,
887                                                                                     final Map<String, DataTypeDefinition> dataTypes,
888                                                                                     final ToscaTopolgyTemplate topologyTemplate) {
889
890         final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
891         final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
892         final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
893         final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
894         final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
895
896         Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
897         log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
898         final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
899
900         Map<String, ToscaGroupTemplate> groupsMap = null;
901         for (final ComponentInstance componentInstance : component.getComponentInstances()) {
902             ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
903             if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
904                 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
905             }
906             nodeTemplate.setType(componentInstance.getToscaComponentName());
907             nodeTemplate.setDirectives(componentInstance.getDirectives());
908             nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
909
910             final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
911                 .getOriginComponent(componentCache, componentInstance);
912             if (originComponentRes.isRight()) {
913                 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
914                 break;
915             }
916             final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
917                 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
918             if (requirements.isRight()) {
919                 convertNodeTemplatesRes = Either.right(requirements.right().value());
920                 break;
921             }
922             final String instanceUniqueId = componentInstance.getUniqueId();
923             log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
924
925             nodeTemplate = requirements.left().value();
926
927             final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
928
929             if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
930                 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
931                 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
932             } else {
933                 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
934             }
935
936             final Either<ToscaNodeTemplate, ToscaError> capabilities =
937                 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
938             if (capabilities.isRight()) {
939                 convertNodeTemplatesRes = Either.right(capabilities.right().value());
940                 break;
941             }
942             log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
943
944             nodeTemplate = capabilities.left().value();
945             final Map<String, Object> props = new HashMap<>();
946             final Map<String, Object> attribs = new HashMap<>();
947
948             if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
949                 // Adds the properties of parent component to map
950                 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
951                 addAttributesOfParentComponent(originalComponent, attribs);
952             }
953
954             if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
955                 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
956             }
957             if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
958                 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
959             }
960
961             if (componentInstancesInputs != null
962                 && componentInstancesInputs.containsKey(instanceUniqueId)
963                 && !isComponentOfTypeServiceProxy(componentInstance)) {
964                 //For service proxy the inputs are already handled under instance properties above
965                 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
966             }
967
968             //M3[00001] - NODE TEMPLATE INTERFACES  - START
969             handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
970             //M3[00001] - NODE TEMPLATE INTERFACES  - END
971             if (MapUtils.isNotEmpty(props)) {
972                 nodeTemplate.setProperties(props);
973             }
974             if (MapUtils.isNotEmpty(attribs)) {
975                 nodeTemplate.setAttributes(attribs);
976             }
977
978             final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
979             if (CollectionUtils.isNotEmpty(groupInstances)) {
980                 if (groupsMap == null) {
981                     groupsMap = new HashMap<>();
982                 }
983                 for (final GroupInstance groupInst : groupInstances) {
984                     if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
985                         groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
986                     }
987                 }
988             }
989
990             nodeTemplates.put(componentInstance.getName(), nodeTemplate);
991         }
992         if (groupsMap != null) {
993             log.debug("instance groups added");
994             topologyTemplate.addGroups(groupsMap);
995         }
996         if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
997             ((Service) component).getForwardingPaths())) {
998             log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
999             ForwardingPathToscaUtil
1000                 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1001             log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1002         }
1003         if (convertNodeTemplatesRes == null) {
1004             convertNodeTemplatesRes = Either.left(nodeTemplates);
1005         }
1006         log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1007         return convertNodeTemplatesRes;
1008     }
1009
1010     private void handleInstanceInterfaces(
1011         Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1012         ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
1013         String instanceUniqueId,
1014         Component parentComponent) {
1015
1016         if (MapUtils.isEmpty(componentInstanceInterfaces)
1017             || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1018             nodeTemplate.setInterfaces(null);
1019             return;
1020         }
1021
1022         final List<ComponentInstanceInterface> currServiceInterfaces =
1023             componentInstanceInterfaces.get(instanceUniqueId);
1024
1025         final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1026         currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
1027             .getUniqueId(), instInterface));
1028
1029         final Map<String, Object> interfaceMap = interfacesOperationsConverter
1030             .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance),
1031                 isComponentOfTypeServiceProxy(componentInstance));
1032
1033         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1034         nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1035     }
1036
1037     private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1038         return Objects.nonNull(componentInstance.getOriginType())
1039             && componentInstance.getOriginType().getValue().equals("Service Proxy");
1040     }
1041
1042     private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1043                                             Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1044                                             String instanceUniqueId, Map<String, Object> props) {
1045
1046         List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1047         if (instanceInputsList != null) {
1048             instanceInputsList.forEach(input -> {
1049                 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue() : input.getDefaultValue();
1050                 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1051             });
1052         }
1053     }
1054
1055     private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1056                                                   final Map<String, DataTypeDefinition> dataTypes,
1057                                                   final String instanceUniqueId,
1058                                                   final Map<String, Object> props) {
1059
1060         if (isNotEmpty(componentInstancesProperties)) {
1061             componentInstancesProperties.get(instanceUniqueId)
1062                 // Converts and adds each value to property map
1063                 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1064         }
1065     }
1066
1067     private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1068                                                   final String instanceUniqueId,
1069                                                   final Map<String, Object> attribs) {
1070
1071         if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1072             componentInstancesAttributes.get(instanceUniqueId).stream()
1073                 // Filters out Attributes with empty default values
1074                 .filter(attributeDefinition -> StringUtils.isNotEmpty(attributeDefinition.getDefaultValue()))
1075                 // Converts and adds each value to attribute map
1076                 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1077         }
1078     }
1079
1080     private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1081                                                 Component componentOfInstance, Map<String, Object> props) {
1082
1083         List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1084         if (isNotEmpty(componentProperties)) {
1085             componentProperties.stream()
1086                 // Filters out properties with empty default values
1087                 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1088                 // Converts and adds each value to property map
1089                 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1090         }
1091     }
1092
1093     private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1094
1095         final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1096         if (isNotEmpty(componentAttributes)) {
1097             componentAttributes.stream()
1098                 // Filters out Attributes with empty default values
1099                 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1100                 // Converts and adds each value to attribute map
1101                 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1102         }
1103     }
1104
1105     private ToscaNodeType createNodeType(Component component) {
1106         ToscaNodeType toscaNodeType = new ToscaNodeType();
1107         if (ModelConverter.isAtomicComponent(component)) {
1108             if (((Resource) component).getDerivedFrom() != null) {
1109                 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1110             }
1111             toscaNodeType.setDescription(component.getDescription());
1112         } else {
1113             String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1114                 : NATIVE_ROOT;
1115             toscaNodeType.setDerived_from(derivedFrom);
1116         }
1117         return toscaNodeType;
1118     }
1119
1120     private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1121
1122         Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1123         Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1124         List<ComponentInstance> componentInstances = container.getComponentInstances();
1125         if (CollectionUtils.isEmpty(componentInstances)) {
1126             return res;
1127         }
1128         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1129         componentInstances.stream()
1130             .filter(this::isComponentOfTypeServiceProxy)
1131             .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1132         if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1133             return res;
1134         }
1135         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1136             Component serviceComponent;
1137             ComponentParametersView componentParametersView = new ComponentParametersView();
1138             componentParametersView.disableAll();
1139             componentParametersView.setIgnoreInterfaces(false);
1140             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1141                 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1142             if (service.isRight()) {
1143                 log.debug("Failed to fetch original service component with id {} for instance {}",
1144                     entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1145                 return Either.right(ToscaError.GENERAL_ERROR);
1146             } else {
1147                 serviceComponent = service.left().value();
1148             }
1149
1150             Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1151                 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1152             if (lifecycleTypeEither.isRight()) {
1153                 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1154                 return Either.right(ToscaError.GENERAL_ERROR);
1155             }
1156
1157             List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1158                 .map(InterfaceDataDefinition::getType)
1159                 .collect(Collectors.toList());
1160             //Add interface types for local interfaces in the original service component for proxy
1161             Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1162                 allGlobalInterfaceTypes);
1163             if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1164                 proxyInterfaceTypes.putAll(localInterfaceTypes);
1165             }
1166
1167         }
1168         return Either.left(proxyInterfaceTypes);
1169     }
1170
1171     private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1172                                                                                 Component container) {
1173
1174         Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1175         Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1176
1177         List<ComponentInstance> componentInstances = container.getComponentInstances();
1178
1179         if (componentInstances == null || componentInstances.isEmpty()) {
1180             return res;
1181         }
1182         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1183         List<ComponentInstance> proxyInst = componentInstances.stream()
1184             .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1185             .collect(Collectors.toList());
1186         if (proxyInst != null && !proxyInst.isEmpty()) {
1187             for (ComponentInstance inst : proxyInst) {
1188                 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1189             }
1190         }
1191
1192         if (serviceProxyInstanceList.isEmpty()) {
1193             return res;
1194         }
1195         Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1196             .getLatestByName("serviceProxy", null);
1197         if (serviceProxyOrigin.isRight()) {
1198             log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1199                 serviceProxyOrigin.right().value());
1200             return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1201         }
1202         Component origComponent = serviceProxyOrigin.left().value();
1203
1204         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1205             Component serviceComponent = null;
1206             ComponentParametersView componentParametersView = new ComponentParametersView();
1207             componentParametersView.disableAll();
1208             componentParametersView.setIgnoreCategories(false);
1209             componentParametersView.setIgnoreProperties(false);
1210             componentParametersView.setIgnoreInputs(false);
1211             componentParametersView.setIgnoreInterfaces(false);
1212             componentParametersView.setIgnoreRequirements(false);
1213             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1214                 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1215             if (service.isRight()) {
1216                 log.debug("Failed to fetch resource with id {} for instance {}",
1217                     entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1218             } else {
1219                 serviceComponent = service.left().value();
1220             }
1221
1222             ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1223                 entryProxy.getValue());
1224             nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1225         }
1226
1227         return Either.left(nodeTypesMap);
1228     }
1229
1230     private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1231                                                     final Component container, final ToscaTemplate toscaNode) {
1232         final List<ComponentInstance> componentInstances = container.getComponentInstances();
1233
1234         if (CollectionUtils.isEmpty(componentInstances)) {
1235             return;
1236         }
1237         final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1238             .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1239             .collect(Collectors.toList());
1240         if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1241             for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1242                 final Map<String, ToscaNodeType> nodeTypes =
1243                     toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1244                 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1245                     nodeTypes, true);
1246             }
1247         }
1248     }
1249
1250     private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1251                                               Component proxyComponent, ComponentInstance componentInstance) {
1252         ToscaNodeType toscaNodeType = new ToscaNodeType();
1253         String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1254
1255         toscaNodeType.setDerived_from(derivedFrom);
1256         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(origComponent.getModel());
1257         if (dataTypesEither.isRight()) {
1258             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1259         }
1260         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1261         Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1262             .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1263
1264         if (MapUtils.isNotEmpty(capabilities)) {
1265             toscaNodeType.setCapabilities(capabilities);
1266         }
1267         List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1268             .convertProxyRequirements(componentCache, componentInstance);
1269         if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1270             toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1271         }
1272         Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1273         proxyProperties.ifPresent(toscaNodeType::setProperties);
1274
1275         Map<String, Object> interfaceMap = new HashMap<>();
1276         if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1277             final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1278             if (proxyInterfaces.isPresent()) {
1279                 interfaceMap = proxyInterfaces.get();
1280             }
1281         } else {
1282             interfaceMap = interfacesOperationsConverter
1283                 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1284
1285         }
1286         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1287         toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1288
1289         return toscaNodeType;
1290     }
1291
1292     private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1293                                                                                        ComponentInstance componentInstance,
1294                                                                                        List<RequirementCapabilityRelDef> relations,
1295                                                                                        ToscaNodeTemplate nodeTypeTemplate,
1296                                                                                        Component originComponent,
1297                                                                                        Map<String, Component> componentCache) {
1298
1299         final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1300             relations);
1301         if (isNotEmpty(requirementDefinitionList)) {
1302             try {
1303                 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance, requirementDefinitionList, originComponent, componentCache);
1304                 if (!toscaRequirements.isEmpty()) {
1305                     nodeTypeTemplate.setRequirements(toscaRequirements);
1306                 }
1307             } catch (final Exception e) {
1308                 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1309                     componentInstance.getName(), e);
1310                 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1311             }
1312         }
1313         log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1314         return Either.left(nodeTypeTemplate);
1315     }
1316
1317     private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1318                                                                           final ComponentInstance componentInstance,
1319                                                                           final List<RequirementCapabilityRelDef> filteredRelations,
1320                                                                           final Component originComponent,
1321                                                                           final Map<String, Component> componentCache)
1322         throws ToscaExportException {
1323
1324         final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1325         for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1326             final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1327                 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1328             toscaRequirements.add(toscaTemplateRequirementMap);
1329         }
1330
1331         return toscaRequirements;
1332     }
1333
1334     private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1335                                                                  List<RequirementCapabilityRelDef> relations) {
1336         return relations.stream()
1337             .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1338     }
1339
1340     private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1341                                                                    final Component fromOriginComponent,
1342                                                                    final List<ComponentInstance> instancesList,
1343                                                                    final RequirementCapabilityRelDef relationshipDefinition,
1344                                                                    final Map<String, Component> componentCache)
1345         throws ToscaExportException {
1346
1347         final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1348         final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1349             .getRelationships().get(0);
1350         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1351
1352         final ComponentInstance toInstance = instancesList.stream()
1353             .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1354             .findFirst().orElse(null);
1355         if (toInstance == null) {
1356             final String errorMsg = String
1357                 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1358                     relationshipDefinition.getToNode());
1359             log.debug(errorMsg);
1360             throw new ToscaExportException(errorMsg);
1361         }
1362         final Optional<RequirementDefinition> reqOpt =
1363             findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1364         if (reqOpt.isEmpty()) {
1365             final String errorMsg = String
1366                 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1367                     relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1368             log.debug(errorMsg);
1369             throw new ToscaExportException(errorMsg);
1370         }
1371         final ComponentParametersView filter = new ComponentParametersView(true);
1372         filter.setIgnoreComponentInstances(false);
1373         filter.setIgnoreCapabilities(false);
1374         filter.setIgnoreGroups(false);
1375         final Either<Component, StorageOperationStatus> getOriginRes =
1376             toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1377         if (getOriginRes.isRight()) {
1378             final String errorMsg = String.format(
1379                 "Failed to build substituted name for the requirement %s. "
1380                     + "Failed to get an origin component with uniqueId %s",
1381                 reqOpt.get().getName(), toInstance.getActualComponentUid());
1382             log.debug(errorMsg);
1383             throw new ToscaExportException(errorMsg);
1384         }
1385         final Component toOriginComponent = getOriginRes.left().value();
1386         Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1387             .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1388         if (capOpt.isEmpty()) {
1389             capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1390             if (capOpt.isEmpty()) {
1391                 final String errorMsg = String
1392                     .format("Failed to find a capability with name %s on a component with uniqueId %s",
1393                         relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1394                 log.debug(errorMsg);
1395                 throw new ToscaExportException(errorMsg);
1396             }
1397         }
1398         return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1399             capabilityRequirementRelationship, toInstance, componentCache);
1400     }
1401
1402     private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1403                                                  CapabilityDefinition capability) {
1404         return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1405             && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1406     }
1407
1408     private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1409                                                           Component toOriginComponent, Component fromOriginComponent,
1410                                                           RequirementDefinition requirement) {
1411         Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1412             .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1413         if (!cap.isPresent()) {
1414             log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1415                 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1416         }
1417         return cap;
1418     }
1419
1420     private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1421                                                                    final Component toOriginComponent,
1422                                                                    final CapabilityDefinition capability,
1423                                                                    final RequirementDefinition requirement,
1424                                                                    final CapabilityRequirementRelationship capabilityRequirementRelationship,
1425                                                                    final ComponentInstance toInstance,
1426                                                                    final Map<String, Component> componentCache)
1427         throws ToscaExportException {
1428
1429         List<String> reducedPath = capability.getPath();
1430         if (capability.getOwnerId() != null) {
1431             reducedPath = capabilityRequirementConverter
1432                 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1433         }
1434         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1435         final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1436             toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1437         if (capabilityNameEither.isRight()) {
1438             final String errorMsg = String.format(
1439                 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1440                 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1441             log.debug(
1442                 errorMsg);
1443             throw new ToscaExportException(errorMsg);
1444         }
1445         final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1446             .buildSubstitutedName(componentCache, fromOriginComponent,
1447                 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1448         if (requirementNameEither.isRight()) {
1449             final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1450                     + "with name %s on a component with uniqueId %s",
1451                 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1452             log.debug(errorMsg);
1453             throw new ToscaExportException(errorMsg);
1454         }
1455         final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1456         final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1457         toscaRequirement.setNode(toInstance.getName());
1458         toscaRequirement.setCapability(capabilityNameEither.left().value());
1459         if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1460             toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1461         }
1462         toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1463         return toscaReqMap;
1464     }
1465
1466     private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1467                                                             Map<String, List<RequirementDefinition>> reqMap,
1468                                                             RelationshipInfo reqAndRelationshipPair,
1469                                                             String fromInstanceId) {
1470         for (List<RequirementDefinition> reqList : reqMap.values()) {
1471             Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1472                 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1473                 .findFirst();
1474             if (reqOpt.isPresent()) {
1475                 return reqOpt;
1476             }
1477         }
1478         return Optional.empty();
1479     }
1480
1481     /**
1482      * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1483      * 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
1484      * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1485      */
1486     private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1487                                                   RequirementDefinition requirement, String fromInstanceId) {
1488         if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1489             log.debug("Failed to find a requirement with name {} and  reqAndRelationshipPair {}", requirement.getName(),
1490                 reqAndRelationshipPair.getRequirement());
1491             return false;
1492         }
1493         return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1494             originComponent);
1495     }
1496
1497     private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1498                                                Component originComponent) {
1499         return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1500             isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1501                 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1502     }
1503
1504     private boolean isCvfc(Component component) {
1505         return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1506     }
1507
1508     private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1509                                                                                              final Map<String, Component> componentCache) {
1510         Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1511             capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1512         if (toscaCapabilitiesRes.isRight()) {
1513             log.debug("Failed convert capabilities for the component {}. ", component.getName());
1514             return Either.right(toscaCapabilitiesRes.right().value());
1515         }
1516         if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1517             log.debug("Finish convert capabilities for the component {}. ", component.getName());
1518             return Either.left(toscaCapabilitiesRes.left().value());
1519         }
1520         log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1521
1522         return Either.left(Collections.emptyMap());
1523     }
1524
1525     private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1526                                                                   Map<String, DataTypeDefinition> dataTypes) {
1527         Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1528         if (!toscaCapabilities.isEmpty()) {
1529             nodeType.setCapabilities(toscaCapabilities);
1530         }
1531         log.debug("Finish convert Capabilities for node type");
1532         return Either.left(nodeType);
1533     }
1534
1535     private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1536         if (artifacts == null) {
1537             return null;
1538         }
1539         Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1540         for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1541             ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1542             artifact.setFile(entry.getValue().getFile());
1543             artifact.setType(entry.getValue().getType());
1544             arts.put(entry.getKey(), artifact);
1545         }
1546         return arts;
1547     }
1548
1549     private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1550         if (inNodeFilter == null) {
1551             return null;
1552         }
1553         NodeFilter nodeFilter = new NodeFilter();
1554         ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1555         ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1556         List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1557         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1558         copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1559         copyNodeFilterProperties(origProperties, propertiesCopy);
1560         if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1561             nodeFilter.setCapabilities(capabilitiesCopy);
1562         }
1563         if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1564             nodeFilter.setProperties(propertiesCopy);
1565         }
1566         nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1567         nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1568         return nodeFilter;
1569     }
1570
1571     private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1572         if (substitutionFilterDataDefinition == null) {
1573             return null;
1574         }
1575         NodeFilter nodeFilter = new NodeFilter();
1576         ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1577         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1578         copySubstitutionFilterProperties(origProperties, propertiesCopy);
1579         if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1580             nodeFilter.setProperties(propertiesCopy);
1581         }
1582         nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1583         return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1584     }
1585
1586     private Object cloneToscaId(Object toscaId) {
1587         return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1588     }
1589
1590     private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1591         String objectAsYml = yamlUtil.objectToYaml(objToClone);
1592         return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1593     }
1594
1595     private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1596                                                     List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1597         if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1598             .isEmpty()) {
1599             return;
1600         }
1601         for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1602             Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1603             CapabilityFilter capabilityFilter = new CapabilityFilter();
1604             List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1605             copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1606             capabilityFilter.setProperties(propertiesCopy);
1607             capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1608             capabilitiesCopy.add(capabilityFilterCopyMap);
1609         }
1610     }
1611
1612     private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1613                                           List<Map<String, List<Object>>> propertiesCopy) {
1614         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1615             return;
1616         }
1617         Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1618         for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1619             for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1620                 Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1621                 String propertyName = propertyDataDefinition.getName();
1622                 if (propertyMapCopy.containsKey(propertyName)) {
1623                     addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1624                 } else {
1625                     if (propertyName != null) {
1626                         List<Object> propsList = new ArrayList<>();
1627                         addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1628                         propertyMapCopy.put(propertyName, propsList);
1629                     } else {
1630                         propertyMapCopy.putAll(propertyValObj);
1631                     }
1632                 }
1633             }
1634         }
1635         propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1636     }
1637
1638     private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1639                                                   final List<Map<String, List<Object>>> propertiesCopy) {
1640         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1641             return;
1642         }
1643         final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1644         for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1645             for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1646                 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1647                 final String propertyName = propertyDataDefinition.getName();
1648                 if (propertyMapCopy.containsKey(propertyName)) {
1649                     addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1650                 } else {
1651                     if (propertyName != null) {
1652                         final List<Object> propsList = new ArrayList<>();
1653                         addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1654                         propertyMapCopy.put(propertyName, propsList);
1655                     } else {
1656                         propertyMapCopy.putAll(propertyValObj);
1657                     }
1658                 }
1659             }
1660         }
1661         propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1662     }
1663
1664     private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1665         if (propertyValObj.containsKey(propertyName)) {
1666             propsList.add(propertyValObj.get(propertyName));
1667         } else {
1668             propsList.add(propertyValObj);
1669         }
1670     }
1671
1672     private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1673         Map<String, List<Object>> tempMap = new HashMap<>();
1674         tempMap.put(entry.getKey(), entry.getValue());
1675         propertiesCopy.add(tempMap);
1676     }
1677
1678     private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1679         if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1680             return Collections.emptyMap();
1681         }
1682         return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName)
1683             .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1684     }
1685
1686     private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1687         if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1688             return Collections.emptyMap();
1689         }
1690         return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1691             .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1692     }
1693
1694     Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1695         if (Objects.isNull(proxyComponent)) {
1696             return Optional.empty();
1697         }
1698         Map<String, ToscaProperty> proxyProperties = new HashMap<>();
1699         addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
1700         if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1701             proxyProperties.putAll(proxyComponent.getProperties().stream()
1702                 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1703                     .toMap(PropertyDataDefinition::getName,
1704                         property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
1705         }
1706         return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1707     }
1708
1709     void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1710                                Map<String, ToscaProperty> mergedProperties) {
1711         if (CollectionUtils.isEmpty(componentInputs)) {
1712             return;
1713         }
1714         for (InputDefinition input : componentInputs) {
1715             ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
1716             mergedProperties.put(input.getName(), property);
1717         }
1718     }
1719
1720     Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1721         if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1722             return Optional.empty();
1723         }
1724         Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1725         //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1726
1727         // always available in the proxy node template
1728         removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1729         return Optional
1730             .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1731     }
1732
1733     private static class CustomRepresenter extends Representer {
1734
1735         CustomRepresenter() {
1736             super();
1737             this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1738             this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1739             // null representer is exceptional and it is stored as an instance
1740
1741             // variable.
1742             this.nullRepresenter = new RepresentNull();
1743         }
1744
1745         public boolean validateGetInputValue(final Object valueObj) {
1746             if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1747                 return false;
1748             }
1749             if (valueObj instanceof List) {
1750                 return ((List) valueObj).size() > 1;
1751             }
1752             return true;
1753         }
1754
1755         public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1756             if (valueObj instanceof List) {
1757                 return ((List) valueObj).size() > 1;
1758             }
1759             return false;
1760         }
1761
1762         @Override
1763         protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1764             if (propertyValue == null) {
1765                 return null;
1766             }
1767             // skip not relevant for Tosca property
1768             if ("dependencies".equals(property.getName())) {
1769                 return null;
1770             }
1771             if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1772                 return null;
1773             }
1774             removeDefaultP(propertyValue);
1775             NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1776             if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1777                 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1778             }
1779             return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1780         }
1781
1782         private void removeDefaultP(final Object propertyValue) {
1783             if (propertyValue instanceof Map) {
1784                 final Map mapPropertyValue = ((Map) propertyValue);
1785                 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1786                 Object defaultValue = null;
1787                 while (iter.hasNext()) {
1788                     final Map.Entry entry = iter.next();
1789                     if ("_defaultp_".equals(entry.getKey())) {
1790                         defaultValue = entry.getValue();
1791                         iter.remove();
1792                     } else if (entry.getValue() instanceof Map) {
1793                         removeDefaultP(entry.getValue());
1794                     }
1795                 }
1796                 if (defaultValue != null) {
1797                     mapPropertyValue.putIfAbsent("default", defaultValue);
1798                 }
1799             }
1800         }
1801
1802         @Override
1803         protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1804             // remove the bean type from the output yaml (!! ...)
1805             if (!classTags.containsKey(javaBean.getClass())) {
1806                 addClassTag(javaBean.getClass(), Tag.MAP);
1807             }
1808             return super.representJavaBean(properties, javaBean);
1809         }
1810
1811         private class RepresentToscaAttribute implements Represent {
1812
1813             @Override
1814             public Node representData(Object data) {
1815                 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1816                 return represent(toscaAttribute.asToscaMap());
1817             }
1818         }
1819
1820         private class RepresentToscaPropertyAssignment implements Represent {
1821
1822             public Node representData(Object data) {
1823                 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1824                 if (toscaOperationAssignment.getValue() instanceof String) {
1825                     final String stringValue = (String) toscaOperationAssignment.getValue();
1826                     if (isPropertyOrAttributeFunction(stringValue)) {
1827                         return representGetAttribute(stringValue);
1828                     }
1829                     return representScalar(Tag.STR, stringValue);
1830                 }
1831                 return represent(null);
1832             }
1833
1834             public Node representGetAttribute(final String getAttributeFunction) {
1835                 return represent(new Yaml().load(getAttributeFunction));
1836             }
1837
1838             public boolean isPropertyOrAttributeFunction(final String value) {
1839                 try {
1840                     final Yaml yaml = new Yaml();
1841                     final Object yamlObj = yaml.load(value);
1842                     if (!(yamlObj instanceof Map)) {
1843                         return false;
1844                     }
1845                     final Map<String, Object> getAttributeMap = (Map) yamlObj;
1846                     if (getAttributeMap.size() != 1) {
1847                         return false;
1848                     }
1849                     final List<String> functionList = Arrays
1850                         .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1851                     final Optional<String> function = getAttributeMap.keySet().stream()
1852                         .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1853                     if (function.isEmpty()) {
1854                         return false;
1855                     }
1856                     final String functionName = function.get();
1857                     final Object getAttributeValueObj = getAttributeMap.get(functionName);
1858                     if (GET_INPUT.getFunctionName().equals(functionName)) {
1859                         return validateGetInputValue(getAttributeValueObj);
1860                     } else {
1861                         return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1862                     }
1863                 } catch (final Exception ignored) {
1864                     return false;
1865                 }
1866             }
1867         }
1868
1869         private class RepresentNull implements Represent {
1870
1871             @Override
1872             public Node representData(Object data) {
1873                 // possible values are here http://yaml.org/type/null.html
1874                 return representScalar(Tag.NULL, "");
1875             }
1876         }
1877     }
1878
1879     private static class UnsortedPropertyUtils extends PropertyUtils {
1880
1881         @Override
1882         protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1883             Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1884             return new LinkedHashSet<>(fields);
1885         }
1886     }
1887
1888     private Configuration getConfiguration() {
1889         return ConfigurationManager.getConfigurationManager().getConfiguration();
1890     }
1891
1892 }