Fix default value for interface operation input 48/127848/2
authorandre.schmid <andre.schmid@est.tech>
Wed, 16 Mar 2022 12:26:32 +0000 (12:26 +0000)
committerMichael Morris <michael.morris@est.tech>
Mon, 21 Mar 2022 12:28:43 +0000 (12:28 +0000)
Fixes default value in interface operation input definitions. The value
is now correctly JSON stringfied.
Fixes required value that was always being set to false.
Fixes UI reporting that false values are empty.

Change-Id: I6ce8eba03d659a091e49180f1d2cc057f4a805f2
Issue-ID: SDC-3920
Signed-off-by: andre.schmid <andre.schmid@est.tech>
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceDefinitionHandler.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InterfaceDefinitionHandlerTest.java
catalog-be/src/test/resources/interfaceDefinition/interfaceDefinition-legacy.yaml
catalog-be/src/test/resources/interfaceDefinition/interfaceDefinition-tosca1.3.yaml
catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list-item/input-list-item.component.html

index 5f2637c..af41007 100644 (file)
@@ -29,6 +29,7 @@ import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIRED;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.STATUS;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TYPE;
 
+import com.google.gson.Gson;
 import fj.data.Either;
 import java.util.Arrays;
 import java.util.Collections;
@@ -64,6 +65,7 @@ import org.springframework.stereotype.Component;
 public class InterfaceDefinitionHandler {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceDefinitionHandler.class);
+    private static final String WITH_ATTRIBUTE = "with attribute '{}': '{}'";
     private final InterfaceOperationBusinessLogic interfaceOperationBusinessLogic;
 
     public InterfaceDefinitionHandler(final InterfaceOperationBusinessLogic interfaceOperationBusinessLogic) {
@@ -169,36 +171,52 @@ public class InterfaceDefinitionHandler {
             operationInput.setUniqueId(UUID.randomUUID().toString());
             operationInput.setInputId(operationInput.getUniqueId());
             operationInput.setName(interfaceInput.getKey());
-            if (interfaceInput.getValue() instanceof Map) {
-                final LinkedHashMap<String, Object> inputPropertyValue = (LinkedHashMap<String, Object>) interfaceInput.getValue();
-                LOGGER.info("createModuleInterface: i interfaceInput.getKey() {}, {} , {}  ", interfaceInput.getKey(), inputPropertyValue.keySet(),
-                    inputPropertyValue.values());
-                if (inputPropertyValue.get(TYPE.getElementName()) != null) {
-                    operationInput.setType(inputPropertyValue.get(TYPE.getElementName()).toString());
-                }
-                if (inputPropertyValue.get(DESCRIPTION.getElementName()) != null) {
-                    operationInput.setDescription(inputPropertyValue.get(DESCRIPTION.getElementName()).toString());
-                }
-                if (inputPropertyValue.get(REQUIRED.getElementName()) != null) {
-                    operationInput.setRequired(Boolean.getBoolean(inputPropertyValue.get(REQUIRED.getElementName()).toString()));
-                }
-                if (inputPropertyValue.get(DEFAULT.getElementName()) != null) {
-                    operationInput.setToscaDefaultValue(inputPropertyValue.get(DEFAULT.getElementName()).toString());
-                }
-                if (inputPropertyValue.get(STATUS.getElementName()) != null) {
-                    operationInput.setStatus(inputPropertyValue.get(STATUS.getElementName()).toString());
-                }
-            } else if (interfaceInput.getValue() instanceof String) {
-                final String value = (String) interfaceInput.getValue();
-                operationInput.setDefaultValue(value);
-                operationInput.setToscaDefaultValue(value);
-                operationInput.setValue(value);
-            }
+            handleInputToscaDefinition(interfaceInput.getKey(), interfaceInput.getValue(), operationInput);
             inputs.add(operationInput);
         }
         return inputs;
     }
 
