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