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