Add node_filter capabilities 90/111890/3
authoraribeiro <anderson.ribeiro@est.tech>
Mon, 24 Aug 2020 16:09:20 +0000 (17:09 +0100)
committerSébastien Determe <sebastien.determe@intl.att.com>
Mon, 7 Sep 2020 07:11:49 +0000 (07:11 +0000)
Issue-ID: SDC-3263
Signed-off-by: aribeiro <anderson.ribeiro@est.tech>
Change-Id: I2965c8b0b9331b035ba5f9cc7f58d9ea3af26402

catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentNodeFilterBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentNodeFilterServlet.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentNodeFilterBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ComponentNodeFilterServletTest.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeFilterOperation.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/NodeFilterConstraintType.java [new file with mode: 0644]

index de6836d..ac5af15 100644 (file)
@@ -32,8 +32,11 @@ import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction;
 import org.openecomp.sdc.be.components.validation.NodeFilterValidator;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.NodeFilterConstraintType;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.ComponentInstance;
 import org.openecomp.sdc.be.model.User;
@@ -166,15 +169,14 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic {
         return Optional.ofNullable(result.left().value());
     }
 
-
-
     public Optional<CINodeFilterDataDefinition> addNodeFilter(final String componentId,
                                                               final String componentInstanceId,
                                                               final NodeFilterConstraintAction action,
                                                               final String propertyName,
                                                               final String constraint,
                                                               final boolean shouldLock,
-                                                              final ComponentTypeEnum componentTypeEnum)
+                                                              final ComponentTypeEnum componentTypeEnum,
+                                                              final NodeFilterConstraintType nodeFilterConstraintType)
         throws BusinessLogicException {
 
         final Component component = getComponent(componentId);
@@ -186,13 +188,13 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic {
                 lockComponent(component.getUniqueId(), component,"Add Node Filter on Component");
                 wasLocked = true;
             }
-            final RequirementNodeFilterPropertyDataDefinition newProperty =
+            final RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition =
                 new RequirementNodeFilterPropertyDataDefinition();
-            newProperty.setName(propertyName);
-            newProperty.setConstraints(Collections.singletonList(constraint));
-            final Either<CINodeFilterDataDefinition, StorageOperationStatus> result = nodeFilterOperation
-                .addNewProperty(componentId, componentInstanceId, nodeFilterDataDefinition, newProperty);
-
+            requirementNodeFilterPropertyDataDefinition.setName(propertyName);
+            requirementNodeFilterPropertyDataDefinition.setConstraints(Collections.singletonList(constraint));
+            final Either<CINodeFilterDataDefinition, StorageOperationStatus> result = addNewNodeFilter(componentId,
+                componentInstanceId, propertyName, nodeFilterConstraintType, nodeFilterDataDefinition,
+                requirementNodeFilterPropertyDataDefinition);
             if (result.isRight()) {
                 janusGraphDao.rollback();
                 throw new BusinessLogicException(componentsUtils.getResponseFormatByResource(componentsUtils
@@ -322,6 +324,30 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic {
         return Optional.ofNullable(nodeFilterDataDefinition);
     }
 
+    private Either<CINodeFilterDataDefinition, StorageOperationStatus> addNewNodeFilter(
+        final String componentId,
+        final String componentInstanceId,
+        final String propertyName,
+        final NodeFilterConstraintType nodeFilterConstraintType,
+        final CINodeFilterDataDefinition nodeFilterDataDefinition,
+        final RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition) {
+
+        if (NodeFilterConstraintType.PROPERTIES.equals(nodeFilterConstraintType)) {
+            return nodeFilterOperation.addNewProperty(componentId, componentInstanceId, nodeFilterDataDefinition,
+                requirementNodeFilterPropertyDataDefinition);
+        }
+        final RequirementNodeFilterCapabilityDataDefinition requirementNodeFilterCapabilityDataDefinition =
+            new RequirementNodeFilterCapabilityDataDefinition();
+        requirementNodeFilterCapabilityDataDefinition.setName(propertyName);
+        final ListDataDefinition<RequirementNodeFilterPropertyDataDefinition>
+            propertyDataDefinitionListDataDefinition = new ListDataDefinition<>();
+        propertyDataDefinitionListDataDefinition.getListToscaDataDefinition().addAll(
+            Collections.singleton(requirementNodeFilterPropertyDataDefinition));
+        requirementNodeFilterCapabilityDataDefinition.setProperties(propertyDataDefinitionListDataDefinition);
+        return nodeFilterOperation.addNewCapabilities(componentId, componentInstanceId, nodeFilterDataDefinition,
+            requirementNodeFilterCapabilityDataDefinition);
+    }
+
     private void unlockComponent(final String componentUniqueId,
                                  final ComponentTypeEnum componentType) {
         graphLockOperation.unlockComponent(componentUniqueId, componentType.getNodeType());
@@ -398,4 +424,4 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic {
                 .getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND, response.right().value().getFormattedMessage()));
         }
     }
-}
\ No newline at end of file
+}
index aa9b931..a682dc9 100644 (file)
@@ -53,6 +53,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor;
 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.NodeFilterConstraintType;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.impl.ServletUtils;
 import org.openecomp.sdc.be.model.User;
