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