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