Fix bugs in attribute outputs page 99/135999/5
authorJvD_Ericsson <jeff.van.dam@est.tech>
Thu, 21 Sep 2023 10:41:34 +0000 (11:41 +0100)
committerVasyl Razinkov <vasyl.razinkov@est.tech>
Sat, 23 Sep 2023 23:47:49 +0000 (23:47 +0000)
  * Attributes being added to the template for each output
    declared if the attribute is a property and has a value
  * Unable to set a default value on a property from Output page
  * Fix issues with the save button
    * infinite save pop up when trying to leave the page with
      changes and clicking save
    * parse error in the console that would make the save button
      remain enabled after save was succesful
  * output values not being removed from attribute after output
    is deleted
  * nested attribute values not being updated

Issue-ID: SDC-4632
Signed-off-by: JvD_Ericsson <jeff.van.dam@est.tech>
Change-Id: I08abd6cd96963b09be7941c3a91559e241ace24f

catalog-be/src/main/java/org/openecomp/sdc/be/components/attribute/ComponentInstanceAttributeDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/OutputsBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/AttributeConverter.java
catalog-ui/src/app/models/attributes.ts
catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.html
catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.html
catalog-ui/src/app/ng2/pages/attributes-outputs/attributes-outputs.page.component.ts

index 4c75624..4fb8bb7 100644 (file)
@@ -17,6 +17,7 @@
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
+
 package org.openecomp.sdc.be.components.attribute;
 
 import fj.data.Either;
@@ -27,6 +28,7 @@ import java.util.Optional;
 import org.apache.commons.collections4.CollectionUtils;
 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.GetOutputValueDataDefinition;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.ComponentInstance;
 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
@@ -70,13 +72,25 @@ public class ComponentInstanceAttributeDeclarator extends DefaultAttributeDeclar
 
     @Override
     public StorageOperationStatus unDeclareAttributesAsOutputs(final Component component, final OutputDefinition output) {
-        final List<ComponentInstanceAttribute> componentInstancePropertiesDeclaredAsInput = componentInstanceBusinessLogic
+        final List<ComponentInstanceAttribute> componentInstanceAttributesDeclaredAsOutput = componentInstanceBusinessLogic
             .getComponentInstanceAttributesByOutputId(component, output.getUniqueId());
-        if (CollectionUtils.isEmpty(componentInstancePropertiesDeclaredAsInput)) {
+        if (CollectionUtils.isEmpty(componentInstanceAttributesDeclaredAsOutput)) {
             return StorageOperationStatus.OK;
         }
+        unDeclareOutput(output, componentInstanceAttributesDeclaredAsOutput);
         return toscaOperationFacade
-            .updateComponentInstanceAttributes(component, componentInstancePropertiesDeclaredAsInput.get(0).getComponentInstanceId(),
-                componentInstancePropertiesDeclaredAsInput);
+            .updateComponentInstanceAttributes(component, componentInstanceAttributesDeclaredAsOutput.get(0).getComponentInstanceId(),
+                componentInstanceAttributesDeclaredAsOutput);
+    }
+
+    private void unDeclareOutput(OutputDefinition output,
+                                 List<ComponentInstanceAttribute> componentInstanceAttributesDeclaredAsOutput) {
+        componentInstanceAttributesDeclaredAsOutput.forEach(attribute -> {
+            Optional<GetOutputValueDataDefinition> attributeOutput =
+                attribute.getGetOutputValues().stream().filter(attOut -> output.getUniqueId().equals(attOut.getOutputId())).findFirst();
+            if (attributeOutput.isPresent()) {
+                attribute.getGetOutputValues().remove(attributeOutput.get());
+            }
+        });
     }
 }