@@ -64,7 +65,7 @@ import org.openecomp.sdc.common.api.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-@Path("/v1/catalog/{componentType}/{componentId}/resourceInstances/{componentInstanceId}/nodeFilter")
+@Path("/v1/catalog/{componentType}/{componentId}/resourceInstances/{componentInstanceId}/nodeFilter/{constraintType}")
 @Consumes(MediaType.APPLICATION_JSON)
 @Produces(MediaType.APPLICATION_JSON)
 @Singleton
@@ -104,7 +105,6 @@ public class ComponentNodeFilterServlet extends AbstractValidationsServlet {
     @POST
     @Consumes(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/")
     @Operation(description = "Add Component Filter Constraint", method = "POST",
         summary = "Add Component Filter Constraint", responses = {
         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
@@ -120,6 +120,10 @@ public class ComponentNodeFilterServlet extends AbstractValidationsServlet {
             schema = @Schema(allowableValues = {
                 ComponentTypeEnum.RESOURCE_PARAM_NAME,
                 ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") final String componentType,
+        @Parameter(description = "Constraint type. Valid values: properties / capabilities",
+            schema = @Schema(allowableValues = {NodeFilterConstraintType.PROPERTIES_PARAM_NAME,
+                NodeFilterConstraintType.CAPABILITIES_PARAM_NAME}))
+        @PathParam("constraintType") final String constraintType,
         @Context final HttpServletRequest request,
         @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
 
@@ -138,9 +142,17 @@ public class ComponentNodeFilterServlet extends AbstractValidationsServlet {
             final UIConstraint uiConstraint = convertResponse.get();
             final String constraint = new ConstraintConvertor().convert(uiConstraint);
 
+            final Optional<NodeFilterConstraintType> nodeFilterConstraintType =
+                NodeFilterConstraintType.parse(constraintType);
+            if (!nodeFilterConstraintType.isPresent()) {
+                return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT_PARAM,
+                    "Invalid value for NodeFilterConstraintType enum %s", constraintType));
+            }
+
             final Optional<CINodeFilterDataDefinition> actionResponse = componentNodeFilterBusinessLogic
                 .addNodeFilter(componentId.toLowerCase(), componentInstanceId, NodeFilterConstraintAction.ADD,
-                    uiConstraint.getServicePropertyName(), constraint, true, componentTypeEnum);
+                    uiConstraint.getServicePropertyName(), constraint, true, componentTypeEnum,
+                    nodeFilterConstraintType.get());
 
             if (!actionResponse.isPresent()) {
                 LOGGER.error(FAILED_TO_CREATE_NODE_FILTER);
@@ -160,7 +172,6 @@ public class ComponentNodeFilterServlet extends AbstractValidationsServlet {
     @PUT
     @Consumes(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/")
     @Operation(description = "Update Component Filter Constraint", method = "PUT",
         summary = "Update Component Filter Constraint", responses = {
         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
@@ -176,6 +187,10 @@ public class ComponentNodeFilterServlet extends AbstractValidationsServlet {
             schema = @Schema(allowableValues = {
                 ComponentTypeEnum.RESOURCE_PARAM_NAME,
                 ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") final String componentType,
+        @Parameter(description = "Constraint type. Valid values: properties / capabilities",
+            schema = @Schema(allowableValues = {NodeFilterConstraintType.PROPERTIES_PARAM_NAME,
+                NodeFilterConstraintType.CAPABILITIES_PARAM_NAME}))
+        @PathParam("constraintType") final String constraintType,
         @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
 
         LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI());
@@ -230,6 +245,10 @@ public class ComponentNodeFilterServlet extends AbstractValidationsServlet {
             schema = @Schema(allowableValues = {
                 ComponentTypeEnum.RESOURCE_PARAM_NAME,
                 ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") final String componentType,
+        @Parameter(description = "Constraint type. Valid values: properties / capabilities",
+            schema = @Schema(allowableValues = {NodeFilterConstraintType.PROPERTIES_PARAM_NAME,
+                NodeFilterConstraintType.CAPABILITIES_PARAM_NAME}))
+        @PathParam("constraintType") final String constraintType,
         @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
 
         LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI());
index c4a4ace..6996465 100644 (file)
@@ -25,6 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -43,7 +45,6 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
@@ -57,8 +58,10 @@ import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
 import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor;
 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.NodeFilterConstraintType;
 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.ComponentInstance;
@@ -145,7 +148,7 @@ public class ComponentNodeFilterBusinessLogicTest extends BaseBusinessLogicMock
         when(toscaOperationFacade.getToscaElement(componentId)).thenReturn(Either.left(resource));
         when(graphLockOperation.lockComponent(componentId, NodeTypeEnum.Resource))
             .thenReturn(StorageOperationStatus.OK);
-        when(componentsUtils.convertFromStorageResponse(Mockito.any())).thenReturn(ActionStatus.GENERAL_ERROR);
+        when(componentsUtils.convertFromStorageResponse(any())).thenReturn(ActionStatus.GENERAL_ERROR);
         when(nodeFilterOperation.createNodeFilter(componentId, componentInstanceId))
             .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR));
         when(graphLockOperation.unlockComponent(componentId, NodeTypeEnum.Resource))
@@ -245,6 +248,76 @@ public class ComponentNodeFilterBusinessLogicTest extends BaseBusinessLogicMock
         verify(graphLockOperation, times(1)).unlockComponent(componentId, NodeTypeEnum.Resource);
     }
 
+    @Test
+    public void addNodeFilterPropertiesTest() throws BusinessLogicException {
+        componentInstance.setNodeFilter(ciNodeFilterDataDefinition);
+
+        when(toscaOperationFacade.getToscaElement(componentId)).thenReturn(Either.left(resource));
+        when(nodeFilterValidator
+            .validateFilter(resource, componentInstanceId,
+                requirementNodeFilterPropertyDataDefinition.getConstraints(),
+                NodeFilterConstraintAction.ADD)).thenReturn(Either.left(true));
+        when(nodeFilterValidator.validateComponentInstanceExist(resource, componentInstanceId))
+            .thenReturn(Either.left(true));
+        when(graphLockOperation.lockComponent(componentId, NodeTypeEnum.Resource))
+            .thenReturn(StorageOperationStatus.OK);
+        when(nodeFilterOperation.addNewProperty(anyString(), anyString(), any(CINodeFilterDataDefinition.class),
+            any(RequirementNodeFilterPropertyDataDefinition.class))).thenReturn(Either.left(ciNodeFilterDataDefinition));
+        when(graphLockOperation.unlockComponent(componentId, NodeTypeEnum.Resource))
+            .thenReturn(StorageOperationStatus.OK);
+
+        final Optional<CINodeFilterDataDefinition> result = componentNodeFilterBusinessLogic
+            .addNodeFilter(componentId, componentInstanceId, NodeFilterConstraintAction.ADD,
+                "MyPropertyName", constraint, true, ComponentTypeEnum.RESOURCE,
+                NodeFilterConstraintType.PROPERTIES);
+
+        assertThat(result).isPresent();
+        assertThat(result.get().getProperties().getListToscaDataDefinition()).hasSize(1);
+        verify(toscaOperationFacade, times(1)).getToscaElement(componentId);
+        verify(nodeFilterValidator, times(1)).validateFilter(resource, componentInstanceId,
+            Collections.singletonList(constraint), NodeFilterConstraintAction.ADD);
+        verify(graphLockOperation, times(1)).lockComponent(componentId, NodeTypeEnum.Resource);
+        verify(nodeFilterOperation, times(1))
+            .addNewProperty(anyString(), anyString(), any(CINodeFilterDataDefinition.class),
+                any(RequirementNodeFilterPropertyDataDefinition.class));
+        verify(graphLockOperation, times(1)).unlockComponent(componentId, NodeTypeEnum.Resource);
+    }
+
+    @Test
+    public void addNodeFilterCapabilitiesTest() throws BusinessLogicException {
+        componentInstance.setNodeFilter(ciNodeFilterDataDefinition);
+
+        when(toscaOperationFacade.getToscaElement(componentId)).thenReturn(Either.left(resource));
+        when(nodeFilterValidator
+            .validateFilter(resource, componentInstanceId,
+                requirementNodeFilterPropertyDataDefinition.getConstraints(),
+                NodeFilterConstraintAction.ADD)).thenReturn(Either.left(true));
+        when(nodeFilterValidator.validateComponentInstanceExist(resource, componentInstanceId))
+            .thenReturn(Either.left(true));
+        when(graphLockOperation.lockComponent(componentId, NodeTypeEnum.Resource))
+            .thenReturn(StorageOperationStatus.OK);
+        when(nodeFilterOperation.addNewCapabilities(anyString(), anyString(), any(CINodeFilterDataDefinition.class),
+            any(RequirementNodeFilterCapabilityDataDefinition.class))).thenReturn(Either.left(ciNodeFilterDataDefinition));
+        when(graphLockOperation.unlockComponent(componentId, NodeTypeEnum.Resource))
+            .thenReturn(StorageOperationStatus.OK);
+
+        final Optional<CINodeFilterDataDefinition> result = componentNodeFilterBusinessLogic
+            .addNodeFilter(componentId, componentInstanceId, NodeFilterConstraintAction.ADD,
+                "MyPropertyName", constraint, true, ComponentTypeEnum.RESOURCE,
+                NodeFilterConstraintType.CAPABILITIES);
+
+        assertThat(result).isPresent();
+        assertThat(result.get().getProperties().getListToscaDataDefinition()).hasSize(1);
+        verify(toscaOperationFacade, times(1)).getToscaElement(componentId);
+        verify(nodeFilterValidator, times(1)).validateFilter(resource, componentInstanceId,
+            Collections.singletonList(constraint), NodeFilterConstraintAction.ADD);
+        verify(graphLockOperation, times(1)).lockComponent(componentId, NodeTypeEnum.Resource);
+        verify(nodeFilterOperation, times(1))
+            .addNewCapabilities(anyString(), anyString(), any(CINodeFilterDataDefinition.class),
+                any(RequirementNodeFilterCapabilityDataDefinition.class));
+        verify(graphLockOperation, times(1)).unlockComponent(componentId, NodeTypeEnum.Resource);
+    }
+
     @Test
     public void addNodeFilterFailTest() {
         componentInstance.setNodeFilter(ciNodeFilterDataDefinition);
@@ -264,7 +337,8 @@ public class ComponentNodeFilterBusinessLogicTest extends BaseBusinessLogicMock
         final List<String> constraints = requirementNodeFilterPropertyDataDefinition.getConstraints();
         assertThrows(BusinessLogicException.class, () -> componentNodeFilterBusinessLogic
             .addNodeFilter(componentId, componentInstanceId, NodeFilterConstraintAction.ADD,
-                "MyPropertyName", constraint, true, ComponentTypeEnum.RESOURCE));
+                "MyPropertyName", constraint, true, ComponentTypeEnum.RESOURCE,
+                NodeFilterConstraintType.PROPERTIES));
 
         verify(toscaOperationFacade, times(1)).getToscaElement(componentId);
         verify(graphLockOperation, times(1)).lockComponent(componentId, NodeTypeEnum.Resource);
@@ -285,7 +359,8 @@ public class ComponentNodeFilterBusinessLogicTest extends BaseBusinessLogicMock
 
         assertThrows(BusinessLogicException.class, () -> componentNodeFilterBusinessLogic
             .addNodeFilter(componentId, componentInstanceId, NodeFilterConstraintAction.ADD,
-                "MyPropertyName", constraint, true, ComponentTypeEnum.RESOURCE));
+                "MyPropertyName", constraint, true, ComponentTypeEnum.RESOURCE,
+                NodeFilterConstraintType.PROPERTIES));
     }
 
     @Test
@@ -477,4 +552,4 @@ public class ComponentNodeFilterBusinessLogicTest extends BaseBusinessLogicMock
             fail(e.getMessage());
         }
     }
-}
\ No newline at end of file
+}
index 08890ef..3bad7dd 100644 (file)
@@ -72,6 +72,7 @@ import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.NodeFilterConstraintType;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.impl.ServletUtils;
 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
@@ -143,10 +144,11 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
     }
 
     @Test
-    public void addNodeFilterSuccessTest() throws BusinessLogicException, JsonProcessingException {
+    public void addNodeFilterPropertiesSuccessTest() throws BusinessLogicException, JsonProcessingException {
         initComponentData();
-        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter";
-        final String path = String.format(pathFormat, componentType, componentId, componentInstance);
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance,
+            NodeFilterConstraintType.PROPERTIES_PARAM_NAME);
 
         when(userValidations.validateUserExists(user)).thenReturn(user);
         when(componentNodeFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
@@ -160,7 +162,7 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
         assertThat(sourceName).isEqualToIgnoringCase(uiConstraint.getSourceName());
         assertThat(propertyValue).isEqualToIgnoringCase(uiConstraint.getValue().toString());
 
-        when(componentsUtils.parseToConstraint(anyString(), any(User.class),ArgumentMatchers.any(ComponentTypeEnum.class)))
+        when(componentsUtils.parseToConstraint(anyString(), any(User.class), ArgumentMatchers.any(ComponentTypeEnum.class)))
             .thenReturn(Optional.of(uiConstraint));
 
         assertNotNull(constraint);
@@ -169,7 +171,8 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
         assertThat("resourceType: {equal: resourceTypeValue}\n").isEqualToIgnoringCase(constraint);
         when(componentNodeFilterBusinessLogic
             .addNodeFilter(componentId, componentInstance, NodeFilterConstraintAction.ADD,
-                uiConstraint.getServicePropertyName(), constraint, true, ComponentTypeEnum.RESOURCE))
+                uiConstraint.getServicePropertyName(), constraint, true, ComponentTypeEnum.RESOURCE,
+                NodeFilterConstraintType.PROPERTIES))
             .thenReturn(Optional.of(ciNodeFilterDataDefinition));
 
         final Response response = target()
@@ -179,8 +182,44 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
             .post(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
 
         verify(componentNodeFilterBusinessLogic, times(1))
-            .addNodeFilter(anyString(), anyString(), ArgumentMatchers.any(NodeFilterConstraintAction.class), anyString(), anyString(), anyBoolean(),
-            ArgumentMatchers.any(ComponentTypeEnum.class));
+            .addNodeFilter(anyString(), anyString(), ArgumentMatchers.any(NodeFilterConstraintAction.class), anyString(),
+                anyString(), anyBoolean(), ArgumentMatchers.any(ComponentTypeEnum.class),
+                ArgumentMatchers.any(NodeFilterConstraintType.class));
+
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200);
+    }
+
+    @Test
+    public void addNodeFilterCapabilitiesSuccessTest() throws BusinessLogicException, JsonProcessingException {
+        initComponentData();
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance,
+            NodeFilterConstraintType.CAPABILITIES_PARAM_NAME);
+
+        when(userValidations.validateUserExists(user)).thenReturn(user);
+        when(componentNodeFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
+        when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
+        when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
+        when(componentsUtils.parseToConstraint(anyString(), any(User.class),ArgumentMatchers.any(ComponentTypeEnum.class)))
+            .thenReturn(Optional.of(uiConstraint));
+
+        assertThat(ciNodeFilterDataDefinition.getProperties().getListToscaDataDefinition()).hasSize(1);
+        when(componentNodeFilterBusinessLogic
+            .addNodeFilter(componentId, componentInstance, NodeFilterConstraintAction.ADD,
+                uiConstraint.getServicePropertyName(), constraint, true, ComponentTypeEnum.RESOURCE,
+                NodeFilterConstraintType.CAPABILITIES))
+            .thenReturn(Optional.of(ciNodeFilterDataDefinition));
+
+        final Response response = target()
+            .path(path)
+            .request(MediaType.APPLICATION_JSON)
+            .header(USER_ID_HEADER, USER_ID)
+            .post(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
+
+        verify(componentNodeFilterBusinessLogic, times(1))
+            .addNodeFilter(anyString(), anyString(), ArgumentMatchers.any(NodeFilterConstraintAction.class), anyString(),
+                anyString(), anyBoolean(), ArgumentMatchers.any(ComponentTypeEnum.class),
+                ArgumentMatchers.any(NodeFilterConstraintType.class));
 
         assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200);
     }
@@ -188,8 +227,9 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
     @Test
     public void addNodeFilterFailTest() throws BusinessLogicException, JsonProcessingException {
         initComponentData();
-        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter";
-        final String path = String.format(pathFormat, componentType, componentId, componentInstance);
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance,
+            NodeFilterConstraintType.PROPERTIES_PARAM_NAME);
 
         when(userValidations.validateUserExists(user)).thenReturn(user);
         when(componentNodeFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
@@ -202,7 +242,8 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
 
         when(componentNodeFilterBusinessLogic
             .addNodeFilter(componentId, componentInstance, NodeFilterConstraintAction.ADD,
-                uiConstraint.getServicePropertyName(), constraint, true, ComponentTypeEnum.RESOURCE))
+                uiConstraint.getServicePropertyName(), constraint, true, ComponentTypeEnum.RESOURCE,
+                NodeFilterConstraintType.PROPERTIES))
             .thenReturn(Optional.empty());
 
         final Response response = target()
