Fix empty interfaces and operations
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / tosca / InterfacesOperationsConverter.java
index 438ad5b..3650422 100644 (file)
@@ -22,6 +22,7 @@ import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.OPERATIONS;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.google.gson.Gson;
 import java.util.Collections;
 import java.util.HashMap;
@@ -32,10 +33,14 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.commons.collections.MapUtils;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.InputDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.ComponentInstance;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
@@ -43,12 +48,16 @@ import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.Product;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
+import org.openecomp.sdc.be.tosca.model.ToscaArtifactDefinition;
 import org.openecomp.sdc.be.tosca.model.ToscaInput;
 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition;
 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceNodeType;
+import org.openecomp.sdc.be.tosca.model.ToscaInterfaceOperationImplementation;
 import org.openecomp.sdc.be.tosca.model.ToscaLifecycleOperationDefinition;
 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
+import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
+import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignmentJsonSerializer;
 import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
@@ -78,7 +87,7 @@ public class InterfacesOperationsConverter {
      * @param component to work on
      * @return the added element
      */
-    public static Map<String, Object> addInterfaceTypeElement(Component component, List<String> allInterfaceTypes) {
+    public Map<String, Object> addInterfaceTypeElement(Component component, List<String> allInterfaceTypes) {
         if (component instanceof Product) {
             return null;
         }
@@ -143,17 +152,14 @@ public class InterfacesOperationsConverter {
         return toscaResourceName.substring(toscaResourceName.lastIndexOf(DOT) + 1);
     }
 
-    private static boolean isArtifactPresent(Map.Entry<String, OperationDataDefinition> operationEntry) {
-        final boolean isImplementationPresent = !Objects.isNull(operationEntry.getValue().getImplementation());
-        if (isImplementationPresent) {
-            return !Objects.isNull(operationEntry.getValue().getImplementation().getArtifactName());
-        }
-        return false;
+    private boolean isArtifactPresent(final OperationDataDefinition operationDataDefinition) {
+        return operationDataDefinition.getImplementation() != null
+            && StringUtils.isNotEmpty(operationDataDefinition.getImplementation().getArtifactName());
     }
 
-    private static String getInputValue(String inputValue) {
-        String toscaInputValue = inputValue;
-        if (Objects.nonNull(inputValue) && inputValue.contains(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName())) {
+    private static String getInputValue(final OperationInputDefinition input) {
+        String inputValue = input.getValue() == null ? input.getToscaDefaultValue() : input.getValue();
+        if (inputValue != null && inputValue.contains(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName())) {
             Gson gson = new Gson();
             Map<String, List<String>> consumptionValue = gson.fromJson(inputValue, Map.class);
             List<String> mappedOutputValue = consumptionValue.get(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName());
@@ -162,9 +168,9 @@ public class InterfacesOperationsConverter {
             String interfaceName = interfaceType.substring(interfaceType.lastIndexOf('.') + 1);
             mappedOutputValue.remove(1);
             mappedOutputValue.add(1, interfaceName);
-            toscaInputValue = gson.toJson(consumptionValue);
+            inputValue = gson.toJson(consumptionValue);
         }
-        return toscaInputValue;
+        return inputValue;
     }
 
     private static String getInterfaceType(Component component, String interfaceType) {
@@ -174,13 +180,22 @@ public class InterfacesOperationsConverter {
         return interfaceType;
     }
 
-    private static Map<String, Object> getObjectAsMap(Object obj) {
-        ObjectMapper objectMapper = new ObjectMapper();
-        if (obj instanceof ToscaInterfaceDefinition) {
-            //Prevent empty field serialization in interface definition
-            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+    private static Map<String, Object> getObjectAsMap(final Object obj) {
+        final Map<String, Object> objectAsMap;
+        if (obj instanceof Map) {
+            objectAsMap = (Map<String, Object>) obj;
+        } else {
+            final ObjectMapper objectMapper = new ObjectMapper();
+            final SimpleModule module = new SimpleModule("ToscaPropertyAssignmentSerializer");
+            module.addSerializer(ToscaPropertyAssignment.class, new ToscaPropertyAssignmentJsonSerializer());
+            objectMapper.registerModule(module);
+            if (obj instanceof ToscaInterfaceDefinition) {
+                //Prevent empty field serialization in interface definition
+                objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+            }
+            objectAsMap = objectMapper.convertValue(obj, Map.class);
         }
-        Map<String, Object> objectAsMap = obj instanceof Map ? (Map<String, Object>) obj : objectMapper.convertValue(obj, Map.class);
+
         final String defaultEntry = DEFAULT.getElementName();
         if (objectAsMap.containsKey(defaultEntry)) {
             objectAsMap.put(DEFAULT_HAS_UNDERSCORE, objectAsMap.remove(defaultEntry));
@@ -210,18 +225,18 @@ public class InterfacesOperationsConverter {
     }
 
     private Map<String, Object> getInterfacesMap(Component component, Map<String, DataTypeDefinition> dataTypes, boolean isAssociatedComponent) {
-        return getInterfacesMap(component, null, component.getInterfaces(), dataTypes, isAssociatedComponent, false);
+        return getInterfacesMap(component, null, component.getInterfaces(), dataTypes, isAssociatedComponent);
     }
 
     public Map<String, Object> getInterfacesMap(final Component component, final ComponentInstance componentInstance,
                                                 final Map<String, InterfaceDefinition> interfaces, final Map<String, DataTypeDefinition> dataTypes,
-                                                final boolean isAssociatedComponent, final boolean isServiceProxyInterface) {
+                                                final boolean isAssociatedComponent) {
         if (MapUtils.isEmpty(interfaces)) {
             return null;
         }
         final Map<String, Object> toscaInterfaceDefinitions = new HashMap<>();
         for (InterfaceDefinition interfaceDefinition : interfaces.values()) {
-            handleInterfaceOperations(component, componentInstance, dataTypes, isAssociatedComponent, isServiceProxyInterface,
+            handleInterfaceOperations(component, componentInstance, dataTypes, isAssociatedComponent,
                 toscaInterfaceDefinitions, interfaceDefinition);
         }
         return toscaInterfaceDefinitions;
@@ -229,13 +244,13 @@ public class InterfacesOperationsConverter {
 
     public Map<String, Object> getInterfacesMapFromComponentInstance(final Component component, final ComponentInstance componentInstance,
                                                                      final Map<String, DataTypeDefinition> dataTypes,
-                                                                     final boolean isAssociatedComponent, final boolean isServiceProxyInterface) {
+                                                                     final boolean isAssociatedComponent) {
         final Map<String, Object> toscaInterfaceDefinitions = new HashMap<>();
         final ObjectMapper objectMapper = new ObjectMapper();
         objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
         for (final Map.Entry<String, Object> interfaceEntry : componentInstance.getInterfaces().entrySet()) {
             final InterfaceDefinition interfaceDefinition = objectMapper.convertValue(interfaceEntry.getValue(), InterfaceDefinition.class);
-            handleInterfaceOperations(component, componentInstance, dataTypes, isAssociatedComponent, isServiceProxyInterface,
+            handleInterfaceOperations(component, componentInstance, dataTypes, isAssociatedComponent,
                 toscaInterfaceDefinitions, interfaceDefinition);
         }
         return toscaInterfaceDefinitions;
@@ -243,7 +258,7 @@ public class InterfacesOperationsConverter {
 
     private void handleInterfaceOperations(final Component component, final ComponentInstance componentInstance,
                                            final Map<String, DataTypeDefinition> dataTypes, final boolean isAssociatedComponent,
-                                           final boolean isServiceProxyInterface, final Map<String, Object> toscaInterfaceDefinitions,
+                                           final Map<String, Object> toscaInterfaceDefinitions,
                                            final InterfaceDefinition interfaceDefinition) {
         final String interfaceType;
         if (componentInstance != null && LOCAL_INTERFACE_TYPE.equals(interfaceDefinition.getType())) {
@@ -258,16 +273,20 @@ public class InterfacesOperationsConverter {
         final Map<String, OperationDataDefinition> operations = interfaceDefinition.getOperations();
         final Map<String, Object> toscaOperationMap = new HashMap<>();
         for (final Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
-            final ToscaLifecycleOperationDefinition toscaLifecycleOperationDefinition = new ToscaLifecycleOperationDefinition();
-            handleInterfaceOperationImplementation(component, componentInstance, isAssociatedComponent, operationEntry,
-                toscaLifecycleOperationDefinition);
-            toscaLifecycleOperationDefinition.setDescription(operationEntry.getValue().getDescription());
-            fillToscaOperationInputs(operationEntry.getValue(), dataTypes, toscaLifecycleOperationDefinition, isServiceProxyInterface);
-            toscaOperationMap.put(operationEntry.getValue().getName(), toscaLifecycleOperationDefinition);
+            if (operationHasAnImplementation(operationEntry.getValue())) {
+                final ToscaLifecycleOperationDefinition toscaLifecycleOperationDefinition = new ToscaLifecycleOperationDefinition();
+                handleInterfaceOperationImplementation(component, componentInstance, isAssociatedComponent, operationEntry.getValue(),
+                    toscaLifecycleOperationDefinition, dataTypes);
+                if (StringUtils.isNotEmpty(operationEntry.getValue().getDescription())) {
+                    toscaLifecycleOperationDefinition.setDescription(operationEntry.getValue().getDescription());
+                }
+                fillToscaOperationInputs(operationEntry.getValue(), dataTypes, toscaLifecycleOperationDefinition);
+                toscaOperationMap.put(operationEntry.getValue().getName(), toscaLifecycleOperationDefinition);
+            }
         }
         toscaInterfaceDefinition.setOperations(toscaOperationMap);
         final Map<String, Object> interfaceInputMap = createInterfaceInputMap(interfaceDefinition, dataTypes);
-        if (!interfaceInputMap.isEmpty()) {
+        if (MapUtils.isNotEmpty(interfaceInputMap)) {
             toscaInterfaceDefinition.setInputs(interfaceInputMap);
         }
         final Map<String, Object> interfaceDefinitionAsMap = getObjectAsMap(toscaInterfaceDefinition);
@@ -279,19 +298,68 @@ public class InterfacesOperationsConverter {
         interfaceDefinitionAsMap.putAll(operationsMap);
         toscaInterfaceDefinitions.put(getLastPartOfName(interfaceType), interfaceDefinitionAsMap);
     }
+    
+    private boolean operationHasAnImplementation(OperationDataDefinition operation) {
+        return operation.getImplementation() != null && StringUtils.isNotEmpty(operation.getImplementation().getArtifactName()) && !operation.getImplementation().getArtifactName().equals("''");
+    }
 
     private void handleInterfaceOperationImplementation(final Component component, final ComponentInstance componentInstance,
                                                         final boolean isAssociatedComponent,
-                                                        final Entry<String, OperationDataDefinition> operationEntry,
-                                                        final ToscaLifecycleOperationDefinition toscaOperation) {
-        final String operationArtifactPath;
-        if (isArtifactPresent(operationEntry) && StringUtils.isNotEmpty(operationEntry.getValue().getImplementation().getArtifactName())) {
-            operationArtifactPath = OperationArtifactUtil
-                .createOperationArtifactPath(component, componentInstance, operationEntry.getValue(), isAssociatedComponent);
-            toscaOperation.setImplementation(operationArtifactPath);
-        } else {
-            toscaOperation.setImplementation(operationEntry.getValue().getImplementation().getArtifactName());
+                                                        final OperationDataDefinition operationDataDefinition,
+                                                        final ToscaLifecycleOperationDefinition toscaOperation,
+                                                        final Map<String, DataTypeDefinition> dataTypes) {
+        final ArtifactDataDefinition implementation = operationDataDefinition.getImplementation();
+        if (implementation == null) {
+            return;
         }
+
+        if (isArtifactPresent(operationDataDefinition)) {
+            final String operationArtifactPath =
+                OperationArtifactUtil.createOperationArtifactPath(component, componentInstance, operationDataDefinition, isAssociatedComponent);
+            if (implementation.getArtifactType() != null) {
+                final ToscaArtifactDefinition toscaArtifactDefinition = new ToscaArtifactDefinition();
+                toscaArtifactDefinition.setFile(operationArtifactPath);
+                final String artifactVersion = implementation.getArtifactVersion();
+                toscaArtifactDefinition.setArtifact_version(!artifactVersion.equals(NumberUtils.INTEGER_ZERO.toString()) ? artifactVersion : null);
+                toscaArtifactDefinition.setType(implementation.getArtifactType());
+                final Map<String, ToscaPropertyAssignment> propertiesMap = handleImplementationProperties(operationDataDefinition, dataTypes);
+                if (MapUtils.isNotEmpty(propertiesMap)) {
+                    toscaArtifactDefinition.setProperties(propertiesMap);
+                }
+                final ToscaInterfaceOperationImplementation toscaInterfaceOperationImplementation = new ToscaInterfaceOperationImplementation();
+                toscaInterfaceOperationImplementation.setPrimary(toscaArtifactDefinition);
+                toscaOperation.setImplementation(toscaInterfaceOperationImplementation);
+            } else {
+                toscaOperation.setImplementation(
+                    StringUtils.isBlank(operationArtifactPath) || "null".equals(operationArtifactPath) ? null : operationArtifactPath);
+            }
+        }
+    }
+
+    private Map<String, ToscaPropertyAssignment> handleImplementationProperties(final OperationDataDefinition operationDataDefinition,
+                                                                                final Map<String, DataTypeDefinition> dataTypes) {
+        if (operationDataDefinition.getImplementation() == null) {
+            return new HashMap<>();
+        }
+
+        final List<PropertyDataDefinition> properties = operationDataDefinition.getImplementation().getProperties();
+        if (CollectionUtils.isEmpty(properties)) {
+            return new HashMap<>();
+        }
+
+        final Map<String, ToscaPropertyAssignment> propertiesMap = new HashMap<>();
+        properties.stream()
+            .filter(propertyDataDefinition -> StringUtils.isNotEmpty(propertyDataDefinition.getValue()))
+            .forEach(propertyDataDefinition -> {
+                    final String propertyValue =
+                        propertyDataDefinition.getValue() != null ? propertyDataDefinition.getValue() : propertyDataDefinition.getDefaultValue();
+                    final ToscaPropertyAssignment toscaPropertyAssignment = new ToscaPropertyAssignment();
+                    toscaPropertyAssignment.setValue(propertyConvertor.convertToToscaObject(propertyDataDefinition, propertyValue, dataTypes, false));
+                    propertiesMap.put(propertyDataDefinition.getName(), toscaPropertyAssignment);
+                }
+            );
+
+        return propertiesMap;
     }
 
     public void removeInterfacesWithoutOperations(final Map<String, Object> interfaceMap) {
@@ -348,7 +416,7 @@ public class InterfacesOperationsConverter {
     }
 
     private void fillToscaOperationInputs(OperationDataDefinition operation, Map<String, DataTypeDefinition> dataTypes,
-                                          ToscaLifecycleOperationDefinition toscaOperation, boolean isServiceProxyInterface) {
+                                          ToscaLifecycleOperationDefinition toscaOperation) {
         if (Objects.isNull(operation.getInputs()) || operation.getInputs().isEmpty()) {
             toscaOperation.setInputs(null);
             return;
@@ -359,14 +427,10 @@ public class InterfacesOperationsConverter {
             toscaInput.setDescription(input.getDescription());
             toscaInput.setType(input.getType());
             toscaInput.setRequired(input.isRequired());
-            if (isServiceProxyInterface) {
-                String inputValue = Objects.nonNull(input.getValue()) ? getInputValue(input.getValue()) : getInputValue(input.getToscaDefaultValue());
-                toscaInput.setDefaultp(propertyConvertor.convertToToscaObject(input, inputValue, dataTypes, false));
-            } else {
-                toscaInput.setDefaultp(propertyConvertor.convertToToscaObject(input, getInputValue(input.getToscaDefaultValue()), dataTypes, false));
-            }
+            toscaInput.setDefaultp(propertyConvertor.convertToToscaObject(input, getInputValue(input), dataTypes, false));
             toscaInputs.put(input.getName(), toscaInput);
         }
         toscaOperation.setInputs(toscaInputs);
     }
+
 }