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