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