index ff98163..ddbc5dc 100644 (file)
@@ -2248,14 +2248,35 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
     private ComponentInstanceAttribute validateAttributeExistsOnComponent(final ComponentInstanceAttribute attribute,
                                                                           final Component containerComponent,
                                                                           final ComponentInstance foundResourceInstance) {
-        final List<ComponentInstanceAttribute> instanceProperties =
+        final List<ComponentInstanceAttribute> instanceAttributes =
             containerComponent.getComponentInstancesAttributes().get(foundResourceInstance.getUniqueId());
+        final List<ComponentInstanceProperty> instanceProperties =
+            containerComponent.getComponentInstancesProperties().get(foundResourceInstance.getUniqueId());
         final Optional<ComponentInstanceAttribute> instanceAttribute =
+            instanceAttributes.stream().filter(p -> p.getName().equals(attribute.getName())).findAny();
+        final Optional<ComponentInstanceProperty> instanceProperty =
             instanceProperties.stream().filter(p -> p.getName().equals(attribute.getName())).findAny();
-        if (!instanceAttribute.isPresent()) {
-            throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, attribute.getName());
+        if (instanceAttribute.isPresent()) {
+            return instanceAttribute.get();
+        }
+        if (instanceProperty.isPresent()) {
+            ComponentInstanceAttribute propAttribute = getComponentInstanceAttribute(instanceProperty.get());
+            return propAttribute;
         }
-        return instanceAttribute.get();
+        throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, attribute.getName());
+    }
+
+    private ComponentInstanceAttribute getComponentInstanceAttribute(ComponentInstanceProperty property) {
+        ComponentInstanceAttribute attribute = new ComponentInstanceAttribute();
+        attribute.setParentUniqueId(property.getParentUniqueId());
+        attribute.setName(property.getName());
+        attribute.setOwnerId(property.getOwnerId());
+        attribute.setType(property.getType());
+        attribute.setSchema(property.getSchema());
+        attribute.setUniqueId(property.getUniqueId());
+        attribute.setValue(property.getValue());
+        attribute.setDefaultValue(property.getDefaultValue());
+        return attribute;
     }
 
     private ResponseFormat updateCapabilityPropertyOnContainerComponent(ComponentInstanceProperty property,
@@ -3051,7 +3072,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
             }
 
             Component eitherOriginComponent = getInstanceOriginNode(currentResourceInstance);
-            DataForMergeHolder dataHolder = compInstMergeDataBL.saveAllDataBeforeDeleting(containerComponent, currentResourceInstance, eitherOriginComponent);
+            DataForMergeHolder dataHolder =
+                compInstMergeDataBL.saveAllDataBeforeDeleting(containerComponent, currentResourceInstance, eitherOriginComponent);
             ComponentInstance resResourceInfo = deleteComponentInstance(containerComponent, componentInstanceId,
                 containerComponentType);
 
index 603270e..c38b3d8 100644 (file)
@@ -136,7 +136,8 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
             component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
             ImmutablePair<StorageOperationStatus, String> status = validateOutputName(component, componentInstOutputsMapUi);
             if (status.getLeft() != StorageOperationStatus.OK) {
-                throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.OUTPUT_NAME_ALREADY_EXIST, status.getRight()));
+                throw new ByResponseFormatComponentException(
+                    componentsUtils.getResponseFormat(ActionStatus.OUTPUT_NAME_ALREADY_EXIST, status.getRight()));
             }
             result = attributeDeclarationOrchestrator.declareAttributesToOutputs(component, componentInstOutputsMapUi)
                 .left().bind(outputsToCreate -> prepareOutputsForCreation(userId, componentId, outputsToCreate))
