Backend support for operation milestones with activity inputs
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / tosca / InterfacesOperationsConverter.java
1 /*
2  * Copyright © 2016-2020 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.be.tosca;
18
19 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DEFAULT;
20 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.INPUTS;
21 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.OPERATIONS;
22
23 import com.fasterxml.jackson.annotation.JsonInclude;
24 import com.fasterxml.jackson.databind.DeserializationFeature;
25 import com.fasterxml.jackson.databind.ObjectMapper;
26 import com.fasterxml.jackson.databind.module.SimpleModule;
27 import com.google.gson.Gson;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Map.Entry;
34 import java.util.Objects;
35 import java.util.Set;
36 import java.util.stream.Collectors;
37 import org.apache.commons.collections.MapUtils;
38 import org.apache.commons.collections4.CollectionUtils;
39 import org.apache.commons.lang3.ObjectUtils;
40 import org.apache.commons.lang3.StringUtils;
41 import org.apache.commons.lang3.math.NumberUtils;
42 import org.openecomp.sdc.be.datatypes.elements.ActivityDataDefinition;
43 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
44 import org.openecomp.sdc.be.datatypes.elements.InputDataDefinition;
45 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
46 import org.openecomp.sdc.be.datatypes.elements.MilestoneDataDefinition;
47 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
48 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
49 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
50 import org.openecomp.sdc.be.datatypes.enums.ActivityTypeEnum;
51 import org.openecomp.sdc.be.datatypes.enums.MilestoneTypeEnum;
52 import org.openecomp.sdc.be.model.Component;
53 import org.openecomp.sdc.be.model.ComponentInstance;
54 import org.openecomp.sdc.be.model.DataTypeDefinition;
55 import org.openecomp.sdc.be.model.InterfaceDefinition;
56 import org.openecomp.sdc.be.model.Product;
57 import org.openecomp.sdc.be.model.PropertyDefinition;
58 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
59 import org.openecomp.sdc.be.tosca.model.ToscaActivity;
60 import org.openecomp.sdc.be.tosca.model.ToscaArtifactDefinition;
61 import org.openecomp.sdc.be.tosca.model.ToscaInput;
62 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition;
63 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceNodeType;
64 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceOperationImplementation;
65 import org.openecomp.sdc.be.tosca.model.ToscaLifecycleOperationDefinition;
66 import org.openecomp.sdc.be.tosca.model.ToscaMilestone;
67 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
68 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
69 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
70 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignmentJsonSerializer;
71 import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
72 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
73 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
74 import org.springframework.beans.factory.annotation.Autowired;
75 import org.springframework.stereotype.Service;
76
77 @Service
78 public class InterfacesOperationsConverter {
79
80     public static final String SELF = "SELF";
81     private static final String DERIVED_FROM_STANDARD_INTERFACE = "tosca.interfaces.node.lifecycle.Standard";
82     private static final String DERIVED_FROM_BASE_DEFAULT = "org.openecomp.interfaces.node.lifecycle.";
83     private static final String DEFAULT_HAS_UNDERSCORE = "_default";
84     private static final String DOT = ".";
85     private static final String DEFAULTP = "defaultp";
86     private static final String LOCAL_INTERFACE_TYPE = "Local";
87     private final PropertyConvertor propertyConvertor;
88
89     @Autowired
90     public InterfacesOperationsConverter(final PropertyConvertor propertyConvertor) {
91         this.propertyConvertor = propertyConvertor;
92     }
93
94     private static Object getDefaultValue(Map<String, Object> inputValueMap) {
95         Object defaultValue = null;
96         for (Map.Entry<String, Object> operationEntry : inputValueMap.entrySet()) {
97             final Object value = operationEntry.getValue();
98             if (value instanceof Map) {
99                 getDefaultValue((Map<String, Object>) value);
100             }
101             final String key = operationEntry.getKey();
102             if (key.equals(DEFAULTP)) {
103                 defaultValue = inputValueMap.remove(key);
104             }
105         }
106         return defaultValue;
107     }
108
109     //Remove input type and copy default value directly into the proxy node template from the node type
110     private static void handleOperationInputValue(Map<String, Object> operationsMap, String parentKey) {
111         for (Map.Entry<String, Object> operationEntry : operationsMap.entrySet()) {
112             final Object value = operationEntry.getValue();
113             final String key = operationEntry.getKey();
114             if (value instanceof Map) {
115                 if (INPUTS.getElementName().equals(parentKey)) {
116                     Object defaultValue = getDefaultValue((Map<String, Object>) value);
117                     operationsMap.put(key, defaultValue);
118                 } else {
119                     handleOperationInputValue((Map<String, Object>) value, key);
120                 }
121             }
122         }
123     }
124
125     private static String getLastPartOfName(String toscaResourceName) {
126         return toscaResourceName.substring(toscaResourceName.lastIndexOf(DOT) + 1);
127     }
128
129     private static String getInputValue(final OperationInputDefinition input) {
130         if (null != input.getToscaFunction()) {
131             return input.getToscaFunction().getJsonObjectValue().toString();
132         }
133         String inputValue = input.getValue() == null ? input.getToscaDefaultValue() : input.getValue();
134         if (inputValue != null && inputValue.contains(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName())) {
135             Gson gson = new Gson();
136             Map<String, List<String>> consumptionValue = gson.fromJson(inputValue, Map.class);
137             List<String> mappedOutputValue = consumptionValue.get(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName());
138             //Extract the interface name from the interface type
139             String interfaceType = mappedOutputValue.get(1);
140             String interfaceName = interfaceType.substring(interfaceType.lastIndexOf('.') + 1);
141             mappedOutputValue.remove(1);
142             mappedOutputValue.add(1, interfaceName);
143             inputValue = gson.toJson(consumptionValue);
144         }
145         return inputValue;
146     }
147
148     private static String getInterfaceType(Component component, String interfaceType) {
149         if (LOCAL_INTERFACE_TYPE.equals(interfaceType)) {
150             return DERIVED_FROM_BASE_DEFAULT + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
151         }
152         return interfaceType;
153     }
154
155     private static Map<String, Object> getObjectAsMap(final Object obj) {
156         final Map<String, Object> objectAsMap;
157         if (obj instanceof Map) {
158             objectAsMap = (Map<String, Object>) obj;
159         } else {
160             final ObjectMapper objectMapper = new ObjectMapper();
161             final SimpleModule module = new SimpleModule("ToscaPropertyAssignmentSerializer");
162             module.addSerializer(ToscaPropertyAssignment.class, new ToscaPropertyAssignmentJsonSerializer());
163             objectMapper.registerModule(module);
164             if (obj instanceof ToscaInterfaceDefinition) {
165                 //Prevent empty field serialization in interface definition
166                 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
167             }
168             objectAsMap = objectMapper.convertValue(obj, Map.class);
169         }
170
171         final String defaultEntry = DEFAULT.getElementName();
172         if (objectAsMap.containsKey(defaultEntry)) {
173             objectAsMap.put(DEFAULT_HAS_UNDERSCORE, objectAsMap.remove(defaultEntry));
174         }
175         return objectAsMap;
176     }
177
178     /**
179      * Creates the interface_types element.
180      *
181      * @param component to work on
182      * @return the added element
183      */
184     public Map<String, Object> addInterfaceTypeElement(Component component, List<String> allInterfaceTypes) {
185         if (component instanceof Product) {
186             return null;
187         }
188         final Map<String, InterfaceDefinition> interfaces = component.getInterfaces();
189         if (MapUtils.isEmpty(interfaces)) {
190             return null;
191         }
192         Map<String, Object> toscaInterfaceTypes = new HashMap<>();
193         for (InterfaceDefinition interfaceDefinition : interfaces.values()) {
194             boolean isInterfaceTypeExistInGlobalType = allInterfaceTypes.stream()
195                 .anyMatch(type -> type.equalsIgnoreCase(interfaceDefinition.getType()));
196             if (!isInterfaceTypeExistInGlobalType) {
197                 ToscaInterfaceNodeType toscaInterfaceType = new ToscaInterfaceNodeType();
198                 toscaInterfaceType.setDerived_from(DERIVED_FROM_STANDARD_INTERFACE);
199                 final Map<String, OperationDataDefinition> operations = interfaceDefinition.getOperations();
200                 Map<String, Object> toscaOperations = new HashMap<>();
201                 for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
202                     toscaOperations.put(operationEntry.getValue().getName(), null);
203                 }
204                 toscaInterfaceType.setOperations(toscaOperations);
205                 Map<String, Object> interfacesAsMap = getObjectAsMap(toscaInterfaceType);
206                 Map<String, Object> operationsMap = (Map<String, Object>) interfacesAsMap.remove(OPERATIONS.getElementName());
207                 interfacesAsMap.putAll(operationsMap);
208                 toscaInterfaceTypes.put(getInterfaceType(component, LOCAL_INTERFACE_TYPE), interfacesAsMap);
209             }
210         }
211         return MapUtils.isNotEmpty(toscaInterfaceTypes) ? toscaInterfaceTypes : null;
212     }
213
214     private boolean isArtifactPresent(final OperationDataDefinition operationDataDefinition) {
215         return operationDataDefinition.getImplementation() != null
216             && StringUtils.isNotEmpty(operationDataDefinition.getImplementation().getArtifactName());
217     }
218
219     /**
220      * Adds the 'interfaces' element to the node type provided.
221      *
222      * @param component to work on
223      * @param nodeType  to which the interfaces element will be added
224      */
225     public void addInterfaceDefinitionElement(Component component, ToscaNodeType nodeType, Map<String, DataTypeDefinition> dataTypes,
226                                               boolean isAssociatedComponent) {
227         if (component instanceof Product) {
228             return;
229         }
230         final Map<String, InterfaceDefinition> interfaces = component.getInterfaces();
231         if (MapUtils.isEmpty(interfaces)) {
232             return;
233         }
234         Map<String, Object> toscaInterfaceDefinitions = getInterfacesMap(component, dataTypes, isAssociatedComponent);
235         if (MapUtils.isNotEmpty(toscaInterfaceDefinitions)) {
236             nodeType.setInterfaces(toscaInterfaceDefinitions);
237         }
238     }
239
240     private Map<String, Object> getInterfacesMap(Component component, Map<String, DataTypeDefinition> dataTypes, boolean isAssociatedComponent) {
241         return getInterfacesMap(component, null, component.getInterfaces(), dataTypes, isAssociatedComponent);
242     }
243
244     public Map<String, Object> getInterfacesMap(final Component component, final ComponentInstance componentInstance,
245                                                 final Map<String, InterfaceDefinition> interfaces, final Map<String, DataTypeDefinition> dataTypes,
246                                                 final boolean isAssociatedComponent) {
247         if (MapUtils.isEmpty(interfaces)) {
248             return null;
249         }
250         final Map<String, Object> toscaInterfaceDefinitions = new HashMap<>();
251         for (InterfaceDefinition interfaceDefinition : interfaces.values()) {
252             handleInterfaceOperations(component, componentInstance, dataTypes, isAssociatedComponent,
253                 toscaInterfaceDefinitions, interfaceDefinition);
254         }
255         return toscaInterfaceDefinitions;
256     }
257
258     public Map<String, Object> getInterfacesMapFromComponentInstance(final Component component, final ComponentInstance componentInstance,
259                                                                      final Map<String, DataTypeDefinition> dataTypes,
260                                                                      final boolean isAssociatedComponent) {
261         final Map<String, Object> toscaInterfaceDefinitions = new HashMap<>();
262         final ObjectMapper objectMapper = new ObjectMapper();
263         objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
264         for (final Map.Entry<String, Object> interfaceEntry : componentInstance.getInterfaces().entrySet()) {
265             final InterfaceDefinition interfaceDefinition = objectMapper.convertValue(interfaceEntry.getValue(), InterfaceDefinition.class);
266             handleInterfaceOperations(component, componentInstance, dataTypes, isAssociatedComponent,
267                 toscaInterfaceDefinitions, interfaceDefinition);
268         }
269         return toscaInterfaceDefinitions;
270     }
271
272     private void handleInterfaceOperations(final Component component, final ComponentInstance componentInstance,
273                                            final Map<String, DataTypeDefinition> dataTypes, final boolean isAssociatedComponent,
274                                            final Map<String, Object> toscaInterfaceDefinitions,
275                                            final InterfaceDefinition interfaceDefinition) {
276         final String interfaceType;
277         if (componentInstance != null && LOCAL_INTERFACE_TYPE.equals(interfaceDefinition.getType())) {
278             interfaceType = DERIVED_FROM_BASE_DEFAULT + componentInstance.getSourceModelName();
279         } else {
280             interfaceType = getInterfaceType(component, interfaceDefinition.getType());
281         }
282         final ToscaInterfaceDefinition toscaInterfaceDefinition = new ToscaInterfaceDefinition();
283         if (componentInstance == null) {
284             toscaInterfaceDefinition.setType(interfaceType);
285         }
286         final Map<String, OperationDataDefinition> operations = interfaceDefinition.getOperations();
287         final Map<String, Object> toscaOperationMap = new HashMap<>();
288         for (final Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
289             if (operationHasAnImplementation(operationEntry.getValue())) {
290                 final ToscaLifecycleOperationDefinition toscaLifecycleOperationDefinition = new ToscaLifecycleOperationDefinition();
291                 handleInterfaceOperationImplementation(component, componentInstance, isAssociatedComponent, operationEntry.getValue(),
292                     toscaLifecycleOperationDefinition, dataTypes);
293                 if (StringUtils.isNotEmpty(operationEntry.getValue().getDescription())) {
294                     toscaLifecycleOperationDefinition.setDescription(operationEntry.getValue().getDescription());
295                 }
296                 fillToscaOperationInputs(operationEntry.getValue(), dataTypes, toscaLifecycleOperationDefinition);
297                 fillToscaOperationMilestones(operationEntry.getValue(), dataTypes, toscaLifecycleOperationDefinition);
298                 toscaOperationMap.put(operationEntry.getValue().getName(), toscaLifecycleOperationDefinition);
299             }
300         }
301         toscaInterfaceDefinition.setOperations(toscaOperationMap);
302         final Map<String, Object> interfaceInputMap = createInterfaceInputMap(interfaceDefinition, dataTypes);
303         if (MapUtils.isNotEmpty(interfaceInputMap)) {
304             toscaInterfaceDefinition.setInputs(interfaceInputMap);
305         }
306         final Map<String, Object> interfaceDefinitionAsMap = getObjectAsMap(toscaInterfaceDefinition);
307         if (interfaceDefinitionAsMap.containsKey(INPUTS.getElementName())) {
308             handleDefaults((Map<String, Object>) interfaceDefinitionAsMap.get(INPUTS.getElementName()));
309         }
310         final Map<String, Object> operationsMap = (Map<String, Object>) interfaceDefinitionAsMap.remove(OPERATIONS.getElementName());
311         handleOperationInputValue(operationsMap, interfaceType);
312         interfaceDefinitionAsMap.putAll(operationsMap);
313         toscaInterfaceDefinitions.put(getLastPartOfName(interfaceType), interfaceDefinitionAsMap);
314     }
315
316     private void fillToscaOperationMilestones(OperationDataDefinition operation, Map<String, DataTypeDefinition> dataTypes,
317                                               ToscaLifecycleOperationDefinition toscaOperation) {
318         if (Objects.isNull(operation.getMilestones()) || operation.getMilestones().isEmpty()) {
319             toscaOperation.setMilestones(null);
320             return;
321         }
322         Map<String, ToscaMilestone> toscaMilestones = new HashMap<>();
323         for (Entry<String, MilestoneDataDefinition> milestone : operation.getMilestones().entrySet()) {
324             ListDataDefinition<ActivityDataDefinition> activities = milestone.getValue().getActivities();
325             if (MilestoneTypeEnum.getEnum(milestone.getKey()).isEmpty() || activities == null || activities.isEmpty()) {
326                 continue;
327             }
328             List<Map<String, ToscaActivity>> toscaActivities = new ArrayList<>();
329             for (ActivityDataDefinition activity : activities.getListToscaDataDefinition()) {
330                 if (ActivityTypeEnum.getEnum(activity.getType()).isEmpty()) {
331                     continue;
332                 }
333                 Map<String, ToscaActivity> toscaActivityMap = new HashMap<>();
334                 ToscaActivity toscaActivity = new ToscaActivity();
335                 toscaActivity.setWorkflow(activity.getWorkflow());
336                 Map<String, Object> inputs = getToscaActivityInputs(activity.getInputs(), dataTypes);
337                 if (!inputs.isEmpty()) {
338                     toscaActivity.setInputs(inputs);
339                 }
340                 toscaActivityMap.put(activity.getType(), toscaActivity);
341                 toscaActivities.add(toscaActivityMap);
342             }
343             ToscaMilestone toscaMilestone = new ToscaMilestone();
344             toscaMilestone.setActivities(toscaActivities);
345             toscaMilestones.put(milestone.getKey(), toscaMilestone);
346         }
347         toscaOperation.setMilestones(toscaMilestones);
348     }
349
350     private Map<String, Object> getToscaActivityInputs(ListDataDefinition<OperationInputDefinition> inputs,
351                                                        Map<String, DataTypeDefinition> dataTypes) {
352         if (Objects.isNull(inputs) || inputs.isEmpty()) {
353             return null;
354         }
355         Map<String, Object> toscaInputs = new HashMap<>();
356         for (OperationInputDefinition input : inputs.getListToscaDataDefinition()) {
357             Object value = propertyConvertor.convertToToscaObject(input, getInputValue(input), dataTypes, false);
358             if (ObjectUtils.isNotEmpty(value)) {
359                 toscaInputs.put(input.getName(), value);
360             }
361         }
362         return toscaInputs;
363     }
364
365     private boolean operationHasAnImplementation(OperationDataDefinition operation) {
366         return operation.getImplementation() != null && StringUtils.isNotEmpty(operation.getImplementation().getArtifactName()) &&
367             !operation.getImplementation().getArtifactName().equals("''");
368     }
369
370     private void handleInterfaceOperationImplementation(final Component component, final ComponentInstance componentInstance,
371                                                         final boolean isAssociatedComponent,
372                                                         final OperationDataDefinition operationDataDefinition,
373                                                         final ToscaLifecycleOperationDefinition toscaOperation,
374                                                         final Map<String, DataTypeDefinition> dataTypes) {
375         final ArtifactDataDefinition implementation = operationDataDefinition.getImplementation();
376         if (implementation == null) {
377             return;
378         }
379
380         if (isArtifactPresent(operationDataDefinition)) {
381             final String operationArtifactPath =
382                 OperationArtifactUtil.createOperationArtifactPath(component, componentInstance, operationDataDefinition, isAssociatedComponent);
383             final ToscaInterfaceOperationImplementation toscaInterfaceOperationImplementation = new ToscaInterfaceOperationImplementation();
384             if (implementation.getTimeout() != null && implementation.getTimeout() > 0) {
385                 toscaInterfaceOperationImplementation.setTimeout(implementation.getTimeout());
386             }
387             if (implementation.getArtifactType() != null) {
388                 final ToscaArtifactDefinition toscaArtifactDefinition = new ToscaArtifactDefinition();
389                 toscaArtifactDefinition.setFile(operationArtifactPath);
390                 final String artifactVersion = implementation.getArtifactVersion();
391                 toscaArtifactDefinition.setArtifact_version(!artifactVersion.equals(NumberUtils.INTEGER_ZERO.toString()) ? artifactVersion : null);
392                 toscaArtifactDefinition.setType(implementation.getArtifactType());
393                 final Map<String, ToscaPropertyAssignment> propertiesMap = handleImplementationProperties(operationDataDefinition, dataTypes);
394                 if (MapUtils.isNotEmpty(propertiesMap)) {
395                     toscaArtifactDefinition.setProperties(propertiesMap);
396                 }
397                 toscaInterfaceOperationImplementation.setPrimary(toscaArtifactDefinition);
398                 toscaOperation.setImplementation(toscaInterfaceOperationImplementation);
399             } else {
400                 if (toscaInterfaceOperationImplementation.getTimeout() != null) {
401                     final ToscaArtifactDefinition toscaArtifactDefinition = new ToscaArtifactDefinition();
402                     toscaArtifactDefinition.setFile(StringUtils.isBlank(operationArtifactPath) || "null".equals(operationArtifactPath) ? null : operationArtifactPath);
403                     toscaInterfaceOperationImplementation.setPrimary(toscaArtifactDefinition);
404                     toscaOperation.setImplementation(toscaInterfaceOperationImplementation);
405                 } else {
406                     toscaOperation.setImplementation(
407                         StringUtils.isBlank(operationArtifactPath) || "null".equals(operationArtifactPath) ? null : operationArtifactPath);
408                 }
409             }
410         }
411     }
412
413     private Map<String, ToscaPropertyAssignment> handleImplementationProperties(final OperationDataDefinition operationDataDefinition,
414                                                                                 final Map<String, DataTypeDefinition> dataTypes) {
415         if (operationDataDefinition.getImplementation() == null) {
416             return new HashMap<>();
417         }
418
419         final List<PropertyDataDefinition> properties = operationDataDefinition.getImplementation().getProperties();
420         if (CollectionUtils.isEmpty(properties)) {
421             return new HashMap<>();
422         }
423
424         final Map<String, ToscaPropertyAssignment> propertiesMap = new HashMap<>();
425         properties.stream()
426             .filter(propertyDataDefinition -> StringUtils.isNotEmpty(propertyDataDefinition.getValue()))
427             .forEach(propertyDataDefinition -> {
428                     final String propertyValue =
429                         propertyDataDefinition.getValue() != null ? propertyDataDefinition.getValue() : propertyDataDefinition.getDefaultValue();
430                     final ToscaPropertyAssignment toscaPropertyAssignment = new ToscaPropertyAssignment();
431                     toscaPropertyAssignment.setValue(propertyConvertor.convertToToscaObject(propertyDataDefinition, propertyValue, dataTypes, false));
432                     propertiesMap.put(propertyDataDefinition.getName(), toscaPropertyAssignment);
433                 }
434             );
435
436         return propertiesMap;
437     }
438
439     public void removeInterfacesWithoutOperations(final Map<String, Object> interfaceMap) {
440         if (MapUtils.isEmpty(interfaceMap)) {
441             return;
442         }
443         final Set<String> emptyInterfaces = interfaceMap.entrySet().stream().filter(entry -> {
444             final Object value = entry.getValue();
445             if (value instanceof ToscaInterfaceDefinition) {
446                 final ToscaInterfaceDefinition interfaceDefinition = (ToscaInterfaceDefinition) value;
447                 return MapUtils.isEmpty(interfaceDefinition.getOperations());
448             } else if (value instanceof Map) {
449                 final Map<String, Object> interfaceDefMap = (Map<String, Object>) value;
450                 return MapUtils.isEmpty(interfaceDefMap);
451             }
452             return false;
453         }).map(Entry::getKey).collect(Collectors.toSet());
454         emptyInterfaces.forEach(interfaceMap::remove);
455     }
456
457     private Map<String, Object> createInterfaceInputMap(final InterfaceDefinition interfaceDefinition,
458                                                         final Map<String, DataTypeDefinition> allDataTypeMap) {
459         final Map<String, InputDataDefinition> inputMap = interfaceDefinition.getInputs();
460         if (MapUtils.isEmpty(inputMap)) {
461             return Collections.emptyMap();
462         }
463         final Map<String, Object> toscaInterfaceInputMap = new HashMap<>();
464         for (final Entry<String, InputDataDefinition> inputEntry : inputMap.entrySet()) {
465             final InputDataDefinition inputDataDefinition = inputEntry.getValue();
466             final ToscaProperty toscaProperty = propertyConvertor
467                 .convertProperty(allDataTypeMap, new PropertyDefinition(inputDataDefinition), PropertyType.INPUT);
468             toscaInterfaceInputMap.put(inputEntry.getKey(), new ToscaInput(toscaProperty));
469         }
470         return toscaInterfaceInputMap;
471     }
472
473     /*
474      * workaround for : currently "defaultp" is not being converted to "default" by the relevant code in
475      * ToscaExportHandler so, any string Map key named "defaultp" will have its named changed to "default"
476      * @param operationsMap the map to update
477      */
478     private void handleDefaults(Map<String, Object> operationsMap) {
479         for (Map.Entry<String, Object> operationEntry : operationsMap.entrySet()) {
480             final Object value = operationEntry.getValue();
481             if (value instanceof Map) {
482                 handleDefaults((Map<String, Object>) value);
483             }
484             final String key = operationEntry.getKey();
485             if (key.equals(DEFAULTP)) {
486                 Object removed = operationsMap.remove(key);
487                 operationsMap.put(ToscaTagNamesEnum.DEFAULT.getElementName(), removed);
488             }
489         }
490     }
491
492     private void fillToscaOperationInputs(OperationDataDefinition operation, Map<String, DataTypeDefinition> dataTypes,
493                                           ToscaLifecycleOperationDefinition toscaOperation) {
494         if (Objects.isNull(operation.getInputs()) || operation.getInputs().isEmpty()) {
495             toscaOperation.setInputs(null);
496             return;
497         }
498         Map<String, ToscaProperty> toscaInputs = new HashMap<>();
499         for (OperationInputDefinition input : operation.getInputs().getListToscaDataDefinition()) {
500             ToscaProperty toscaInput = new ToscaProperty();
501             toscaInput.setDescription(input.getDescription());
502             toscaInput.setType(input.getType());
503             toscaInput.setRequired(input.isRequired());
504             toscaInput.setDefaultp(propertyConvertor.convertToToscaObject(input, getInputValue(input), dataTypes, false));
505             toscaInputs.put(input.getName(), toscaInput);
506         }
507         toscaOperation.setInputs(toscaInputs);
508     }
509
510 }