ef5192c0489a0d3b2357c2addf015e06761e1700
[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 applicationDataTypeCache;
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 applicationDataTypeCache,
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.applicationDataTypeCache = applicationDataTypeCache;
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 = applicationDataTypeCache.getAll(component.getModel());
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                 break;
476             case SERVICE:
477                 Service service = (Service) component;
478                 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
479                 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
480                 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
481                 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
482                 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
483                 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
484                     service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
485                 if (!isInstance) {
486                     // DE268546
487                     toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
488                     toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
489                     toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
490                 }
491                 break;
492             default:
493                 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
494         }
495         for (final String key : component.getCategorySpecificMetadata().keySet()) {
496             if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
497                 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
498             }
499         }
500         return toscaMetadata;
501     }
502
503     private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
504         if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
505             return INVARIANT_UUID;
506         }
507         return jsonPresentationField.getPresentation();
508     }
509
510     private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
511         final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
512         if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
513             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
514             return Either.right(ToscaError.GENERAL_ERROR);
515         }
516         Map<String, Component> componentCache = new HashMap<>();
517         if (!ModelConverter.isAtomicComponent(component)) {
518             final List<Map<String, Map<String, String>>> additionalImports =
519                 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
520             List<Triple<String, String, Component>> dependencies = new ArrayList<>();
521             Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
522             if (isNotEmpty(toscaArtifacts)) {
523                 ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
524                 if (artifactDefinition != null) {
525                     Map<String, Map<String, String>> importsListMember = new HashMap<>();
526                     Map<String, String> interfaceFiles = new HashMap<>();
527                     interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
528                     StringBuilder keyNameBuilder = new StringBuilder();
529                     keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-").append(component.getName())
530                         .append("-interface");
531                     importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
532                     additionalImports.add(importsListMember);
533                 }
534             }
535             List<ComponentInstance> componentInstances = component.getComponentInstances();
536             if (componentInstances != null && !componentInstances.isEmpty()) {
537                 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
538             }
539             toscaTemplate.setDependencies(dependencies);
540             toscaTemplate.setImports(additionalImports);
541         } else {
542             log.debug("currently imports supported for VF and service only");
543         }
544         return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
545     }
546
547     private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
548         return getConfiguration().getDefaultImports();
549     }
550
551     private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
552                                   final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
553         log.debug("createDependency componentCache {}", componentCache);
554         Component componentRI = componentCache.get(componentInstance.getComponentUid());
555         if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
556             // all resource must be only once!
557             final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
558             if ((resource.isRight()) && (log.isDebugEnabled())) {
559                 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
560                     componentInstance.getUniqueId());
561                 return;
562             }
563             final Component fetchedComponent = resource.left().value();
564             componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
565             addDependencies(imports, dependencies, componentRI);
566         }
567     }
568
569     /**
570      * Sets a componentCache from the given component/resource.
571      */
572     private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
573                                         final Component fetchedComponent) {
574         componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
575         if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
576             || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
577             final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
578                 .getToscaFullElement(componentInstance.getSourceModelUid());
579             if (sourceService.isRight() && (log.isDebugEnabled())) {
580                 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
581                     componentInstance.getUniqueId());
582             }
583             final Component fetchedSource = sourceService.left().value();
584             componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
585             return fetchedSource;
586         }
587         return fetchedComponent;
588     }
589
590     /**
591      * Retrieves all derived_from nodes and stores it in a predictable order.
592      */
593     private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
594                                  final Component fetchedComponent) {
595         final Set<Component> componentsList = new LinkedHashSet<>();
596         if (fetchedComponent instanceof Resource) {
597             log.debug("fetchedComponent is a resource {}", fetchedComponent);
598             final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
599             if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
600                 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
601                     log.debug("Started entry.getValue() : {}", entry.getValue());
602                     if (!NATIVE_ROOT.equals(entry.getValue())) {
603                         Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
604                         if (resourcefetched != null && resourcefetched.isLeft()) {
605                             componentsList.add(resourcefetched.left().value());
606                         }
607                     }
608                 });
609                 setImports(imports, dependencies, componentsList);
610             } else {
611                 setImports(imports, dependencies, fetchedComponent);
612             }
613         }
614     }
615
616     /**
617      * Returns all derived_from nodes found.
618      */
619     private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
620         final Resource parentResource = (Resource) fetchedComponent;
621         Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
622         if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
623             componentsList.add(fetchedComponent);
624             for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
625                 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
626                     .getToscaElement(componentInstance.getComponentUid());
627                 if (resourcefetched != null && resourcefetched.isLeft()) {
628                     final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
629                     if (MapUtils.isNotEmpty(derivedWithId)) {
630                         derivedFromMapOfIdToName.putAll(derivedWithId);
631                     }
632                 }
633             }
634         } else {
635             derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
636         }
637         log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
638         return Optional.ofNullable(derivedFromMapOfIdToName);
639     }
640
641     /**
642      * Creates a resource map and adds it to the import list.
643      */
644     private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
645                             final Set<Component> componentsList) {
646         componentsList.forEach(component -> setImports(imports, dependencies, component));
647     }
648
649     private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
650                             final Component component) {
651         final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
652         final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
653         if (artifactDefinition != null) {
654             final Map<String, String> files = new HashMap<>();
655             final String artifactName = artifactDefinition.getArtifactName();
656             files.put(IMPORTS_FILE_KEY, artifactName);
657             final StringBuilder keyNameBuilder = new StringBuilder();
658             keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
659             keyNameBuilder.append("-");
660             keyNameBuilder.append(component.getName());
661             addImports(imports, keyNameBuilder, files);
662             dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
663             if (!ModelConverter.isAtomicComponent(component)) {
664                 final Map<String, String> interfaceFiles = new HashMap<>();
665                 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
666                 keyNameBuilder.append("-interface");
667                 addImports(imports, keyNameBuilder, interfaceFiles);
668             }
669         }
670     }
671
672     /**
673      * Adds the found resource to the import definition list.
674      */
675     private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
676                             final Map<String, String> files) {
677         final String mapKey = keyNameBuilder.toString();
678         if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
679             final Map<String, Map<String, String>> importsListMember = new HashMap<>();
680             importsListMember.put(keyNameBuilder.toString(), files);
681             imports.add(importsListMember);
682         }
683     }
684
685     private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
686                                                               Map<String, ToscaNodeType> nodeTypes) {
687         return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
688     }
689
690     public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
691                                                                       ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
692                                                                       boolean isAssociatedComponent) {
693         log.debug("start convert node type for {}", component.getUniqueId());
694         ToscaNodeType toscaNodeType = createNodeType(component);
695         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
696             .getAllInterfaceLifecycleTypes(component.getModel());
697         if (lifecycleTypeEither.isRight()) {
698             log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
699             return Either.right(ToscaError.GENERAL_ERROR);
700         }
701         List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
702             .collect(Collectors.toList());
703         toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
704         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
705         if (dataTypesEither.isRight()) {
706             log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
707             return Either.right(ToscaError.GENERAL_ERROR);
708         }
709         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
710         List<InputDefinition> inputDef = component.getInputs();
711         Map<String, ToscaProperty> mergedProperties = new HashMap<>();
712         interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
713         addInputsToProperties(dataTypes, inputDef, mergedProperties);
714         final Map<String, ToscaAttribute> toscaAttributeMap;
715         toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
716         if (!toscaAttributeMap.isEmpty()) {
717             toscaNodeType.setAttributes(toscaAttributeMap);
718         }
719         if (CollectionUtils.isNotEmpty(component.getProperties())) {
720             List<PropertyDefinition> properties = component.getProperties();
721             Map<String, ToscaProperty> convertedProperties = properties.stream()
722                 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
723                     .toMap(PropertyDataDefinition::getName,
724                         property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
725             // merge component properties and inputs properties
726             mergedProperties.putAll(convertedProperties);
727         }
728         if (MapUtils.isNotEmpty(mergedProperties)) {
729             toscaNodeType.setProperties(mergedProperties);
730         }
731         /* convert private data_types */
732         List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
733         if (CollectionUtils.isNotEmpty(privateDataTypes)) {
734             Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
735             for (DataTypeDefinition dataType : privateDataTypes) {
736                 log.debug("Emitting private data type: component.name={} dataType.name={}",
737                     component.getNormalizedName(), dataType.getName());
738                 ToscaDataType toscaDataType = new ToscaDataType();
739                 toscaDataType.setDerived_from(dataType.getDerivedFromName());
740                 toscaDataType.setDescription(dataType.getDescription());
741                 toscaDataType.setVersion(dataType.getVersion());
742                 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
743                     toscaDataType.setProperties(dataType.getProperties().stream()
744                         .collect(Collectors.toMap(
745                             PropertyDataDefinition::getName,
746                             s -> propertyConvertor
747                                 .convertProperty(dataTypes, s, PropertyType.PROPERTY)
748                         )));
749                 }
750                 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
751             }
752             toscaNode.setData_types(toscaDataTypeMap);
753         }
754
755         // Extracted to method for code reuse
756         return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
757     }
758
759     private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
760                                                                  final Map<String, DataTypeDefinition> dataTypes) {
761         if (CollectionUtils.isEmpty(attributeList)) {
762             return Collections.emptyMap();
763         }
764         final AttributeConverter converter = new AttributeConverter(dataTypes);
765         final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
766         for (final AttributeDefinition attributeDefinition : attributeList) {
767             toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
768         }
769         return toscaAttributeMap;
770     }
771
772     private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
773                                                                        Component component, ToscaTemplate toscaNode,
774                                                                        Map<String, ToscaNodeType> nodeTypes,
775                                                                        ToscaNodeType toscaNodeType,
776                                                                        Map<String, DataTypeDefinition> dataTypes) {
777         Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
778             dataTypes);
779         if (capabilities.isRight()) {
780             return Either.right(capabilities.right().value());
781         }
782         toscaNodeType = capabilities.left().value();
783         log.debug("Capabilities converted for {}", component.getUniqueId());
784
785         Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
786             .convertRequirements(componentsCache, component, toscaNodeType);
787         if (requirements.isRight()) {
788             return Either.right(requirements.right().value());
789         }
790         toscaNodeType = requirements.left().value();
791         log.debug("Requirements converted for {}", component.getUniqueId());
792
793         String toscaResourceName;
794         switch (component.getComponentType()) {
795             case RESOURCE:
796                 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
797                     .getMetadataDataDefinition()).getToscaResourceName();
798                 break;
799             case SERVICE:
800                 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
801                     + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
802                 break;
803             default:
804                 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
805                 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
806         }
807
808         nodeTypes.put(toscaResourceName, toscaNodeType);
809         toscaNode.setNode_types(nodeTypes);
810         log.debug("finish convert node type for {}", component.getUniqueId());
811         return Either.left(toscaNode);
812     }
813
814     private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
815                                                                                     final Map<String, Component> componentCache,
816                                                                                     final Map<String, DataTypeDefinition> dataTypes,
817                                                                                     final ToscaTopolgyTemplate topologyTemplate) {
818
819         final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
820         final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
821         final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
822         final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
823         final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
824
825         Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
826         log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
827         final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
828
829         Map<String, ToscaGroupTemplate> groupsMap = null;
830         for (final ComponentInstance componentInstance : component.getComponentInstances()) {
831             ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
832             if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
833                 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
834             }
835             nodeTemplate.setType(componentInstance.getToscaComponentName());
836             nodeTemplate.setDirectives(componentInstance.getDirectives());
837             nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
838
839             final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
840                 .getOriginComponent(componentCache, componentInstance);
841             if (originComponentRes.isRight()) {
842                 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
843                 break;
844             }
845             final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
846                 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
847             if (requirements.isRight()) {
848                 convertNodeTemplatesRes = Either.right(requirements.right().value());
849                 break;
850             }
851             final String instanceUniqueId = componentInstance.getUniqueId();
852             log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
853
854             nodeTemplate = requirements.left().value();
855
856             final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
857
858             if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
859                 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
860                 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
861             } else {
862                 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
863             }
864
865             final Either<ToscaNodeTemplate, ToscaError> capabilities =
866                 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
867             if (capabilities.isRight()) {
868                 convertNodeTemplatesRes = Either.right(capabilities.right().value());
869                 break;
870             }
871             log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
872
873             nodeTemplate = capabilities.left().value();
874             final Map<String, Object> props = new HashMap<>();
875             final Map<String, Object> attribs = new HashMap<>();
876
877             if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
878                 // Adds the properties of parent component to map
879                 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
880                 addAttributesOfParentComponent(originalComponent, attribs);
881             }
882
883             if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
884                 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
885             }
886             if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
887                 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
888             }
889
890             if (componentInstancesInputs != null
891                 && componentInstancesInputs.containsKey(instanceUniqueId)
892                 && !isComponentOfTypeServiceProxy(componentInstance)) {
893                 //For service proxy the inputs are already handled under instance properties above
894                 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
895             }
896
897             //M3[00001] - NODE TEMPLATE INTERFACES  - START
898             handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
899             //M3[00001] - NODE TEMPLATE INTERFACES  - END
900             if (MapUtils.isNotEmpty(props)) {
901                 nodeTemplate.setProperties(props);
902             }
903             if (MapUtils.isNotEmpty(attribs)) {
904                 nodeTemplate.setAttributes(attribs);
905             }
906
907             final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
908             if (CollectionUtils.isNotEmpty(groupInstances)) {
909                 if (groupsMap == null) {
910                     groupsMap = new HashMap<>();
911                 }
912                 for (final GroupInstance groupInst : groupInstances) {
913                     if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
914                         groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
915                     }
916                 }
917             }
918
919             nodeTemplates.put(componentInstance.getName(), nodeTemplate);
920         }
921         if (groupsMap != null) {
922             log.debug("instance groups added");
923             topologyTemplate.addGroups(groupsMap);
924         }
925         if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
926             ((Service) component).getForwardingPaths())) {
927             log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
928             ForwardingPathToscaUtil
929                 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
930             log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
931         }
932         if (convertNodeTemplatesRes == null) {
933             convertNodeTemplatesRes = Either.left(nodeTemplates);
934         }
935         log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
936         return convertNodeTemplatesRes;
937     }
938
939     private void handleInstanceInterfaces(
940         Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
941         ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
942         String instanceUniqueId,
943         Component parentComponent) {
944
945         if (MapUtils.isEmpty(componentInstanceInterfaces)
946             || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
947             nodeTemplate.setInterfaces(null);
948             return;
949         }
950
951         final List<ComponentInstanceInterface> currServiceInterfaces =
952             componentInstanceInterfaces.get(instanceUniqueId);
953
954         final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
955         currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
956             .getUniqueId(), instInterface));
957
958         final Map<String, Object> interfaceMap = interfacesOperationsConverter
959             .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance),
960                 isComponentOfTypeServiceProxy(componentInstance));
961
962         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
963         nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
964     }
965
966     private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
967         return Objects.nonNull(componentInstance.getOriginType())
968             && componentInstance.getOriginType().getValue().equals("Service Proxy");
969     }
970
971     private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
972                                             Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
973                                             String instanceUniqueId, Map<String, Object> props) {
974
975         List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
976         if (instanceInputsList != null) {
977             instanceInputsList.forEach(input -> {
978                 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue() : input.getDefaultValue();
979                 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
980             });
981         }
982     }
983
984     private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
985                                                   final Map<String, DataTypeDefinition> dataTypes,
986                                                   final String instanceUniqueId,
987                                                   final Map<String, Object> props) {
988
989         if (isNotEmpty(componentInstancesProperties)) {
990             componentInstancesProperties.get(instanceUniqueId)
991                 // Converts and adds each value to property map
992                 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
993         }
994     }
995
996     private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
997                                                   final String instanceUniqueId,
998                                                   final Map<String, Object> attribs) {
999
1000         if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1001             componentInstancesAttributes.get(instanceUniqueId).stream()
1002                 // Filters out Attributes with empty default values
1003                 .filter(attributeDefinition -> StringUtils.isNotEmpty(attributeDefinition.getDefaultValue()))
1004                 // Converts and adds each value to attribute map
1005                 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1006         }
1007     }
1008
1009     private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1010                                                 Component componentOfInstance, Map<String, Object> props) {
1011
1012         List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1013         if (isNotEmpty(componentProperties)) {
1014             componentProperties.stream()
1015                 // Filters out properties with empty default values
1016                 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1017                 // Converts and adds each value to property map
1018                 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1019         }
1020     }
1021
1022     private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1023
1024         final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1025         if (isNotEmpty(componentAttributes)) {
1026             componentAttributes.stream()
1027                 // Filters out Attributes with empty default values
1028                 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1029                 // Converts and adds each value to attribute map
1030                 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1031         }
1032     }
1033
1034     private ToscaNodeType createNodeType(Component component) {
1035         ToscaNodeType toscaNodeType = new ToscaNodeType();
1036         if (ModelConverter.isAtomicComponent(component)) {
1037             if (((Resource) component).getDerivedFrom() != null) {
1038                 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1039             }
1040             toscaNodeType.setDescription(component.getDescription());
1041         } else {
1042             String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1043                 : NATIVE_ROOT;
1044             toscaNodeType.setDerived_from(derivedFrom);
1045         }
1046         return toscaNodeType;
1047     }
1048
1049     private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1050
1051         Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1052         Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1053         List<ComponentInstance> componentInstances = container.getComponentInstances();
1054         if (CollectionUtils.isEmpty(componentInstances)) {
1055             return res;
1056         }
1057         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1058         componentInstances.stream()
1059             .filter(this::isComponentOfTypeServiceProxy)
1060             .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1061         if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1062             return res;
1063         }
1064         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1065             Component serviceComponent;
1066             ComponentParametersView componentParametersView = new ComponentParametersView();
1067             componentParametersView.disableAll();
1068             componentParametersView.setIgnoreInterfaces(false);
1069             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1070                 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1071             if (service.isRight()) {
1072                 log.debug("Failed to fetch original service component with id {} for instance {}",
1073                     entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1074                 return Either.right(ToscaError.GENERAL_ERROR);
1075             } else {
1076                 serviceComponent = service.left().value();
1077             }
1078
1079             Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1080                 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1081             if (lifecycleTypeEither.isRight()) {
1082                 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1083                 return Either.right(ToscaError.GENERAL_ERROR);
1084             }
1085
1086             List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1087                 .map(InterfaceDataDefinition::getType)
1088                 .collect(Collectors.toList());
1089             //Add interface types for local interfaces in the original service component for proxy
1090             Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1091                 allGlobalInterfaceTypes);
1092             if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1093                 proxyInterfaceTypes.putAll(localInterfaceTypes);
1094             }
1095
1096         }
1097         return Either.left(proxyInterfaceTypes);
1098     }
1099
1100     private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1101                                                                                 Component container) {
1102
1103         Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1104         Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1105
1106         List<ComponentInstance> componentInstances = container.getComponentInstances();
1107
1108         if (componentInstances == null || componentInstances.isEmpty()) {
1109             return res;
1110         }
1111         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1112         List<ComponentInstance> proxyInst = componentInstances.stream()
1113             .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1114             .collect(Collectors.toList());
1115         if (proxyInst != null && !proxyInst.isEmpty()) {
1116             for (ComponentInstance inst : proxyInst) {
1117                 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1118             }
1119         }
1120
1121         if (serviceProxyInstanceList.isEmpty()) {
1122             return res;
1123         }
1124         Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1125             .getLatestByName("serviceProxy", null);
1126         if (serviceProxyOrigin.isRight()) {
1127             log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1128                 serviceProxyOrigin.right().value());
1129             return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1130         }
1131         Component origComponent = serviceProxyOrigin.left().value();
1132
1133         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1134             Component serviceComponent = null;
1135             ComponentParametersView componentParametersView = new ComponentParametersView();
1136             componentParametersView.disableAll();
1137             componentParametersView.setIgnoreCategories(false);
1138             componentParametersView.setIgnoreProperties(false);
1139             componentParametersView.setIgnoreInputs(false);
1140             componentParametersView.setIgnoreInterfaces(false);
1141             componentParametersView.setIgnoreRequirements(false);
1142             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1143                 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1144             if (service.isRight()) {
1145                 log.debug("Failed to fetch resource with id {} for instance {}",
1146                     entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1147             } else {
1148                 serviceComponent = service.left().value();
1149             }
1150
1151             ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1152                 entryProxy.getValue());
1153             nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1154         }
1155
1156         return Either.left(nodeTypesMap);
1157     }
1158
1159     private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1160                                                     final Component container, final ToscaTemplate toscaNode) {
1161         final List<ComponentInstance> componentInstances = container.getComponentInstances();
1162
1163         if (CollectionUtils.isEmpty(componentInstances)) {
1164             return;
1165         }
1166         final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1167             .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1168             .collect(Collectors.toList());
1169         if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1170             for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1171                 final Map<String, ToscaNodeType> nodeTypes =
1172                     toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1173                 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1174                     nodeTypes, true);
1175             }
1176         }
1177     }
1178
1179     private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1180                                               Component proxyComponent, ComponentInstance componentInstance) {
1181         ToscaNodeType toscaNodeType = new ToscaNodeType();
1182         String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1183
1184         toscaNodeType.setDerived_from(derivedFrom);
1185         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(origComponent.getModel());
1186         if (dataTypesEither.isRight()) {
1187             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1188         }
1189         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1190         Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1191             .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1192
1193         if (MapUtils.isNotEmpty(capabilities)) {
1194             toscaNodeType.setCapabilities(capabilities);
1195         }
1196         List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1197             .convertProxyRequirements(componentCache, componentInstance);
1198         if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1199             toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1200         }
1201         Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1202         proxyProperties.ifPresent(toscaNodeType::setProperties);
1203
1204         Map<String, Object> interfaceMap = new HashMap<>();
1205         if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1206             final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1207             if (proxyInterfaces.isPresent()) {
1208                 interfaceMap = proxyInterfaces.get();
1209             }
1210         } else {
1211             interfaceMap = interfacesOperationsConverter
1212                 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1213
1214         }
1215         interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1216         toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1217
1218         return toscaNodeType;
1219     }
1220
1221     private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1222                                                                                        ComponentInstance componentInstance,
1223                                                                                        List<RequirementCapabilityRelDef> relations,
1224                                                                                        ToscaNodeTemplate nodeTypeTemplate,
1225                                                                                        Component originComponent,
1226                                                                                        Map<String, Component> componentCache) {
1227
1228         final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1229             relations);
1230         if (isNotEmpty(requirementDefinitionList)) {
1231             try {
1232                 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance, requirementDefinitionList, originComponent, componentCache);
1233                 if (!toscaRequirements.isEmpty()) {
1234                     nodeTypeTemplate.setRequirements(toscaRequirements);
1235                 }
1236             } catch (final Exception e) {
1237                 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1238                     componentInstance.getName(), e);
1239                 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1240             }
1241         }
1242         log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1243         return Either.left(nodeTypeTemplate);
1244     }
1245
1246     private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1247                                                                           final ComponentInstance componentInstance,
1248                                                                           final List<RequirementCapabilityRelDef> filteredRelations,
1249                                                                           final Component originComponent,
1250                                                                           final Map<String, Component> componentCache)
1251         throws ToscaExportException {
1252
1253         final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1254         for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1255             final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1256                 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1257             toscaRequirements.add(toscaTemplateRequirementMap);
1258         }
1259
1260         return toscaRequirements;
1261     }
1262
1263     private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1264                                                                  List<RequirementCapabilityRelDef> relations) {
1265         return relations.stream()
1266             .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1267     }
1268
1269     private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1270                                                                    final Component fromOriginComponent,
1271                                                                    final List<ComponentInstance> instancesList,
1272                                                                    final RequirementCapabilityRelDef relationshipDefinition,
1273                                                                    final Map<String, Component> componentCache)
1274         throws ToscaExportException {
1275
1276         final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1277         final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1278             .getRelationships().get(0);
1279         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1280
1281         final ComponentInstance toInstance = instancesList.stream()
1282             .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1283             .findFirst().orElse(null);
1284         if (toInstance == null) {
1285             final String errorMsg = String
1286                 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1287                     relationshipDefinition.getToNode());
1288             log.debug(errorMsg);
1289             throw new ToscaExportException(errorMsg);
1290         }
1291         final Optional<RequirementDefinition> reqOpt =
1292             findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1293         if (reqOpt.isEmpty()) {
1294             final String errorMsg = String
1295                 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1296                     relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1297             log.debug(errorMsg);
1298             throw new ToscaExportException(errorMsg);
1299         }
1300         final ComponentParametersView filter = new ComponentParametersView(true);
1301         filter.setIgnoreComponentInstances(false);
1302         filter.setIgnoreCapabilities(false);
1303         filter.setIgnoreGroups(false);
1304         final Either<Component, StorageOperationStatus> getOriginRes =
1305             toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1306         if (getOriginRes.isRight()) {
1307             final String errorMsg = String.format(
1308                 "Failed to build substituted name for the requirement %s. "
1309                     + "Failed to get an origin component with uniqueId %s",
1310                 reqOpt.get().getName(), toInstance.getActualComponentUid());
1311             log.debug(errorMsg);
1312             throw new ToscaExportException(errorMsg);
1313         }
1314         final Component toOriginComponent = getOriginRes.left().value();
1315         Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1316             .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1317         if (capOpt.isEmpty()) {
1318             capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1319             if (capOpt.isEmpty()) {
1320                 final String errorMsg = String
1321                     .format("Failed to find a capability with name %s on a component with uniqueId %s",
1322                         relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1323                 log.debug(errorMsg);
1324                 throw new ToscaExportException(errorMsg);
1325             }
1326         }
1327         return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1328             capabilityRequirementRelationship, toInstance, componentCache);
1329     }
1330
1331     private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1332                                                  CapabilityDefinition capability) {
1333         return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1334             && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1335     }
1336
1337     private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1338                                                           Component toOriginComponent, Component fromOriginComponent,
1339                                                           RequirementDefinition requirement) {
1340         Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1341             .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1342         if (!cap.isPresent()) {
1343             log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1344                 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1345         }
1346         return cap;
1347     }
1348
1349     private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1350                                                                    final Component toOriginComponent,
1351                                                                    final CapabilityDefinition capability,
1352                                                                    final RequirementDefinition requirement,
1353                                                                    final CapabilityRequirementRelationship capabilityRequirementRelationship,
1354                                                                    final ComponentInstance toInstance,
1355                                                                    final Map<String, Component> componentCache)
1356         throws ToscaExportException {
1357
1358         List<String> reducedPath = capability.getPath();
1359         if (capability.getOwnerId() != null) {
1360             reducedPath = capabilityRequirementConverter
1361                 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1362         }
1363         final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1364         final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1365             toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName());
1366         if (capabilityNameEither.isRight()) {
1367             final String errorMsg = String.format(
1368                 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1369                 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1370             log.debug(
1371                 errorMsg);
1372             throw new ToscaExportException(errorMsg);
1373         }
1374         final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1375             .buildSubstitutedName(componentCache, fromOriginComponent,
1376                 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName());
1377         if (requirementNameEither.isRight()) {
1378             final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1379                     + "with name %s on a component with uniqueId %s",
1380                 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1381             log.debug(errorMsg);
1382             throw new ToscaExportException(errorMsg);
1383         }
1384         final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1385         final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1386         toscaRequirement.setNode(toInstance.getName());
1387         toscaRequirement.setCapability(capabilityNameEither.left().value());
1388         if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1389             toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1390         }
1391         toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1392         return toscaReqMap;
1393     }
1394
1395     private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1396                                                             Map<String, List<RequirementDefinition>> reqMap,
1397                                                             RelationshipInfo reqAndRelationshipPair,
1398                                                             String fromInstanceId) {
1399         for (List<RequirementDefinition> reqList : reqMap.values()) {
1400             Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1401                 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1402                 .findFirst();
1403             if (reqOpt.isPresent()) {
1404                 return reqOpt;
1405             }
1406         }
1407         return Optional.empty();
1408     }
1409
1410     /**
1411      * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1412      * 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
1413      * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1414      */
1415     private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1416                                                   RequirementDefinition requirement, String fromInstanceId) {
1417         if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1418             log.debug("Failed to find a requirement with name {} and  reqAndRelationshipPair {}", requirement.getName(),
1419                 reqAndRelationshipPair.getRequirement());
1420             return false;
1421         }
1422         return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1423             originComponent);
1424     }
1425
1426     private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1427                                                Component originComponent) {
1428         return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1429             isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1430                 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1431     }
1432
1433     private boolean isCvfc(Component component) {
1434         return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1435     }
1436
1437     private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component, SubstitutionMapping substitutionMappings,
1438                                                                         Map<String, Component> componentCache) {
1439         Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
1440         Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
1441             .convertSubstitutionMappingCapabilities(componentCache, component);
1442         if (toscaCapabilitiesRes.isRight()) {
1443             result = Either.right(toscaCapabilitiesRes.right().value());
1444             log.debug("Failed convert capabilities for the component {}. ", component.getName());
1445         } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1446             substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
1447             log.debug("Finish convert capabilities for the component {}. ", component.getName());
1448         }
1449         log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1450         return result;
1451     }
1452
1453     private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1454                                                                   Map<String, DataTypeDefinition> dataTypes) {
1455         Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1456         if (!toscaCapabilities.isEmpty()) {
1457             nodeType.setCapabilities(toscaCapabilities);
1458         }
1459         log.debug("Finish convert Capabilities for node type");
1460         return Either.left(nodeType);
1461     }
1462
1463     private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1464         if (artifacts == null) {
1465             return null;
1466         }
1467         Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1468         for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1469             ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1470             artifact.setFile(entry.getValue().getFile());
1471             artifact.setType(entry.getValue().getType());
1472             arts.put(entry.getKey(), artifact);
1473         }
1474         return arts;
1475     }
1476
1477     private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1478         if (inNodeFilter == null) {
1479             return null;
1480         }
1481         NodeFilter nodeFilter = new NodeFilter();
1482         ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1483         ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1484         List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1485         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1486         copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1487         copyNodeFilterProperties(origProperties, propertiesCopy);
1488         if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1489             nodeFilter.setCapabilities(capabilitiesCopy);
1490         }
1491         if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1492             nodeFilter.setProperties(propertiesCopy);
1493         }
1494         nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1495         nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1496         return nodeFilter;
1497     }
1498
1499     private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1500         if (substitutionFilterDataDefinition == null) {
1501             return null;
1502         }
1503         NodeFilter nodeFilter = new NodeFilter();
1504         ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1505         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1506         copySubstitutionFilterProperties(origProperties, propertiesCopy);
1507         if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1508             nodeFilter.setProperties(propertiesCopy);
1509         }
1510         nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1511         return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1512     }
1513
1514     private Object cloneToscaId(Object toscaId) {
1515         return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1516     }
1517
1518     private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1519         String objectAsYml = yamlUtil.objectToYaml(objToClone);
1520         return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1521     }
1522
1523     private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1524                                                     List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1525         if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1526             .isEmpty()) {
1527             return;
1528         }
1529         for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1530             Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1531             CapabilityFilter capabilityFilter = new CapabilityFilter();
1532             List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1533             copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1534             capabilityFilter.setProperties(propertiesCopy);
1535             capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1536             capabilitiesCopy.add(capabilityFilterCopyMap);
1537         }
1538     }
1539
1540     private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1541                                           List<Map<String, List<Object>>> propertiesCopy) {
1542         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1543             return;
1544         }
1545         Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1546         for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1547             for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1548                 Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1549                 String propertyName = propertyDataDefinition.getName();
1550                 if (propertyMapCopy.containsKey(propertyName)) {
1551                     addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1552                 } else {
1553                     if (propertyName != null) {
1554                         List<Object> propsList = new ArrayList<>();
1555                         addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1556                         propertyMapCopy.put(propertyName, propsList);
1557                     } else {
1558                         propertyMapCopy.putAll(propertyValObj);
1559                     }
1560                 }
1561             }
1562         }
1563         propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1564     }
1565
1566     private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1567                                                   final List<Map<String, List<Object>>> propertiesCopy) {
1568         if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1569             return;
1570         }
1571         final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1572         for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1573             for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1574                 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1575                 final String propertyName = propertyDataDefinition.getName();
1576                 if (propertyMapCopy.containsKey(propertyName)) {
1577                     addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1578                 } else {
1579                     if (propertyName != null) {
1580                         final List<Object> propsList = new ArrayList<>();
1581                         addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1582                         propertyMapCopy.put(propertyName, propsList);
1583                     } else {
1584                         propertyMapCopy.putAll(propertyValObj);
1585                     }
1586                 }
1587             }
1588         }
1589         propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1590     }
1591
1592     private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1593         if (propertyValObj.containsKey(propertyName)) {
1594             propsList.add(propertyValObj.get(propertyName));
1595         } else {
1596             propsList.add(propertyValObj);
1597         }
1598     }
1599
1600     private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1601         Map<String, List<Object>> tempMap = new HashMap<>();
1602         tempMap.put(entry.getKey(), entry.getValue());
1603         propertiesCopy.add(tempMap);
1604     }
1605
1606     private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1607         if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1608             return Collections.emptyMap();
1609         }
1610         return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName)
1611             .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1612     }
1613
1614     private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1615         if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1616             return Collections.emptyMap();
1617         }
1618         return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1619             .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1620     }
1621
1622     Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1623         if (Objects.isNull(proxyComponent)) {
1624             return Optional.empty();
1625         }
1626         Map<String, ToscaProperty> proxyProperties = new HashMap<>();
1627         addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
1628         if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1629             proxyProperties.putAll(proxyComponent.getProperties().stream()
1630                 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1631                     .toMap(PropertyDataDefinition::getName,
1632                         property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
1633         }
1634         return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1635     }
1636
1637     void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1638                                Map<String, ToscaProperty> mergedProperties) {
1639         if (CollectionUtils.isEmpty(componentInputs)) {
1640             return;
1641         }
1642         for (InputDefinition input : componentInputs) {
1643             ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
1644             mergedProperties.put(input.getName(), property);
1645         }
1646     }
1647
1648     Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1649         if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1650             return Optional.empty();
1651         }
1652         Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1653         //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1654
1655         // always available in the proxy node template
1656         removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1657         return Optional
1658             .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1659     }
1660
1661     private static class CustomRepresenter extends Representer {
1662
1663         CustomRepresenter() {
1664             super();
1665             this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1666             this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1667             // null representer is exceptional and it is stored as an instance
1668
1669             // variable.
1670             this.nullRepresenter = new RepresentNull();
1671         }
1672
1673         public boolean validateGetInputValue(final Object valueObj) {
1674             if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1675                 return false;
1676             }
1677             if (valueObj instanceof List) {
1678                 return ((List) valueObj).size() > 1;
1679             }
1680             return true;
1681         }
1682
1683         public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1684             if (valueObj instanceof List) {
1685                 return ((List) valueObj).size() > 1;
1686             }
1687             return false;
1688         }
1689
1690         @Override
1691         protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1692             if (propertyValue == null) {
1693                 return null;
1694             }
1695             // skip not relevant for Tosca property
1696             if ("dependencies".equals(property.getName())) {
1697                 return null;
1698             }
1699             if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1700                 return null;
1701             }
1702             removeDefaultP(propertyValue);
1703             NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1704             if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1705                 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1706             }
1707             return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1708         }
1709
1710         private void removeDefaultP(final Object propertyValue) {
1711             if (propertyValue instanceof Map) {
1712                 final Map mapPropertyValue = ((Map) propertyValue);
1713                 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1714                 Object defaultValue = null;
1715                 while (iter.hasNext()) {
1716                     final Map.Entry entry = iter.next();
1717                     if ("_defaultp_".equals(entry.getKey())) {
1718                         defaultValue = entry.getValue();
1719                         iter.remove();
1720                     } else if (entry.getValue() instanceof Map) {
1721                         removeDefaultP(entry.getValue());
1722                     }
1723                 }
1724                 if (defaultValue != null) {
1725                     mapPropertyValue.putIfAbsent("default", defaultValue);
1726                 }
1727             }
1728         }
1729
1730         @Override
1731         protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1732             // remove the bean type from the output yaml (!! ...)
1733             if (!classTags.containsKey(javaBean.getClass())) {
1734                 addClassTag(javaBean.getClass(), Tag.MAP);
1735             }
1736             return super.representJavaBean(properties, javaBean);
1737         }
1738
1739         private class RepresentToscaAttribute implements Represent {
1740
1741             @Override
1742             public Node representData(Object data) {
1743                 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1744                 return represent(toscaAttribute.asToscaMap());
1745             }
1746         }
1747
1748         private class RepresentToscaPropertyAssignment implements Represent {
1749
1750             public Node representData(Object data) {
1751                 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1752                 if (toscaOperationAssignment.getValue() instanceof String) {
1753                     final String stringValue = (String) toscaOperationAssignment.getValue();
1754                     if (isPropertyOrAttributeFunction(stringValue)) {
1755                         return representGetAttribute(stringValue);
1756                     }
1757                     return representScalar(Tag.STR, stringValue);
1758                 }
1759                 return represent(null);
1760             }
1761
1762             public Node representGetAttribute(final String getAttributeFunction) {
1763                 return represent(new Yaml().load(getAttributeFunction));
1764             }
1765
1766             public boolean isPropertyOrAttributeFunction(final String value) {
1767                 try {
1768                     final Yaml yaml = new Yaml();
1769                     final Object yamlObj = yaml.load(value);
1770                     if (!(yamlObj instanceof Map)) {
1771                         return false;
1772                     }
1773                     final Map<String, Object> getAttributeMap = (Map) yamlObj;
1774                     if (getAttributeMap.size() != 1) {
1775                         return false;
1776                     }
1777                     final List<String> functionList = Arrays
1778                         .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1779                     final Optional<String> function = getAttributeMap.keySet().stream()
1780                         .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1781                     if (function.isEmpty()) {
1782                         return false;
1783                     }
1784                     final String functionName = function.get();
1785                     final Object getAttributeValueObj = getAttributeMap.get(functionName);
1786                     if (GET_INPUT.getFunctionName().equals(functionName)) {
1787                         return validateGetInputValue(getAttributeValueObj);
1788                     } else {
1789                         return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1790                     }
1791                 } catch (final Exception ignored) {
1792                     return false;
1793                 }
1794             }
1795         }
1796
1797         private class RepresentNull implements Represent {
1798
1799             @Override
1800             public Node representData(Object data) {
1801                 // possible values are here http://yaml.org/type/null.html
1802                 return representScalar(Tag.NULL, "");
1803             }
1804         }
1805     }
1806
1807     private static class UnsortedPropertyUtils extends PropertyUtils {
1808
1809         @Override
1810         protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1811             Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1812             return new LinkedHashSet<>(fields);
1813         }
1814     }
1815
1816     private Configuration getConfiguration() {
1817         return ConfigurationManager.getConfigurationManager().getConfiguration();
1818     }
1819
1820 }