@@ -164,7 +165,7 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
     }
 
     private ImmutablePair<StorageOperationStatus, String> validateOutputName(final Component component,
-                                                                            final ComponentInstOutputsMap componentInstOutputsMapUi) {
+                                                                             final ComponentInstOutputsMap componentInstOutputsMapUi) {
         final Map<String, List<ComponentInstanceAttribOutput>> outputDeclaredProperties = new HashMap<>();
         if (MapUtils.isNotEmpty(componentInstOutputsMapUi.getComponentInstanceOutputsMap())) {
             outputDeclaredProperties.putAll(componentInstOutputsMapUi.getComponentInstanceOutputsMap());
@@ -300,7 +301,8 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
                     final var optionalComponentInstance = component.getComponentInstanceByName(getAttribute.get(0));
                     if (optionalComponentInstance.isPresent()) {
                         final var createdOutputs
-                            = createOutputs(component.getUniqueId(), userId, getAttribute.get(1), optionalComponentInstance.get(),outputDefinitionValue.getName());
+                            = createOutputs(component.getUniqueId(), userId, getAttribute.get(1), optionalComponentInstance.get(),
+                            outputDefinitionValue.getName());
                         if (createdOutputs.isRight()) {
                             return Either.right((createdOutputs.right().value()));
                         }
@@ -328,7 +330,7 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
             if (componentInstanceAttributeOptional.isPresent()) {
                 final var componentInstOutputsMap = new ComponentInstOutputsMap();
                 componentInstOutputsMap.setComponentInstanceAttributes(Collections.singletonMap(componentInstance.getUniqueId(),
-                    Collections.singletonList(new ComponentInstanceAttribOutput(componentInstanceAttributeOptional.get(),outputName))));
+                    Collections.singletonList(new ComponentInstanceAttribOutput(componentInstanceAttributeOptional.get(), outputName))));
                 return createMultipleOutputs(userId, componentUniqueId, ComponentTypeEnum.SERVICE,
                     componentInstOutputsMap, true, false);
             }
@@ -342,7 +344,7 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
                 final ComponentInstOutputsMap componentInstOutputsMap = new ComponentInstOutputsMap();
                 ComponentInstanceAttribOutput attribute = getComponentInstanceAttribOutput(propertyDefinition);
                 componentInstOutputsMap.setComponentInstanceAttributes(Collections.singletonMap(componentInstance.getUniqueId(),
-                    Collections.singletonList(new ComponentInstanceAttribOutput(attribute,outputName))));
+                    Collections.singletonList(new ComponentInstanceAttribOutput(attribute, outputName))));
                 return createMultipleOutputs(userId, componentUniqueId, ComponentTypeEnum.SERVICE, componentInstOutputsMap, true, false);
             }
         }
