Fix formatting error for operation input of complex type 38/134738/5
authorJvD_Ericsson <jeff.van.dam@est.tech>
Tue, 30 May 2023 13:57:47 +0000 (14:57 +0100)
committerJEFF VAN DAM <jeff.van.dam@est.tech>
Thu, 1 Jun 2023 14:10:01 +0000 (14:10 +0000)
Issue-ID: SDC-4523
Signed-off-by: JvD_Ericsson <jeff.van.dam@est.tech>
Change-Id: I3dff94cee1d1dbcb26099d02505a679249a6b46e

catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverterTest.java
catalog-ui/src/app/models/interfaceOperation.ts
catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list-item/input-list-item.component.html
catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list-item/input-list-item.component.ts
catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.html
catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.spec.ts
catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts
catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.ts

index bdb659b..b90e3bb 100644 (file)
@@ -1288,12 +1288,23 @@ public class YamlTemplateParsingHandler {
         final OperationInputDefinition operationInput
     ) {
         if (value instanceof Map) {
+            final Map<String, Object> valueMap = (Map<String, Object>) value;
             log.debug("Creating interface operation input '{}'", inputName);
             Type type = new TypeToken<LinkedHashMap<String, Object>>() {
             }.getType();
             String stringValue = gson.toJson(value, type);
             if (toscaFunctionYamlParsingHandler.isPropertyValueToscaFunction(value)) {
                 toscaFunctionYamlParsingHandler.buildToscaFunctionBasedOnPropertyValue((Map<String, Object>) value).ifPresent(operationInput::setToscaFunction);
+            } else {
+                final Collection<SubPropertyToscaFunction> subPropertyToscaFunctions = buildSubPropertyToscaFunctions(valueMap, new ArrayList<>());
+                if (CollectionUtils.isNotEmpty(subPropertyToscaFunctions)) {
+                    Collection<SubPropertyToscaFunction> existingSubPropertyToscaFunctions = operationInput.getSubPropertyToscaFunctions();
+                    if (existingSubPropertyToscaFunctions == null) {
+                        operationInput.setSubPropertyToscaFunctions(subPropertyToscaFunctions);
+                    } else {
+                        operationInput.getSubPropertyToscaFunctions().addAll(subPropertyToscaFunctions);
+                    }
+                }
             }
             operationInput.setValue(stringValue);
         }
index 8f5f271..e56472a 100644 (file)
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.openecomp.sdc.be.tosca;
 
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DEFAULT;
@@ -20,28 +21,35 @@ import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.INPUTS;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.OPERATIONS;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
 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.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Optional;
 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.json.JSONObject;
+import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
 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.datatypes.elements.ToscaGetFunctionDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
+import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.ComponentInstance;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
@@ -82,42 +90,6 @@ public class InterfacesOperationsConverter {
         this.propertyConvertor = propertyConvertor;
     }
 
-    /**
-     * Creates the interface_types element.
-     *
-     * @param component to work on
-     * @return the added element
-     */
-    public Map<String, Object> addInterfaceTypeElement(Component component, List<String> allInterfaceTypes) {
-        if (component instanceof Product) {
-            return null;
-        }
-        final Map<String, InterfaceDefinition> interfaces = component.getInterfaces();
-        if (MapUtils.isEmpty(interfaces)) {
-            return null;
-        }
-        Map<String, Object> toscaInterfaceTypes = new HashMap<>();
-        for (InterfaceDefinition interfaceDefinition : interfaces.values()) {
-            boolean isInterfaceTypeExistInGlobalType = allInterfaceTypes.stream()
-                .anyMatch(type -> type.equalsIgnoreCase(interfaceDefinition.getType()));
-            if (!isInterfaceTypeExistInGlobalType) {
-                ToscaInterfaceNodeType toscaInterfaceType = new ToscaInterfaceNodeType();
-                toscaInterfaceType.setDerived_from(DERIVED_FROM_STANDARD_INTERFACE);
-                final Map<String, OperationDataDefinition> operations = interfaceDefinition.getOperations();
-                Map<String, Object> toscaOperations = new HashMap<>();
-                for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
-                    toscaOperations.put(operationEntry.getValue().getName(), null);
-                }
-                toscaInterfaceType.setOperations(toscaOperations);
-                Map<String, Object> interfacesAsMap = getObjectAsMap(toscaInterfaceType);
-                Map<String, Object> operationsMap = (Map<String, Object>) interfacesAsMap.remove(OPERATIONS.getElementName());
-                interfacesAsMap.putAll(operationsMap);
-                toscaInterfaceTypes.put(getInterfaceType(component, LOCAL_INTERFACE_TYPE), interfacesAsMap);
-            }
-        }
-        return MapUtils.isNotEmpty(toscaInterfaceTypes) ? toscaInterfaceTypes : null;
-    }
-
     private static Object getDefaultValue(Map<String, Object> inputValueMap) {
         Object defaultValue = null;
         for (Map.Entry<String, Object> operationEntry : inputValueMap.entrySet()) {
@@ -153,11 +125,6 @@ public class InterfacesOperationsConverter {
         return toscaResourceName.substring(toscaResourceName.lastIndexOf(DOT) + 1);
     }
 
-    private boolean isArtifactPresent(final OperationDataDefinition operationDataDefinition) {
-        return operationDataDefinition.getImplementation() != null
-            && StringUtils.isNotEmpty(operationDataDefinition.getImplementation().getArtifactName());
-    }
-
     private static String getInputValue(final OperationInputDefinition input) {
         if (null != input.getToscaFunction()) {
             return input.getToscaFunction().getJsonObjectValue().toString();
@@ -173,10 +140,42 @@ public class InterfacesOperationsConverter {
             mappedOutputValue.remove(1);
             mappedOutputValue.add(1, interfaceName);
             inputValue = gson.toJson(consumptionValue);
+        } else {
+            String finalInputValue = inputValue;
+            if (inputValue != null &&
+                Arrays.stream(ToscaFunctionType.values()).anyMatch(toscaType -> finalInputValue.contains(toscaType.getName().toUpperCase()))) {
+                inputValue = getInputValuesAsToscaFunction(inputValue);
+            }
         }
         return inputValue;
     }
 
+    private static String getInputValuesAsToscaFunction(String inputValue) {
+        Gson gson = new Gson();
+        Map<String, Object> mapOfValues = gson.fromJson(inputValue, Map.class);
+        for (Entry<String, Object> entry : mapOfValues.entrySet()) {
+            Object value = entry.getValue();
+            if (value instanceof Map) {
+                Map<String, Object> valueMap = (Map<String, Object>) value;
+                if (valueMap.containsKey("type")) {
+                    String type = (String) valueMap.get("type");
+                    Optional<ToscaFunctionType> toscaType = ToscaFunctionType.findType(type);
+                    if (toscaType.isPresent()) {
+                        ObjectMapper mapper = new ObjectMapper();
+                        try {
+                            String json = gson.toJson(value);
+                            ToscaFunction toscaFunction = mapper.readValue(json, ToscaFunction.class);
+                            entry.setValue(toscaFunction.getJsonObjectValue());
+                        } catch (JsonProcessingException e) {
+                            throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
+                        }
+                    }
+                }
+            }
+        }
+        return String.valueOf(new JSONObject(mapOfValues));
+    }
+
     private static String getInterfaceType(Component component, String interfaceType) {
         if (LOCAL_INTERFACE_TYPE.equals(interfaceType)) {
             return DERIVED_FROM_BASE_DEFAULT + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
@@ -207,6 +206,47 @@ public class InterfacesOperationsConverter {
         return objectAsMap;
     }
 
+    /**
+     * Creates the interface_types element.
+     *
+     * @param component to work on
+     * @return the added element
+     */
+    public Map<String, Object> addInterfaceTypeElement(Component component, List<String> allInterfaceTypes) {
+        if (component instanceof Product) {
+            return null;
+        }
+        final Map<String, InterfaceDefinition> interfaces = component.getInterfaces();
+        if (MapUtils.isEmpty(interfaces)) {
+            return null;
+        }
+        Map<String, Object> toscaInterfaceTypes = new HashMap<>();
+        for (InterfaceDefinition interfaceDefinition : interfaces.values()) {
+            boolean isInterfaceTypeExistInGlobalType = allInterfaceTypes.stream()
+                .anyMatch(type -> type.equalsIgnoreCase(interfaceDefinition.getType()));
+            if (!isInterfaceTypeExistInGlobalType) {
+                ToscaInterfaceNodeType toscaInterfaceType = new ToscaInterfaceNodeType();
+                toscaInterfaceType.setDerived_from(DERIVED_FROM_STANDARD_INTERFACE);
+                final Map<String, OperationDataDefinition> operations = interfaceDefinition.getOperations();
+                Map<String, Object> toscaOperations = new HashMap<>();
+                for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
+                    toscaOperations.put(operationEntry.getValue().getName(), null);
+                }
+                toscaInterfaceType.setOperations(toscaOperations);
+                Map<String, Object> interfacesAsMap = getObjectAsMap(toscaInterfaceType);
+                Map<String, Object> operationsMap = (Map<String, Object>) interfacesAsMap.remove(OPERATIONS.getElementName());
+                interfacesAsMap.putAll(operationsMap);
+                toscaInterfaceTypes.put(getInterfaceType(component, LOCAL_INTERFACE_TYPE), interfacesAsMap);
+            }
+        }
+        return MapUtils.isNotEmpty(toscaInterfaceTypes) ? toscaInterfaceTypes : null;
+    }
+
+    private boolean isArtifactPresent(final OperationDataDefinition operationDataDefinition) {
+        return operationDataDefinition.getImplementation() != null
+            && StringUtils.isNotEmpty(operationDataDefinition.getImplementation().getArtifactName());
+    }
+
     /**
      * Adds the 'interfaces' element to the node type provided.
      *
@@ -302,9 +342,10 @@ 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("''");
+        return operation.getImplementation() != null && StringUtils.isNotEmpty(operation.getImplementation().getArtifactName()) &&
+            !operation.getImplementation().getArtifactName().equals("''");
     }
 
     private void handleInterfaceOperationImplementation(final Component component, final ComponentInstance componentInstance,
index b347056..5158ae7 100644 (file)
 
 package org.openecomp.sdc.be.tosca;
 
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.Matchers.equalTo;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
 import static org.openecomp.sdc.be.tosca.InterfacesOperationsConverter.SELF;
-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.INPUTS;
-import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.INTERFACES;
-import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE_TYPES;
-import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIRED;
-import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TYPE;
 
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.gson.Gson;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Objects;
-import java.util.function.Function;
-import java.util.stream.Collectors;
 import org.apache.commons.collections4.MapUtils;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.onap.sdc.tosca.services.YamlUtil;
 import org.openecomp.sdc.be.DummyConfigurationManager;
 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.InputDataDefinition;
@@ -68,15 +54,14 @@ import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.Resource;
 import org.openecomp.sdc.be.model.Service;
 import org.openecomp.sdc.be.model.ServiceMetadataDefinition;
 import org.openecomp.sdc.be.model.tosca.ToscaType;
 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition;
 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
-import org.openecomp.sdc.common.util.YamlToObjectConverter;
 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
-import org.yaml.snakeyaml.Yaml;
 
 class InterfacesOperationsConverterTest {
 
@@ -84,10 +69,9 @@ class InterfacesOperationsConverterTest {
     private static final String INPUT_NAME_PREFIX = "input_";
     private static final String OUTPUT_NAME_PREFIX = "output_";
     private static final String NODE_TYPE_NAME = "test";
-    private final String[] inputTypes = {"string", "integer", "float", "boolean"};
-    private static ObjectMapper mapper;
     private static final Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
-
+    private static ObjectMapper mapper;
+    private final String[] inputTypes = {"string", "integer", "float", "boolean"};
     private InterfacesOperationsConverter interfacesOperationsConverter;
 
     @BeforeAll
@@ -112,7 +96,7 @@ class InterfacesOperationsConverterTest {
         component.getComponentMetadataDefinition().getMetadataDataDefinition().setSystemName("NodeTypeName");
         InterfaceDefinition addedInterface = new InterfaceDefinition();
         addedInterface.setType("Local");
-        addOperationsToInterface(component, addedInterface, 5, 3, true, false);
+        addOperationsToInterface(component, addedInterface, 5, 3, true, false, false);
         final String interfaceType = "normalizedComponentName-interface";
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
@@ -135,7 +119,7 @@ class InterfacesOperationsConverterTest {
         component.getComponentMetadataDefinition().getMetadataDataDefinition().setSystemName("NodeTypeName");
         InterfaceDefinition addedInterface = new InterfaceDefinition();
         addedInterface.setType("Local");
-        addOperationsToInterface(component, addedInterface, 5, 3, true, false);
+        addOperationsToInterface(component, addedInterface, 5, 3, true, false, false);
         final String interfaceType = "normalizedServiceComponentName-interface";
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
@@ -156,7 +140,7 @@ class InterfacesOperationsConverterTest {
         InterfaceDefinition addedInterface = new InterfaceDefinition();
         addedInterface.setType("com.some.resource.or.other.resourceName");
 
-        addOperationsToInterface(component, addedInterface, 3, 2, true, false);
+        addOperationsToInterface(component, addedInterface, 3, 2, true, false, false);
         final String interfaceType = "normalizedComponentName-interface";
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
@@ -179,7 +163,7 @@ class InterfacesOperationsConverterTest {
         component.setNormalizedName("normalizedServiceComponentName");
         InterfaceDefinition addedInterface = new InterfaceDefinition();
         addedInterface.setType("com.some.service.or.other.serviceName");
-        addOperationsToInterface(component, addedInterface, 3, 2, true, false);
+        addOperationsToInterface(component, addedInterface, 3, 2, true, false, false);
         final String interfaceType = "normalizedServiceComponentName-interface";
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
@@ -196,7 +180,6 @@ class InterfacesOperationsConverterTest {
 
     }
 
-
     @Test
     void testGetInterfaceAsMapServiceProxy() {
         Component component = new Resource();
@@ -204,7 +187,7 @@ class InterfacesOperationsConverterTest {
         InterfaceDefinition addedInterface = new InterfaceDefinition();
         addedInterface.setToscaResourceName("com.some.resource.or.other.resourceName");
         addedInterface.setType("com.some.resource.or.other.resourceName");
-        addOperationsToInterface(component, addedInterface, 3, 2, true, false);
+        addOperationsToInterface(component, addedInterface, 3, 2, true, false, false);
         final String interfaceType = "normalizedComponentName-interface";
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
@@ -225,7 +208,7 @@ class InterfacesOperationsConverterTest {
         component.setNormalizedName("normalizedComponentName");
         InterfaceDefinition addedInterface = new InterfaceDefinition();
         addedInterface.setType("com.some.resource.or.other.resourceNameNoInputs");
-        addOperationsToInterface(component, addedInterface, 3, 3, false, false);
+        addOperationsToInterface(component, addedInterface, 3, 3, false, false, false);
         final String interfaceType = "normalizedComponentName-interface";
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
@@ -249,7 +232,7 @@ class InterfacesOperationsConverterTest {
         component.setNormalizedName("normalizedComponentName");
         InterfaceDefinition addedInterface = new InterfaceDefinition();
         addedInterface.setType(addedInterfaceType);
-        addOperationsToInterface(component, addedInterface, 2, 2, true, true);
+        addOperationsToInterface(component, addedInterface, 2, 2, true, true, false);
         addedInterface.getOperationsMap().values().stream()
             .filter(operationInputDefinition -> operationInputDefinition.getName().equalsIgnoreCase(
                 "name_for_op_0"))
@@ -280,7 +263,7 @@ class InterfacesOperationsConverterTest {
         InterfaceDefinition addedInterface = new InterfaceDefinition();
         addedInterface.setType(addedInterfaceType);
         addedInterface.setToscaResourceName("com.some.resource.or.other.resourceName");
-        addOperationsToInterface(component, addedInterface, 2, 2, true, true);
+        addOperationsToInterface(component, addedInterface, 2, 2, true, true, false);
         addedInterface.getOperationsMap().values().stream()
             .filter(operationInputDefinition -> operationInputDefinition.getName().equalsIgnoreCase(
                 "name_for_op_0"))
@@ -293,7 +276,7 @@ class InterfacesOperationsConverterTest {
         InterfaceDefinition secondInterface = new InterfaceDefinition();
         secondInterface.setType(secondInterfaceType);
         secondInterface.setToscaResourceName("com.some.resource.or.other.resourceName");
-        addOperationsToInterface(component, secondInterface, 2, 2, true, true);
+        addOperationsToInterface(component, secondInterface, 2, 2, true, true, false);
         secondInterface.getOperationsMap().values().stream()
             .filter(operationInputDefinition -> operationInputDefinition.getName().equalsIgnoreCase(
                 "name_for_op_0"))
@@ -408,65 +391,8 @@ class InterfacesOperationsConverterTest {
         assertTrue(expectedListOfStringPropValue.contains("value3"));
     }
 
-
-    private void validateInterfaceInputs(final String yaml, final String interfaceName, final Map<String, InputDataDefinition> expectedInputMap) {
-        String fixedMainYaml = yaml;
-        final String nullString = "null";
-        if (fixedMainYaml.startsWith(nullString)) {
-            fixedMainYaml = yaml.substring(nullString.length());
-        }
-        if (fixedMainYaml.endsWith(nullString)) {
-            fixedMainYaml = fixedMainYaml.substring(0, fixedMainYaml.length() - nullString.length());
-        }
-        final Map<String, Object> yamlMap = new Yaml().load(fixedMainYaml);
-        final Map<String, Object> nodeTypesMap = (Map<String, Object>) yamlMap.get(NODE_TYPES.getElementName());
-        final Map<String, Object> node = (Map<String, Object>) nodeTypesMap.get(NODE_TYPE_NAME);
-        final Map<String, Object> interfacesMap = (Map<String, Object>) node.get(INTERFACES.getElementName());
-        final Map<String, Object> interface1 = (Map<String, Object>) interfacesMap.get(interfaceName);
-        final Map<String, Object> actualInputsMap = (Map<String, Object>) interface1.get(INPUTS.getElementName());
-        assertThat(actualInputsMap.keySet(), containsInAnyOrder(expectedInputMap.keySet().toArray()));
-        expectedInputMap.forEach((inputName, inputDataDefinition) -> {
-            final Map<String, Object> actualInput = (Map<String, Object>) actualInputsMap.get(inputName);
-            compareInputYaml(inputName, actualInput, inputDataDefinition);
-        });
-    }
-
-    private void compareInputYaml(final String inputName, final Map<String, Object> actualInput,
-                                  final InputDataDefinition expectedInput) {
-        final String msgFormat = "%s should be equal in input %s";
-        String field = TYPE.getElementName();
-        assertThat(String.format(msgFormat, field, inputName),
-            actualInput.get(field), equalTo(expectedInput.getType()));
-        field = DESCRIPTION.getElementName();
-        assertThat(String.format(msgFormat, field, inputName),
-            actualInput.get(field), equalTo(expectedInput.getDescription()));
-        field = REQUIRED.getElementName();
-        assertThat(String.format(msgFormat, field, inputName),
-            actualInput.get(field), equalTo(expectedInput.getRequired()));
-        field = DEFAULT.getElementName();
-        assertThat(String.format(msgFormat, field, inputName),
-            actualInput.get(field), equalTo(expectedInput.getDefaultValue()));
-    }
-
-    @FunctionalInterface
-    interface MainYamlAssertion extends Function<String, Boolean> {
-
-    }
-
-    private static Function<String, Boolean> all(MainYamlAssertion... fs) {
-        return s -> io.vavr.collection.List.of(fs).map(f -> f.apply(s)).fold(true, (l, r) -> l && r);
-    }
-
-    private static MainYamlAssertion containsNone(String... expected) {
-        return s -> io.vavr.collection.List.of(expected).map(e -> !s.contains(e)).fold(true, (l, r) -> l && r);
-    }
-
-    private static MainYamlAssertion containsAll(String... expected) {
-        return s -> io.vavr.collection.List.of(expected).map(s::contains).fold(true, (l, r) -> l && r);
-    }
-
     private void addOperationsToInterface(Component component, InterfaceDefinition addedInterface, int numOfOps,
-                                          int numOfInputsPerOp, boolean hasInputs, boolean hasOutputs) {
+                                          int numOfInputsPerOp, boolean hasInputs, boolean hasOutputs, boolean addAComplexType) {
 
         addedInterface.setOperations(new HashMap<>());
         for (int i = 0; i < numOfOps; i++) {
@@ -477,7 +403,7 @@ class InterfacesOperationsConverterTest {
             implementation.setArtifactName(i + "_createBPMN.bpmn");
             operation.setImplementation(implementation);
             if (hasInputs) {
-                operation.setInputs(createInputs(component, numOfInputsPerOp));
+                operation.setInputs(createInputs(component, numOfInputsPerOp, addAComplexType));
             }
             if (hasOutputs) {
                 operation.setOutputs(createOutputs(addedInterface.getToscaResourceName(),
@@ -505,8 +431,14 @@ class InterfacesOperationsConverterTest {
         return new InputDataDefinition(propertyDataDefinition);
     }
 
-    private ListDataDefinition<OperationInputDefinition> createInputs(Component component, int numOfInputs) {
+    private ListDataDefinition<OperationInputDefinition> createInputs(Component component, int numOfInputs, boolean addAComplexType) {
         ListDataDefinition<OperationInputDefinition> operationInputDefinitionList = new ListDataDefinition<>();
+        if (addAComplexType) {
+            String mappedPropertyName = java.util.UUID.randomUUID() + "." + MAPPED_PROPERTY_NAME + numOfInputs;
+            operationInputDefinitionList.add(
+                createMockComplexOperationInputDefinition(INPUT_NAME_PREFIX + "Complex" + "_" + numOfInputs, mappedPropertyName));
+            numOfInputs -= 1;
+        }
         for (int i = 0; i < numOfInputs; i++) {
             String mappedPropertyName = java.util.UUID.randomUUID() + "." + MAPPED_PROPERTY_NAME + i;
             operationInputDefinitionList.add(createMockOperationInputDefinition(
@@ -554,6 +486,17 @@ class InterfacesOperationsConverterTest {
         return operationInputDefinition;
     }
 
+    private OperationInputDefinition createMockComplexOperationInputDefinition(String name, String id) {
+        OperationInputDefinition operationInputDefinition = new OperationInputDefinition();
+        operationInputDefinition.setName(name);
+        operationInputDefinition.setInputId(id);
+        operationInputDefinition.setType("complexDataType");
+        operationInputDefinition.setRequired(false);
+        operationInputDefinition.setValue(
+            "{\"intProp\":1,\"stringProp\":{\"type\":\"GET_ATTRIBUTE\",\"propertyUniqueId\":\"ac4bc339-56d1-4ea2-9802-2da219a1247a.designer\",\"propertyName\":\"designer\",\"propertySource\":\"SELF\",\"sourceUniqueId\":\"ac4bc339-56d1-4ea2-9802-2da219a1247a\",\"sourceName\":\"service\",\"functionType\":\"GET_ATTRIBUTE\",\"propertyPathFromSource\":[\"designer\"]}}");
+        return operationInputDefinition;
+    }
+
     private OperationOutputDefinition createMockOperationOutputDefinition(String interfaceName, String operationName,
                                                                           String outputName, int index) {
         OperationOutputDefinition operationInputDefinition = new OperationOutputDefinition();
@@ -570,91 +513,6 @@ class InterfacesOperationsConverterTest {
         return operationInputDefinition;
     }
 
-    private void validateOperationInputs(final String mainYaml, int numOfInputsPerOp, String mappedOperationName) {
-        String nodeTypeKey = NODE_TYPE_NAME + ":";
-        String nodeTypesRepresentation = mainYaml.substring(mainYaml.indexOf(nodeTypeKey) + nodeTypeKey.length(),
-            mainYaml.lastIndexOf(MAPPED_PROPERTY_NAME) + MAPPED_PROPERTY_NAME.length()
-                + String.valueOf(numOfInputsPerOp).length());
-        YamlToObjectConverter objectConverter = new YamlToObjectConverter();
-        ToscaNodeType toscaNodeType = objectConverter.convert(nodeTypesRepresentation.getBytes(), ToscaNodeType.class);
-        Map<String, Object> interfaces = toscaNodeType.getInterfaces();
-        for (Map.Entry<String, Object> interfaceEntry : interfaces.entrySet()) {
-            Map<String, Object> interfaceDefinition = mapper.convertValue(interfaceEntry.getValue(), Map.class);
-            final Map<String, Object> operationsMap = interfaceDefinition.entrySet().stream()
-                .filter(entry -> !INPUTS.getElementName().equals(entry.getKey()) &&
-                    !TYPE.getElementName().equals(entry.getKey()))
-                .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
-            for (Map.Entry<String, Object> operationEntry : operationsMap.entrySet()) {
-                Object operationVal = operationEntry.getValue();
-                if (operationVal instanceof Map) {
-                    //Since the inputs are mapped to output operations from only first interface so using that name
-                    validateOperationInputDefinition(interfaces.keySet().iterator().next(), mappedOperationName,
-                        operationVal);
-                }
-            }
-        }
-    }
-
-    private void validateOperationInputDefinition(String interfaceType, String operationName, Object operationVal) {
-        Map<String, Object> operation = mapper.convertValue(operationVal, Map.class);
-        Map<String, Object> inputs = (Map<String, Object>) operation.get("inputs");
-        for (Map.Entry<String, Object> inputEntry : inputs.entrySet()) {
-            String[] inputNameSplit = inputEntry.getKey().split("_");
-            Map<String, Object> inputValueObject = (Map<String, Object>) inputEntry.getValue();
-            validateOperationInputDefinitionDefaultValue(interfaceType, operationName, inputNameSplit[1],
-                Integer.parseInt(inputNameSplit[2]), inputValueObject);
-        }
-    }
-
-
-    private void validateOperationInputDefinitionDefaultValue(String interfaceType, String operationName,
-                                                              String inputType, int index,
-                                                              Map<String, Object> inputValueObject) {
-        if (inputValueObject.containsKey(ToscaFunctions.GET_PROPERTY.getFunctionName())) {
-            String mappedPropertyValue = MAPPED_PROPERTY_NAME + index;
-            List<String> mappedPropertyDefaultValue = (List<String>) inputValueObject
-                .get(ToscaFunctions.GET_PROPERTY.getFunctionName());
-            assertEquals(2, mappedPropertyDefaultValue.size());
-            assertTrue(mappedPropertyDefaultValue.contains(SELF));
-            assertTrue(mappedPropertyDefaultValue.contains(mappedPropertyValue));
-        } else if (inputValueObject.containsKey(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName())) {
-            List<String> mappedPropertyDefaultValue = (List<String>) inputValueObject
-                .get(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName());
-            assertEquals(4, mappedPropertyDefaultValue.size());
-            String mappedPropertyValue = OUTPUT_NAME_PREFIX + inputType + "_" + index;
-            assertTrue(mappedPropertyDefaultValue.contains(SELF));
-            assertTrue(mappedPropertyDefaultValue.contains(interfaceType));
-            assertTrue(mappedPropertyDefaultValue.contains(operationName));
-            assertTrue(mappedPropertyDefaultValue.contains(mappedPropertyValue));
-        } else {
-            fail("Invalid Tosca function in default value. Allowed values: " + ToscaFunctions.GET_PROPERTY.getFunctionName() +
-                "/" + ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName());
-        }
-    }
-
-    private void validateServiceProxyOperationInputs(String mainYaml) {
-        String nodeTypeKey = NODE_TYPE_NAME + ":";
-        String nodeTypesRepresentation = mainYaml.substring(mainYaml.indexOf(nodeTypeKey) + nodeTypeKey.length(),
-            mainYaml.lastIndexOf(MAPPED_PROPERTY_NAME) + MAPPED_PROPERTY_NAME.length());
-        YamlUtil yamlUtil = new YamlUtil();
-        ToscaNodeType toscaNodeType = yamlUtil.yamlToObject(nodeTypesRepresentation, ToscaNodeType.class);
-        for (Object interfaceVal : toscaNodeType.getInterfaces().values()) {
-            Map<String, Object> interfaceDefinition = mapper.convertValue(interfaceVal, Map.class);
-            for (Object operationVal : interfaceDefinition.values()) {
-                if (operationVal instanceof Map) {
-                    Map<String, Object> operation = (Map<String, Object>) mapper.convertValue(operationVal, Map.class);
-                    Map<String, Object> operationInputs = (Map<String, Object>) operation.get("inputs");
-                    for (Object inputValue : operationInputs.values()) {
-                        Map<String, Object> inputValueAsMap = (Map<String, Object>) inputValue;
-                        assertFalse(inputValueAsMap.keySet().contains("type"));
-                        assertFalse(inputValueAsMap.keySet().contains("required"));
-                        assertFalse(inputValueAsMap.keySet().contains("default"));
-                    }
-                }
-            }
-        }
-    }
-
     @Test
     void testAddInterfaceTypeElementGetCorrectLocalInterfaceName() {
         Service service = new Service();
@@ -684,6 +542,56 @@ class InterfacesOperationsConverterTest {
             && resultMap.containsKey("NotLocal"));
     }
 
+    @Test
+    void testGetInterfaceAsMapWithComplexType() {
+        addComplexTypeToDataTypes();
+        Component component = new Resource();
+        component.setNormalizedName("normalizedComponentName");
+        InterfaceDefinition addedInterface = new InterfaceDefinition();
+        addedInterface.setToscaResourceName("com.some.resource.or.other.resourceName");
+        addedInterface.setType("com.some.resource.or.other.resourceName");
+        addOperationsToInterface(component, addedInterface, 3, 2, true, false, true);
+        final String interfaceType = "normalizedComponentName-interface";
+        component.setInterfaces(new HashMap<>());
+        component.getInterfaces().put(interfaceType, addedInterface);
+        final var interfacesMap = interfacesOperationsConverter.getInterfacesMap(component, null, component.getInterfaces(), dataTypes, false);
+        assertNotNull(interfacesMap);
+        assertEquals(1, interfacesMap.size());
+        assertTrue(interfacesMap.containsKey("resourceName"));
+        Object resourceName = interfacesMap.get("resourceName");
+        assertNotNull(resourceName);
+        assertTrue(resourceName instanceof Map);
+        assertEquals(4, ((Map) resourceName).size());
+        assertTrue(resourceName instanceof Map);
+        Map<String, Object> resource = (Map<String, Object>) resourceName;
+        assertTrue(resource.containsKey("name_for_op_0"));
+        Map<String, Object> operation0 = (Map<String, Object>) resource.get("name_for_op_0");
+        assertTrue(operation0.containsKey("inputs"));
+        Map<String, Object> operation0Inputs = (Map<String, Object>) operation0.get("inputs");
+        assertTrue(operation0Inputs.containsKey("input_Complex_2"));
+        Map<String, Object> complexInput = (Map<String, Object>) operation0Inputs.get("input_Complex_2");
+        assertTrue(complexInput.containsKey("stringProp"));
+        Map<String, Object> complexInputStringProp = (Map<String, Object>) complexInput.get("stringProp");
+        assertTrue(complexInputStringProp.containsKey("get_attribute"));
+        List<String> complexInputStringPropToscaFunction = (List<String>) complexInputStringProp.get("get_attribute");
+        assertEquals(2, complexInputStringPropToscaFunction.size());
+        assertEquals("SELF", complexInputStringPropToscaFunction.get(0));
+        assertEquals("designer", complexInputStringPropToscaFunction.get(1));
+    }
+
+    private void addComplexTypeToDataTypes() {
+        PropertyDefinition intProp = new PropertyDefinition();
+        intProp.setType("integer");
+        intProp.setName("intProp");
+        PropertyDefinition stringProp = new PropertyDefinition();
+        stringProp.setType("string");
+        stringProp.setName("stringProp");
+        DataTypeDefinition dataType = new DataTypeDefinition();
+        dataType.setName("complexDataType");
+        dataType.setProperties(new ArrayList<>(Arrays.asList(stringProp, intProp)));
+        dataTypes.put("complexDataType", dataType);
+    }
+
     @Test
     void testRemoveInterfacesWithoutOperationsEmptyMap() {
         final Map<String, Object> interfaceMap = new HashMap<>();
index 14715b7..20f73af 100644 (file)
@@ -33,6 +33,7 @@ export class InputOperationParameter {
     value?: any;
     toscaFunction?: ToscaFunction;
     valid:boolean= true;
+    subPropertyToscaFunctions: any;
 
     constructor(param?: any) {
         if (param) {
@@ -44,6 +45,7 @@ export class InputOperationParameter {
             this.value = param.value;
             this.toscaFunction = param.toscaFunction;
             this.valid = param.valid;
+            this.subPropertyToscaFunctions = param.subPropertyToscaFunctions;
         }
     }
 
index 3824d75..88a4d6b 100644 (file)
                 [dataTypeMap]="dataTypeMap"
                 [valueObjRef]="valueObjRef ? valueObjRef[property.name] : undefined"
                 [schema]="property.schema"
+                [toscaFunction]="getToscaFunction(property.name)"
                 [nestingLevel]="nestingLevel + 1"
                 [isViewOnly]="isViewOnly"
                 [showToscaFunctionOption]="showToscaFunctionOption"
               [dataTypeMap]="dataTypeMap"
               [valueObjRef]="valueObjRef[i]"
               [schema]="buildSchemaGroupProperty()"
+              [toscaFunction]="getToscaFunction(i)"
               [nestingLevel]="nestingLevel + 1"
               [listIndex]="i"
               [isListChild]="true"
               [dataTypeMap]="dataTypeMap"
               [valueObjRef]="valueObjRef[key]"
               [schema]="buildSchemaGroupProperty()"
+              [toscaFunction]="getToscaFunction(key)"
               [isMapChild]="true"
               [nestingLevel]="nestingLevel + 1"
               [isViewOnly]="isViewOnly"
index 103fc5c..61708ab 100644 (file)
@@ -25,6 +25,7 @@ import {SchemaProperty, SchemaPropertyGroupModel} from '../../../../../../../mod
 import {PropertyBEModel} from '../../../../../../../models/properties-inputs/property-be-model';
 import {PROPERTY_DATA, PROPERTY_TYPES} from '../../../../../../../utils/constants';
 import {ToscaFunction} from '../../../../../../../models/tosca-function';
+import {ToscaFunctionType} from "../../../../../../../models/tosca-function-type.enum";
 import {ToscaFunctionValidationEvent} from "../../../../../properties-assignment/tosca-function/tosca-function.component";
 import {InstanceFeDetails} from "../../../../../../../models/instance-fe-details";
 import {ToscaTypeHelper} from "app/utils/tosca-type-helper";
@@ -48,6 +49,7 @@ export class InputListItemComponent implements OnInit {
   @Input() isMapChild: boolean = false;
   @Input() showToscaFunctionOption: boolean = false;
   @Input() listIndex: number;
+  @Input() subPropertyToscaFunctions: SubPropertyToscaFunctions[];
   @Input() isViewOnly: boolean;
   @Input() allowDeletion: boolean = false;
   @Input() toscaFunction: ToscaFunction;
@@ -96,6 +98,24 @@ export class InputListItemComponent implements OnInit {
     }
   }
 
+  getToscaFunction(key: any): any {
+    if (this.subPropertyToscaFunctions) {
+      for (let subPropertyToscaFunction of this.subPropertyToscaFunctions) {
+        let found = subPropertyToscaFunction.subPropertyPath.find(value => value === key);
+        if (found) {
+          return subPropertyToscaFunction.toscaFunction;
+        }
+      }
+    }
+    if ((key && this.valueObjRef[key] && this.valueObjRef[key].type)) {
+      const type = this.valueObjRef[key].type;
+      if (type in ToscaFunctionType) {
+        return <ToscaFunction> this.valueObjRef[key];
+      }
+    }
+    return undefined;
+  }
+
   isTypeSimple(typeName: string): boolean {
     return ToscaTypeHelper.isTypeSimple(typeName) || this.isTypeDerivedFromSimple(typeName) && (this.isTypeWithoutProperties(typeName));
   }
@@ -327,3 +347,8 @@ export class InputListItemComponent implements OnInit {
   }
 
 }
+
+export interface SubPropertyToscaFunctions {
+  subPropertyPath: string[];
+  toscaFunction: ToscaFunction;
+}
index d4b70f9..64726f1 100644 (file)
@@ -32,6 +32,7 @@
         [valueObjRef]="input.value"
         [schema]="input.schema"
         [toscaFunction]="input.toscaFunction"
+        [subPropertyToscaFunctions]="input.subPropertyToscaFunctions"
         [showToscaFunctionOption]="showToscaFunctionOption"
         [isViewOnly]="isViewOnly"
         [allowDeletion]="allowDeletion"
index 3230306..824592f 100644 (file)
@@ -29,6 +29,7 @@ import {TranslateService} from '../../../../../shared/translator/translate.servi
 import {ToscaFunction} from '../../../../../../models/tosca-function';
 import {InstanceFeDetails} from "../../../../../../models/instance-fe-details";
 import {CustomToscaFunction} from "../../../../../../models/default-custom-functions";
+import {SubPropertyToscaFunctions} from "./input-list-item/input-list-item.component";
 
 @Component({selector: 'app-input-list-item', template: ''})
 class InputListItemStubComponent {
@@ -36,6 +37,7 @@ class InputListItemStubComponent {
   @Input() type: DataTypeModel;
   @Input() dataTypeMap: any;
   @Input() valueObjRef: any;
+  @Input() subPropertyToscaFunctions: SubPropertyToscaFunctions[];
   @Input() schema: any;
   @Input() allowDeletion: any;
   @Input() isViewOnly: boolean;
index 4ceaa78..812490c 100644 (file)
@@ -303,6 +303,9 @@ export class InterfaceOperationHandlerComponent {
         const inputOperationParameter = this.inputs.find(value => value.name == changedInput.name);
         inputOperationParameter.toscaFunction = null;
         inputOperationParameter.value = changedInput.value;
+        if (inputOperationParameter.subPropertyToscaFunctions) {
+            inputOperationParameter.subPropertyToscaFunctions = undefined;
+        }
         if (changedInput.isToscaFunction()) {
             inputOperationParameter.toscaFunction = changedInput.toscaFunction;
             inputOperationParameter.value = changedInput.toscaFunction.buildValueString();
index cbbc2d9..07058ea 100644 (file)
@@ -125,7 +125,7 @@ export class ToscaGetFunctionComponent implements OnInit, OnChanges {
                 this.loadPropertyDropdown(() => {
                     this.selectedProperty
                     .setValue(this.propertyDropdownList.find(property => property.propertyName === this.toscaGetFunction.propertyName));
-                    if (this.toscaGetFunction.toscaIndexList.length > 0) {
+                    if (this.toscaGetFunction.toscaIndexList && this.toscaGetFunction.toscaIndexList.length > 0) {
                         let tempSelectedProperty : PropertyDropdownValue = this.selectedProperty.value;
                         this.toscaGetFunction.toscaIndexList.forEach((indexValue: string, index) => {
                             let tempIndexFlag = false;