@@ -211,18 +252,14 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
             .header(USER_ID_HEADER, USER_ID)
             .post(Entity.entity(inputJson, MediaType.APPLICATION_JSON));
 
-        verify(componentNodeFilterBusinessLogic, times(1))
-            .addNodeFilter(anyString(), anyString(), ArgumentMatchers.any(NodeFilterConstraintAction.class), anyString(), anyString(), anyBoolean(),
-                ArgumentMatchers.any(ComponentTypeEnum.class));
-
         assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
     }
 
     @Test
     public void addNodeFilterFailConstraintParseTest() throws JsonProcessingException {
         initComponentData();
-        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter";
-        final String path = String.format(pathFormat, componentType, componentId, componentInstance);
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance, NodeFilterConstraintType.PROPERTIES_PARAM_NAME);
 
         when(userValidations.validateUserExists(user)).thenReturn(user);
         when(componentNodeFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
@@ -247,8 +284,9 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
     @Test
     public void addNodeFilterFailConvertTest() throws JsonProcessingException, BusinessLogicException {
         initComponentData();
-        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter";
-        final String path = String.format(pathFormat, componentType, componentId, componentInstance);
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance,
+            NodeFilterConstraintType.PROPERTIES.getType());
 
         when(userValidations.validateUserExists(user)).thenReturn(user);
         when(componentNodeFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
@@ -273,8 +311,9 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
     @Test
     public void updateNodeFilterSuccessTest() throws BusinessLogicException, JsonProcessingException {
         initComponentData();
-        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter";
-        final String path = String.format(pathFormat, componentType, componentId, componentInstance);
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance,
+            NodeFilterConstraintType.PROPERTIES_PARAM_NAME);
 
         when(userValidations.validateUserExists(user)).thenReturn(user);
         when(componentNodeFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
@@ -306,8 +345,9 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
     @Test
     public void updateNodeFilterFailTest() throws BusinessLogicException, JsonProcessingException {
         initComponentData();
-        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter";
-        final String path = String.format(pathFormat, componentType, componentId, componentInstance);
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance,
+            NodeFilterConstraintType.PROPERTIES_PARAM_NAME);
 
         when(userValidations.validateUserExists(user)).thenReturn(user);
         when(componentNodeFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
@@ -338,8 +378,9 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
     @Test
     public void updateNodeFilterFailConstraintParseTest() throws JsonProcessingException {
         initComponentData();
-        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter";
-        final String path = String.format(pathFormat, componentType, componentId, componentInstance);
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance,
+            NodeFilterConstraintType.PROPERTIES_PARAM_NAME);
 
         when(userValidations.validateUserExists(user)).thenReturn(user);
         when(componentNodeFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
@@ -360,8 +401,9 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
     @Test
     public void updateNodeFilterFailConvertTest() throws JsonProcessingException {
         initComponentData();
-        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter";
-        final String path = String.format(pathFormat, componentType, componentId, componentInstance);
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance,
+            NodeFilterConstraintType.PROPERTIES_PARAM_NAME);
 
         when(userValidations.validateUserExists(user)).thenReturn(user);
         when(componentNodeFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
@@ -384,8 +426,9 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
     @Test
     public void deleteNodeFilterSuccessTest() throws BusinessLogicException, JsonProcessingException {
         initComponentData();
-        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
-        final String path = String.format(pathFormat, componentType, componentId, componentInstance, 0);
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance,
+            NodeFilterConstraintType.PROPERTIES_PARAM_NAME, 0);
 
         when(userValidations.validateUserExists(user)).thenReturn(user);
         when(componentNodeFilterBusinessLogic.validateUser(USER_ID)).thenReturn(user);
@@ -413,8 +456,9 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
 
     @Test
     public void deleteNodeFilterFailTest() {
-        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s";
-        final String path = String.format(pathFormat, componentType, componentId, componentInstance, 1);
+        final String pathFormat = "/v1/catalog/%s/%s/resourceInstances/%s/nodeFilter/%s/%s";
+        final String path = String.format(pathFormat, componentType, componentId, componentInstance,
+            NodeFilterConstraintType.PROPERTIES_PARAM_NAME, 1);
         final Response response = target()
             .path(path)
             .request(MediaType.APPLICATION_JSON)
@@ -488,4 +532,4 @@ public class ComponentNodeFilterServletTest extends JerseyTest {
         return mapper.writeValueAsString(uiConstraint);
     }
 
-}
\ No newline at end of file
+}
index 69c9f4e..02f8e83 100644 (file)
@@ -33,6 +33,7 @@ import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
 import org.openecomp.sdc.be.model.Component;
@@ -115,6 +116,22 @@ public class NodeFilterOperation extends BaseOperation {
         return addOrUpdateNodeFilter(true, componentId, componentInstanceId, nodeFilterDataDefinition);
     }
 
+    public Either<CINodeFilterDataDefinition, StorageOperationStatus> addNewCapabilities(
+        final String componentId, final String componentInstanceId,
+        final CINodeFilterDataDefinition nodeFilterDataDefinition,
+        final RequirementNodeFilterCapabilityDataDefinition requirementNodeFilterCapabilityDataDefinition) {
+
+        ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> capabilities =
+            nodeFilterDataDefinition.getCapabilities();
+        if(capabilities == null) {
+            capabilities = new ListDataDefinition<>();
+            nodeFilterDataDefinition.setCapabilities(capabilities);
+        }
+        capabilities.getListToscaDataDefinition().add(requirementNodeFilterCapabilityDataDefinition);
+        nodeFilterDataDefinition.setCapabilities(capabilities);
+        return addOrUpdateNodeFilter(true, componentId, componentInstanceId, nodeFilterDataDefinition);
+    }
+
     public Either<CINodeFilterDataDefinition, StorageOperationStatus> updateProperties(
         final String serviceId, final String componentInstanceId,
         final CINodeFilterDataDefinition nodeFilterDataDefinition,
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/NodeFilterConstraintType.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/NodeFilterConstraintType.java
new file mode 100644 (file)
index 0000000..76db876
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 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.datatypes.enums;
+
+import java.util.Optional;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Represents the type of a node filter constraint.
+ */
+@Getter
+@AllArgsConstructor
+public enum NodeFilterConstraintType {
+
+    PROPERTIES(NodeFilterConstraintType.PROPERTIES_PARAM_NAME),
+    CAPABILITIES(NodeFilterConstraintType.CAPABILITIES_PARAM_NAME);
+
+    private final String type;
+
+    // Those values are needed as constants for Swagger allowedValues param
+    public static final String PROPERTIES_PARAM_NAME = "properties";
+    public static final String CAPABILITIES_PARAM_NAME = "capabilities";
+
+    /**
+     * Parse a String to the related {@link NodeFilterConstraintType}.
+     *
+     * @param type the {@link NodeFilterConstraintType} type
+     * @return The {@link NodeFilterConstraintType} representing the given type.
+     */
+    public static Optional<NodeFilterConstraintType> parse(final String type) {
+        for (final NodeFilterConstraintType nodeFilterConstraintType : values()) {
+            if (nodeFilterConstraintType.getType().equals(type)) {
+                return Optional.of(nodeFilterConstraintType);
+            }
+        }
+        return Optional.empty();
+    }
+}