+    private void handleInputToscaDefinition(final String inputName, final Object value, final OperationInputDefinition operationInput) {
+        if (value instanceof Map) {
+            final LinkedHashMap<String, Object> inputPropertyValue = (LinkedHashMap<String, Object>) value;
+            LOGGER.debug("Creating interface operation input '{}'", inputName);
+            if (inputPropertyValue.get(TYPE.getElementName()) != null) {
+                final String type = inputPropertyValue.get(TYPE.getElementName()).toString();
+                LOGGER.debug(WITH_ATTRIBUTE, TYPE.getElementName(), type);
+                operationInput.setType(type);
+            }
+            if (inputPropertyValue.get(DESCRIPTION.getElementName()) != null) {
+                final String description = inputPropertyValue.get(DESCRIPTION.getElementName()).toString();
+                LOGGER.debug(WITH_ATTRIBUTE, DESCRIPTION.getElementName(), description);
+                operationInput.setDescription(description);
+            }
+            if (inputPropertyValue.get(REQUIRED.getElementName()) != null) {
+                final boolean required = Boolean.parseBoolean(inputPropertyValue.get(REQUIRED.getElementName()).toString());
+                LOGGER.debug(WITH_ATTRIBUTE, REQUIRED.getElementName(), required);
+                operationInput.setRequired(required);
+            }
+            if (inputPropertyValue.get(DEFAULT.getElementName()) != null) {
+                final Gson gson = new Gson();
+                final String json = gson.toJson(inputPropertyValue.get(DEFAULT.getElementName()));
+                LOGGER.debug(WITH_ATTRIBUTE, DEFAULT.getElementName(), json);
+                operationInput.setToscaDefaultValue(json);
+            }
+            if (inputPropertyValue.get(STATUS.getElementName()) != null) {
+                final String status = inputPropertyValue.get(STATUS.getElementName()).toString();
+                LOGGER.debug(WITH_ATTRIBUTE, STATUS.getElementName(), status);
+                operationInput.setStatus(status);
+            }
+            return;
+        }
+        if (value instanceof String) {
+            final String stringValue = (String) value;
+            operationInput.setDefaultValue(stringValue);
+            operationInput.setToscaDefaultValue(stringValue);
+            operationInput.setValue(stringValue);
+        }
+    }
+
     private Optional<ArtifactDataDefinition> handleOperationImplementation(final Map<String, Object> operationDefinitionMap) {
         if (!operationDefinitionMap.containsKey(IMPLEMENTATION.getElementName())) {
             return Optional.empty();
index 83fa8e2..0ff1d69 100644 (file)
@@ -25,20 +25,30 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasItems;
 import static org.hamcrest.Matchers.hasSize;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 import static org.mockito.Mockito.when;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DEFAULT;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DESCRIPTION;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIRED;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.STATUS;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TYPE;
 
+import com.google.gson.Gson;
+import fj.data.Either;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
 import java.util.stream.Collectors;
-
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.junit.jupiter.api.BeforeEach;
@@ -54,8 +64,6 @@ import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.yaml.snakeyaml.Yaml;
 
-import fj.data.Either;
-
 @ExtendWith(MockitoExtension.class)
 class InterfaceDefinitionHandlerTest {
 
@@ -124,19 +132,74 @@ class InterfaceDefinitionHandlerTest {
         final OperationDataDefinition deleteOperation = actualInterfaceDefinition.getOperations().get(DELETE_OPERATION);
         assertOperation("'camunda/serviceDeselect'", deleteOperation);
 
-        final Map<String, String> expectedInputMap = new HashMap<>();
-        expectedInputMap.put("action", "org.openecomp.resource.datatypes.Action");
+        final Map<String, Map<String, Object>> startOperationExpectedInputMap = createStartOperationInputMap();
         final OperationDataDefinition startOperation = actualInterfaceDefinition.getOperations().get(START_OPERATION);
-        assertOperation("'camunda/executeAction'", expectedInputMap, startOperation);
+        assertOperation("'camunda/executeAction'", startOperationExpectedInputMap, startOperation);
+        final Map<String, Map<String, Object>> stopOperationExpectedInputMap = createStopOperationInputMap();
         final OperationDataDefinition stopOperation = actualInterfaceDefinition.getOperations().get(STOP_OPERATION);
-        assertOperation("'camunda/executeAction'", expectedInputMap, stopOperation);
+        assertOperation("'camunda/executeAction'", stopOperationExpectedInputMap, stopOperation);
+    }
+
+    private Map<String, Map<String, Object>> createStopOperationInputMap() {
+        final Map<String, Map<String, Object>> stopOperationExpectedInputMap = new HashMap<>();
+        final Map<String, Object> actionInput = Map.of(
+            "type", "org.openecomp.resource.datatypes.Action"
+        );
+        stopOperationExpectedInputMap.put("action", actionInput);
+        return stopOperationExpectedInputMap;
+    }
+
+    private Map<String, Map<String, Object>> createStartOperationInputMap() {
+        final Map<String, Map<String, Object>> startOperationExpectedInputMap = new HashMap<>();
+        final Map<String, Object> actionInput = Map.of(
+            "type", "org.openecomp.resource.datatypes.Action"
+        );
+        startOperationExpectedInputMap.put("action", actionInput);
+        final Map<String, Object> stringInput = Map.of(
+            "type", "string",
+            "default", "this is a string"
+        );
+        startOperationExpectedInputMap.put("stringInput", stringInput);
+        final Map<String, Object> booleanInput = Map.of(
+            "type", "boolean",
+            "default", true
+        );
+        startOperationExpectedInputMap.put("booleanInput", booleanInput);
+        final Map<String, Object> integerInput = Map.of(
+            "type", "integer",
+            "description", "an integer",
+            "status", "supported",
+            "required", true,
+            "default", 11
+        );
+        startOperationExpectedInputMap.put("integerInput", integerInput);
+        final Map<String, Object> floatInput = Map.of(
+            "type", "float",
+            "required", false,
+            "default", 11.1
+        );
+        startOperationExpectedInputMap.put("floatInput", floatInput);
+
+        final LinkedHashMap<String, Object> complexInputDefault = new LinkedHashMap<>();
+        complexInputDefault.put("dsl_stability_profile", "dsl_stability_profile_value");
+        complexInputDefault.put("central_splitter", false);
+        complexInputDefault.put("service_restoration_sla", "service_restoration_sla_value");
+        complexInputDefault.put("battery_backup", true);
+        complexInputDefault.put("partner_priorty_assist", false);
+        final Map<String, Object> complexInput = Map.of(
+            "type", "onap.datatypes.partner.access_details",
+            "status", "experimental",
+            "default", complexInputDefault
+        );
+        startOperationExpectedInputMap.put("complexInput", complexInput);
+        return startOperationExpectedInputMap;
     }
 
     private void assertOperation(final String implementation, final OperationDataDefinition actualOperation) {
         assertOperation(implementation, Collections.emptyMap(), actualOperation);
     }
 
-    private void assertOperation(final String implementation, final Map<String, String> inputNameTypeMap,
+    private void assertOperation(final String implementation, final Map<String, Map<String, Object>> inputNameTypeMap,
                                  final OperationDataDefinition actualOperation) {
         final ArtifactDataDefinition artifactDefinition = actualOperation.getImplementation();
         assertThat("Implementation should be as expected", artifactDefinition.getArtifactName(), equalTo(implementation));
@@ -158,6 +221,38 @@ class InterfaceDefinitionHandlerTest {
 
         assertThat(String.format(msgFormat, "the expected inputs"), inputNames,
             hasItems(inputNameTypeMap.keySet().toArray(new String[0])));
+
+        for (final Entry<String, Map<String, Object>> inputEntry : inputNameTypeMap.entrySet()) {
+            final String expectedInputName = inputEntry.getKey();
+            final Optional<OperationInputDefinition> inputDefinitionOptional = inputList.stream()
+                .filter(operationInputDefinition -> operationInputDefinition.getName().equals(expectedInputName)).findFirst();
+            assertTrue(inputDefinitionOptional.isPresent(), String.format("Input '%s' should be present", expectedInputName));
+            final OperationInputDefinition actualInputDefinition = inputDefinitionOptional.get();
+            final Map<String, Object> expectedInput = inputEntry.getValue();
+
+            assertEquals(expectedInput.get(STATUS.getElementName()), actualInputDefinition.getStatus(),
+                String.format("%s attribute of input %s should be as expected", STATUS.getElementName(), expectedInputName)
+            );
+            assertEquals(expectedInput.get(TYPE.getElementName()), actualInputDefinition.getType(),
+                String.format("%s attribute of input %s should be as expected", TYPE.getElementName(), expectedInputName)
+            );
+            assertEquals(expectedInput.get(DESCRIPTION.getElementName()), actualInputDefinition.getDescription(),
+                String.format("%s attribute of input %s should be as expected", DESCRIPTION.getElementName(), expectedInputName)
+            );
+            final Object expectedRequired =
+                expectedInput.get(REQUIRED.getElementName()) == null ? false : expectedInput.get(REQUIRED.getElementName());
+            assertEquals(expectedRequired, actualInputDefinition.getRequired(),
+                String.format("%s attribute of input %s should be as expected", REQUIRED.getElementName(), expectedInputName)
+            );
+
+            String expectedJson = null;
+            if (expectedInput.get(DEFAULT.getElementName()) != null) {
+                expectedJson = new Gson().toJson(expectedInput.get(DEFAULT.getElementName()));
+            }
+            assertEquals(expectedJson, actualInputDefinition.getToscaDefaultValue(),
+                String.format("%s of input %s should be as expected", DEFAULT.getElementName(), expectedInputName)
+            );
+        }
     }
 
     private void assertInput(final String type, final String description, final Boolean required,
@@ -172,6 +267,6 @@ class InterfaceDefinitionHandlerTest {
     private Map<String, Object> loadYaml(final Path filePathFromResource) throws FileNotFoundException {
         final Path filePath = Paths.get(TEST_RESOURCE_PATH.toString(), filePathFromResource.toString());
         final FileInputStream fileInputStream = new FileInputStream(filePath.toString());
-        return (Map<String, Object>) new Yaml().load(fileInputStream);
+        return new Yaml().load(fileInputStream);
     }
 }
\ No newline at end of file
index d12664b..2c4c1ec 100644 (file)
@@ -15,6 +15,31 @@ start:
   inputs:
     action:
       type: org.openecomp.resource.datatypes.Action
+    stringInput:
+      type: string
+      default: this is a string
+    booleanInput:
+      type: boolean
+      default: true
+    integerInput:
+      type: integer
+      description: an integer
+      status: supported
+      required: true
+      default: 11
+    floatInput:
+      type: float
+      required: false
+      default: 11.1
+    complexInput:
+      type: onap.datatypes.partner.access_details
+      status: experimental
+      default:
+        dsl_stability_profile: dsl_stability_profile_value
+        central_splitter: false
+        service_restoration_sla: service_restoration_sla_value
+        battery_backup: true
+        partner_priorty_assist: false
 stop:
   implementation: "camunda/executeAction"
   inputs:
index 13dfb9a..164280d 100644 (file)
@@ -16,6 +16,31 @@ operations:
     inputs:
       action:
         type: org.openecomp.resource.datatypes.Action
+      stringInput:
+        type: string
+        default: this is a string
+      booleanInput:
+        type: boolean
+        default: true
+      integerInput:
+        type: integer
+        description: an integer
+        status: supported
+        required: true
+        default: 11
+      floatInput:
+        type: float
+        required: false
+        default: 11.1
+      complexInput:
+        type: onap.datatypes.partner.access_details
+        status: experimental
+        default:
+          dsl_stability_profile: dsl_stability_profile_value
+          central_splitter: false
+          service_restoration_sla: service_restoration_sla_value
+          battery_backup: true
+          partner_priorty_assist: false
   stop:
     implementation: "camunda/executeAction"
     inputs:
index 47e50b0..1441a9e 100644 (file)
@@ -30,7 +30,7 @@
     <ul *ngIf="isExpanded">
       <li class="input-value">
         <ng-container *ngIf="isViewOnly">
-          {{valueObjRef}}<em class="empty-value" *ngIf="!valueObjRef">empty</em>
+          {{valueObjRef}}<em class="empty-value" *ngIf="valueObjRef !== false && !valueObjRef">empty</em>
         </ng-container>
         <input *ngIf="!isViewOnly" [type]="getSimpleValueInputType()" name="value"
                [(ngModel)]="valueObjRef"