Backend support for operation milestone filters
[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.Optional;
36 import java.util.Set;
37 import java.util.stream.Collectors;
38 import org.apache.commons.collections.MapUtils;
39 import org.apache.commons.collections4.CollectionUtils;
40 import org.apache.commons.lang3.ObjectUtils;
41 import org.apache.commons.lang3.StringUtils;
42 import org.apache.commons.lang3.math.NumberUtils;
43 import org.openecomp.sdc.be.datatypes.elements.ActivityDataDefinition;
44 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
45 import org.openecomp.sdc.be.datatypes.elements.FilterDataDefinition;
46 import org.openecomp.sdc.be.datatypes.elements.InputDataDefinition;
47 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
48 import org.openecomp.sdc.be.datatypes.elements.MilestoneDataDefinition;
49 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
50 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
51 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
52 import org.openecomp.sdc.be.datatypes.enums.ActivityTypeEnum;
53 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
54 import org.openecomp.sdc.be.datatypes.enums.MilestoneTypeEnum;
55 import org.openecomp.sdc.be.model.Component;
56 import org.openecomp.sdc.be.model.ComponentInstance;
57 import org.openecomp.sdc.be.model.DataTypeDefinition;
58 import org.openecomp.sdc.be.model.InterfaceDefinition;
59 import org.openecomp.sdc.be.model.Product;
60 import org.openecomp.sdc.be.model.PropertyDefinition;
61 import org.openecomp.sdc.be.model.tosca.constraints.EqualConstraint;
62 import org.openecomp.sdc.be.model.tosca.constraints.GreaterOrEqualConstraint;
63 import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint;
64 import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
65 import org.openecomp.sdc.be.model.tosca.constraints.LengthConstraint;
66 import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint;
67 import org.openecomp.sdc.be.model.tosca.constraints.LessThanConstraint;
68 import org.openecomp.sdc.be.model.tosca.constraints.MaxLengthConstraint;
69 import org.openecomp.sdc.be.model.tosca.constraints.MinLengthConstraint;
70 import org.openecomp.sdc.be.model.tosca.constraints.PatternConstraint;
71 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
72 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
73 import org.openecomp.sdc.be.tosca.model.ToscaActivity;
74 import org.openecomp.sdc.be.tosca.model.ToscaArtifactDefinition;
75 import org.openecomp.sdc.be.tosca.model.ToscaInput;
76 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition;
77 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceNodeType;
78 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceOperationImplementation;
79 import org.openecomp.sdc.be.tosca.model.ToscaLifecycleOperationDefinition;
80 import org.openecomp.sdc.be.tosca.model.ToscaMilestone;
81 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
82 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
83 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
84 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignmentJsonSerializer;
85 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraint;
86 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintEqual;
87 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintGreaterOrEqual;
88 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintGreaterThan;
89 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintInRange;
90 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintLength;
91 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintLessOrEqual;
92 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintLessThan;
93 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintMaxLength;
94 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintMinLength;
95 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintPattern;
96 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintValidValues;
97 import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
98 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
99 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
100 import org.springframework.beans.factory.annotation.Autowired;
101 import org.springframework.stereotype.Service;
102
103 @Service
104 public class InterfacesOperationsConverter {
105
106     public static final String SELF = "SELF";
107     private static final String DERIVED_FROM_STANDARD_INTERFACE = "tosca.interfaces.node.lifecycle.Standard";
108     private static final String DERIVED_FROM_BASE_DEFAULT = "org.openecomp.interfaces.node.lifecycle.";
109     private static final String DEFAULT_HAS_UNDERSCORE = "_default";
110     private static final String DOT = ".";
111     private static final String DEFAULTP = "defaultp";
112     private static final String LOCAL_INTERFACE_TYPE = "Local";
113     private final PropertyConvertor propertyConvertor;
114
115     @Autowired
116     public InterfacesOperationsConverter(final PropertyConvertor propertyConvertor) {
117         this.propertyConvertor = propertyConvertor;
118     }
119
120     private static Object getDefaultValue(Map<String, Object> inputValueMap) {
121         Object defaultValue = null;
122         for (Map.Entry<String, Object> operationEntry : inputValueMap.entrySet()) {
123             final Object value = operationEntry.getValue();
124             if (value instanceof Map) {
125                 getDefaultValue((Map<String, Object>) value);
126             }
127             final String key = operationEntry.getKey();
128             if (key.equals(DEFAULTP)) {
129                 defaultValue = inputValueMap.remove(key);
130             }
131         }
132         return defaultValue;
133     }
134
135     //Remove input type and copy default value directly into the proxy node template from the node type
136     private static void handleOperationInputValue(Map<String, Object> operationsMap, String parentKey) {
137         for (Map.Entry<String, Object> operationEntry : operationsMap.entrySet()) {
138             final Object value = operationEntry.getValue();
139             final String key = operationEntry.getKey();
140             if (value instanceof Map) {
141                 if (INPUTS.getElementName().equals(parentKey)) {
142                     Object defaultValue = getDefaultValue((Map<String, Object>) value);
143                     operationsMap.put(key, defaultValue);
144                 } else {
145                     handleOperationInputValue((Map<String, Object>) value, key);
146                 }
147             }
148         }
149     }
150
151     private static String getLastPartOfName(String toscaResourceName) {
152         return toscaResourceName.substring(toscaResourceName.lastIndexOf(DOT) + 1);
153     }
154
155     private static String getInputValue(final OperationInputDefinition input) {
156         if (null != input.getToscaFunction()) {
157             return input.getToscaFunction().getJsonObjectValue().toString();
158         }
159         String inputValue = input.getValue() == null ? input.getToscaDefaultValue() : input.getValue();
160         if (inputValue != null && inputValue.contains(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName())) {
161             Gson gson = new Gson();
162             Map<String, List<String>> consumptionValue = gson.fromJson(inputValue, Map.class);
163             List<String> mappedOutputValue = consumptionValue.get(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName());
164             //Extract the interface name from the interface type
165             String interfaceType = mappedOutputValue.get(1);
166             String interfaceName = interfaceType.substring(interfaceType.lastIndexOf('.') + 1);
167             mappedOutputValue.remove(1);
168             mappedOutputValue.add(1, interfaceName);
169             inputValue = gson.toJson(consumptionValue);
170         }
171         return inputValue;
172     }
173
174     private static String getInterfaceType(Component component, String interfaceType) {
175         if (LOCAL_INTERFACE_TYPE.equals(interfaceType)) {
176             return DERIVED_FROM_BASE_DEFAULT + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
177         }
178         return interfaceType;
179     }
180
181     private static Map<String, Object> getObjectAsMap(final Object obj) {
182         final Map<String, Object> objectAsMap;
183         if (obj instanceof Map) {
184             objectAsMap = (Map<String, Object>) obj;
185         } else {
186             final ObjectMapper objectMapper = new ObjectMapper();
187             final SimpleModule module = new SimpleModule("ToscaPropertyAssignmentSerializer");
188             module.addSerializer(ToscaPropertyAssignment.class, new ToscaPropertyAssignmentJsonSerializer());
189             objectMapper.registerModule(module);
190             if (obj instanceof ToscaInterfaceDefinition) {
191                 //Prevent empty field serialization in interface definition
192                 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
193             }
194             objectAsMap = objectMapper.convertValue(obj, Map.class);
195         }
196
197         final String defaultEntry = DEFAULT.getElementName();
198         if (objectAsMap.containsKey(defaultEntry)) {
199             objectAsMap.put(DEFAULT_HAS_UNDERSCORE, objectAsMap.remove(defaultEntry));
200         }
201         return objectAsMap;
202     }
203
204     /**
205      * Creates the interface_types element.
206      *
207      * @param component to work on
208      * @return the added element
209      */
210     public Map<String, Object> addInterfaceTypeElement(Component component, List<String> allInterfaceTypes) {
211         if (component instanceof Product) {
212             return null;
213         }
214         final Map<String, InterfaceDefinition> interfaces = component.getInterfaces();
215         if (MapUtils.isEmpty(interfaces)) {
216             return null;
217         }
218         Map<String, Object> toscaInterfaceTypes = new HashMap<>();
219         for (InterfaceDefinition interfaceDefinition : interfaces.values()) {
220             boolean isInterfaceTypeExistInGlobalType = allInterfaceTypes.stream()
221                 .anyMatch(type -> type.equalsIgnoreCase(interfaceDefinition.getType()));
222             if (!isInterfaceTypeExistInGlobalType) {
223                 ToscaInterfaceNodeType toscaInterfaceType = new ToscaInterfaceNodeType();
224                 toscaInterfaceType.setDerived_from(DERIVED_FROM_STANDARD_INTERFACE);
225                 final Map<String, OperationDataDefinition> operations = interfaceDefinition.getOperations();
226                 Map<String, Object> toscaOperations = new HashMap<>();
227                 for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
228                     toscaOperations.put(operationEntry.getValue().getName(), null);
229                 }
230                 toscaInterfaceType.setOperations(toscaOperations);
231                 Map<String, Object> interfacesAsMap = getObjectAsMap(toscaInterfaceType);
232                 Map<String, Object> operationsMap = (Map<String, Object>) interfacesAsMap.remove(OPERATIONS.getElementName());
233                 interfacesAsMap.putAll(operationsMap);
234                 toscaInterfaceTypes.put(getInterfaceType(component, LOCAL_INTERFACE_TYPE), interfacesAsMap);
235             }
236         }
237         return MapUtils.isNotEmpty(toscaInterfaceTypes) ? toscaInterfaceTypes : null;
238     }
239
240     private boolean isArtifactPresent(final OperationDataDefinition operationDataDefinition) {
241         return operationDataDefinition.getImplementation() != null
242             && StringUtils.isNotEmpty(operationDataDefinition.getImplementation().getArtifactName());
243     }
244
245     /**
246      * Adds the 'interfaces' element to the node type provided.
247      *
248      * @param component to work on
249      * @param nodeType  to which the interfaces element will be added
250      */
251     public void addInterfaceDefinitionElement(Component component, ToscaNodeType nodeType, Map<String, DataTypeDefinition> dataTypes,
252                                               boolean isAssociatedComponent) {
253         if (component instanceof Product) {
254             return;
255         }
256         final Map<String, InterfaceDefinition> interfaces = component.getInterfaces();
257         if (MapUtils.isEmpty(interfaces)) {
258             return;
259         }
260         Map<String, Object> toscaInterfaceDefinitions = getInterfacesMap(component, dataTypes, isAssociatedComponent);
261         if (MapUtils.isNotEmpty(toscaInterfaceDefinitions)) {
262             nodeType.setInterfaces(toscaInterfaceDefinitions);
263         }
264     }
265
266     private Map<String, Object> getInterfacesMap(Component component, Map<String, DataTypeDefinition> dataTypes, boolean isAssociatedComponent) {
267         return getInterfacesMap(component, null, component.getInterfaces(), dataTypes, isAssociatedComponent);
268     }
269
270     public Map<String, Object> getInterfacesMap(final Component component, final ComponentInstance componentInstance,
271                                                 final Map<String, InterfaceDefinition> interfaces, final Map<String, DataTypeDefinition> dataTypes,
272                                                 final boolean isAssociatedComponent) {
273         if (MapUtils.isEmpty(interfaces)) {
274             return null;
275         }
276         final Map<String, Object> toscaInterfaceDefinitions = new HashMap<>();
277         for (InterfaceDefinition interfaceDefinition : interfaces.values()) {
278             handleInterfaceOperations(component, componentInstance, dataTypes, isAssociatedComponent,
279                 toscaInterfaceDefinitions, interfaceDefinition);
280         }
281         return toscaInterfaceDefinitions;
282     }
283
284     public Map<String, Object> getInterfacesMapFromComponentInstance(final Component component, final ComponentInstance componentInstance,
285                                                                      final Map<String, DataTypeDefinition> dataTypes,
286                                                                      final boolean isAssociatedComponent) {
287         final Map<String, Object> toscaInterfaceDefinitions = new HashMap<>();
288         final ObjectMapper objectMapper = new ObjectMapper();
289         objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
290         for (final Map.Entry<String, Object> interfaceEntry : componentInstance.getInterfaces().entrySet()) {
291             final InterfaceDefinition interfaceDefinition = objectMapper.convertValue(interfaceEntry.getValue(), InterfaceDefinition.class);
292             handleInterfaceOperations(component, componentInstance, dataTypes, isAssociatedComponent,
293                 toscaInterfaceDefinitions, interfaceDefinition);
294         }
295         return toscaInterfaceDefinitions;
296     }
297
298     private void handleInterfaceOperations(final Component component, final ComponentInstance componentInstance,
299                                            final Map<String, DataTypeDefinition> dataTypes, final boolean isAssociatedComponent,
300                                            final Map<String, Object> toscaInterfaceDefinitions,
301                                            final InterfaceDefinition interfaceDefinition) {
302         final String interfaceType;
303         if (componentInstance != null && LOCAL_INTERFACE_TYPE.equals(interfaceDefinition.getType())) {
304             interfaceType = DERIVED_FROM_BASE_DEFAULT + componentInstance.getSourceModelName();
305         } else {
306             interfaceType = getInterfaceType(component, interfaceDefinition.getType());
307         }
308         final ToscaInterfaceDefinition toscaInterfaceDefinition = new ToscaInterfaceDefinition();
309         if (componentInstance == null) {
310             toscaInterfaceDefinition.setType(interfaceType);
311         }
312         final Map<String, OperationDataDefinition> operations = interfaceDefinition.getOperations();
313         final Map<String, Object> toscaOperationMap = new HashMap<>();
314         for (final Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
315             if (operationHasAnImplementation(operationEntry.getValue())) {
316                 final ToscaLifecycleOperationDefinition toscaLifecycleOperationDefinition = new ToscaLifecycleOperationDefinition();
317                 handleInterfaceOperationImplementation(component, componentInstance, isAssociatedComponent, operationEntry.getValue(),
318                     toscaLifecycleOperationDefinition, dataTypes);
319                 if (StringUtils.isNotEmpty(operationEntry.getValue().getDescription())) {
320                     toscaLifecycleOperationDefinition.setDescription(operationEntry.getValue().getDescription());
321                 }
322                 fillToscaOperationInputs(operationEntry.getValue(), dataTypes, toscaLifecycleOperationDefinition);
323                 fillToscaOperationMilestones(operationEntry.getValue(), dataTypes, toscaLifecycleOperationDefinition);
324                 toscaOperationMap.put(operationEntry.getValue().getName(), toscaLifecycleOperationDefinition);
325             }
326         }
327         toscaInterfaceDefinition.setOperations(toscaOperationMap);
328         final Map<String, Object> interfaceInputMap = createInterfaceInputMap(interfaceDefinition, dataTypes);
329         if (MapUtils.isNotEmpty(interfaceInputMap)) {
330             toscaInterfaceDefinition.setInputs(interfaceInputMap);
331         }
332         final Map<String, Object> interfaceDefinitionAsMap = getObjectAsMap(toscaInterfaceDefinition);
333         if (interfaceDefinitionAsMap.containsKey(INPUTS.getElementName())) {
334             handleDefaults((Map<String, Object>) interfaceDefinitionAsMap.get(INPUTS.getElementName()));
335         }
336         final Map<String, Object> operationsMap = (Map<String, Object>) interfaceDefinitionAsMap.remove(OPERATIONS.getElementName());
337         handleOperationInputValue(operationsMap, interfaceType);
338         interfaceDefinitionAsMap.putAll(operationsMap);
339         toscaInterfaceDefinitions.put(getLastPartOfName(interfaceType), interfaceDefinitionAsMap);
340     }
341
342     private void fillToscaOperationMilestones(OperationDataDefinition operation, Map<String, DataTypeDefinition> dataTypes,
343                                               ToscaLifecycleOperationDefinition toscaOperation) {
344         if (Objects.isNull(operation.getMilestones()) || operation.getMilestones().isEmpty()) {
345             toscaOperation.setMilestones(null);
346             return;
347         }
348         Map<String, ToscaMilestone> toscaMilestones = new HashMap<>();
349         for (Entry<String, MilestoneDataDefinition> milestone : operation.getMilestones().entrySet()) {
350             ListDataDefinition<ActivityDataDefinition> activities = milestone.getValue().getActivities();
351             if (MilestoneTypeEnum.getEnum(milestone.getKey()).isEmpty() || activities == null || activities.isEmpty()) {
352                 continue;
353             }
354             List<Map<String, ToscaActivity>> toscaActivities = new ArrayList<>();
355             for (ActivityDataDefinition activity : activities.getListToscaDataDefinition()) {
356                 if (ActivityTypeEnum.getEnum(activity.getType()).isEmpty()) {
357                     continue;
358                 }
359                 Map<String, ToscaActivity> toscaActivityMap = new HashMap<>();
360                 ToscaActivity toscaActivity = new ToscaActivity();
361                 toscaActivity.setWorkflow(activity.getWorkflow());
362                 Map<String, Object> inputs = getToscaActivityInputs(activity.getInputs(), dataTypes);
363                 if (!inputs.isEmpty()) {
364                     toscaActivity.setInputs(inputs);
365                 }
366                 toscaActivityMap.put(activity.getType(), toscaActivity);
367                 toscaActivities.add(toscaActivityMap);
368             }
369             ToscaMilestone toscaMilestone = new ToscaMilestone();
370             toscaMilestone.setActivities(toscaActivities);
371             toscaMilestone.setFilters(getToscaFilters(milestone.getValue().getFilters()));
372             toscaMilestones.put(milestone.getKey(), toscaMilestone);
373         }
374         toscaOperation.setMilestones(toscaMilestones);
375     }
376
377     private List<Map<String, ToscaPropertyConstraint>> getToscaFilters(ListDataDefinition<FilterDataDefinition> filters) {
378         if (filters != null && !filters.isEmpty()) {
379             List<Map<String, ToscaPropertyConstraint>> toscaFilters = new ArrayList<>();
380             for (FilterDataDefinition filter : filters.getListToscaDataDefinition()) {
381                 Optional<ConstraintType> typeOptional = ConstraintType.findByType(filter.getConstraint());
382                 if (typeOptional.isEmpty()) {
383                     continue;
384                 }
385                 ConstraintType type = typeOptional.get();
386                 Object value = filter.isToscaFunction() ? filter.getToscaFunction().getJsonObjectValue() : filter.getFilterValue();
387                 if (ConstraintType.EQUAL.equals(type)) {
388                     EqualConstraint equalConstraint = new EqualConstraint(value);
389                     ToscaPropertyConstraint prop = new ToscaPropertyConstraintEqual(equalConstraint.getEqual());
390                     toscaFilters.add(Map.of(filter.getName(), prop));
391                 }
392                 if (ConstraintType.GREATER_THAN.equals(type)) {
393                     GreaterThanConstraint greaterThanConstraint = new GreaterThanConstraint(value);
394                     ToscaPropertyConstraintGreaterThan prop = new ToscaPropertyConstraintGreaterThan(greaterThanConstraint.getGreaterThan());
395                     toscaFilters.add(Map.of(filter.getName(), prop));
396                 }
397                 if (ConstraintType.GREATER_OR_EQUAL.equals(type)) {
398                     GreaterOrEqualConstraint greaterOrEqualConstraint = new GreaterOrEqualConstraint<>(value);
399                     ToscaPropertyConstraintGreaterOrEqual prop =
400                         new ToscaPropertyConstraintGreaterOrEqual(greaterOrEqualConstraint.getGreaterOrEqual());
401                     toscaFilters.add(Map.of(filter.getName(), prop));
402                 }
403                 if (ConstraintType.LESS_THAN.equals(type)) {
404                     LessThanConstraint lessThanConstraint = new LessThanConstraint(value);
405                     ToscaPropertyConstraintLessThan prop = new ToscaPropertyConstraintLessThan(lessThanConstraint.getLessThan());
406                     toscaFilters.add(Map.of(filter.getName(), prop));
407                 }
408                 if (ConstraintType.LESS_OR_EQUAL.equals(type)) {
409                     LessOrEqualConstraint lessOrEqualConstraint = new LessOrEqualConstraint<>(value);
410                     ToscaPropertyConstraintLessOrEqual prop = new ToscaPropertyConstraintLessOrEqual(lessOrEqualConstraint.getLessOrEqual());
411                     toscaFilters.add(Map.of(filter.getName(), prop));
412                 }
413                 if (ConstraintType.IN_RANGE.equals(type)) {
414                     InRangeConstraint inRangeConstraint = new InRangeConstraint((List<Object>) value);
415                     toscaFilters.add(Map.of(filter.getName(), new ToscaPropertyConstraintInRange(inRangeConstraint.getInRange())));
416                 }
417                 if (ConstraintType.VALID_VALUES.equals(type)) {
418                     ValidValuesConstraint validValues = new ValidValuesConstraint((List<Object>) value);
419                     List prop = validValues.getValidValues();
420                     toscaFilters.add(Map.of(filter.getName(), (new ToscaPropertyConstraintValidValues(prop))));
421                 }
422                 if (ConstraintType.LENGTH.equals(type)) {
423                     LengthConstraint lengthConstraint = new LengthConstraint((Integer) value);
424                     toscaFilters.add(Map.of(filter.getName(), (new ToscaPropertyConstraintLength(lengthConstraint.getLength()))));
425                 }
426                 if (ConstraintType.MIN_LENGTH.equals(type)) {
427                     MinLengthConstraint minLengthConstraint = new MinLengthConstraint((Integer) value);
428                     toscaFilters.add(Map.of(filter.getName(), new ToscaPropertyConstraintMinLength(minLengthConstraint.getMinLength())));
429                 }
430                 if (ConstraintType.MAX_LENGTH.equals(type)) {
431                     MaxLengthConstraint maxLengthConstraint = new MaxLengthConstraint((Integer) value);
432                     toscaFilters.add(Map.of(filter.getName(), new ToscaPropertyConstraintMaxLength(maxLengthConstraint.getMaxLength())));
433                 }
434             }
435             return toscaFilters;
436         }
437         return null;
438     }
439
440     private Map<String, Object> getToscaActivityInputs(ListDataDefinition<OperationInputDefinition> inputs,
441                                                        Map<String, DataTypeDefinition> dataTypes) {
442         if (Objects.isNull(inputs) || inputs.isEmpty()) {
443             return null;
444         }
445         Map<String, Object> toscaInputs = new HashMap<>();
446         for (OperationInputDefinition input : inputs.getListToscaDataDefinition()) {
447             Object value = propertyConvertor.convertToToscaObject(input, getInputValue(input), dataTypes, false);
448             if (ObjectUtils.isNotEmpty(value)) {
449                 toscaInputs.put(input.getName(), value);
450             }
451         }
452         return toscaInputs;
453     }
454
455     private boolean operationHasAnImplementation(OperationDataDefinition operation) {
456         return operation.getImplementation() != null && StringUtils.isNotEmpty(operation.getImplementation().getArtifactName()) &&
457             !operation.getImplementation().getArtifactName().equals("''");
458     }
459
460     private void handleInterfaceOperationImplementation(final Component component, final ComponentInstance componentInstance,
461                                                         final boolean isAssociatedComponent,
462                                                         final OperationDataDefinition operationDataDefinition,
463                                                         final ToscaLifecycleOperationDefinition toscaOperation,
464                                                         final Map<String, DataTypeDefinition> dataTypes) {
465         final ArtifactDataDefinition implementation = operationDataDefinition.getImplementation();
466         if (implementation == null) {
467             return;
468         }
469
470         if (isArtifactPresent(operationDataDefinition)) {
471             final String operationArtifactPath =
472                 OperationArtifactUtil.createOperationArtifactPath(component, componentInstance, operationDataDefinition, isAssociatedComponent);
473             final ToscaInterfaceOperationImplementation toscaInterfaceOperationImplementation = new ToscaInterfaceOperationImplementation();
474             if (implementation.getTimeout() != null && implementation.getTimeout() > 0) {
475                 toscaInterfaceOperationImplementation.setTimeout(implementation.getTimeout());
476             }
477             if (implementation.getArtifactType() != null) {
478                 final ToscaArtifactDefinition toscaArtifactDefinition = new ToscaArtifactDefinition();
479                 toscaArtifactDefinition.setFile(operationArtifactPath);
480                 final String artifactVersion = implementation.getArtifactVersion();
481                 toscaArtifactDefinition.setArtifact_version(!artifactVersion.equals(NumberUtils.INTEGER_ZERO.toString()) ? artifactVersion : null);
482                 toscaArtifactDefinition.setType(implementation.getArtifactType());
483                 final Map<String, ToscaPropertyAssignment> propertiesMap = handleImplementationProperties(operationDataDefinition, dataTypes);
484                 if (MapUtils.isNotEmpty(propertiesMap)) {
485                     toscaArtifactDefinition.setProperties(propertiesMap);
486                 }
487                 toscaInterfaceOperationImplementation.setPrimary(toscaArtifactDefinition);
488                 toscaOperation.setImplementation(toscaInterfaceOperationImplementation);
489             } else {
490                 if (toscaInterfaceOperationImplementation.getTimeout() != null) {
491                     final ToscaArtifactDefinition toscaArtifactDefinition = new ToscaArtifactDefinition();
492                     toscaArtifactDefinition.setFile(StringUtils.isBlank(operationArtifactPath) || "null".equals(operationArtifactPath) ? null : operationArtifactPath);
493                     toscaInterfaceOperationImplementation.setPrimary(toscaArtifactDefinition);
494                     toscaOperation.setImplementation(toscaInterfaceOperationImplementation);
495                 } else {
496                     toscaOperation.setImplementation(
497                         StringUtils.isBlank(operationArtifactPath) || "null".equals(operationArtifactPath) ? null : operationArtifactPath);
498                 }
499             }
500         }
501     }
502
503     private Map<String, ToscaPropertyAssignment> handleImplementationProperties(final OperationDataDefinition operationDataDefinition,
504                                                                                 final Map<String, DataTypeDefinition> dataTypes) {
505         if (operationDataDefinition.getImplementation() == null) {
506             return new HashMap<>();
507         }
508
509         final List<PropertyDataDefinition> properties = operationDataDefinition.getImplementation().getProperties();
510         if (CollectionUtils.isEmpty(properties)) {
511             return new HashMap<>();
512         }
513
514         final Map<String, ToscaPropertyAssignment> propertiesMap = new HashMap<>();
515         properties.stream()
516             .filter(propertyDataDefinition -> StringUtils.isNotEmpty(propertyDataDefinition.getValue()))
517             .forEach(propertyDataDefinition -> {
518                     final String propertyValue =
519                         propertyDataDefinition.getValue() != null ? propertyDataDefinition.getValue() : propertyDataDefinition.getDefaultValue();
520                     final ToscaPropertyAssignment toscaPropertyAssignment = new ToscaPropertyAssignment();
521                     toscaPropertyAssignment.setValue(propertyConvertor.convertToToscaObject(propertyDataDefinition, propertyValue, dataTypes, false));
522                     propertiesMap.put(propertyDataDefinition.getName(), toscaPropertyAssignment);
523                 }
524             );
525
526         return propertiesMap;
527     }
528
529     public void removeInterfacesWithoutOperations(final Map<String, Object> interfaceMap) {
530         if (MapUtils.isEmpty(interfaceMap)) {
531             return;
532         }
533         final Set<String> emptyInterfaces = interfaceMap.entrySet().stream().filter(entry -> {
534             final Object value = entry.getValue();
535             if (value instanceof ToscaInterfaceDefinition) {
536                 final ToscaInterfaceDefinition interfaceDefinition = (ToscaInterfaceDefinition) value;
537                 return MapUtils.isEmpty(interfaceDefinition.getOperations());
538             } else if (value instanceof Map) {
539                 final Map<String, Object> interfaceDefMap = (Map<String, Object>) value;
540                 return MapUtils.isEmpty(interfaceDefMap);
541             }
542             return false;
543         }).map(Entry::getKey).collect(Collectors.toSet());
544         emptyInterfaces.forEach(interfaceMap::remove);
545     }
546
547     private Map<String, Object> createInterfaceInputMap(final InterfaceDefinition interfaceDefinition,
548                                                         final Map<String, DataTypeDefinition> allDataTypeMap) {
549         final Map<String, InputDataDefinition> inputMap = interfaceDefinition.getInputs();
550         if (MapUtils.isEmpty(inputMap)) {
551             return Collections.emptyMap();
552         }
553         final Map<String, Object> toscaInterfaceInputMap = new HashMap<>();
554         for (final Entry<String, InputDataDefinition> inputEntry : inputMap.entrySet()) {
555             final InputDataDefinition inputDataDefinition = inputEntry.getValue();
556             final ToscaProperty toscaProperty = propertyConvertor
557                 .convertProperty(allDataTypeMap, new PropertyDefinition(inputDataDefinition), PropertyType.INPUT);
558             toscaInterfaceInputMap.put(inputEntry.getKey(), new ToscaInput(toscaProperty));
559         }
560         return toscaInterfaceInputMap;
561     }
562
563     /*
564      * workaround for : currently "defaultp" is not being converted to "default" by the relevant code in
565      * ToscaExportHandler so, any string Map key named "defaultp" will have its named changed to "default"
566      * @param operationsMap the map to update
567      */
568     private void handleDefaults(Map<String, Object> operationsMap) {
569         for (Map.Entry<String, Object> operationEntry : operationsMap.entrySet()) {
570             final Object value = operationEntry.getValue();
571             if (value instanceof Map) {
572                 handleDefaults((Map<String, Object>) value);
573             }
574             final String key = operationEntry.getKey();
575             if (key.equals(DEFAULTP)) {
576                 Object removed = operationsMap.remove(key);
577                 operationsMap.put(ToscaTagNamesEnum.DEFAULT.getElementName(), removed);
578             }
579         }
580     }
581
582     private void fillToscaOperationInputs(OperationDataDefinition operation, Map<String, DataTypeDefinition> dataTypes,
583                                           ToscaLifecycleOperationDefinition toscaOperation) {
584         if (Objects.isNull(operation.getInputs()) || operation.getInputs().isEmpty()) {
585             toscaOperation.setInputs(null);
586             return;
587         }
588         Map<String, ToscaProperty> toscaInputs = new HashMap<>();
589         for (OperationInputDefinition input : operation.getInputs().getListToscaDataDefinition()) {
590             ToscaProperty toscaInput = new ToscaProperty();
591             toscaInput.setDescription(input.getDescription());
592             toscaInput.setType(input.getType());
593             toscaInput.setRequired(input.isRequired());
594             toscaInput.setDefaultp(propertyConvertor.convertToToscaObject(input, getInputValue(input), dataTypes, false));
595             toscaInputs.put(input.getName(), toscaInput);
596         }
597         toscaOperation.setInputs(toscaInputs);
598     }
599
600 }