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