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