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