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