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