summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandre.schmid <andre.schmid@est.tech>2022-03-07 18:48:09 +0000
committerMichael Morris <michael.morris@est.tech>2022-03-11 16:48:13 +0000
commite5488e5e3623646125802b8ab7e12b7159a2c0d3 (patch)
tree58c896b9d2f434041cff1cafad7835dd9cd691f3
parentf13f58eb867c763e6ed1c3b674fd99b1081a0664 (diff)
Support complex types in artifact properties
Adds support to complex types in artifact properties of an interface operation implementation. Change-Id: I7a82a3652541b35230fe4ce87bf703a1dbe72d50 Issue-ID: SDC-3899 Signed-off-by: andre.schmid <andre.schmid@est.tech>
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java95
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaArtifactDefinition.java3
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyAssignmentJsonSerializer.java42
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverterTest.java69
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaListValueConverter.java46
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaValueBaseConverter.java13
-rw-r--r--catalog-model/src/test/java/org/openecomp/sdc/be/model/tosca/converters/ToscaValueBaseConverterTest.java2
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list-item/input-list-item.component.ts3
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.html6
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.spec.ts1
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.ts5
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html35
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less7
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts31
-rw-r--r--catalog-ui/src/assets/languages/en_US.json3
-rw-r--r--common-app-api/src/main/java/org/openecomp/sdc/common/util/JsonUtils.java7
16 files changed, 284 insertions, 84 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java
index 64e61699ed..b689959572 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java
@@ -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;
@@ -38,6 +39,7 @@ import org.apache.commons.lang3.math.NumberUtils;
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;
@@ -53,6 +55,8 @@ 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;
@@ -147,12 +151,8 @@ 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 static boolean isArtifactPresent(final OperationDataDefinition operationDataDefinition) {
+ return operationDataDefinition.getImplementation() != null && operationDataDefinition.getImplementation().getArtifactName() != null;
}
private static String getInputValue(final OperationInputDefinition input) {
@@ -178,13 +178,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));
@@ -263,10 +272,10 @@ public class InterfacesOperationsConverter {
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);
+ handleInterfaceOperationImplementation(component, componentInstance, isAssociatedComponent, operationEntry.getValue(),
+ toscaLifecycleOperationDefinition, dataTypes);
toscaLifecycleOperationDefinition.setDescription(operationEntry.getValue().getDescription());
- fillToscaOperationInputs(operationEntry.getValue(), dataTypes, toscaLifecycleOperationDefinition, isServiceProxyInterface);
+ fillToscaOperationInputs(operationEntry.getValue(), dataTypes, toscaLifecycleOperationDefinition);
toscaOperationMap.put(operationEntry.getValue().getName(), toscaLifecycleOperationDefinition);
}
toscaInterfaceDefinition.setOperations(toscaOperationMap);
@@ -286,37 +295,56 @@ public class InterfacesOperationsConverter {
private void handleInterfaceOperationImplementation(final Component component, final ComponentInstance componentInstance,
final boolean isAssociatedComponent,
- final Entry<String, OperationDataDefinition> operationEntry,
- final ToscaLifecycleOperationDefinition toscaOperation) {
+ final OperationDataDefinition operationDataDefinition,
+ final ToscaLifecycleOperationDefinition toscaOperation,
+ final Map<String, DataTypeDefinition> dataTypes) {
final String operationArtifactPath;
final ToscaInterfaceOperationImplementation toscaInterfaceOperationImplementation = new ToscaInterfaceOperationImplementation();
toscaInterfaceOperationImplementation.setPrimary(new ToscaArtifactDefinition());
final ToscaArtifactDefinition toscaArtifactDefinition = toscaInterfaceOperationImplementation.getPrimary();
- if (isArtifactPresent(operationEntry) && StringUtils.isNotEmpty(operationEntry.getValue().getImplementation().getArtifactName())) {
+ if (isArtifactPresent(operationDataDefinition) && StringUtils.isNotEmpty(operationDataDefinition.getImplementation().getArtifactName())) {
operationArtifactPath = OperationArtifactUtil
- .createOperationArtifactPath(component, componentInstance, operationEntry.getValue(), isAssociatedComponent);
+ .createOperationArtifactPath(component, componentInstance, operationDataDefinition, isAssociatedComponent);
toscaArtifactDefinition.setFile(operationArtifactPath);
- toscaArtifactDefinition.setArtifact_version(!operationEntry.getValue().getImplementation().getArtifactVersion()
- .equals(NumberUtils.INTEGER_ZERO.toString()) ? operationEntry.getValue().getImplementation().getArtifactVersion() : null);
- toscaArtifactDefinition.setType(operationEntry.getValue().getImplementation().getArtifactType());
- handleInterfaceOperationImplementationProperties(operationEntry, toscaArtifactDefinition);
+ toscaArtifactDefinition.setArtifact_version(!operationDataDefinition.getImplementation().getArtifactVersion()
+ .equals(NumberUtils.INTEGER_ZERO.toString()) ? operationDataDefinition.getImplementation().getArtifactVersion() : null);
+ toscaArtifactDefinition.setType(operationDataDefinition.getImplementation().getArtifactType());
+ final Map<String, ToscaPropertyAssignment> propertiesMap = handleImplementationProperties(operationDataDefinition, dataTypes);
+ if (!propertiesMap.isEmpty()) {
+ toscaArtifactDefinition.setProperties(propertiesMap);
+ }
toscaOperation.setImplementation(
toscaArtifactDefinition.getType() != null ? toscaInterfaceOperationImplementation : operationArtifactPath);
} else {
- toscaArtifactDefinition.setFile(operationEntry.getValue().getImplementation().getArtifactName());
+ toscaArtifactDefinition.setFile(operationDataDefinition.getImplementation().getArtifactName());
toscaOperation.setImplementation(toscaInterfaceOperationImplementation);
}
}
- private void handleInterfaceOperationImplementationProperties(final Entry<String, OperationDataDefinition> operationEntry,
- final ToscaArtifactDefinition toscaArtifactDefinition) {
- final var properties = operationEntry.getValue().getImplementation().getProperties();
- if (CollectionUtils.isNotEmpty(properties)) {
- final Map<String, String> propertiesMap = new HashMap<>();
- properties.stream().filter(propertyDataDefinition -> StringUtils.isNotEmpty(propertyDataDefinition.getValue()))
- .forEach(propertyDataDefinition -> propertiesMap.put(propertyDataDefinition.getName(), propertyDataDefinition.getValue()));
- toscaArtifactDefinition.setProperties(propertiesMap);
+ 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) {
@@ -373,7 +401,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;
@@ -389,4 +417,5 @@ public class InterfacesOperationsConverter {
}
toscaOperation.setInputs(toscaInputs);
}
+
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaArtifactDefinition.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaArtifactDefinition.java
index 689dc91d23..ac306073c1 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaArtifactDefinition.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaArtifactDefinition.java
@@ -36,5 +36,6 @@ public class ToscaArtifactDefinition {
private String artifact_version;
private String checksum;
private String checksum_algorithm;
- private Map<String, String> properties;
+ private Map<String, ToscaPropertyAssignment> properties;
+
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyAssignmentJsonSerializer.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyAssignmentJsonSerializer.java
new file mode 100644
index 0000000000..9c695f6924
--- /dev/null
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyAssignmentJsonSerializer.java
@@ -0,0 +1,42 @@
+/*
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.tosca.model;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import java.io.IOException;
+
+/**
+ * Jackson JSON serializer for the ToscaPropertyAssignment class
+ */
+public class ToscaPropertyAssignmentJsonSerializer extends StdSerializer<ToscaPropertyAssignment> {
+
+ public ToscaPropertyAssignmentJsonSerializer() {
+ super(ToscaPropertyAssignment.class);
+ }
+
+ @Override
+ public void serialize(ToscaPropertyAssignment toscaPropertyAssignment, JsonGenerator gen, SerializerProvider provider) throws IOException {
+ gen.writeObject(toscaPropertyAssignment.getValue());
+ }
+} \ No newline at end of file
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverterTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverterTest.java
index e55a92dd0b..e3e4590d0f 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverterTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverterTest.java
@@ -66,6 +66,8 @@ import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition;
import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
+import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
import org.openecomp.sdc.be.model.Component;
import org.openecomp.sdc.be.model.DataTypeDefinition;
import org.openecomp.sdc.be.model.InputDefinition;
@@ -73,6 +75,7 @@ import org.openecomp.sdc.be.model.InterfaceDefinition;
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.be.tosca.model.ToscaTemplate;
@@ -366,10 +369,10 @@ class InterfacesOperationsConverterTest {
@Test
void interfaceWithInputsToscaExportTest() {
final Component component = new Service();
- final InterfaceDefinition aInterfaceWithInput = new InterfaceDefinition();
+ final InterfaceDefinition anInterfaceWithInput = new InterfaceDefinition();
final String interfaceName = "myInterfaceName";
final String interfaceType = "my.type." + interfaceName;
- aInterfaceWithInput.setType(interfaceType);
+ anInterfaceWithInput.setType(interfaceType);
final String input1Name = "input1";
final InputDataDefinition input1 = createInput("string", "input1 description", false, "input1 value");
final String input2Name = "input2";
@@ -377,9 +380,9 @@ class InterfacesOperationsConverterTest {
final Map<String, InputDataDefinition> inputMap = new HashMap<>();
inputMap.put(input1Name, input1);
inputMap.put(input2Name, input2);
- aInterfaceWithInput.setInputs(inputMap);
+ anInterfaceWithInput.setInputs(inputMap);
component.setInterfaces(new HashMap<>());
- component.getInterfaces().put(interfaceName, aInterfaceWithInput);
+ component.getInterfaces().put(interfaceName, anInterfaceWithInput);
final ToscaNodeType nodeType = new ToscaNodeType();
interfacesOperationsConverter.addInterfaceDefinitionElement(component, nodeType, dataTypes, false);
final ToscaExportHandler handler = new ToscaExportHandler(null, null, null, null, null, null, null, null, null, null,
@@ -395,6 +398,62 @@ class InterfacesOperationsConverterTest {
validateInterfaceInputs(toscaTemplateYaml, interfaceName, inputMap);
}
+ @Test
+ void interfaceWithOperationImplementationArtifactPropertiesTest() {
+ //given
+ final Component component = new Service();
+ final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
+ final String interfaceName = "myInterfaceName";
+ interfaceDefinition.setType("my.type." + interfaceName);
+ final var operation1DataDefinition = new OperationDataDefinition();
+ operation1DataDefinition.setName("anOperation");
+
+ final PropertyDataDefinition listOfStringProperty = new PropertyDataDefinition();
+ listOfStringProperty.setName("listProperty");
+ listOfStringProperty.setType(ToscaType.LIST.getType());
+ final PropertyDataDefinition listOfStringSchemaProperty = new PropertyDataDefinition();
+ listOfStringSchemaProperty.setType(ToscaType.STRING.getType());
+ final SchemaDefinition listPropertySchema = new SchemaDefinition();
+ listPropertySchema.setProperty(listOfStringProperty);
+ listOfStringProperty.setSchema(listPropertySchema);
+ listOfStringProperty.setValue("[ \"value1\", \"value2\", \"value3\" ]");
+ final ArrayList<Object> propertyList = new ArrayList<>();
+ propertyList.add(listOfStringProperty);
+ final HashMap<String, Object> artifactDefinitionMapInitializer = new HashMap<>();
+ artifactDefinitionMapInitializer.put(JsonPresentationFields.PROPERTIES.getPresentation(), propertyList);
+ final ArtifactDataDefinition artifactDataDefinition = new ArtifactDataDefinition(artifactDefinitionMapInitializer);
+ artifactDataDefinition.setArtifactName("artifact1");
+ artifactDataDefinition.setArtifactType("my.artifact.Type");
+ operation1DataDefinition.setImplementation(artifactDataDefinition);
+ interfaceDefinition.setOperations(Map.of(operation1DataDefinition.getName(), operation1DataDefinition));
+ component.setInterfaces(new HashMap<>());
+ component.getInterfaces().put(interfaceName, interfaceDefinition);
+ //when
+ Map<String, Object> interfacesMap = interfacesOperationsConverter
+ .getInterfacesMap(component, null, component.getInterfaces(), null, false, true);
+ //then
+ assertTrue(interfacesMap.containsKey(interfaceName));
+ final Map<String, Object> actualInterfaceMap = (Map<String, Object>) interfacesMap.get(interfaceName);
+ assertTrue(actualInterfaceMap.containsKey(operation1DataDefinition.getName()));
+ final Map<String, Object> actualOperationMap = (Map<String, Object>) actualInterfaceMap.get(operation1DataDefinition.getName());
+ assertTrue(actualOperationMap.containsKey("implementation"));
+ final Map<String, Object> actualImplementationMap = (Map<String, Object>) actualOperationMap.get("implementation");
+ assertTrue(actualImplementationMap.containsKey("primary"));
+ final Map<String, Object> actualArtifactImplementationMap = (Map<String, Object>) actualImplementationMap.get("primary");
+ assertTrue(actualArtifactImplementationMap.containsKey("properties"));
+ final Map<String, Object> actualArtifactPropertiesMap = (Map<String, Object>) actualArtifactImplementationMap.get("properties");
+ assertEquals(actualArtifactPropertiesMap.keySet().size(), 1);
+ assertTrue(actualArtifactPropertiesMap.containsKey(listOfStringProperty.getName()));
+ final Object expectedListObject = actualArtifactPropertiesMap.get(listOfStringProperty.getName());
+ assertTrue(expectedListObject instanceof List);
+ final List<String> expectedListOfStringPropValue = (List<String>) expectedListObject;
+ assertEquals(expectedListOfStringPropValue.size(), 3);
+ assertTrue(expectedListOfStringPropValue.contains("value1"));
+ assertTrue(expectedListOfStringPropValue.contains("value2"));
+ 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";
@@ -404,7 +463,7 @@ class InterfacesOperationsConverterTest {
if (fixedMainYaml.endsWith(nullString)) {
fixedMainYaml = fixedMainYaml.substring(0, fixedMainYaml.length() - nullString.length());
}
- final Map<String, Object> yamlMap = (Map<String, Object>) new Yaml().load(fixedMainYaml);
+ 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());
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaListValueConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaListValueConverter.java
index 4093e9d364..67894bdade 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaListValueConverter.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaListValueConverter.java
@@ -32,17 +32,18 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import org.jetbrains.annotations.Nullable;
import org.openecomp.sdc.be.config.BeEcompErrorManager;
import org.openecomp.sdc.be.model.DataTypeDefinition;
import org.openecomp.sdc.be.model.PropertyDefinition;
import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.openecomp.sdc.common.util.JsonUtils;
public class ToscaListValueConverter extends ToscaValueBaseConverter implements ToscaValueConverter {
private static final Logger log = Logger.getLogger(ToscaListValueConverter.class.getName());
- private static ToscaListValueConverter listConverter = new ToscaListValueConverter();
- private JsonParser jsonParser = new JsonParser();
+ private static final ToscaListValueConverter listConverter = new ToscaListValueConverter();
private ToscaListValueConverter() {
}
@@ -77,16 +78,8 @@ public class ToscaListValueConverter extends ToscaValueBaseConverter implements
return value;
}
}
- JsonElement jsonElement = null;
- try {
- StringReader reader = new StringReader(value);
- JsonReader jsonReader = new JsonReader(reader);
- jsonReader.setLenient(true);
- jsonElement = jsonParser.parse(jsonReader);
- } catch (JsonSyntaxException e) {
- log.debug("convertToToscaValue failed to parse json value :", e);
- return null;
- }
+ JsonElement jsonElement;
+ jsonElement = parseToJson(value);
if (jsonElement == null || jsonElement.isJsonNull()) {
log.debug("convertToToscaValue json element is null");
return null;
@@ -122,7 +115,6 @@ public class ToscaListValueConverter extends ToscaValueBaseConverter implements
if (propertyDefinition == null) {
log.debug("The property {} was not found under data type {}", propName, dataTypeDefinition.getName());
continue;
- // return null;
}
String type = propertyDefinition.getType();
ToscaPropertyType propertyType = ToscaPropertyType.isValidType(type);
@@ -132,13 +124,17 @@ public class ToscaListValueConverter extends ToscaValueBaseConverter implements
ToscaValueConverter valueConverter = propertyType.getValueConverter();
convValue = valueConverter.convertToToscaValue(elementValue.getAsString(), type, dataTypes);
} else {
- if (ToscaPropertyType.MAP.equals(type) || ToscaPropertyType.LIST.equals(propertyType)) {
- ToscaValueConverter valueConverter = propertyType.getValueConverter();
- String json = gson.toJson(elementValue);
- String innerTypeRecursive = propertyDefinition.getSchema().getProperty().getType();
- convValue = valueConverter.convertToToscaValue(json, innerTypeRecursive, dataTypes);
+ if (JsonUtils.isEmptyJson(elementValue)) {
+ convValue = null;
} else {
- convValue = handleComplexJsonValue(elementValue);
+ if (ToscaPropertyType.MAP == propertyType || ToscaPropertyType.LIST == propertyType) {
+ ToscaValueConverter valueConverter = propertyType.getValueConverter();
+ String json = gson.toJson(elementValue);
+ String innerTypeRecursive = propertyDefinition.getSchema().getProperty().getType();
+ convValue = valueConverter.convertToToscaValue(json, innerTypeRecursive, dataTypes);
+ } else {
+ convValue = handleComplexJsonValue(elementValue);
+ }
}
}
} else {
@@ -158,4 +154,16 @@ public class ToscaListValueConverter extends ToscaValueBaseConverter implements
return null;
}
}
+
+ private JsonElement parseToJson(final String value) {
+ try {
+ final StringReader reader = new StringReader(value);
+ final JsonReader jsonReader = new JsonReader(reader);
+ jsonReader.setLenient(true);
+ return JsonParser.parseReader(jsonReader);
+ } catch (final JsonSyntaxException e) {
+ log.debug("convertToToscaValue failed to parse json value :", e);
+ return null;
+ }
+ }
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaValueBaseConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaValueBaseConverter.java
index ee254811b1..7505d2af88 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaValueBaseConverter.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaValueBaseConverter.java
@@ -98,12 +98,19 @@ public class ToscaValueBaseConverter {
}
private Map<String, Object> handleJsonObject(final JsonElement jsonElement) {
- final Map<String, Object> jsonObjectAsMap = new HashMap<>();
final JsonObject jsonObject = jsonElement.getAsJsonObject();
+ if (jsonObject.entrySet().isEmpty()) {
+ return null;
+ }
+ final Map<String, Object> jsonObjectAsMap = new HashMap<>();
for (final Entry<String, JsonElement> entry : jsonObject.entrySet()) {
- jsonObjectAsMap.put(entry.getKey(), handleComplexJsonValue(entry.getValue()));
+ final Object value = handleComplexJsonValue(entry.getValue());
+ if (value != null) {
+ jsonObjectAsMap.put(entry.getKey(), value);
+ }
+
}
- return jsonObjectAsMap;
+ return jsonObjectAsMap.isEmpty() ? null : jsonObjectAsMap;
}
private List<Object> handleJsonArray(final JsonElement entry) {
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/tosca/converters/ToscaValueBaseConverterTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/tosca/converters/ToscaValueBaseConverterTest.java
index 179d3cf7a1..5387b46dd6 100644
--- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/tosca/converters/ToscaValueBaseConverterTest.java
+++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/tosca/converters/ToscaValueBaseConverterTest.java
@@ -138,7 +138,7 @@ class ToscaValueBaseConverterTest {
final Object objectProperty = jsonObjectAsMap.get("objectProperty");
assertTrue(objectProperty instanceof Map);
final Map<String, Object> objectPropertyAsMap = (Map<String, Object>) objectProperty;
- assertEquals(4, objectPropertyAsMap.keySet().size());
+ assertEquals(3, objectPropertyAsMap.keySet().size());
assertTrue(objectPropertyAsMap.containsKey("string"));
assertEquals(innerObject.get("string").getAsString(), objectPropertyAsMap.get("string"));
assertEquals(innerObject.get("int").getAsInt(), objectPropertyAsMap.get("int"));
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list-item/input-list-item.component.ts b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list-item/input-list-item.component.ts
index cd75fe87e6..7c0465f62a 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list-item/input-list-item.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list-item/input-list-item.component.ts
@@ -42,6 +42,7 @@ export class InputListItemComponent implements OnInit {
@Input() isMapChild: boolean = false;
@Input() listIndex: number;
@Input() isViewOnly: boolean;
+ @Input() allowDeletion: boolean = false;
@Output('onValueChange') onValueChangeEvent: EventEmitter<any> = new EventEmitter<any>();
@Output('onDelete') onDeleteEvent: EventEmitter<string> = new EventEmitter<string>();
@Output('onChildListItemDelete') onChildListItemDeleteEvent: EventEmitter<number> = new EventEmitter<number>();
@@ -145,7 +146,7 @@ export class InputListItemComponent implements OnInit {
}
showInputDelete(): boolean {
- return !this.isViewOnly && (this.isRoot() || this.isMapChild);
+ return this.allowDeletion && !this.isViewOnly && (this.isRoot() || this.isMapChild);
}
resolveType(): string {
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.html b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.html
index 802bd63838..273fc7eac1 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.html
@@ -19,8 +19,11 @@
~ ============LICENSE_END=========================================================
-->
-<label>{{ 'INPUT_LIST_TITLE' | translate }}</label>
+<label *ngIf="title">{{title}}</label>
<div class="input-tree">
+ <div *ngIf="!_inputs.length">
+ {{emptyMessage}}
+ </div>
<ul *ngFor="let input of _inputs">
<app-input-list-item
[name]="input.name"
@@ -29,6 +32,7 @@
[valueObjRef]="input.value"
[schema]="input.schema"
[isViewOnly]="isViewOnly"
+ [allowDeletion]="allowDeletion"
(onValueChange)="onValueChange($event)"
(onDelete)="onDelete($event)">
</app-input-list-item>
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.spec.ts
index b07a4bb55f..99cfd21566 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.spec.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.spec.ts
@@ -34,6 +34,7 @@ class InputListItemStubComponent {
@Input() dataTypeMap: any;
@Input() valueObjRef: any;
@Input() schema: any;
+ @Input() allowDeletion: any;
@Input() isViewOnly: boolean;
}
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.ts b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.ts
index 72812d810d..832a40e841 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-list/input-list.component.ts
@@ -45,10 +45,13 @@ export class InputListComponent {
}
@Input() dataTypeMap: Map<string, DataTypeModel>;
@Input() isViewOnly: boolean;
+ @Input() title: string;
+ @Input() emptyMessage: string;
+ @Input() allowDeletion: boolean = false;
@Output('onValueChange') inputValueChangeEvent: EventEmitter<InputOperationParameter> = new EventEmitter<InputOperationParameter>();
@Output('onDelete') inputDeleteEvent: EventEmitter<string> = new EventEmitter<string>();
- _inputs: Array<InputOperationParameter>;
+ _inputs: Array<InputOperationParameter> = [];
getDataType(type: string): DataTypeModel {
return this.dataTypeMap.get(type);
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html
index 46db3b94a9..ce4738a780 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html
@@ -104,30 +104,27 @@
</div>
</div>
<div class="form-item" *ngIf="toscaArtifactTypeSelected && enableAddArtifactImplementation">
- <label class="sdc-input__label">{{ 'ENTITY_VIEWER_PROPERTIES_TAB' | translate }}</label>
- <div class="generic-table">
- <div class="header-row table-row">
- <span class="cell header-cell field-input-name">{{ 'IMPLEMENTATION_ARTIFACT_PROPERTY_NAME' | translate }}</span>
- <span class="cell header-cell field-input-type">{{ 'IMPLEMENTATION_ARTIFACT_PROPERTY_TYPE' | translate }}</span>
- <span class="cell header-cell field-input-value">{{ 'IMPLEMENTATION_ARTIFACT_PROPERTY_VALUE' | translate }}</span>
- </div>
-
- <div class="empty-msg data-row" *ngIf="!toscaArtifactTypeProperties.length">
- <div>{{ 'EMPTY_PARAM_TABLE_HEADER' | translate }}</div>
- </div>
- <property-param-row
- *ngFor="let property of toscaArtifactTypeProperties"
- class="data-row"
- [artifactProperty]="property"
- [isPropertyValueValid]="propertyValueValidation">
- </property-param-row>
- </div>
+ <input-list
+ *ngIf="artifactTypeProperties && dataTypeMap"
+ [title]="'ARTIFACT_PROPERTY_LIST_TITLE' | translate"
+ [emptyMessage]="'ARTIFACT_PROPERTY_LIST_EMPTY' | translate"
+ [inputs]="artifactTypeProperties"
+ [dataTypeMap]="dataTypeMap"
+ [isViewOnly]="isViewOnly"
+ [allowDeletion]="false"
+ (onValueChange)="onArtifactPropertyValueChange($event)"
+ >
+ </input-list>
</div>
</div>
<div class="group-with-border content-row" *ngIf="dataTypeMap">
<input-list
- [inputs]="inputs" [dataTypeMap]="dataTypeMap"
+ [title]="'INPUT_LIST_TITLE' | translate"
+ [emptyMessage]="'INPUT_LIST_EMPTY' | translate"
+ [inputs]="inputs"
+ [dataTypeMap]="dataTypeMap"
[isViewOnly]="isViewOnly"
+ [allowDeletion]="true"
(onValueChange)="onInputValueChange($event)"
(onDelete)="onInputDelete($event)"
>
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less
index cb47c8d167..5edf97f33c 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less
@@ -22,6 +22,9 @@
@import '../../../../../../assets/styles/override.less';
.operation-handler {
+ overflow: scroll;
+ max-height: 700px;
+ max-width: 100%;
font-family: @font-opensans-regular;
user-select: none;
padding-top: 12px;
@@ -221,3 +224,7 @@
}
}
+
+.operation-handler::-webkit-scrollbar-track {
+ border: 0;
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts
index ed295e867c..f357ddfc54 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts
@@ -66,6 +66,7 @@ export class InterfaceOperationHandlerComponent {
toscaArtifactTypeSelected: string;
toscaArtifactTypeProperties: Array<PropertyBEModel> = [];
+ artifactTypeProperties: Array<InputOperationParameter> = [];
toscaArtifactTypes: Array<DropdownValue> = [];
@@ -112,6 +113,7 @@ export class InterfaceOperationHandlerComponent {
this.artifactVersion = this.operationToUpdate.implementation.artifactVersion;
this.artifactName = this.operationToUpdate.implementation.artifactName;
this.toscaArtifactTypeProperties = this.operationToUpdate.implementation.properties;
+ this.artifactTypeProperties = this.convertArtifactsPropertiesToInput();
this.getArtifactTypesSelected();
}
@@ -142,6 +144,7 @@ export class InterfaceOperationHandlerComponent {
this.artifactName = undefined;
}
this.toscaArtifactTypeProperties = undefined;
+ this.artifactTypeProperties = undefined;
} else {
this.getArtifactTypesSelected();
}
@@ -158,6 +161,7 @@ export class InterfaceOperationHandlerComponent {
artifact.artifactType = toscaArtifactType.type;
artifact.properties = toscaArtifactType.properties;
this.toscaArtifactTypeProperties = artifact.properties;
+ this.artifactTypeProperties = this.convertArtifactsPropertiesToInput();
this.toscaArtifactTypeSelected = artifact.artifactType;
this.operationToUpdate.implementation = artifact;
this.getArtifactTypesSelected();
@@ -225,6 +229,7 @@ export class InterfaceOperationHandlerComponent {
this.toscaArtifactTypeSelected = this.operationToUpdate.implementation.artifactType;
this.artifactVersion = this.operationToUpdate.implementation.artifactVersion;
this.toscaArtifactTypeProperties = this.operationToUpdate.implementation.properties;
+ this.artifactTypeProperties = this.convertArtifactsPropertiesToInput();
this.enableAddArtifactImplementation = true;
}
this.validateRequiredField();
@@ -272,6 +277,15 @@ export class InterfaceOperationHandlerComponent {
inputOperationParameter.value = changedInput.value;
}
+ onArtifactPropertyValueChange(changedProperty: InputOperationParameter) {
+ if (changedProperty.value instanceof Object) {
+ changedProperty.value = JSON.stringify(changedProperty.value);
+ }
+ this.toscaArtifactTypeProperties.find(artifactProperty => artifactProperty.name == changedProperty.name);
+ const property = this.toscaArtifactTypeProperties.find(artifactProperty => artifactProperty.name == changedProperty.name);
+ property.value = changedProperty.value;
+ }
+
/**
* Handles the add input event.
* @param input the input to add
@@ -304,4 +318,21 @@ export class InterfaceOperationHandlerComponent {
currentInputs.splice(currentInputs.indexOf(input1), 1);
this.inputs = Array.from(currentInputs);
}
+
+ private convertArtifactsPropertiesToInput(): Array<InputOperationParameter> {
+ if (!this.toscaArtifactTypeProperties) {
+ return [];
+ }
+ const inputList: Array<InputOperationParameter> = [];
+ this.toscaArtifactTypeProperties.forEach(property => {
+ const input = new InputOperationParameter();
+ input.name = property.name;
+ input.type = property.type;
+ input.schema = property.schema;
+ input.toscaDefaultValue = property.defaultValue;
+ input.value = property.value;
+ inputList.push(input);
+ });
+ return inputList;
+ }
}
diff --git a/catalog-ui/src/assets/languages/en_US.json b/catalog-ui/src/assets/languages/en_US.json
index 85e2ec2141..88bd40767f 100644
--- a/catalog-ui/src/assets/languages/en_US.json
+++ b/catalog-ui/src/assets/languages/en_US.json
@@ -445,7 +445,10 @@
"INPUT_LIST_ADD_MAP_ENTRY": "Add Map Entry",
"INPUT_LIST_ADD_LIST_ENTRY": "Add List Entry",
"INPUT_LIST_TITLE": "Inputs",
+ "INPUT_LIST_EMPTY": "The input list is empty",
"ADD_INPUT_TITLE": "New Input",
+ "ARTIFACT_PROPERTY_LIST_EMPTY": "The artifact type has no properties",
+ "ARTIFACT_PROPERTY_LIST_TITLE": "Artifact properties",
"INTERFACE_OPERATION_IMPLEMENTATION": "Implementation",
"INTERFACE_OPERATION_IMPLEMENTATION_NAME": "Name",
"INTERFACE_OPERATION_IMPLEMENTATION_FILE": "File",
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/util/JsonUtils.java b/common-app-api/src/main/java/org/openecomp/sdc/common/util/JsonUtils.java
index be534d2909..c76310ecf4 100644
--- a/common-app-api/src/main/java/org/openecomp/sdc/common/util/JsonUtils.java
+++ b/common-app-api/src/main/java/org/openecomp/sdc/common/util/JsonUtils.java
@@ -24,6 +24,10 @@ import com.google.gson.JsonObject;
public class JsonUtils {
+ private JsonUtils() {
+
+ }
+
public static String toString(JsonElement jsonElement) {
if (jsonElement == null) {
return null;
@@ -48,6 +52,9 @@ public class JsonUtils {
}
public static boolean isEmptyJson(final JsonElement json) {
+ if (json == null || json.isJsonNull()) {
+ return true;
+ }
if (json.isJsonArray()) {
return json.getAsJsonArray().isEmpty();
}