Import service with outputs mapped to implicit attributes
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / OutputsBusinessLogic.java
index cfb6004..62ef98b 100644 (file)
 package org.openecomp.sdc.be.components.impl;
 
 import fj.data.Either;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import org.apache.commons.collections4.CollectionUtils;
+import org.jetbrains.annotations.NotNull;
 import org.openecomp.sdc.be.components.attribute.AttributeDeclarationOrchestrator;
 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
@@ -33,11 +36,16 @@ import org.openecomp.sdc.be.components.validation.ComponentValidations;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.dao.utils.MapUtil;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.ComponentInstOutputsMap;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.ComponentInstanceAttribOutput;
+import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
 import org.openecomp.sdc.be.model.ComponentInstanceOutput;
 import org.openecomp.sdc.be.model.ComponentParametersView;
 import org.openecomp.sdc.be.model.OutputDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
@@ -52,29 +60,26 @@ import org.openecomp.sdc.common.log.enums.StatusCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 
 @org.springframework.stereotype.Component("outputsBusinessLogic")
 public class OutputsBusinessLogic extends BaseBusinessLogic {
 
     private static final String CREATE_OUTPUT = "CreateOutput";
-
     private static final Logger log = Logger.getLogger(OutputsBusinessLogic.class);
     private static final String FAILED_TO_FOUND_COMPONENT_ERROR = "Failed to found component {}, error: {}";
-    private static final String GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP = "Going to execute rollback on create group.";
-    private static final String GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP = "Going to execute commit on create group.";
+    private static final String GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_OUTPUTS = "Going to execute rollback on create outputs.";
+    private static final String GOING_TO_EXECUTE_COMMIT_ON_CREATE_OUTPUTS = "Going to execute commit on create outputs.";
     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(OutputsBusinessLogic.class);
-    private static final String FAILED_TO_FOUND_COMPONENT_INSTANCE_OUTPUTS_COMPONENT_INSTANCE_ID = "Failed to found component instance outputs componentInstanceId: {}";
+    private static final String FAILED_TO_FOUND_COMPONENT_INSTANCE_OUTPUTS_COMPONENT_INSTANCE_ID =
+        "Failed to found component instance outputs componentInstanceId: {}";
     private static final String FAILED_TO_FOUND_COMPONENT_INSTANCE_OUTPUTS_ERROR = "Failed to found component instance outputs {}, error: {}";
-
     private final AttributeDeclarationOrchestrator attributeDeclarationOrchestrator;
 
     @Autowired
-    public OutputsBusinessLogic(final IElementOperation elementDao,
-                                final IGroupOperation groupOperation,
-                                final IGroupInstanceOperation groupInstanceOperation,
-                                final IGroupTypeOperation groupTypeOperation,
-                                final InterfaceOperation interfaceOperation,
-                                final InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
+    public OutputsBusinessLogic(final IElementOperation elementDao, final IGroupOperation groupOperation,
+                                final IGroupInstanceOperation groupInstanceOperation, final IGroupTypeOperation groupTypeOperation,
+                                final InterfaceOperation interfaceOperation, final InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
                                 final AttributeDeclarationOrchestrator attributeDeclarationOrchestrator,
                                 final ArtifactsOperations artifactToscaOperation) {
         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
@@ -82,82 +87,64 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
         this.attributeDeclarationOrchestrator = attributeDeclarationOrchestrator;
     }
 
-    public Either<List<ComponentInstanceOutput>, ResponseFormat> getComponentInstanceOutputs(final String userId,
-                                                                                             final String componentId,
+    public Either<List<ComponentInstanceOutput>, ResponseFormat> getComponentInstanceOutputs(final String userId, final String componentId,
                                                                                              final String componentInstanceId) {
-
         validateUserExists(userId);
         final ComponentParametersView filters = new ComponentParametersView();
         filters.disableAll();
         filters.setIgnoreOutputs(false);
         filters.setIgnoreComponentInstances(false);
         filters.setIgnoreComponentInstancesOutputs(false);
-
         final Either<Component, StorageOperationStatus> getComponentEither = toscaOperationFacade.getToscaElement(componentId, filters);
-        if(getComponentEither.isRight()){
+        if (getComponentEither.isRight()) {
             ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
             log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
             return Either.right(componentsUtils.getResponseFormat(actionStatus));
-
         }
         final Component component = getComponentEither.left().value();
-
         if (!ComponentValidations.validateComponentInstanceExist(component, componentInstanceId)) {
             final ActionStatus actionStatus = ActionStatus.COMPONENT_INSTANCE_NOT_FOUND;
             log.debug(FAILED_TO_FOUND_COMPONENT_INSTANCE_OUTPUTS_ERROR, componentInstanceId, actionStatus);
-            loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, component.getComponentMetadataForSupportLog(),
-                StatusCode.ERROR, FAILED_TO_FOUND_COMPONENT_INSTANCE_OUTPUTS_COMPONENT_INSTANCE_ID, componentInstanceId);
+            loggerSupportability.log(LoggerSupportabilityActions.CREATE_OUTPUTS, component.getComponentMetadataForSupportLog(), StatusCode.ERROR,
+                FAILED_TO_FOUND_COMPONENT_INSTANCE_OUTPUTS_COMPONENT_INSTANCE_ID, componentInstanceId);
             return Either.right(componentsUtils.getResponseFormat(actionStatus));
         }
         final Map<String, List<ComponentInstanceOutput>> ciOutputs = Optional.ofNullable(component.getComponentInstancesOutputs())
             .orElse(Collections.emptyMap());
-
         return Either.left(ciOutputs.getOrDefault(componentInstanceId, Collections.emptyList()));
     }
 
     @Override
-    public Either<List<OutputDefinition>, ResponseFormat> declareAttributes(final String userId,
-                                                                            final String componentId,
+    public Either<List<OutputDefinition>, ResponseFormat> declareAttributes(final String userId, final String componentId,
                                                                             final ComponentTypeEnum componentTypeEnum,
                                                                             final ComponentInstOutputsMap componentInstOutputsMap) {
-
         return createMultipleOutputs(userId, componentId, componentTypeEnum, componentInstOutputsMap, true, false);
     }
 
-    public Either<List<OutputDefinition>, ResponseFormat> createMultipleOutputs(final String userId,
-                                                                                final String componentId,
-                                                                                final ComponentTypeEnum componentType,
-                                                                                final ComponentInstOutputsMap componentInstOutputsMapUi,
-                                                                                final boolean shouldLockComp,
-                                                                                final boolean inTransaction) {
-
-        Either<List<OutputDefinition>, ResponseFormat> result = null;
+    private Either<List<OutputDefinition>, ResponseFormat> createMultipleOutputs(final String userId, final String componentId,
+                                                                                 final ComponentTypeEnum componentType,
+                                                                                 final ComponentInstOutputsMap componentInstOutputsMapUi,
+                                                                                 final boolean shouldLockComp, final boolean inTransaction) {
+        Either<List<OutputDefinition>, ResponseFormat> result = Either.right(new ResponseFormat(HttpStatus.BAD_REQUEST.value()));
         org.openecomp.sdc.be.model.Component component = null;
-
         try {
             validateUserExists(userId);
-
             component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
-
-            result = attributeDeclarationOrchestrator.declareAttributesToOutputs(component, componentInstOutputsMapUi)
-                .left()
-                .bind(outputsToCreate -> prepareOutputsForCreation(userId, componentId, outputsToCreate))
-                .right()
+            result = attributeDeclarationOrchestrator.declareAttributesToOutputs(component, componentInstOutputsMapUi).left()
+                .bind(outputsToCreate -> prepareOutputsForCreation(userId, componentId, outputsToCreate)).right()
                 .map(componentsUtils::getResponseFormat);
             return result;
-
         } catch (final ByResponseFormatComponentException e) {
             log.error("#createMultipleOutputs: Exception thrown: ", e);
             result = Either.right(e.getResponseFormat());
             return result;
         } finally {
-
             if (!inTransaction) {
-                if (result == null || result.isRight()) {
-                    log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
+                if (result.isRight()) {
+                    log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_OUTPUTS);
                     janusGraphDao.rollback();
                 } else {
-                    log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
+                    log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_OUTPUTS);
                     janusGraphDao.commit();
                 }
             }
@@ -165,16 +152,14 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
             if (shouldLockComp && component != null) {
                 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
             }
-
         }
     }
 
-    private org.openecomp.sdc.be.model.Component getAndValidateComponentForCreate(final String userId,
-                                                                                  final String componentId,
-                                                                                  final ComponentTypeEnum componentType,
-                                                                                  final boolean shouldLockComp) {
+    private Component getAndValidateComponentForCreate(final String userId, final String componentId,
+                                                       final ComponentTypeEnum componentType,
+                                                       final boolean shouldLockComp) {
         final ComponentParametersView componentParametersView = getBaseComponentParametersView();
-        final org.openecomp.sdc.be.model.Component component = validateComponentExists(componentId, componentType, componentParametersView);
+        final Component component = validateComponentExists(componentId, componentType, componentParametersView);
         if (shouldLockComp) {
             // lock the component
             lockComponent(component, CREATE_OUTPUT);
@@ -183,15 +168,15 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
         return component;
     }
 
-    private Either<List<OutputDefinition>, StorageOperationStatus> prepareOutputsForCreation(final String userId,
-                                                                                             final String cmptId,
+    private Either<List<OutputDefinition>, StorageOperationStatus> prepareOutputsForCreation(final String userId, final String cmptId,
                                                                                              final List<OutputDefinition> outputsToCreate) {
         final Map<String, OutputDefinition> outputsToPersist = MapUtil.toMap(outputsToCreate, OutputDefinition::getName);
         assignOwnerIdToOutputs(userId, outputsToPersist);
-
-        return toscaOperationFacade.addOutputsToComponent(outputsToPersist, cmptId)
-            .left()
-            .map(persistedOutputs -> outputsToCreate);
+        final var statusEither = toscaOperationFacade.addOutputsToComponent(outputsToPersist, cmptId);
+        if (statusEither.isRight()) {
+            return statusEither;
+        }
+        return statusEither.left().map(persistedOutputs -> outputsToCreate);
     }
 
     private void assignOwnerIdToOutputs(final String userId, final Map<String, OutputDefinition> outputsToCreate) {
@@ -219,24 +204,18 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
      * @return
      */
     public OutputDefinition deleteOutput(final String componentId, final String userId, final String outputId) {
-
-        Either<OutputDefinition, ResponseFormat> deleteEither = null;
         if (log.isDebugEnabled()) {
             log.debug("Going to delete output id: {}", outputId);
         }
-
         validateUserExists(userId);
-
         final ComponentParametersView componentParametersView = getBaseComponentParametersView();
         componentParametersView.setIgnoreAttributes(false);
-
-        final Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> componentEither =
-            toscaOperationFacade.getToscaElement(componentId, componentParametersView);
+        final Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> componentEither = toscaOperationFacade
+            .getToscaElement(componentId, componentParametersView);
         if (componentEither.isRight()) {
             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(componentEither.right().value()));
         }
         final org.openecomp.sdc.be.model.Component component = componentEither.left().value();
-
         // Validate outputId is child of the component
         final Optional<OutputDefinition> optionalOutput = component.getOutputs().stream().
             // filter by ID
@@ -246,23 +225,19 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
         if (!optionalOutput.isPresent()) {
             throw new ByActionStatusComponentException(ActionStatus.OUTPUT_IS_NOT_CHILD_OF_COMPONENT, outputId, componentId);
         }
-
         final OutputDefinition outputForDelete = optionalOutput.get();
-
         // Lock component
         lockComponent(componentId, component, "deleteOutput");
         // Delete output operations
         boolean failed = false;
         try {
-            final StorageOperationStatus status =
-                toscaOperationFacade.deleteOutputOfResource(component, outputForDelete.getName());
+            final StorageOperationStatus status = toscaOperationFacade.deleteOutputOfResource(component, outputForDelete.getName());
             if (status != StorageOperationStatus.OK) {
                 log.debug("Component id: {} delete output id: {} failed", componentId, outputId);
                 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status), component.getName());
             }
-
-            final StorageOperationStatus storageOperationStatus =
-                attributeDeclarationOrchestrator.unDeclareAttributesAsOutputs(component, outputForDelete);
+            final StorageOperationStatus storageOperationStatus = attributeDeclarationOrchestrator
+                .unDeclareAttributesAsOutputs(component, outputForDelete);
             if (storageOperationStatus != StorageOperationStatus.OK) {
                 log.debug("Component id: {} update attributes declared as output for outputId: {} failed", componentId, outputId);
                 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(storageOperationStatus), component.getName());
@@ -276,4 +251,86 @@ public class OutputsBusinessLogic extends BaseBusinessLogic {
         }
     }
 
+    public Either<List<OutputDefinition>, ResponseFormat> createOutputsInGraph(final Map<String, OutputDefinition> outputs,
+                                                                               final Component component,
+                                                                               final String userId) {
+
+        final List<OutputDefinition> result = new ArrayList<>();
+        for (final Map.Entry<String, OutputDefinition> outputDefinition : outputs.entrySet()) {
+            final var outputDefinitionValue = outputDefinition.getValue();
+            outputDefinitionValue.setName(outputDefinition.getKey());
+
+            final String value = outputDefinitionValue.getValue();
+            if (value != null) {
+                final List<String> getAttribute = (List<String>) ImportUtils.loadYamlAsStrictMap(value)
+                    .get(ToscaGetFunctionType.GET_ATTRIBUTE.getFunctionName());
+                if (getAttribute.size() == 2) {
+                    final var optionalComponentInstance = component.getComponentInstanceByName(getAttribute.get(0));
+                    if (optionalComponentInstance.isPresent()) {
+                        final var createdOutputs
+                            = createOutputs(component.getUniqueId(), userId, getAttribute.get(1), optionalComponentInstance.get());
+                        if (createdOutputs.isRight()) {
+                            return Either.right((createdOutputs.right().value()));
+                        }
+                        result.addAll(createdOutputs.left().value());
+                    } else {
+                        // From SELF
+                        outputDefinitionValue.setInstanceUniqueId(component.getUniqueId());
+                    }
+                }
+            }
+        }
+        return Either.left(result);
+
+    }
+
+    private Either<List<OutputDefinition>, ResponseFormat> createOutputs(final String componentUniqueId, final String userId,
+                                                                         final String attributeName,
+                                                                         final ComponentInstance componentInstance) {
+        // From Instance
+        final List<OutputDefinition> result = new ArrayList<>();
+        final var componentInstanceAttributes = componentInstance.getAttributes();
+        if (CollectionUtils.isNotEmpty(componentInstanceAttributes)) {
+            final var componentInstanceAttributeOptional = componentInstanceAttributes.stream()
+                .filter(ad -> ad.getName().equals(attributeName)).map(ComponentInstanceAttribute::new).findFirst();
+            if (componentInstanceAttributeOptional.isPresent()) {
+                final var componentInstOutputsMap = new ComponentInstOutputsMap();
+                componentInstOutputsMap.setComponentInstanceAttributes(Collections.singletonMap(componentInstance.getUniqueId(),
+                    Collections.singletonList(new ComponentInstanceAttribOutput(componentInstanceAttributeOptional.get()))));
+                final var createdOutputs = createMultipleOutputs(userId, componentUniqueId, ComponentTypeEnum.SERVICE,
+                    componentInstOutputsMap, true, false);
+                if (createdOutputs.isRight()) {
+                    return Either.right((createdOutputs.right().value()));
+                }
+                result.addAll(createdOutputs.left().value());
+            }
+        }
+        final List<PropertyDefinition> componentInstanceProperties = componentInstance.getProperties();
+        if (CollectionUtils.isNotEmpty(componentInstanceProperties)) {
+            final Optional<PropertyDefinition> componentInstancePropertyOptional = componentInstanceProperties.stream()
+                .filter(prop -> prop.getName().equals(attributeName)).findFirst();
+            if (componentInstancePropertyOptional.isPresent()) {
+                PropertyDefinition propertyDefinition = componentInstancePropertyOptional.get();
+                final ComponentInstOutputsMap componentInstOutputsMap = new ComponentInstOutputsMap();
+                ComponentInstanceAttribOutput attribute = getComponentInstanceAttribOutput(propertyDefinition);
+                componentInstOutputsMap.setComponentInstanceAttributes(Collections.singletonMap(componentInstance.getUniqueId(),
+                    Collections.singletonList(new ComponentInstanceAttribOutput(attribute))));
+                return createMultipleOutputs(userId, componentUniqueId, ComponentTypeEnum.SERVICE, componentInstOutputsMap, true, false);
+            }
+        }
+        return Either.left(result);
+    }
+
+    @NotNull
+    private ComponentInstanceAttribOutput getComponentInstanceAttribOutput(PropertyDefinition propertyDefinition) {
+        ComponentInstanceAttribOutput attribute = new ComponentInstanceAttribOutput();
+        attribute.setParentUniqueId(propertyDefinition.getParentUniqueId());
+        attribute.setName(propertyDefinition.getName());
+        attribute.setOwnerId(propertyDefinition.getOwnerId());
+        attribute.setType(propertyDefinition.getType());
+        attribute.setSchema(propertyDefinition.getSchema());
+        attribute.setUniqueId(propertyDefinition.getUniqueId());
+        return attribute;
+    }
+
 }