Catalog alignment
[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
21 package org.openecomp.sdc.be.tosca;
22
23 import com.fasterxml.jackson.databind.ObjectMapper;
24 import com.fasterxml.jackson.databind.SerializationFeature;
25 import fj.data.Either;
26 import org.apache.commons.collections.CollectionUtils;
27 import org.apache.commons.collections.MapUtils;
28 import org.apache.commons.lang.StringUtils;
29 import org.apache.commons.lang3.tuple.ImmutablePair;
30 import org.apache.commons.lang3.tuple.ImmutableTriple;
31 import org.apache.commons.lang3.tuple.Triple;
32 import org.onap.sdc.tosca.services.YamlUtil;
33 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
34 import org.openecomp.sdc.be.config.ConfigurationManager;
35 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
36 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
37 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
38 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
39 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
40 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
41 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
42 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
43 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
44 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
45 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
46 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
47 import org.openecomp.sdc.be.model.ArtifactDefinition;
48 import org.openecomp.sdc.be.model.CapabilityDefinition;
49 import org.openecomp.sdc.be.model.Component;
50 import org.openecomp.sdc.be.model.ComponentInstance;
51 import org.openecomp.sdc.be.model.ComponentInstanceInput;
52 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
53 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
54 import org.openecomp.sdc.be.model.ComponentParametersView;
55 import org.openecomp.sdc.be.model.DataTypeDefinition;
56 import org.openecomp.sdc.be.model.GroupInstance;
57 import org.openecomp.sdc.be.model.InputDefinition;
58 import org.openecomp.sdc.be.model.InterfaceDefinition;
59 import org.openecomp.sdc.be.model.PropertyDefinition;
60 import org.openecomp.sdc.be.model.RelationshipInfo;
61 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
62 import org.openecomp.sdc.be.model.RequirementDefinition;
63 import org.openecomp.sdc.be.model.Resource;
64 import org.openecomp.sdc.be.model.Service;
65 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
66 import org.openecomp.sdc.be.model.category.CategoryDefinition;
67 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
68 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
69 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
70 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
71 import org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter;
72 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
73 import org.openecomp.sdc.be.tosca.model.NodeFilter;
74 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
75 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
76 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
77 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
78 import org.openecomp.sdc.be.tosca.model.ToscaMetadata;
79 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
80 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
81 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
82 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
83 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
84 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
85 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
86 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
87 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
88 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
89 import org.openecomp.sdc.be.tosca.utils.InputConverter;
90 import org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil;
91 import org.openecomp.sdc.common.log.wrappers.Logger;
92 import org.openecomp.sdc.externalupload.utils.ServiceUtils;
93 import org.springframework.beans.factory.annotation.Autowired;
94 import org.yaml.snakeyaml.DumperOptions;
95 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
96 import org.yaml.snakeyaml.Yaml;
97 import org.yaml.snakeyaml.introspector.BeanAccess;
98 import org.yaml.snakeyaml.introspector.Property;
99 import org.yaml.snakeyaml.introspector.PropertyUtils;
100 import org.yaml.snakeyaml.nodes.MappingNode;
101 import org.yaml.snakeyaml.nodes.Node;
102 import org.yaml.snakeyaml.nodes.NodeTuple;
103 import org.yaml.snakeyaml.nodes.Tag;
104 import org.yaml.snakeyaml.representer.Represent;
105 import org.yaml.snakeyaml.representer.Representer;
106
107 import java.beans.IntrospectionException;
108 import java.util.ArrayList;
109 import java.util.Collection;
110 import java.util.HashMap;
111 import java.util.LinkedHashSet;
112 import java.util.List;
113 import java.util.Map;
114 import java.util.Map.Entry;
115 import java.util.Objects;
116 import java.util.Optional;
117 import java.util.Set;
118 import java.util.function.Supplier;
119 import java.util.stream.Collectors;
120
121 import static org.apache.commons.collections.CollectionUtils.isEmpty;
122 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
123 import static org.apache.commons.collections.MapUtils.isNotEmpty;
124 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput;
125 import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceDefinitionElement;
126 import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceTypeElement;
127 import static org.openecomp.sdc.be.tosca.utils.ToscaExportUtils.addInputsToProperties;
128 import static org.openecomp.sdc.be.tosca.utils.ToscaExportUtils.getProxyNodeTypeInterfaces;
129 import static org.openecomp.sdc.be.tosca.utils.ToscaExportUtils.getProxyNodeTypeProperties;
130
131 @org.springframework.stereotype.Component("tosca-export-handler")
132 public class ToscaExportHandler {
133
134     private ApplicationDataTypeCache dataTypeCache;
135     private ToscaOperationFacade toscaOperationFacade;
136     private CapabilityRequirementConverter capabilityRequirementConverter;
137     private PolicyExportParser policyExportParser;
138     private GroupExportParser groupExportParser;
139     private PropertyConvertor propertyConvertor;
140     private InputConverter inputConverter;
141     private InterfaceLifecycleOperation interfaceLifecycleOperation;
142
143     @Autowired
144     public ToscaExportHandler(ApplicationDataTypeCache dataTypeCache, ToscaOperationFacade toscaOperationFacade,
145                               CapabilityRequirementConverter capabilityRequirementConverter, PolicyExportParser policyExportParser,
146                               GroupExportParser groupExportParser, InputConverter inputConverter, InterfaceLifecycleOperation interfaceLifecycleOperation) {
147             this.dataTypeCache = dataTypeCache;
148             this.toscaOperationFacade = toscaOperationFacade;
149             this.capabilityRequirementConverter = capabilityRequirementConverter;
150             this.policyExportParser = policyExportParser;
151             this.groupExportParser = groupExportParser;
152             this.propertyConvertor = PropertyConvertor.getInstance();
153             this.inputConverter =  inputConverter;
154             this.interfaceLifecycleOperation = interfaceLifecycleOperation;
155       }
156
157
158     private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
159
160     private static final String TOSCA_VERSION = "tosca_simple_yaml_1_1";
161     private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
162     private static final String IMPORTS_FILE_KEY = "file";
163     private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
164     public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
165     private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
166     private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
167     private static final List<Map<String, Map<String, String>>> DEFAULT_IMPORTS = ConfigurationManager
168                                                                                           .getConfigurationManager().getConfiguration().getDefaultImports();
169     private static YamlUtil yamlUtil = new YamlUtil();
170
171     public ToscaExportHandler(){}
172
173     public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
174
175         Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertToToscaTemplate(component);
176         if (toscaTemplateRes.isRight()) {
177             return Either.right(toscaTemplateRes.right().value());
178         }
179
180         ToscaTemplate toscaTemplate = toscaTemplateRes.left().value();
181         ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
182         return Either.left(toscaRepresentation);
183     }
184
185     public Either<ToscaRepresentation, ToscaError> exportComponentInterface(Component component,
186             boolean isAssociatedComponent) {
187         if (null == DEFAULT_IMPORTS) {
188             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
189             return Either.right(ToscaError.GENERAL_ERROR);
190         }
191
192         ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION);
193         toscaTemplate.setImports(new ArrayList<>(DEFAULT_IMPORTS));
194         Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
195         Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component,
196                 toscaTemplate, nodeTypes, isAssociatedComponent);
197         if (toscaTemplateRes.isRight()) {
198             return Either.right(toscaTemplateRes.right().value());
199         }
200
201         toscaTemplate = toscaTemplateRes.left().value();
202         ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
203         return Either.left(toscaRepresentation);
204     }
205
206     public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
207         CustomRepresenter representer = new CustomRepresenter();
208         DumperOptions options = new DumperOptions();
209         options.setAllowReadOnlyProperties(false);
210         options.setPrettyFlow(true);
211
212         options.setDefaultFlowStyle(FlowStyle.FLOW);
213         options.setCanonical(false);
214
215         representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
216
217         representer.setPropertyUtils(new UnsortedPropertyUtils());
218         Yaml yaml = new Yaml(representer, options);
219
220         String yamlAsString = yaml.dumpAsMap(toscaTemplate);
221
222         StringBuilder sb = new StringBuilder();
223         sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactHeader());
224         sb.append(yamlAsString);
225         sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactFooter());
226
227         ToscaRepresentation toscaRepresentation = new ToscaRepresentation();
228         toscaRepresentation.setMainYaml(sb.toString());
229         toscaRepresentation.setDependencies(toscaTemplate.getDependencies());
230
231         return toscaRepresentation;
232     }
233
234     public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
235         ToscaTemplate toscaTemplate = new ToscaTemplate(null);
236         Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component,
237                 toscaTemplate);
238         if (fillImports.isRight()) {
239             return Either.right(fillImports.right().value());
240         }
241         return Either.left(fillImports.left().value().left);
242     }
243
244     private Either<ToscaTemplate, ToscaError> convertToToscaTemplate(Component component) {
245         if (null == DEFAULT_IMPORTS) {
246             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
247             return Either.right(ToscaError.GENERAL_ERROR);
248         }
249
250         log.trace("start tosca export for {}", component.getUniqueId());
251         ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION);
252
253         toscaTemplate.setMetadata(convertMetadata(component));
254         toscaTemplate.setImports(new ArrayList<>(DEFAULT_IMPORTS));
255         Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
256         if (ModelConverter.isAtomicComponent(component)) {
257             log.trace("convert component as node type");
258             return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
259         } else {
260             log.trace("convert component as topology template");
261             return convertToscaTemplate(component, toscaTemplate);
262         }
263
264     }
265
266     private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
267
268         Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component,
269                 toscaNode);
270         if (importsRes.isRight()) {
271             return Either.right(importsRes.right().value());
272         }
273         toscaNode = importsRes.left().value().left;
274         Map<String, Component> componentCache = importsRes.left().value().right;
275         Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache,
276                 component);
277         if (nodeTypesMapEither.isRight()) {
278             log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
279                     nodeTypesMapEither.right().value());
280             return Either.right(nodeTypesMapEither.right().value());
281         }
282         Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
283         if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
284             toscaNode.setNode_types(nodeTypesMap);
285         }
286
287         Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
288         if (proxyInterfaceTypesEither.isRight()) {
289             log.debug("Failed to populate service proxy local interface types in tosca, error {}",
290                     nodeTypesMapEither.right().value());
291             return Either.right(proxyInterfaceTypesEither.right().value());
292         }
293         Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
294         if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
295             toscaNode.setInterface_types(proxyInterfaceTypes);
296         }
297
298         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
299         if (dataTypesEither.isRight()) {
300             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
301             return Either.right(ToscaError.GENERAL_ERROR);
302         }
303         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
304         ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
305         List<InputDefinition> inputDef = component.getInputs();
306         Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
307
308         if (!inputs.isEmpty()) {
309             topologyTemplate.setInputs(inputs);
310         }
311
312         List<ComponentInstance> componentInstances = component.getComponentInstances();
313         Map<String, List<ComponentInstanceProperty>> componentInstancesProperties =
314                 component.getComponentInstancesProperties();
315         Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces =
316             component.getComponentInstancesInterfaces();
317         if (componentInstances != null && !componentInstances.isEmpty()) {
318
319             Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
320                     convertNodeTemplates(component, componentInstances,
321                         componentInstancesProperties, componentInstanceInterfaces,
322                         componentCache, dataTypes, topologyTemplate);
323             if (nodeTemplates.isRight()) {
324                 return Either.right(nodeTemplates.right().value());
325             }
326             log.debug("node templates converted");
327
328             topologyTemplate.setNode_templates(nodeTemplates.left().value());
329         }
330
331
332         addGroupsToTopologyTemplate(component, topologyTemplate);
333
334         try {
335             addPoliciesToTopologyTemplate(component, topologyTemplate);
336         } catch (SdcResourceNotFoundException e) {
337             log.debug("Fail to add policies to topology template:",e);
338             return Either.right(ToscaError.GENERAL_ERROR);
339         }
340
341
342         SubstitutionMapping substitutionMapping = new SubstitutionMapping();
343         String toscaResourceName;
344         switch (component.getComponentType()) {
345         case RESOURCE:
346             toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
347                     .getMetadataDataDefinition()).getToscaResourceName();
348             break;
349         case SERVICE:
350             toscaResourceName = SERVICE_NODE_TYPE_PREFIX
351                     + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
352             break;
353         default:
354             log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
355             return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
356         }
357         substitutionMapping.setNode_type(toscaResourceName);
358
359         Either<SubstitutionMapping, ToscaError> capabilities = convertCapabilities(component, substitutionMapping, componentCache);
360         if (capabilities.isRight()) {
361             return Either.right(capabilities.right().value());
362         }
363         substitutionMapping = capabilities.left().value();
364
365         Either<SubstitutionMapping, ToscaError> requirements = capabilityRequirementConverter
366                 .convertSubstitutionMappingRequirements(componentCache, component, substitutionMapping);
367         if (requirements.isRight()) {
368             return Either.right(requirements.right().value());
369         }
370         substitutionMapping = requirements.left().value();
371
372         topologyTemplate.setSubstitution_mappings(substitutionMapping);
373
374         toscaNode.setTopology_template(topologyTemplate);
375
376         return Either.left(toscaNode);
377     }
378
379   private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
380         Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
381         if(groups!= null) {
382             topologyTemplate.addGroups(groups);
383         }
384     }
385
386       private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate)
387                   throws SdcResourceNotFoundException {
388             Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
389             if(policies!= null) {
390                   topologyTemplate.addPolicies(policies);
391             }
392       }
393
394     private ToscaMetadata convertMetadata(Component component) {
395         return convertMetadata(component, false, null);
396     }
397
398     private ToscaMetadata convertMetadata(Component component, boolean isInstance,
399             ComponentInstance componentInstance) {
400         ToscaMetadata toscaMetadata = new ToscaMetadata();
401         toscaMetadata.setInvariantUUID(component.getInvariantUUID());
402         toscaMetadata.setUUID(component.getUUID());
403         toscaMetadata.setDescription(component.getDescription());
404         toscaMetadata.setName(component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
405
406         List<CategoryDefinition> categories = component.getCategories();
407         CategoryDefinition categoryDefinition = categories.get(0);
408         toscaMetadata.setCategory(categoryDefinition.getName());
409
410         if (isInstance) {
411             toscaMetadata.setVersion(component.getVersion());
412             toscaMetadata.setCustomizationUUID(componentInstance.getCustomizationUUID());
413             if (componentInstance.getSourceModelInvariant() != null
414                     && !componentInstance.getSourceModelInvariant().isEmpty()) {
415                 toscaMetadata.setVersion(componentInstance.getComponentVersion());
416                 toscaMetadata.setSourceModelInvariant(componentInstance.getSourceModelInvariant());
417                 toscaMetadata.setSourceModelUuid(componentInstance.getSourceModelUuid());
418                 toscaMetadata.setSourceModelName(componentInstance.getSourceModelName());
419                 toscaMetadata.setName(
420                         componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
421                 toscaMetadata.setDescription(componentInstance.getDescription());
422             }
423
424         }
425         switch (component.getComponentType()) {
426         case RESOURCE:
427             Resource resource = (Resource) component;
428
429             if (isInstance && componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
430                 toscaMetadata.setType(componentInstance.getOriginType().getDisplayValue());
431             } else {
432                 toscaMetadata.setType(resource.getResourceType().name());
433             }
434             toscaMetadata.setSubcategory(categoryDefinition.getSubcategories().get(0).getName());
435             toscaMetadata.setResourceVendor(resource.getVendorName());
436             toscaMetadata.setResourceVendorRelease(resource.getVendorRelease());
437             toscaMetadata.setResourceVendorModelNumber(resource.getResourceVendorModelNumber());
438             break;
439         case SERVICE:
440             Service service = (Service) component;
441             toscaMetadata.setType(component.getComponentType().getValue());
442             toscaMetadata.setServiceType(service.getServiceType());
443             toscaMetadata.setServiceRole(service.getServiceRole());
444             toscaMetadata.setServiceFunction(service.getServiceFunction());
445             toscaMetadata.setEnvironmentContext(service.getEnvironmentContext());
446             resolveInstantiationTypeAndSetItToToscaMetaData(toscaMetadata, service);
447             if (!isInstance) {
448                 // DE268546
449                 toscaMetadata.setServiceEcompNaming(((Service) component).isEcompGeneratedNaming());
450                 toscaMetadata.setEcompGeneratedNaming(((Service) component).isEcompGeneratedNaming());
451                 toscaMetadata.setNamingPolicy(((Service) component).getNamingPolicy());
452             }
453             break;
454         default:
455             log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
456         }
457         return toscaMetadata;
458     }
459
460     private void resolveInstantiationTypeAndSetItToToscaMetaData(ToscaMetadata toscaMetadata, Service service) {
461         if (service.getInstantiationType() != null) {
462             toscaMetadata.setInstantiationType(service.getInstantiationType());
463         }
464         else {
465             toscaMetadata.setInstantiationType(StringUtils.EMPTY);
466         }
467     }
468
469     private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component,
470             ToscaTemplate toscaTemplate) {
471
472         if (null == DEFAULT_IMPORTS) {
473             log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
474             return Either.right(ToscaError.GENERAL_ERROR);
475         }
476         Map<String, Component> componentCache = new HashMap<>();
477
478         if (!ModelConverter.isAtomicComponent(component)) {
479             List<Map<String, Map<String, String>>> additionalImports = toscaTemplate.getImports() == null
480                                                                                ? new ArrayList<>(DEFAULT_IMPORTS) : new ArrayList<>(toscaTemplate.getImports());
481
482             List<Triple<String, String, Component>> dependecies = new ArrayList<>();
483
484             Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
485             if (isNotEmpty(toscaArtifacts)) {
486                 ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
487                 if(artifactDefinition != null) {
488                     Map<String, Map<String, String>> importsListMember = new HashMap<>();
489                     Map<String, String> interfaceFiles = new HashMap<>();
490                     interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
491                     StringBuilder keyNameBuilder = new StringBuilder();
492                     keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-")
493                                   .append(component.getName()).append("-interface");
494                     importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
495                     additionalImports.add(importsListMember);
496                 }
497             }
498             List<ComponentInstance> componentInstances = component.getComponentInstances();
499             if (componentInstances != null && !componentInstances.isEmpty()) {
500                 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependecies, ci));
501             }
502             toscaTemplate.setDependencies(dependecies);
503             toscaTemplate.setImports(additionalImports);
504         } else {
505             log.debug("currently imports supported for VF and service only");
506         }
507         return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
508     }
509
510     private void createDependency(Map<String, Component> componentCache, List<Map<String, Map<String, String>>> imports,
511             List<Triple<String, String, Component>> dependecies, ComponentInstance ci) {
512         Map<String, String> files = new HashMap<>();
513         Map<String, Map<String, String>> importsListMember = new HashMap<>();
514         StringBuilder keyNameBuilder;
515
516         Component componentRI = componentCache.get(ci.getComponentUid());
517         if (componentRI == null) {
518             // all resource must be only once!
519             Either<Component, StorageOperationStatus> resource = toscaOperationFacade
520                     .getToscaFullElement(ci.getComponentUid());
521             if ((resource.isRight()) && (log.isDebugEnabled())) {
522                 log.debug("Failed to fetch resource with id {} for instance {}",ci.getComponentUid() ,ci.getUniqueId());
523                 return ;
524             }
525
526             Component fetchedComponent = resource.left().value();
527             componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
528
529             if (ci.getOriginType() == OriginTypeEnum.ServiceProxy){
530                 Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
531                         .getToscaFullElement(ci.getSourceModelUid());
532                 if (sourceService.isRight() && (log.isDebugEnabled())) {
533                     log.debug("Failed to fetch source service with id {} for proxy {}", ci.getSourceModelUid(), ci.getUniqueId());
534                 }
535                 Component fetchedSource = sourceService.left().value();
536                 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
537             }
538
539             componentRI = fetchedComponent;
540
541             Map<String, ArtifactDefinition> toscaArtifacts = componentRI.getToscaArtifacts();
542             ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
543             if (artifactDefinition != null) {
544                 String artifactName = artifactDefinition.getArtifactName();
545                 files.put(IMPORTS_FILE_KEY, artifactName);
546                 keyNameBuilder = new StringBuilder();
547                 keyNameBuilder.append(fetchedComponent.getComponentType().toString().toLowerCase());
548                 keyNameBuilder.append("-");
549                 keyNameBuilder.append(ci.getComponentName());
550                 importsListMember.put(keyNameBuilder.toString(), files);
551                 imports.add(importsListMember);
552                 dependecies.add(new ImmutableTriple<>(artifactName,
553                         artifactDefinition.getEsId(), fetchedComponent));
554
555                 if (!ModelConverter.isAtomicComponent(componentRI)) {
556                     importsListMember = new HashMap<>();
557                     Map<String, String> interfaceFiles = new HashMap<>();
558                     interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
559                     keyNameBuilder.append("-interface");
560                     importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
561                     imports.add(importsListMember);
562                 }
563             }
564         }
565     }
566
567     public static String getInterfaceFilename(String artifactName) {
568         return artifactName.substring(0, artifactName.lastIndexOf('.')) + ToscaExportHandler.TOSCA_INTERFACE_NAME;
569     }
570
571     private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
572                                                               Map<String, ToscaNodeType> nodeTypes) {
573         return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
574     }
575
576     private Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache,
577                                                                        Component component, ToscaTemplate toscaNode,
578                                                                        Map<String, ToscaNodeType> nodeTypes,
579             boolean isAssociatedComponent) {
580         log.debug("start convert node type for {}", component.getUniqueId());
581         ToscaNodeType toscaNodeType = createNodeType(component);
582
583         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
584                 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes();
585         if(lifecycleTypeEither.isRight()){
586             log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
587             return Either.right(ToscaError.GENERAL_ERROR);
588         }
589         List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value()
590                                                        .values()
591                                                        .stream()
592                 .map(InterfaceDataDefinition::getType)
593                                                        .collect(Collectors.toList());
594         toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
595
596         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
597         if (dataTypesEither.isRight()) {
598             log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
599             return Either.right(ToscaError.GENERAL_ERROR);
600         }
601
602         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
603
604         List<InputDefinition> inputDef = component.getInputs();
605         Map<String, ToscaProperty> mergedProperties = new HashMap<>();
606         addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
607         addInputsToProperties(dataTypes, inputDef, mergedProperties);
608
609         if(CollectionUtils.isNotEmpty(component.getProperties())) {
610             List<PropertyDefinition> properties = component.getProperties();
611             Map<String, ToscaProperty> convertedProperties = properties.stream()
612                     .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs()))
613                     .collect(Collectors.toMap(PropertyDataDefinition::getName,
614                             property -> propertyConvertor.convertProperty(dataTypes, property,
615                                     PropertyConvertor.PropertyType.PROPERTY)));
616             // merge component properties and inputs properties
617             mergedProperties.putAll(convertedProperties);
618         }
619         if (MapUtils.isNotEmpty(mergedProperties)) {
620             toscaNodeType.setProperties(mergedProperties);
621         }
622
623         /* convert private data_types */
624         List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
625         if (CollectionUtils.isNotEmpty(privateDataTypes) ) {
626             Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
627             for (DataTypeDefinition dataType: privateDataTypes) {
628                 log.debug("Emitting private data type: component.name={} dataType.name={}",
629                         component.getNormalizedName(), dataType.getName());
630                 ToscaDataType toscaDataType = new ToscaDataType();
631                 toscaDataType.setDerived_from(dataType.getDerivedFromName());
632                 toscaDataType.setDescription(dataType.getDescription());
633                 toscaDataType.setVersion(dataType.getVersion());
634                 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
635                     toscaDataType.setProperties(dataType.getProperties().stream()
636                             .collect(Collectors.toMap(
637                                     s -> s.getName(),
638                                     s -> propertyConvertor.convertProperty(dataTypes, s, PropertyConvertor.PropertyType.PROPERTY)
639                             )));
640                 }
641                 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
642             }
643             toscaNode.setData_types(toscaDataTypeMap);
644         }
645
646         // Extracted to method for code reuse
647         return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
648     }
649
650     private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
651             Map<String, ToscaNodeType> nodeTypes, ToscaNodeType toscaNodeType,
652             Map<String, DataTypeDefinition> dataTypes) {
653         Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType, dataTypes);
654         if (capabilities.isRight()) {
655             return Either.right(capabilities.right().value());
656         }
657         toscaNodeType = capabilities.left().value();
658         log.debug("Capabilities converted for {}", component.getUniqueId());
659
660         Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter.convertRequirements(componentsCache, component,
661                 toscaNodeType);
662         if (requirements.isRight()) {
663             return Either.right(requirements.right().value());
664         }
665         toscaNodeType = requirements.left().value();
666         log.debug("Requirements converted for {}", component.getUniqueId());
667
668         String toscaResourceName;
669         switch (component.getComponentType()) {
670         case RESOURCE:
671             toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
672                     .getMetadataDataDefinition()).getToscaResourceName();
673             break;
674         case SERVICE:
675             toscaResourceName = SERVICE_NODE_TYPE_PREFIX
676                     + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
677             break;
678         default:
679             log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
680             return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
681         }
682
683         nodeTypes.put(toscaResourceName, toscaNodeType);
684         toscaNode.setNode_types(nodeTypes);
685         log.debug("finish convert node type for {}", component.getUniqueId());
686         return Either.left(toscaNode);
687     }
688
689     protected Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(
690             Component component,
691             List<ComponentInstance> componentInstances,
692             Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
693             Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
694             Map<String, Component> componentCache, Map<String, DataTypeDefinition> dataTypes,
695             ToscaTopolgyTemplate topologyTemplate) {
696
697         Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
698         log.debug("start convert topology template for {} for type {}", component.getUniqueId(),
699                 component.getComponentType());
700         Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
701         Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
702
703         Map<String, ToscaGroupTemplate> groupsMap = null;
704         for (ComponentInstance componentInstance : componentInstances) {
705             ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
706             if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
707                 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
708             }
709             nodeTemplate.setType(componentInstance.getToscaComponentName());
710             nodeTemplate.setDirectives(componentInstance.getDirectives());
711             nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
712
713             Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
714                     .getOriginComponent(componentCache, componentInstance);
715             if (originComponentRes.isRight()) {
716                 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
717                 break;
718             }
719             Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component,
720                     componentInstance, component.getComponentInstancesRelations(), nodeTemplate,
721                     originComponentRes.left().value(), componentCache);
722             if (requirements.isRight()) {
723                 convertNodeTemplatesRes = Either.right(requirements.right().value());
724                 break;
725             }
726             String instanceUniqueId = componentInstance.getUniqueId();
727             log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
728
729             nodeTemplate = requirements.left().value();
730
731             Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
732
733             if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy){
734                 Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
735                 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
736             } else {
737                 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
738             }
739
740             Either<ToscaNodeTemplate, ToscaError> capabilities = capabilityRequirementConverter
741                     .convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
742             if (capabilities.isRight()) {
743                 convertNodeTemplatesRes = Either.right(capabilities.right().value());
744                 break;
745             }
746             log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
747
748             nodeTemplate = capabilities.left().value();
749             Map<String, Object> props = new HashMap<>();
750
751             if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
752                 // Adds the properties of parent component to map
753                 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
754             }
755
756             if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
757                 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId,
758                         props);
759             }
760
761             if (componentInstancesInputs != null && componentInstancesInputs.containsKey(instanceUniqueId)
762                     && !isComponentOfTypeServiceProxy(componentInstance)) {
763                 //For service proxy the inputs are already handled under instance properties above
764                 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId,
765                         props);
766             }
767             //M3[00001] - NODE TEMPLATE INTERFACES  - START
768             handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate,
769                     instanceUniqueId, component);
770             //M3[00001] - NODE TEMPLATE INTERFACES  - END
771             if (props != null && !props.isEmpty()) {
772                 nodeTemplate.setProperties(props);
773             }
774
775             List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
776             if (groupInstances != null) {
777                 if (groupsMap == null) {
778                     groupsMap = new HashMap<>();
779                 }
780                 for (GroupInstance groupInst : groupInstances) {
781                     boolean addToTosca = true;
782
783                     List<String> artifacts = groupInst.getArtifacts();
784                     if (artifacts == null || artifacts.isEmpty()) {
785                         addToTosca = false;
786                     }
787
788                     if (addToTosca) {
789                         ToscaGroupTemplate toscaGroup = groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName());
790                         groupsMap.put(groupInst.getName(), toscaGroup);
791                     }
792                 }
793             }
794
795             nodeTemplates.put(componentInstance.getName(), nodeTemplate);
796         }
797         if (groupsMap != null) {
798             log.debug("instance groups added");
799             topologyTemplate.addGroups(groupsMap);
800         }
801         if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(((Service) component).getForwardingPaths())) {
802             log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(),
803                     component.getName());
804             ForwardingPathToscaUtil.addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
805             log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(),
806                     component.getName());
807         }
808         if (convertNodeTemplatesRes == null) {
809             convertNodeTemplatesRes = Either.left(nodeTemplates);
810         }
811         log.debug("finish convert topology template for {} for type {}", component.getUniqueId(),
812                 component.getComponentType());
813         return convertNodeTemplatesRes;
814     }
815
816     private void handleInstanceInterfaces(
817             Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
818             ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
819             String instanceUniqueId,
820             Component parentComponent) {
821
822         Map<String, Object> interfaces;
823
824         // we need to handle service proxy interfaces
825         if(isComponentOfTypeServiceProxy(componentInstance)) {
826             if(MapUtils.isEmpty(componentInstanceInterfaces)
827                 || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
828                 interfaces = null;
829             } else {
830                 List<ComponentInstanceInterface> currServiceInterfaces =
831                     componentInstanceInterfaces.get(instanceUniqueId);
832
833                 Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
834                 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
835                     .getUniqueId(), instInterface));
836
837                 interfaces = InterfacesOperationsToscaUtil
838                                      .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, true, true);
839             }
840         } else {
841             interfaces =
842                 getComponentInstanceInterfaceInstances(componentInstanceInterfaces,
843                     componentInstance, instanceUniqueId);
844         }
845         nodeTemplate.setInterfaces(interfaces);
846     }
847
848     private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
849         return Objects.nonNull(componentInstance.getOriginType())
850             && componentInstance.getOriginType().getValue().equals("Service Proxy");
851     }
852
853     //M3[00001] - NODE TEMPLATE INTERFACES  - START
854     private Map<String, Object> getComponentInstanceInterfaceInstances(Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces,
855                                                                         ComponentInstance componentInstance,
856                                                                        String instanceUniqueId) {
857         if(MapUtils.isEmpty(componentInstancesInterfaces)) {
858             return null;
859         }
860
861         List<ComponentInstanceInterface> componentInstanceInterfaces =
862             componentInstancesInterfaces.get(instanceUniqueId);
863
864         if(CollectionUtils.isEmpty(componentInstanceInterfaces)) {
865           return null;
866         }
867
868         Map<String, Object> interfaces = new HashMap<>();
869         for(ComponentInstanceInterface componentInstanceInterface : componentInstanceInterfaces) {
870             interfaces.put(componentInstanceInterface.getInterfaceId(),
871                 removeOperationsKeyFromInterface(componentInstanceInterface.getInterfaceInstanceDataDefinition()));
872         }
873
874         componentInstance.setInterfaces(interfaces);
875
876         return interfaces;
877     }
878
879     private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
880                                             Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
881                                             String instanceUniqueId, Map<String, Object> props) {
882
883         List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
884         if (instanceInputsList != null) {
885             instanceInputsList.forEach(input -> {
886
887                 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue())
888                         ? input.getValue() : input.getDefaultValue();
889                         propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
890             });
891         }
892     }
893
894     private void addPropertiesOfComponentInstance(
895             Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
896             Map<String, DataTypeDefinition> dataTypes, String instanceUniqueId,
897             Map<String, Object> props) {
898
899         if (isNotEmpty(componentInstancesProperties)) {
900             componentInstancesProperties.get(instanceUniqueId)
901                     // Converts and adds each value to property map
902                     .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop,
903                             prop::getValue));
904         }
905     }
906
907     private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
908                                                 Component componentOfInstance, Map<String, Object> props) {
909
910         List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
911         if (isNotEmpty(componentProperties)) {
912             componentProperties.stream()
913                     // Filters out properties with empty default values
914                                .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
915                     // Converts and adds each value to property map
916                     .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop,
917                             prop::getDefaultValue));
918         }
919     }
920
921     /**
922      * @param dataTypes
923      * @param componentInstance
924      * @param props
925      * @param prop
926      * @param supplier
927      */
928     private void convertAndAddValue(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance,
929             Map<String, Object> props, PropertyDefinition prop, Supplier<String> supplier) {
930         Object convertedValue = convertValue(dataTypes, componentInstance, prop, supplier);
931         if (!ToscaValueBaseConverter.isEmptyObjectValue(convertedValue)) {
932             props.put(prop.getName(), convertedValue);
933         }
934     }
935
936     private <T extends PropertyDefinition> Object convertValue(Map<String, DataTypeDefinition> dataTypes,
937             ComponentInstance componentInstance, T input, Supplier<String> supplier) {
938         log.debug("Convert property or input value {} for instance {}", input.getName(),
939                 componentInstance.getUniqueId());
940         String propertyType = input.getType();
941         String innerType = null;
942         if (input.getSchema() != null && input.getSchema().getProperty() != null) {
943             innerType = input.getSchema().getProperty().getType();
944         }
945         return propertyConvertor.convertToToscaObject(propertyType, supplier.get(), innerType,
946             dataTypes, true);
947     }
948
949     private ToscaNodeType createNodeType(Component component) {
950         ToscaNodeType toscaNodeType = new ToscaNodeType();
951         if (ModelConverter.isAtomicComponent(component)) {
952             if (((Resource) component).getDerivedFrom() != null) {
953                 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
954             }
955             toscaNodeType.setDescription(component.getDescription());
956         } else {
957             String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
958                     : "tosca.nodes.Root";
959             toscaNodeType.setDerived_from(derivedFrom);
960         }
961         return toscaNodeType;
962     }
963
964     private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
965
966         Map<String, Object> proxyInterfaceTypes = new HashMap<>();
967         Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
968         List<ComponentInstance> componentInstances = container.getComponentInstances();
969         if (CollectionUtils.isEmpty(componentInstances)) {
970             return res;
971         }
972         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
973         componentInstances.stream()
974                 .filter(this::isComponentOfTypeServiceProxy)
975                 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
976         if (MapUtils.isEmpty(serviceProxyInstanceList)) {
977             return res;
978         }
979         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
980             Component serviceComponent;
981             ComponentParametersView componentParametersView = new ComponentParametersView();
982             componentParametersView.disableAll();
983             componentParametersView.setIgnoreInterfaces(false);
984             Either<Component, StorageOperationStatus> service = toscaOperationFacade
985                     .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
986             if (service.isRight()) {
987                 log.debug("Failed to fetch original service component with id {} for instance {}",
988                         entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
989                 return Either.right(ToscaError.GENERAL_ERROR);
990             } else {
991                 serviceComponent = service.left().value();
992             }
993
994             Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
995                     interfaceLifecycleOperation.getAllInterfaceLifecycleTypes();
996             if(lifecycleTypeEither.isRight()){
997                 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
998                 return Either.right(ToscaError.GENERAL_ERROR);
999             }
1000
1001             List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1002                     .map(InterfaceDataDefinition::getType)
1003                     .collect(Collectors.toList());
1004             //Add interface types for local interfaces in the original service component for proxy
1005             Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1006                     allGlobalInterfaceTypes);
1007             if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1008                 proxyInterfaceTypes.putAll(localInterfaceTypes);
1009             }
1010
1011         }
1012         return Either.left(proxyInterfaceTypes);
1013     }
1014
1015     private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1016                                                                                 Component container) {
1017
1018         Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1019         Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1020
1021         List<ComponentInstance> componentInstances = container.getComponentInstances();
1022
1023         if (componentInstances == null || componentInstances.isEmpty()) {
1024             return res;
1025         }
1026         Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1027         List<ComponentInstance> proxyInst = componentInstances.stream()
1028                 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1029                 .collect(Collectors.toList());
1030         if (proxyInst != null && !proxyInst.isEmpty()) {
1031             for (ComponentInstance inst : proxyInst) {
1032                 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1033             }
1034         }
1035
1036         if (serviceProxyInstanceList.isEmpty()) {
1037             return res;
1038         }
1039         Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1040                 .getLatestByName("serviceProxy");
1041         if (serviceProxyOrigin.isRight()) {
1042             log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1043                     serviceProxyOrigin.right().value());
1044             return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1045         }
1046         Component origComponent = serviceProxyOrigin.left().value();
1047
1048         for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1049             Component serviceComponent = null;
1050             ComponentParametersView componentParametersView = new ComponentParametersView();
1051             componentParametersView.disableAll();
1052             componentParametersView.setIgnoreCategories(false);
1053             componentParametersView.setIgnoreProperties(false);
1054             componentParametersView.setIgnoreInputs(false);
1055             componentParametersView.setIgnoreInterfaces(false);
1056             componentParametersView.setIgnoreRequirements(false);
1057             Either<Component, StorageOperationStatus> service = toscaOperationFacade
1058                     .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1059             if (service.isRight()) {
1060                 log.debug("Failed to fetch resource with id {} for instance {}", entryProxy.getValue().getSourceModelUid(),  entryProxy.getValue().getName());
1061             } else {
1062                 serviceComponent = service.left().value();
1063             }
1064
1065             ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1066                     entryProxy.getValue());
1067             nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1068         }
1069
1070         return Either.left(nodeTypesMap);
1071     }
1072
1073     private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache , Component origComponent,
1074                                               Component proxyComponent, ComponentInstance instance) {
1075         ToscaNodeType toscaNodeType = new ToscaNodeType();
1076         String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1077
1078         toscaNodeType.setDerived_from(derivedFrom);
1079         Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
1080         if (dataTypesEither.isRight()) {
1081             log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1082         }
1083         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1084         Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1085                 .convertProxyCapabilities(componentCache, instance, dataTypes);
1086
1087         if (MapUtils.isNotEmpty(capabilities)) {
1088             toscaNodeType.setCapabilities(capabilities);
1089         }
1090         List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1091                 .convertProxyRequirements(componentCache, instance);
1092         if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1093             toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1094         }
1095         Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1096         proxyProperties.ifPresent(toscaNodeType::setProperties);
1097
1098         Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1099         proxyInterfaces.ifPresent(toscaNodeType::setInterfaces);
1100
1101         return toscaNodeType;
1102     }
1103
1104     private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1105             ComponentInstance componentInstance, List<RequirementCapabilityRelDef> relations,
1106             ToscaNodeTemplate nodeTypeTemplate, Component originComponent, Map<String, Component> componentCache) {
1107
1108         List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1109         if (!addRequirements(component, componentInstance, relations, originComponent, toscaRequirements, componentCache)) {
1110             log.debug("Failed to convert component instance requirements for the component instance {}. ",
1111                     componentInstance.getName());
1112             return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1113         }
1114         if (!toscaRequirements.isEmpty()) {
1115             nodeTypeTemplate.setRequirements(toscaRequirements);
1116         }
1117         log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1118         return Either.left(nodeTypeTemplate);
1119     }
1120
1121     private boolean addRequirements(Component component, ComponentInstance componentInstance,
1122             List<RequirementCapabilityRelDef> relations, Component originComponent,
1123             List<Map<String, ToscaTemplateRequirement>> toscaRequirements, Map<String, Component> componentCache) {
1124         List<RequirementCapabilityRelDef> filteredRelations = relations.stream()
1125                 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1126         return isEmpty(filteredRelations) ||
1127                 filteredRelations.stream()
1128                         .allMatch(rel -> addRequirement(componentInstance, originComponent, component.getComponentInstances(), rel, toscaRequirements, componentCache));
1129     }
1130
1131     private boolean addRequirement(ComponentInstance fromInstance, Component fromOriginComponent,
1132             List<ComponentInstance> instancesList, RequirementCapabilityRelDef rel,
1133             List<Map<String, ToscaTemplateRequirement>> toscaRequirements, Map<String, Component> componentCache) {
1134
1135         boolean result = true;
1136         Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1137         RelationshipInfo reqAndRelationshipPair = rel.getRelationships().get(0).getRelation();
1138         Either<Component, StorageOperationStatus> getOriginRes = null;
1139         Optional<RequirementDefinition> reqOpt = Optional.empty();
1140         Component toOriginComponent = null;
1141         Optional<CapabilityDefinition> capOpt = Optional.empty();
1142
1143         ComponentInstance toInstance = instancesList.stream().filter(i -> rel.getToNode().equals(i.getUniqueId()))
1144                 .findFirst().orElse(null);
1145         if (toInstance == null) {
1146             log.debug("Failed to find a relation from the node {} to the node {}", fromInstance.getName(),
1147                     rel.getToNode());
1148             result = false;
1149         }
1150         if (result) {
1151             reqOpt = findRequirement(fromOriginComponent, reqMap, reqAndRelationshipPair, fromInstance.getUniqueId());
1152             if (!reqOpt.isPresent()) {
1153                 log.debug("Failed to find a requirement with uniqueId {} on a component with uniqueId {}",
1154                         reqAndRelationshipPair.getRequirementUid(), fromOriginComponent.getUniqueId());
1155                 result = false;
1156             }
1157         }
1158         if (result) {
1159             ComponentParametersView filter = new ComponentParametersView(true);
1160             filter.setIgnoreComponentInstances(false);
1161             filter.setIgnoreCapabilities(false);
1162             filter.setIgnoreGroups(false);
1163             getOriginRes = toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1164             if (getOriginRes.isRight()) {
1165                 log.debug("Failed to build substituted name for the requirement {}. Failed to get an origin component with uniqueId {}",
1166                         reqOpt.get().getName(), toInstance.getActualComponentUid());
1167                 result = false;
1168             }
1169         }
1170         if (result) {
1171             toOriginComponent = getOriginRes.left().value();
1172             capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1173                     .filter(c -> isCapabilityBelongToRelation(reqAndRelationshipPair, c)).findFirst();
1174             if (!capOpt.isPresent()) {
1175                 capOpt = findCapability(reqAndRelationshipPair, toOriginComponent, fromOriginComponent, reqOpt.get());
1176                 if(!capOpt.isPresent()){
1177                 result = false;
1178                 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1179                         reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1180                 }
1181             }
1182         }
1183         if (result) {
1184             result = buildAndAddRequirement(toscaRequirements, fromOriginComponent, toOriginComponent, capOpt.get(),
1185                     reqOpt.get(), reqAndRelationshipPair, toInstance, componentCache);
1186         }
1187         return result;
1188     }
1189
1190     private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair, CapabilityDefinition capability) {
1191         return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() !=null && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1192     }
1193
1194     private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair, Component toOriginComponent, Component fromOriginComponent, RequirementDefinition requirement) {
1195         Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability()).stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1196         if (!cap.isPresent()) {
1197             log.debug("Failed to find a capability with name {} on a component with uniqueId {}", reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1198         }
1199         return cap;
1200     }
1201
1202     private boolean buildAndAddRequirement(List<Map<String, ToscaTemplateRequirement>> toscaRequirements, Component fromOriginComponent, Component toOriginComponent, CapabilityDefinition capability, RequirementDefinition requirement, RelationshipInfo reqAndRelationshipPair, ComponentInstance toInstance, Map<String, Component> componentCache) {
1203         List<String> reducedPath = capability.getPath();
1204         if(capability.getOwnerId() !=null){
1205             reducedPath =   capabilityRequirementConverter.getReducedPathByOwner(capability.getPath() , capability.getOwnerId() );
1206         }
1207         Either<String, Boolean> buildCapNameRes = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1208                 toOriginComponent, reducedPath, reqAndRelationshipPair.getCapability(), capability.getPreviousName());
1209         if (buildCapNameRes.isRight()) {
1210             log.debug(
1211                     "Failed to build a substituted capability name for the capability with name {} on a component with uniqueId {}",
1212                     reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1213             return false;
1214         }
1215         Either<String, Boolean> buildReqNameRes  = capabilityRequirementConverter.buildSubstitutedName(componentCache, fromOriginComponent,
1216                 requirement.getPath(), reqAndRelationshipPair.getRequirement(), requirement.getPreviousName());
1217         if (buildReqNameRes.isRight()) {
1218             log.debug(
1219                     "Failed to build a substituted requirement name for the requirement with name {} on a component with uniqueId {}",
1220                     reqAndRelationshipPair.getRequirement(), fromOriginComponent.getUniqueId());
1221             return false;
1222         }
1223         ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1224         Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1225         toscaRequirement.setNode(toInstance.getName());
1226         toscaRequirement.setCapability(buildCapNameRes.left().value());
1227         toscaReqMap.put(buildReqNameRes.left().value(), toscaRequirement);
1228         toscaRequirements.add(toscaReqMap);
1229         return true;
1230     }
1231
1232     private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent, Map<String, List<RequirementDefinition>> reqMap, RelationshipInfo reqAndRelationshipPair,  String fromInstanceId) {
1233         for(List<RequirementDefinition> reqList: reqMap.values()){
1234             Optional<RequirementDefinition> reqOpt = reqList.stream().filter(r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId)).findFirst();
1235             if(reqOpt.isPresent()){
1236                 return reqOpt;
1237             }
1238         }
1239         return Optional.empty();
1240     }
1241
1242     /**
1243      * Allows detecting the requirement belonging to the received relationship
1244      * The detection logic is: A requirement belongs to a relationship IF 1.The
1245      * name of the requirement equals to the "requirement" field of the
1246      * relation; AND 2. In case of a non-atomic resource, OwnerId of the
1247      * requirement equals to requirementOwnerId of the relation OR uniqueId of
1248      * toInstance equals to capabilityOwnerId of the relation
1249      */
1250     private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId) {
1251         if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1252             log.debug("Failed to find a requirement with name {} and  reqAndRelationshipPair {}",
1253                     requirement.getName(), reqAndRelationshipPair.getRequirement());
1254             return false;
1255         }
1256         return ModelConverter.isAtomicComponent(originComponent) ||
1257                 isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId, originComponent);
1258     }
1259
1260     private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId, Component originComponent) {
1261         return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId())
1262                 || (isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId())
1263                 || StringUtils.equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1264     }
1265
1266     private boolean isCvfc(Component component) {
1267         return component.getComponentType() == ComponentTypeEnum.RESOURCE &&
1268                 ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1269     }
1270
1271     private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component,
1272             SubstitutionMapping substitutionMappings, Map<String, Component> componentCache) {
1273
1274         Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
1275         Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
1276                 .convertSubstitutionMappingCapabilities(componentCache, component);
1277         if (toscaCapabilitiesRes.isRight()) {
1278             result = Either.right(toscaCapabilitiesRes.right().value());
1279             log.debug("Failed convert capabilities for the component {}. ", component.getName());
1280         } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1281             substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
1282             log.debug("Finish convert capabilities for the component {}. ", component.getName());
1283         }
1284         log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1285         return result;
1286     }
1287
1288     private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1289             Map<String, DataTypeDefinition> dataTypes) {
1290         Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component,
1291                 dataTypes);
1292         if (!toscaCapabilities.isEmpty()) {
1293             nodeType.setCapabilities(toscaCapabilities);
1294         }
1295         log.debug("Finish convert Capabilities for node type");
1296
1297         return Either.left(nodeType);
1298     }
1299
1300     private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1301         if (artifacts == null) {
1302             return null;
1303         }
1304         Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1305         for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1306            ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1307            artifact.setFile(entry.getValue().getFile());
1308            artifact.setType(entry.getValue().getType());
1309            arts.put(entry.getKey(), artifact);
1310         }
1311         return arts;
1312     }
1313
1314     protected NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1315         if (inNodeFilter == null){
1316             return null;
1317         }
1318         NodeFilter nodeFilter = new NodeFilter();
1319
1320         ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities =
1321                 inNodeFilter.getCapabilities();
1322
1323         ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1324
1325         List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1326         List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1327
1328         copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1329         copyNodeFilterProperties(origProperties, propertiesCopy);
1330
1331         if(CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1332             nodeFilter.setCapabilities(capabilitiesCopy);
1333         }
1334
1335         if(CollectionUtils.isNotEmpty(propertiesCopy)) {
1336             nodeFilter.setProperties(propertiesCopy);
1337         }
1338
1339         nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1340
1341
1342         nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1343
1344         return nodeFilter;
1345     }
1346
1347     private Object cloneToscaId(Object toscaId) {
1348         return Objects.isNull(toscaId) ? null
1349                        : cloneObjectFromYml(toscaId, toscaId.getClass());
1350     }
1351
1352
1353     private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1354         String objectAsYml = yamlUtil.objectToYaml(objToClone);
1355         return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1356     }
1357     private void copyNodeFilterCapabilitiesTemplate(
1358             ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1359             List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1360         if(origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null ||
1361                    origCapabilities.getListToscaDataDefinition().isEmpty() ) {
1362             return;
1363         }
1364         for(RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1365             Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1366             CapabilityFilter capabilityFilter = new CapabilityFilter();
1367             List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1368             copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1369             capabilityFilter.setProperties(propertiesCopy);
1370             capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1371             capabilitiesCopy.add(capabilityFilterCopyMap);
1372         }
1373     }
1374
1375     private List<Object> copyNodeFilterProperty(List<Object> propertyList) {
1376         String listAsString = yamlUtil.objectToYaml(propertyList);
1377         return yamlUtil.yamlToObject(listAsString, List.class);
1378     }
1379
1380
1381     private void copyNodeFilterProperties(
1382             ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1383             List<Map<String, List<Object>>> propertiesCopy) {
1384         if(origProperties == null || origProperties.getListToscaDataDefinition() == null ||
1385                    origProperties.isEmpty()) {
1386             return;
1387         }
1388         Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1389         for(RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1390             for(String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1391                 Map propertyValObj =  new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1392                 String propertyName = propertyDataDefinition.getName();
1393                 if (propertyMapCopy.containsKey(propertyName)){
1394                     addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1395                 } else {
1396                     if (propertyName != null) {
1397                         List propsList = new ArrayList();
1398                         addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1399                         propertyMapCopy.put(propertyName, propsList);
1400                     } else {
1401                         propertyMapCopy.putAll(propertyValObj);
1402                     }
1403                 }
1404             }
1405         }
1406         propertyMapCopy.entrySet().stream().forEach(entry ->
1407             addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1408     }
1409
1410     private void addPropertyConstraintValueToList(String propertyName, Map propertyValObj, List propsList) {
1411         if(propertyValObj.containsKey(propertyName)) {
1412             propsList.add(propertyValObj.get(propertyName));
1413         } else {
1414             propsList.add(propertyValObj);
1415         }
1416     }
1417
1418
1419
1420     private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy,
1421             Entry<String, List<Object>> entry) {
1422         Map<String, List<Object>> tempMap = new HashMap<>();
1423         tempMap.put(entry.getKey(), entry.getValue());
1424         propertiesCopy.add(tempMap);
1425     }
1426
1427     private static class CustomRepresenter extends Representer {
1428         public CustomRepresenter() {
1429             super();
1430             // null representer is exceptional and it is stored as an instance
1431             // variable.
1432             this.nullRepresenter = new RepresentNull();
1433
1434         }
1435
1436         @Override
1437         protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue,
1438                 Tag customTag) {
1439             if (propertyValue == null) {
1440                 return null;
1441             } else {
1442                 // skip not relevant for Tosca property
1443                 if ("dependencies".equals(property.getName())) {
1444                     return null;
1445                 }
1446                 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1447
1448                 return "_defaultp_".equals(property.getName())
1449                         ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1450             }
1451         }
1452
1453         @Override
1454         protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1455             // remove the bean type from the output yaml (!! ...)
1456             if (!classTags.containsKey(javaBean.getClass())) {
1457                 addClassTag(javaBean.getClass(), Tag.MAP);
1458             }
1459
1460             return super.representJavaBean(properties, javaBean);
1461         }
1462
1463         private class RepresentNull implements Represent {
1464             @Override
1465             public Node representData(Object data) {
1466                 // possible values are here http://yaml.org/type/null.html
1467                 return representScalar(Tag.NULL, "");
1468             }
1469         }
1470     }
1471
1472     private static class UnsortedPropertyUtils extends PropertyUtils {
1473         @Override
1474         protected Set<Property> createPropertySet(Class type, BeanAccess bAccess)
1475                 throws IntrospectionException {
1476             Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1477             return new LinkedHashSet<>(fields);
1478         }
1479     }
1480
1481     private Object removeOperationsKeyFromInterface(Object interfaceInstanceDataDefinition) {
1482         ObjectMapper objectMapper = new ObjectMapper();
1483         objectMapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
1484
1485             Map<String, Object> interfaceAsMap = ServiceUtils.getObjectAsMap(interfaceInstanceDataDefinition);
1486             Map<String, Object> operations = (Map<String, Object>) interfaceAsMap.remove("operations");
1487             interfaceAsMap.remove("empty");
1488
1489             if(MapUtils.isNotEmpty(operations)) {
1490                 interfaceAsMap.putAll(operations);
1491             }
1492
1493             Object interfaceObject = objectMapper.convertValue(interfaceAsMap, Object.class);
1494
1495             return interfaceObject;
1496
1497     }
1498 }
1499