index 316c940..7dadbee 100644 (file)
@@ -2157,6 +2157,7 @@ public class ServiceImportBusinessLogic {
         if (originResource.getAttributes() != null && !originResource.getAttributes().isEmpty()) {
             instAttributes.put(resourceInstanceId, originResource.getAttributes());
             addAttributeValueToResourceInstance(instAttributes, uploadComponentInstanceInfo.getAttributes());
+            instAttributes.get(resourceInstanceId).addAll(addImplicitAttributeValues(originResource, uploadComponentInstanceInfo));
         }
         if (uploadComponentInstanceInfo.getUploadNodeFilterInfo() == null) {
             instNodeFilter.put(resourceInstanceId, new UploadNodeFilterInfo());
@@ -2187,6 +2188,41 @@ public class ServiceImportBusinessLogic {
         }
     }
 
+    private List<AttributeDefinition> addImplicitAttributeValues(Resource originResource, UploadComponentInstanceInfo uploadComponentInstanceInfo) {
+        List<String> origAttributes = originResource.getAttributes().stream().map(AttributeDefinition::getName).collect(toList());
+        Map<String, UploadAttributeInfo> uploadAttributes = uploadComponentInstanceInfo.getAttributes();
+        List<String> newAttributesToAdd =
+            uploadAttributes.keySet().stream().filter(newAttribute -> !origAttributes.contains(newAttribute))
+                .collect(toList());
+        List<PropertyDefinition> propsToAddAsAttributes =
+            originResource.getProperties().stream().filter(prop -> newAttributesToAdd.contains(prop.getName())).collect(toList());
+        propsToAddAsAttributes.stream().forEach(prop -> {
+            Object value = uploadAttributes.get(prop.getName()).getValue();
+            if (value instanceof Collection<?> || value instanceof Map<?, ?>) {
+                Gson gson = new Gson();
+                String json = gson.toJson(value);
+                prop.setValue(json);
+            } else {
+                prop.setValue(String.valueOf(value));
+            }
+        });
+        List<AttributeDefinition> attributesToAdd = new ArrayList<>();
+        for (PropertyDefinition prop: propsToAddAsAttributes) {
+            attributesToAdd.add(getPropertyAsAttribute(prop));
+        }
+        return attributesToAdd;
+    }
+
+    private AttributeDefinition getPropertyAsAttribute(PropertyDefinition property) {
+        AttributeDefinition attribute = new AttributeDefinition();
+        attribute.setName(property.getName());
+        attribute.setType(property.getType());
+        attribute.setSchema(property.getSchema());
+        attribute.setValue(property.getValue());
+        attribute.setDefaultValue(property.getDefaultValue());
+        return attribute;
+    }
+
     protected void addInputsValuesToRi(UploadComponentInstanceInfo uploadComponentInstanceInfo, Component component, Resource originResource,
                                        ComponentInstance currentCompInstance, Map<String, List<ComponentInstanceInput>> instInputs,
                                        Map<String, DataTypeDefinition> allDataTypes) {
index 4a98fa9..143fb7b 100644 (file)
@@ -16,6 +16,7 @@
  *  SPDX-License-Identifier: Apache-2.0
  *  ============LICENSE_END=========================================================
  */
+
 package org.openecomp.sdc.be.tosca;
 
 import com.google.gson.JsonElement;
@@ -183,7 +184,7 @@ public class AttributeConverter {
     public void convertAndAddValue(final Map<String, Object> attribs,
                                    final AttributeDefinition attribute) {
         final Object convertedValue = convertToToscaObject(attribute, attribute.getValue(), false);
-        if (!ToscaValueBaseConverter.isEmptyObjectValue(convertedValue)) {
+        if (!ToscaValueBaseConverter.isEmptyObjectValue(convertedValue) && !attribute.isGetOutputAttribute()) {
             attribs.put(attribute.getName(), convertedValue);
         }
     }
index 711e5b3..3bbbd1e 100644 (file)
@@ -105,8 +105,6 @@ export class AttributeModel extends AttributeBEModel implements IAttributeModel
       // forcing creating new object, so editing different one than the object in the table
       this.schema = new SchemaAttributeGroupModel(new SchemaAttribute(this.schema.property));
     }
-
-    this.convertValueToView();
   }
 
   public convertToServerObject(): string {
index e936042..a6ce288 100644 (file)
@@ -84,7 +84,7 @@
                         [attributeNameSearchText]="attributeNameSearchText"
                         [readonly]="readonly"
                         (attributeChanged)="onAttributeChanged(property)"
-                        (expandChild)="property.updateExpandedChildPropertyId($event)"
+                        (expandChild)="property.updateExpandedChildAttributeId($event)"
                         (clickOnAttributeRow)="onClickAttributeInnerRow($event, instanceId)"
                         (checkAttribute)="attributeChecked(property, $event)"
                         >
index 7f271af..f5de4aa 100644 (file)
@@ -89,7 +89,7 @@
             [attributeNameSearchText]="attributeNameSearchText"
             [readonly]="readonly"
             [hasChildren]="getHasChildren(prop)"
-            (propertyChanged)="childValueChanged(prop)"
+            (attributeChanged)="childValueChanged(prop)"
             (mapKeyChanged)="updateChildKeyInParent(prop, $event)"
             (expandChild)="expandChildById($event)"
             (deleteItem)="deleteListOrMapItem($event)"
index 48700f2..6dc8abf 100644 (file)
@@ -655,6 +655,8 @@ export class AttributesOutputsComponent {
           if (this.isAttributesTabSelected) {
             this.checkedAttributesCount = 0;
           }
+          this.hasChangedData = false;
+          this.isValidChangedData = false;
         },
         () => {
           this.Notification.error({