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