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