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