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