Restrict workflow certify if artifact not present 58/71958/10
authorsiddharth0905 <siddharth.singh4@amdocs.com>
Mon, 5 Nov 2018 12:39:38 +0000 (14:39 +0200)
committerAvi Gaffa <avi.gaffa@amdocs.com>
Tue, 20 Nov 2018 09:44:22 +0000 (09:44 +0000)
Support Workflow Archive and restore

SDCNEW-972 Issue & Archive Workflow changes

Change-Id: Ie98501fddaf3543ad1084998153727b6932d449e
Issue-ID: SDC-1901
Signed-off-by: siddharth0905 <siddharth.singh4@amdocs.com>
21 files changed:
workflow-bdd/features/ArchiveWorkflow.feature [new file with mode: 0644]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/ExceptionsHandler.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/WorkflowStatusDto.java [new file with mode: 0644]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/validation/ValidStatus.java [new file with mode: 0644]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/validation/WorkflowStatusValidator.java [new file with mode: 0644]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/WorkflowManager.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionStateModificationException.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionStateModificationMissingArtifactException.java [new file with mode: 0644]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/WorkflowModificationException.java [new file with mode: 0644]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/WorkflowStatusModificationException.java [new file with mode: 0644]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImpl.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowVersionManagerImpl.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/types/Workflow.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/types/WorkflowStatus.java [new file with mode: 0644]
workflow-designer-be/src/test/java/org/onap/sdc/workflow/RestPath.java
workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/ExceptionsHandlerTest.java
workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowControllerTest.java
workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/validation/WorkflowStatusVelidatorTest.java [new file with mode: 0644]
workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImplTest.java
workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowVersionManagerImplTest.java

diff --git a/workflow-bdd/features/ArchiveWorkflow.feature b/workflow-bdd/features/ArchiveWorkflow.feature
new file mode 100644 (file)
index 0000000..e63227d
--- /dev/null
@@ -0,0 +1,68 @@
+# Copyright © 2018 European Support Limited
+#
+# 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.
+
+Feature: Archive Workflow
+
+  Scenario: Archive workflow
+    Given I want to create a Workflow
+    When I want to create input data
+    And I want to update the input property "status" with value "ARCHIVED"
+    And I want to create for path "/workflows/{item.id}/archiving" with the input data from the context
+    Then I want to get path "/workflows/{item.id}"
+    And I want to check property "status" for value "ARCHIVED"
+    When I want to get path "/workflows?limit=2000&statusFilter=ARCHIVED"
+    Then I want to check in the list "items" property "id" with value "{item.id}" exists
+    When I want to get path "/workflows?limit=2000&"
+    Then I want to check in the list "items" property "id" with value "{item.id}" does not exist
+
+
+  Scenario: Archive and then Restore workflow
+    Given I want to create a Workflow
+    When I want to create input data
+    And I want to update the input property "status" with value "ARCHIVED"
+    And I want to create for path "/workflows/{item.id}/archiving" with the input data from the context
+    Then I want to get path "/workflows/{item.id}"
+    And I want to check property "status" for value "ARCHIVED"
+    When I want to get path "/workflows?limit=2000&statusFilter=ARCHIVED"
+    Then I want to check in the list "items" property "id" with value "{item.id}" exists
+    When I want to get path "/workflows?limit=2000&"
+    Then I want to check in the list "items" property "id" with value "{item.id}" does not exist
+    And I want to update the input property "status" with value "ACTIVE"
+    And I want to create for path "/workflows/{item.id}/archiving" with the input data from the context
+    Then I want to get path "/workflows/{item.id}"
+    And I want to check property "status" for value "ACTIVE"
+    When I want to get path "/workflows?limit=2000&statusFilter=ARCHIVED"
+    Then I want to check in the list "items" property "id" with value "{item.id}" does not exist
+    When I want to get path "/workflows?limit=2000&"
+    Then I want to check in the list "items" property "id" with value "{item.id}" exists
+
+  Scenario: Archive already archived workflow
+    Given I want to create a Workflow
+    When I want to create input data
+    And I want to update the input property "status" with value "ARCHIVED"
+    And I want to create for path "/workflows/{item.id}/archiving" with the input data from the context
+    When I want to create input data
+    And I want to update the input property "status" with value "ARCHIVED"
+    Then I want the following to fail with response status code 422
+    And I want to create for path "/workflows/{item.id}/archiving" with the input data from the context
+
+  Scenario: Restore already active workflow
+    Given I want to create a Workflow
+    When I want to create input data
+    And I want to update the input property "status" with value "ACTIVE"
+    Then I want the following to fail with response status code 422
+    And I want to create for path "/workflows/{item.id}/archiving" with the input data from the context
+
+
+
index 642c343..083206c 100644 (file)
@@ -32,7 +32,10 @@ import org.onap.sdc.workflow.services.exceptions.UniqueValueViolationException;
 import org.onap.sdc.workflow.services.exceptions.VersionCreationException;
 import org.onap.sdc.workflow.services.exceptions.VersionModificationException;
 import org.onap.sdc.workflow.services.exceptions.VersionStateModificationException;
+import org.onap.sdc.workflow.services.exceptions.VersionStateModificationMissingArtifactException;
 import org.onap.sdc.workflow.services.exceptions.VersionStatusModificationException;
+import org.onap.sdc.workflow.services.exceptions.WorkflowModificationException;
+import org.onap.sdc.workflow.services.exceptions.WorkflowStatusModificationException;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
 import org.springframework.context.support.DefaultMessageSourceResolvable;
@@ -90,8 +93,11 @@ public class ExceptionsHandler extends ResponseEntityExceptionHandler {
 
     @ExceptionHandler(
             {InvalidArtifactException.class, VersionCreationException.class, VersionModificationException.class,
-                    VersionStateModificationException.class, VersionStatusModificationException.class,
-                    UniqueValueViolationException.class})
+                    VersionStateModificationException.class,
+                    VersionStateModificationMissingArtifactException.class,
+                    VersionStatusModificationException.class,
+                    UniqueValueViolationException.class, WorkflowStatusModificationException.class,
+                    WorkflowModificationException.class})
     public final ResponseEntity<ErrorResponse> handleUnprocessableEntityException(Exception exception) {
         LOG.debug(LOG_MSG, UNPROCESSABLE_ENTITY, exception);
         return new ResponseEntity<>(new ErrorResponse(exception.getMessage()), UNPROCESSABLE_ENTITY);
index 9010fea..8eb2239 100644 (file)
@@ -27,9 +27,11 @@ import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
+import javax.validation.Valid;
 import org.onap.sdc.workflow.api.types.Paging;
 import org.onap.sdc.workflow.api.types.Sorting;
 import org.onap.sdc.workflow.api.types.VersionStatesFormatter;
+import org.onap.sdc.workflow.api.types.WorkflowStatusDto;
 import org.onap.sdc.workflow.services.WorkflowManager;
 import org.onap.sdc.workflow.services.WorkflowVersionManager;
 import org.onap.sdc.workflow.services.annotations.UserId;
@@ -38,6 +40,7 @@ import org.onap.sdc.workflow.services.types.PagingRequest;
 import org.onap.sdc.workflow.services.types.RequestSpec;
 import org.onap.sdc.workflow.services.types.SortingRequest;
 import org.onap.sdc.workflow.services.types.Workflow;
+import org.onap.sdc.workflow.services.types.WorkflowStatus;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.http.HttpStatus;
@@ -81,11 +84,13 @@ public class WorkflowController {
                     value = "Sorting criteria in the format: property:(asc|desc). Default sort order is ascending.",
                     allowableValues = "name:asc,name:desc"),
             @ApiImplicitParam(name = "searchNameFilter", dataType = "string", paramType = "query",
-            value = "Filter by workflow name")})
-    public Page<Workflow> list(@ApiIgnore String searchNameFilter,
+                    value = "Filter by workflow name"),
+            @ApiImplicitParam(name = "archiving", dataType = "string", paramType = "query",
+                    allowableValues = "ACTIVE,ARCHIVED", value = "Filter by workflow status")})
+    public Page<Workflow> list(@ApiIgnore String archiving, @ApiIgnore String searchNameFilter,
             @ApiIgnore VersionStatesFormatter versionStateFilter, @ApiIgnore Paging paging,
             @ApiIgnore Sorting sorting, @UserId String user) {
-        return workflowManager.list(searchNameFilter, versionStateFilter.getVersionStates(), initRequestSpec(paging, sorting));
+        return workflowManager.list(archiving, searchNameFilter, versionStateFilter.getVersionStates(), initRequestSpec(paging, sorting));
     }
 
     @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
@@ -117,6 +122,14 @@ public class WorkflowController {
         return workflow;
     }
 
+    @PostMapping(path = "/{workflowId}/archiving", consumes = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation("Update workflow status")
+    public ResponseEntity updateStatus(@RequestBody @Valid WorkflowStatusDto request, @PathVariable("workflowId") String workflowId,
+            @UserId String user) {
+        workflowManager.updateStatus(workflowId,WorkflowStatus.valueOf(request.getStatus()));
+        return new ResponseEntity(HttpStatus.OK);
+    }
+
     private RequestSpec initRequestSpec(Paging paging, Sorting sorting) {
         return new RequestSpec(new PagingRequest(paging.getOffset() == null ? DEFAULT_OFFSET : paging.getOffset(),
                 paging.getLimit() == null ? DEFAULT_LIMIT : paging.getLimit()),
diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/WorkflowStatusDto.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/WorkflowStatusDto.java
new file mode 100644 (file)
index 0000000..6e5ab1c
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.onap.sdc.workflow.api.types;
+
+import lombok.Data;
+import org.onap.sdc.workflow.api.validation.ValidStatus;
+
+@Data
+public class WorkflowStatusDto {
+    @ValidStatus(message = "Invalid status. Allowable values are: ARCHIVED,ACTIVE.")
+    private String status;
+}
diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/validation/ValidStatus.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/validation/ValidStatus.java
new file mode 100644 (file)
index 0000000..9632591
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.onap.sdc.workflow.api.validation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+@Target({ElementType.TYPE, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Constraint(validatedBy = {WorkflowStatusValidator.class})
+public @interface ValidStatus {
+
+  String message();
+
+  Class<?>[] groups() default {};
+
+  Class<? extends Payload>[] payload() default {};
+}
diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/validation/WorkflowStatusValidator.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/validation/WorkflowStatusValidator.java
new file mode 100644 (file)
index 0000000..b99b424
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.onap.sdc.workflow.api.validation;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import org.onap.sdc.workflow.services.types.WorkflowStatus;
+
+public class WorkflowStatusValidator implements ConstraintValidator<ValidStatus, String> {
+
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext context) {
+        if (value == null) {
+            return false;
+        } else {
+            try {
+                Enum.valueOf(WorkflowStatus.class, value);
+                return true;
+            } catch (IllegalArgumentException var3) {
+                return false;
+            }
+        }
+    }
+}
index 5190da1..0f8f27e 100644 (file)
@@ -20,15 +20,18 @@ import java.util.Set;
 import org.onap.sdc.workflow.services.types.Page;
 import org.onap.sdc.workflow.services.types.RequestSpec;
 import org.onap.sdc.workflow.services.types.Workflow;
+import org.onap.sdc.workflow.services.types.WorkflowStatus;
 import org.onap.sdc.workflow.services.types.WorkflowVersionState;
 
 public interface WorkflowManager {
 
-    Page<Workflow> list(String searchNameFilter, Set<WorkflowVersionState> versionStatesFilter, RequestSpec requestSpec);
+    Page<Workflow> list(String statusFilter, String searchNameFilter, Set<WorkflowVersionState> versionStatesFilter, RequestSpec requestSpec);
 
     Workflow get(Workflow workflow);
 
     Workflow create(Workflow workflow);
 
     void update(Workflow workflow);
+
+    void updateStatus(String workflowId, WorkflowStatus status);
 }
index 379d8e2..43360bd 100644 (file)
@@ -21,12 +21,12 @@ import org.onap.sdc.workflow.services.types.WorkflowVersionState;
 public class VersionStateModificationException extends RuntimeException {
 
     public VersionStateModificationException(String workflowId, String versionId, WorkflowVersionState sourceState,
-            WorkflowVersionState targetState) {
+                                             WorkflowVersionState targetState) {
         this(workflowId, versionId, sourceState, targetState, null);
     }
 
     public VersionStateModificationException(String workflowId, String versionId, WorkflowVersionState sourceState,
-            WorkflowVersionState targetState, Exception submitException) {
+                                             WorkflowVersionState targetState, Exception submitException) {
         super(String.format("Workflow %s, version %s: state can not be changed from %s to %s", workflowId, versionId,
                 sourceState.name(), targetState.name()), submitException);
     }
diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionStateModificationMissingArtifactException.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/VersionStateModificationMissingArtifactException.java
new file mode 100644 (file)
index 0000000..48aaa5c
--- /dev/null
@@ -0,0 +1,16 @@
+package org.onap.sdc.workflow.services.exceptions;
+
+import org.onap.sdc.workflow.services.types.WorkflowVersionState;
+
+public class VersionStateModificationMissingArtifactException extends RuntimeException {
+
+    public static final String WORKFLOW_MODIFICATION_STATE_MISSING_ARTIFACT_TEMPLATE =
+            "Workflow %s, version %s: state can not be changed from %s to %s. Missing artifact";
+
+    public VersionStateModificationMissingArtifactException(String workflowId, String versionId,
+                                                            WorkflowVersionState sourceState,
+                                                            WorkflowVersionState targetState) {
+        super(String.format(WORKFLOW_MODIFICATION_STATE_MISSING_ARTIFACT_TEMPLATE, workflowId, versionId,
+                sourceState.name(), targetState.name()));
+    }
+}
diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/WorkflowModificationException.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/WorkflowModificationException.java
new file mode 100644 (file)
index 0000000..7aa5ac0
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.onap.sdc.workflow.services.exceptions;
+
+public class WorkflowModificationException extends RuntimeException {
+
+    public WorkflowModificationException(String workflowId) {
+      super(String.format(
+        "Error while trying to modify workflow %s: Workflow is ARCHIVED and can not be edited", workflowId));
+    }
+}
diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/WorkflowStatusModificationException.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/exceptions/WorkflowStatusModificationException.java
new file mode 100644 (file)
index 0000000..380b140
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.onap.sdc.workflow.services.exceptions;
+
+import org.openecomp.sdc.common.errors.CoreException;
+
+public class WorkflowStatusModificationException extends RuntimeException {
+
+    public WorkflowStatusModificationException(CoreException ex) {
+      super(ex.getMessage());
+    }
+}
index 9dd3313..27257b4 100644 (file)
@@ -30,6 +30,8 @@ import java.util.stream.Collectors;
 import org.onap.sdc.workflow.services.UniqueValueService;
 import org.onap.sdc.workflow.services.WorkflowManager;
 import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
+import org.onap.sdc.workflow.services.exceptions.WorkflowModificationException;
+import org.onap.sdc.workflow.services.exceptions.WorkflowStatusModificationException;
 import org.onap.sdc.workflow.services.impl.mappers.VersionStateMapper;
 import org.onap.sdc.workflow.services.impl.mappers.WorkflowMapper;
 import org.onap.sdc.workflow.services.types.Page;
@@ -38,7 +40,9 @@ import org.onap.sdc.workflow.services.types.RequestSpec;
 import org.onap.sdc.workflow.services.types.Sort;
 import org.onap.sdc.workflow.services.types.SortingRequest;
 import org.onap.sdc.workflow.services.types.Workflow;
+import org.onap.sdc.workflow.services.types.WorkflowStatus;
 import org.onap.sdc.workflow.services.types.WorkflowVersionState;
+import org.openecomp.sdc.common.errors.CoreException;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
 import org.openecomp.sdc.versioning.ItemManager;
@@ -54,7 +58,7 @@ public class WorkflowManagerImpl implements WorkflowManager {
 
     private static final String WORKFLOW_NOT_FOUND_ERROR_MSG = "Workflow with id '%s' does not exist";
     private static final String WORKFLOW_NAME_UNIQUE_TYPE = "WORKFLOW_NAME";
-    private static final Predicate<Item> WORKFLOW_ITEM_FILTER = item -> WORKFLOW.name().equals(item.getType());
+    private static final Predicate<Item> WORKFLOW_ITEM_TYPE_FILTER = item -> WORKFLOW.name().equals(item.getType());
     private static final String WORKSPACES_SORT_PROPERTY = "name";
     private static final RequestSpec WORKSPACES_DEFAULT_REQUEST_SPEC =
             new RequestSpec(new PagingRequest(DEFAULT_OFFSET, DEFAULT_LIMIT),
@@ -78,17 +82,12 @@ public class WorkflowManagerImpl implements WorkflowManager {
     }
 
     @Override
-    public Page<Workflow> list(String searchNameFilter, Set<WorkflowVersionState> versionStatesFilter,
-            RequestSpec requestSpec) {
+    public Page<Workflow> list(String statusFilter, String searchNameFilter,
+            Set<WorkflowVersionState> versionStatesFilter, RequestSpec requestSpec) {
         requestSpec = getRequestSpec(requestSpec);
 
-        Set<VersionStatus> versionStatusesFilter =
-                versionStatesFilter == null ? null :
-                        versionStatesFilter.stream().map(versionStateMapper::workflowVersionStateToVersionStatus)
-                                .collect(Collectors.toSet());
-
-        Predicate<Item> filter = addSearchNameFilter(WORKFLOW_ITEM_FILTER, searchNameFilter);
-        Collection<Item> workflowItems = itemManager.list(addVersionStatusFilter(filter, versionStatusesFilter));
+        Collection<Item> workflowItems =
+                itemManager.list(createFilter(statusFilter, searchNameFilter, versionStatesFilter));
 
         List<Workflow> workflowsSlice = workflowItems.stream().map(workflowMapper::itemToWorkflow)
                                                      .sorted(getWorkflowComparator(requestSpec.getSorting()))
@@ -128,6 +127,10 @@ public class WorkflowManagerImpl implements WorkflowManager {
             throw new EntityNotFoundException(String.format(WORKFLOW_NOT_FOUND_ERROR_MSG, workflow.getId()));
         }
 
+        if (ItemStatus.ARCHIVED.equals(retrievedItem.getStatus())) {
+            throw new WorkflowModificationException(workflow.getId());
+        }
+
         uniqueValueService.updateUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, retrievedItem.getName(), workflow.getName());
 
         Item item = workflowMapper.workflowToItem(workflow);
@@ -137,7 +140,25 @@ public class WorkflowManagerImpl implements WorkflowManager {
         itemManager.update(item);
     }
 
-    private static RequestSpec getRequestSpec(RequestSpec requestSpec) {
+    @Override
+    public void updateStatus(String workflowId, WorkflowStatus status) {
+        Item item = itemManager.get(workflowId);
+        if (item == null) {
+            LOGGER.error(String.format("Workflow with id %s was not found",workflowId));
+            throw new EntityNotFoundException(String.format(WORKFLOW_NOT_FOUND_ERROR_MSG, workflowId));
+        }
+        try {
+            if (WorkflowStatus.ARCHIVED.equals(status)) {
+                itemManager.archive(item);
+            } else if (WorkflowStatus.ACTIVE.equals(status)) {
+                itemManager.restore(item);
+            }
+        } catch (CoreException ex) {
+            throw new WorkflowStatusModificationException(ex);
+        }
+    }
+
+  private static RequestSpec getRequestSpec(RequestSpec requestSpec) {
         if (requestSpec == null) {
             return WORKSPACES_DEFAULT_REQUEST_SPEC;
         }
@@ -172,15 +193,42 @@ public class WorkflowManagerImpl implements WorkflowManager {
         return byNameAscending ? byName : byName.reversed();
     }
 
+    private Predicate<Item> createFilter(String itemStatusFilter, String searchNameFilter,
+            Set<WorkflowVersionState> versionStatesFilter) {
+
+        Set<VersionStatus> versionStatusesFilter =
+                versionStatesFilter == null ? null :
+                        versionStatesFilter.stream().map(versionStateMapper::workflowVersionStateToVersionStatus)
+                                           .collect(Collectors.toSet());
+
+        Predicate<Item> filter = addSearchNameFilter(WORKFLOW_ITEM_TYPE_FILTER, searchNameFilter);
+
+        filter = addVersionStatusFilter(filter, versionStatusesFilter);
+
+        return addItemStatusFilter(filter, itemStatusFilter);
+
+    }
+
     private static Predicate<Item> addSearchNameFilter(Predicate<Item> filter, String searchNameFilter) {
-        return filter
-                       .and(item -> searchNameFilter == null ||
-                                            item.getName().toLowerCase().contains(searchNameFilter.toLowerCase()));
+        return filter.and(item -> searchNameFilter == null
+            ||  item.getName().toLowerCase().contains(searchNameFilter.toLowerCase()));
     }
 
     private static Predicate<Item> addVersionStatusFilter(Predicate<Item> filter, Set<VersionStatus> versionStatuses) {
-        return filter
-                       .and(item -> versionStatuses == null || item.getVersionStatusCounters().keySet().stream()
-                                                                   .anyMatch(versionStatuses::contains));
+        return filter.and(item -> versionStatuses == null
+            || item.getVersionStatusCounters().keySet().stream().anyMatch(versionStatuses::contains));
+    }
+
+    private static Predicate<Item> addItemStatusFilter(Predicate<Item> filter, String itemStatusFilter) {
+        if (itemStatusFilter != null) {
+            try {
+                ItemStatus.valueOf(itemStatusFilter.toUpperCase());
+            } catch (IllegalArgumentException e) {
+                LOGGER.debug(String.format("Illegal Workflow status filter: %s. Ignoring filter", itemStatusFilter));
+                return filter;
+            }
+            return filter.and(item -> item.getStatus().equals(ItemStatus.valueOf(itemStatusFilter.toUpperCase())));
+        }
+        return filter;
     }
 }
index f2f8c27..5eba8d4 100644 (file)
@@ -29,6 +29,7 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
+
 import org.onap.sdc.workflow.persistence.ArtifactRepository;
 import org.onap.sdc.workflow.persistence.ParameterRepository;
 import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
@@ -40,15 +41,20 @@ import org.onap.sdc.workflow.services.exceptions.InvalidArtifactException;
 import org.onap.sdc.workflow.services.exceptions.VersionCreationException;
 import org.onap.sdc.workflow.services.exceptions.VersionModificationException;
 import org.onap.sdc.workflow.services.exceptions.VersionStateModificationException;
+import org.onap.sdc.workflow.services.exceptions.VersionStateModificationMissingArtifactException;
+import org.onap.sdc.workflow.services.exceptions.WorkflowModificationException;
 import org.onap.sdc.workflow.services.impl.mappers.VersionMapper;
 import org.onap.sdc.workflow.services.impl.mappers.VersionStateMapper;
 import org.onap.sdc.workflow.services.types.WorkflowVersion;
 import org.onap.sdc.workflow.services.types.WorkflowVersionState;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
+import org.openecomp.sdc.versioning.ItemManager;
 import org.openecomp.sdc.versioning.VersioningManager;
 import org.openecomp.sdc.versioning.dao.types.Version;
 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
+import org.openecomp.sdc.versioning.types.Item;
+import org.openecomp.sdc.versioning.types.ItemStatus;
 import org.openecomp.sdc.versioning.types.VersionCreationMethod;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -60,6 +66,7 @@ public class WorkflowVersionManagerImpl implements WorkflowVersionManager {
 
     private static final String VERSION_NOT_EXIST_MSG = "version with id '%s' does not exist for workflow with id '%s'";
     private final VersioningManager versioningManager;
+    private final ItemManager itemManager;
     private final ArtifactRepository artifactRepository;
     private final ParameterRepository parameterRepository;
     private final VersionMapper versionMapper;
@@ -68,8 +75,9 @@ public class WorkflowVersionManagerImpl implements WorkflowVersionManager {
 
     @Autowired
     public WorkflowVersionManagerImpl(VersioningManager versioningManager, ArtifactRepository artifactRepository,
-            VersionMapper versionMapper, VersionStateMapper versionStateMapper,
+            VersionMapper versionMapper, VersionStateMapper versionStateMapper, ItemManager itemManager,
             ParameterRepository parameterRepository) {
+        this.itemManager = itemManager;
         this.versioningManager = versioningManager;
         this.artifactRepository = artifactRepository;
         this.parameterRepository = parameterRepository;
@@ -103,6 +111,7 @@ public class WorkflowVersionManagerImpl implements WorkflowVersionManager {
 
     @Override
     public WorkflowVersion create(String workflowId, String baseVersionId, WorkflowVersion workflowVersion) {
+        validateWorkflowStatus(workflowId);
         List<Version> versions = versioningManager.list(workflowId);
 
         if (baseVersionId != null) {
@@ -131,6 +140,7 @@ public class WorkflowVersionManagerImpl implements WorkflowVersionManager {
 
     @Override
     public void update(String workflowId, WorkflowVersion workflowVersion) {
+        validateWorkflowStatus(workflowId);
         Version retrievedVersion = getVersion(workflowId, workflowVersion.getId());
         if (CERTIFIED.equals(versionStateMapper.versionStatusToWorkflowVersionState(retrievedVersion.getStatus()))) {
             throw new VersionModificationException(workflowId, workflowVersion.getId());
@@ -157,23 +167,28 @@ public class WorkflowVersionManagerImpl implements WorkflowVersionManager {
     }
 
     @Override
-    public void updateState(String workflowId, String versionId, WorkflowVersionState state) {
-        WorkflowVersionState retrievedState = getState(workflowId, versionId);
-        if (state == CERTIFIED) {
+    public void updateState(String workflowId, String versionId, WorkflowVersionState newState) {
+        WorkflowVersionState currentState = getState(workflowId, versionId);
+        if (newState == CERTIFIED) {
+            if(!artifactRepository.isExist(workflowId,versionId)){
+                throw new VersionStateModificationMissingArtifactException(workflowId, versionId, currentState,
+                        newState);
+            }
             try {
                 versioningManager.submit(workflowId, new Version(versionId),
-                        String.format("Update version state to %s", state.name()));
+                        String.format("Update version state to %s", newState.name()));
             } catch (Exception submitException) {
-                throw new VersionStateModificationException(workflowId, versionId, retrievedState,
-                        state, submitException);
+                throw new VersionStateModificationException(workflowId, versionId, currentState, newState,
+                        submitException);
             }
         } else {
-            throw new VersionStateModificationException(workflowId, versionId, retrievedState, state);
+            throw new VersionStateModificationException(workflowId, versionId, currentState, newState);
         }
     }
 
     @Override
     public void uploadArtifact(String workflowId, String versionId, MultipartFile artifact) {
+        validateWorkflowStatus(workflowId);
         Version retrievedVersion = getVersion(workflowId, versionId);
         if (CERTIFIED.equals(versionStateMapper.versionStatusToWorkflowVersionState(retrievedVersion.getStatus()))) {
             throw new VersionModificationException(workflowId, versionId);
@@ -210,6 +225,7 @@ public class WorkflowVersionManagerImpl implements WorkflowVersionManager {
 
     @Override
     public void deleteArtifact(String workflowId, String versionId) {
+        validateWorkflowStatus(workflowId);
         WorkflowVersion retrievedVersion = get(workflowId, versionId);
         if (CERTIFIED.equals(retrievedVersion.getState())) {
             LOGGER.error(String.format(
@@ -286,4 +302,11 @@ public class WorkflowVersionManagerImpl implements WorkflowVersionManager {
         return versions.stream().filter(version -> versionId.equals(version.getId())).findFirst();
     }
 
+    protected void validateWorkflowStatus(String workflowId) {
+        Item workflowItem = itemManager.get(workflowId);
+        if (ItemStatus.ARCHIVED.equals(workflowItem.getStatus())) {
+            throw new WorkflowModificationException(workflowId);
+        }
+    }
+
 }
\ No newline at end of file
index 3d8e4c7..0c0179e 100644 (file)
@@ -39,4 +39,5 @@ public class Workflow {
     private String description;
     private Set<WorkflowVersionState> versionStates;
     private Collection<WorkflowVersion> versions;
+    private WorkflowStatus status;
 }
diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/types/WorkflowStatus.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/types/WorkflowStatus.java
new file mode 100644 (file)
index 0000000..6df7ff3
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.onap.sdc.workflow.services.types;
+
+public enum WorkflowStatus {
+  ARCHIVED,
+  ACTIVE
+}
index 6c825f9..9821d51 100644 (file)
@@ -12,6 +12,7 @@ public class RestPath {
 
     private static final String WORKFLOWS_URL = "/wf/workflows";
     private static final String WORKFLOW_URL_FORMATTER = WORKFLOWS_URL + "/%s";
+    private static final String ARCHIVE_URL_FORMATTER = WORKFLOWS_URL + "/%s/archiving";
     private static final String VERSIONS_URL_FORMATTER = WORKFLOWS_URL + "/%s/versions";
     private static final String VERSION_URL_FORMATTER = WORKFLOWS_URL + "/%s/versions/%s";
     private static final String SORT_QUERY_STRING_FORMATTER = SORT + "=%s";
@@ -25,15 +26,15 @@ public class RestPath {
     private static final String WORKFLOW_URL_FORMATTER_QUERY_PARAMS_NO_SORT_AND_OFFSET =
             WORKFLOWS_URL + "?" + LIMIT_QUERY_STRING_FORMATTER;
 
-    public static String getWorkflowsPathAllQueryParams(String sort, String limit, String offset){
+    public static String getWorkflowsPathAllQueryParams(String sort, String limit, String offset) {
         return String.format(WORKFLOW_URL_FORMATTER_QUERY_PARAMS_ALL, sort, limit, offset);
     }
 
-    public static String getWorkflowsPathNoSortAndLimit(String offset){
+    public static String getWorkflowsPathNoSortAndLimit(String offset) {
         return String.format(WORKFLOW_URL_FORMATTER_QUERY_PARAMS_NO_SORT_AND_LIMIT, offset);
     }
 
-    public static String getWorkflowsPathNoSortAndOffset(String limit){
+    public static String getWorkflowsPathNoSortAndOffset(String limit) {
         return String.format(WORKFLOW_URL_FORMATTER_QUERY_PARAMS_NO_SORT_AND_OFFSET, limit);
     }
 
@@ -45,6 +46,10 @@ public class RestPath {
         return String.format(WORKFLOW_URL_FORMATTER, workflowId);
     }
 
+    public static String getArchiveWorkflowPath(String workflowId) {
+        return String.format(ARCHIVE_URL_FORMATTER, workflowId);
+    }
+
     public static String getWorkflowVersions(String workflowId) {
         return String.format(VERSIONS_URL_FORMATTER, workflowId);
     }
index e4008bb..fc35c4a 100644 (file)
@@ -14,6 +14,8 @@ import org.onap.sdc.workflow.api.types.ErrorResponse;
 import org.onap.sdc.workflow.api.types.UnexpectedErrorResponse;
 import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
 import org.onap.sdc.workflow.services.exceptions.VersionModificationException;
+import org.onap.sdc.workflow.services.exceptions.VersionStateModificationMissingArtifactException;
+import org.onap.sdc.workflow.services.types.WorkflowVersionState;
 import org.springframework.http.ResponseEntity;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
@@ -41,6 +43,17 @@ public class ExceptionsHandlerTest {
         assertEquals(exception.getMessage(), response.getBody().getMessage());
     }
 
+    @Test
+    public void handleUnprocessableEntityVersionStateModificationMissingArtifactException() {
+        VersionStateModificationMissingArtifactException exception =
+                new VersionStateModificationMissingArtifactException("WF_ID", "Version_id",
+                        WorkflowVersionState.DRAFT, WorkflowVersionState.CERTIFIED);
+        ResponseEntity<ErrorResponse> response = exceptionsHandler.handleUnprocessableEntityException(exception);
+
+        assertEquals(UNPROCESSABLE_ENTITY, response.getStatusCode());
+        assertEquals(exception.getMessage(), response.getBody().getMessage());
+    }
+
     @Test
     public void handleUnexpectedException() {
         Exception exception = new Exception("message");
index 9c48128..0c48fd6 100644 (file)
@@ -40,6 +40,7 @@ import org.onap.sdc.workflow.services.types.PagingRequest;
 import org.onap.sdc.workflow.services.types.RequestSpec;
 import org.onap.sdc.workflow.services.types.Sort;
 import org.onap.sdc.workflow.services.types.Workflow;
+import org.onap.sdc.workflow.services.types.WorkflowStatus;
 import org.onap.sdc.workflow.services.utilities.JsonUtil;
 import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
 import org.springframework.test.web.servlet.MockMvc;
@@ -94,6 +95,22 @@ public class WorkflowControllerTest {
                .andExpect(status().isBadRequest()).andExpect(jsonPath("$.message", is(MISSING_USER_HEADER_ERROR)));
     }
 
+    @Test
+    public void shouldReturnOkWhenArchivingWorkflow() throws Exception {
+        Workflow workflowMock = createWorkflow(1, true);
+        mockMvc.perform(post(RestPath.getArchiveWorkflowPath(workflowMock.getId())).header(USER_ID_HEADER, USER_ID)
+                 .contentType(APPLICATION_JSON).content("{\"status\": \"ARCHIVED\"}")).andExpect(status().isOk());
+        verify(workflowManagerMock).updateStatus(workflowMock.getId(),WorkflowStatus.ARCHIVED);
+    }
+
+    @Test
+    public void shouldReturnOkWhenRestoringWorkflow() throws Exception {
+        Workflow workflowMock = createWorkflow(1, true);
+        mockMvc.perform(post(RestPath.getArchiveWorkflowPath(workflowMock.getId())).header(USER_ID_HEADER, USER_ID)
+                .contentType(APPLICATION_JSON).content("{\"status\": \"ACTIVE\"}")).andExpect(status().isOk());
+        verify(workflowManagerMock).updateStatus(workflowMock.getId(),WorkflowStatus.ACTIVE);
+    }
+
     @Test
     public void listWhenExist() throws Exception {
         mockManagerList3();
@@ -105,7 +122,7 @@ public class WorkflowControllerTest {
             result.andExpect(jsonPath(String.format("$.items[%s].id", i), is(String.valueOf(i + 1))));
         }
 
-        verify(workflowManagerMock).list(any(), any(), requestSpecArg.capture());
+        verify(workflowManagerMock).list(any(), any(), any(), requestSpecArg.capture());
         assertRequestSpec(requestSpecArg.getValue(), DEFAULT_OFFSET, DEFAULT_LIMIT, Collections.emptyList());
     }
 
@@ -115,7 +132,7 @@ public class WorkflowControllerTest {
         mockMvc.perform(get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "2", "1"))
                                 .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON))
                .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(3)));
-        verify(workflowManagerMock).list(any(), any(), requestSpecArg.capture());
+        verify(workflowManagerMock).list(any(), any(), any(), requestSpecArg.capture());
         assertRequestSpec(requestSpecArg.getValue(), 1, 2, Collections.singletonList(new Sort("name", true)));
     }
 
@@ -125,7 +142,7 @@ public class WorkflowControllerTest {
         mockMvc.perform(get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "-2", "1"))
                                 .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON))
                .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(3)));
-        verify(workflowManagerMock).list(any(), any(), requestSpecArg.capture());
+        verify(workflowManagerMock).list(any(), any(), any(), requestSpecArg.capture());
         assertRequestSpec(requestSpecArg.getValue(), 1, DEFAULT_LIMIT,
                 Collections.singletonList(new Sort("name", true)));
     }
@@ -136,7 +153,7 @@ public class WorkflowControllerTest {
         mockMvc.perform(get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "2", "-1"))
                                 .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON))
                .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(3)));
-        verify(workflowManagerMock).list(any(), any(), requestSpecArg.capture());
+        verify(workflowManagerMock).list(any(), any(), any(), requestSpecArg.capture());
         assertRequestSpec(requestSpecArg.getValue(), DEFAULT_OFFSET, 2,
                 Collections.singletonList(new Sort("name", true)));
     }
@@ -147,7 +164,7 @@ public class WorkflowControllerTest {
         mockMvc.perform(get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "abc", "0"))
                                 .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON))
                .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(3)));
-        verify(workflowManagerMock).list(any(), any(), requestSpecArg.capture());
+        verify(workflowManagerMock).list(any(), any(), any(), requestSpecArg.capture());
         assertRequestSpec(requestSpecArg.getValue(), 0, DEFAULT_LIMIT,
                 Collections.singletonList(new Sort("name", true)));
     }
@@ -158,7 +175,7 @@ public class WorkflowControllerTest {
         mockMvc.perform(get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "2", "abc"))
                                 .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON))
                .andExpect(jsonPath("$.items", hasSize(3)));
-        verify(workflowManagerMock).list(any(), any(), requestSpecArg.capture());
+        verify(workflowManagerMock).list(any(), any(), any(), requestSpecArg.capture());
         assertRequestSpec(requestSpecArg.getValue(), DEFAULT_OFFSET, 2,
                 Collections.singletonList(new Sort("name", true)));
     }
@@ -169,7 +186,7 @@ public class WorkflowControllerTest {
         mockMvc.perform(get(RestPath.getWorkflowsPathNoSortAndLimit("1")).header(USER_ID_HEADER, USER_ID)
                                                                          .contentType(APPLICATION_JSON))
                .andExpect(jsonPath("$.items", hasSize(3)));
-        verify(workflowManagerMock).list(any(), any(), requestSpecArg.capture());
+        verify(workflowManagerMock).list(any(), any(), any(), requestSpecArg.capture());
         assertRequestSpec(requestSpecArg.getValue(), 1, DEFAULT_LIMIT, Collections.emptyList());
     }
 
@@ -179,7 +196,7 @@ public class WorkflowControllerTest {
         mockMvc.perform(get(RestPath.getWorkflowsPathNoSortAndOffset("1")).header(USER_ID_HEADER, USER_ID)
                                                                           .contentType(APPLICATION_JSON))
                .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(3)));
-        verify(workflowManagerMock).list(any(), any(), requestSpecArg.capture());
+        verify(workflowManagerMock).list(any(), any(), any(), requestSpecArg.capture());
         assertRequestSpec(requestSpecArg.getValue(), DEFAULT_OFFSET, 1, Collections.emptyList());
     }
 
@@ -258,7 +275,7 @@ public class WorkflowControllerTest {
         doReturn(new Page<>(Arrays.asList(createWorkflow(1, true),
                 createWorkflow(2, true), createWorkflow(3, true)),
                 new PagingRequest(DEFAULT_OFFSET, DEFAULT_LIMIT), 3)).when(workflowManagerMock)
-                                                                     .list(any(), any(), any());
+                                                                     .list(any(), any(), any(), any());
     }
 
     private static void assertRequestSpec(RequestSpec actual, int expectedOffset, int expectedLimit,
diff --git a/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/validation/WorkflowStatusVelidatorTest.java b/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/validation/WorkflowStatusVelidatorTest.java
new file mode 100644 (file)
index 0000000..289c935
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.onap.sdc.workflow.api.validation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.validation.ConstraintValidatorContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class WorkflowStatusVelidatorTest {
+
+    class AnnotationWrapper {
+
+        @ValidName(message = "test message")
+        public String status;
+    }
+
+    @Mock
+    private ConstraintValidatorContext context;
+    @Mock
+    private ConstraintValidatorContext.ConstraintViolationBuilder constraintViolationBuilder;
+    @Mock
+    private ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext nodeBuilderCustomizableContext;
+
+    private WorkflowStatusValidator validator;
+
+    @Before
+    public void setup() throws NoSuchFieldException {
+        MockitoAnnotations.initMocks(this);
+        when(context.buildConstraintViolationWithTemplate(anyString())).thenReturn(constraintViolationBuilder);
+        when(constraintViolationBuilder.addPropertyNode(anyString())).thenReturn(nodeBuilderCustomizableContext);
+        validator = initializeValidator(WorkflowStatusVelidatorTest.AnnotationWrapper.class);
+    }
+
+    @Test
+    public void shouldFailIfValueIsNull() {
+    assertFalse(validator.isValid(null, context));
+  }
+
+    @Test
+    public void shouldFailIfValueInvalid() {
+    assertFalse(validator.isValid("blahblah", context));
+  }
+
+    @Test
+    public void shouldPassIfValueIsActive() {
+    assertTrue(validator.isValid("ACTIVE", context));
+  }
+
+    @Test
+    public void shouldPassIfValueIsArchived() {
+    assertTrue(validator.isValid("ARCHIVED", context));
+  }
+
+
+
+
+  private WorkflowStatusValidator initializeValidator(Class<?> classWithAnnotation)
+            throws NoSuchFieldException {
+        ValidStatus constraint = classWithAnnotation.getField("status").getAnnotation(ValidStatus.class);
+        WorkflowStatusValidator validator = new WorkflowStatusValidator();
+        validator.initialize(constraint);
+        return validator;
+    }
+
+
+}
index e2df4ec..702da4c 100644 (file)
@@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.onap.sdc.workflow.TestUtil.createItem;
@@ -27,6 +28,7 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.onap.sdc.workflow.services.UniqueValueService;
 import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
+import org.onap.sdc.workflow.services.exceptions.WorkflowStatusModificationException;
 import org.onap.sdc.workflow.services.impl.mappers.VersionStateMapper;
 import org.onap.sdc.workflow.services.impl.mappers.WorkflowMapper;
 import org.onap.sdc.workflow.services.types.Page;
@@ -36,7 +38,11 @@ import org.onap.sdc.workflow.services.types.RequestSpec;
 import org.onap.sdc.workflow.services.types.Sort;
 import org.onap.sdc.workflow.services.types.SortingRequest;
 import org.onap.sdc.workflow.services.types.Workflow;
+import org.onap.sdc.workflow.services.types.WorkflowStatus;
 import org.onap.sdc.workflow.services.types.WorkflowVersionState;
+import org.openecomp.sdc.common.errors.CoreException;
+import org.openecomp.sdc.common.errors.ErrorCategory;
+import org.openecomp.sdc.common.errors.ErrorCode;
 import org.openecomp.sdc.versioning.ItemManager;
 import org.openecomp.sdc.versioning.types.Item;
 import org.openecomp.sdc.versioning.types.ItemStatus;
@@ -80,7 +86,7 @@ public class WorkflowManagerImplTest {
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
         RequestSpec requestSpec = createRequestSpec(0, 20, true);
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
 
         Map<String, Workflow> workflowById =
                 workflows.getItems().stream().collect(Collectors.toMap(Workflow::getId, Function.identity()));
@@ -102,7 +108,7 @@ public class WorkflowManagerImplTest {
 
         RequestSpec requestSpec = createRequestSpec(0, 20, true);
         Page<Workflow> workflows =
-                workflowManager.list(null,Collections.singleton(WorkflowVersionState.CERTIFIED), requestSpec);
+                workflowManager.list(null,null,Collections.singleton(WorkflowVersionState.CERTIFIED), requestSpec);
 
         Map<String, Workflow> workflowById =
                 workflows.getItems().stream().collect(Collectors.toMap(Workflow::getId, Function.identity()));
@@ -113,6 +119,42 @@ public class WorkflowManagerImplTest {
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(), 2);
     }
 
+    @Test(expected = EntityNotFoundException.class)
+    public void shouldThrowExceptionWhenWorkflowDontExistTryingToUpdateStatus() {
+        doReturn(null).when(itemManagerMock).get(ITEM1_ID);
+        workflowManager.updateStatus(ITEM1_ID,WorkflowStatus.ARCHIVED);
+    }
+
+    @Test(expected = WorkflowStatusModificationException.class)
+    public void shouldThrowExceptionWhenFailingToUpdateStatus() {
+        Item mockItem = new Item();
+        mockItem.setId(ITEM1_ID);
+        mockItem.setStatus(ItemStatus.ARCHIVED);
+        doReturn(mockItem).when(itemManagerMock).get(ITEM1_ID);
+        doThrow(new CoreException(new ErrorCode.ErrorCodeBuilder().build())).when(itemManagerMock).archive(mockItem);
+        workflowManager.updateStatus(ITEM1_ID,WorkflowStatus.ARCHIVED);
+    }
+
+    @Test
+    public void shouldArchiveWorkflow() {
+        Item mockItem = new Item();
+        mockItem.setId(ITEM1_ID);
+        mockItem.setStatus(ItemStatus.ACTIVE);
+        doReturn(mockItem).when(itemManagerMock).get(ITEM1_ID);
+        workflowManager.updateStatus(ITEM1_ID,WorkflowStatus.ARCHIVED);
+        verify(itemManagerMock).archive(mockItem);
+    }
+
+    @Test
+    public void shouldRestoreWorkflow() {
+        Item mockItem = new Item();
+        mockItem.setId(ITEM1_ID);
+        mockItem.setStatus(ItemStatus.ARCHIVED);
+        doReturn(mockItem).when(itemManagerMock).get(ITEM1_ID);
+        workflowManager.updateStatus(ITEM1_ID,WorkflowStatus.ACTIVE);
+        verify(itemManagerMock).restore(mockItem);
+    }
+
     @Test(expected = EntityNotFoundException.class)
     public void shouldThrowExceptionWhenWorkflowDontExist() {
         Workflow nonExistingWorkflow = new Workflow();
@@ -172,7 +214,7 @@ public class WorkflowManagerImplTest {
     public void listWhenRequestSpecIsNull() {
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
-        Page<Workflow> workflows = workflowManager.list(null,null, null);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, null);
 
         assertEquals(ITEMS.size(), workflows.getItems().size());
         assertPaging(workflows.getPaging(), DEFAULT_OFFSET, DEFAULT_LIMIT, ITEMS.size());
@@ -187,7 +229,7 @@ public class WorkflowManagerImplTest {
     public void listWhenPagingIsNull() {
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
-        Page<Workflow> workflows = workflowManager.list(null,null, new RequestSpec(null,
+        Page<Workflow> workflows = workflowManager.list(null,null,null, new RequestSpec(null,
                 SortingRequest.builder().sort(new Sort(SORT_FIELD_NAME, true)).build()));
 
         assertEquals(ITEMS.size(), workflows.getItems().size());
@@ -200,7 +242,7 @@ public class WorkflowManagerImplTest {
         mockItemToWorkflowMaps();
         RequestSpec requestSpec = new RequestSpec(new PagingRequest(-2, -8),
                 SortingRequest.builder().sort(new Sort(SORT_FIELD_NAME, true)).build());
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
 
         assertEquals(ITEMS.size(), workflows.getItems().size());
         assertPaging(workflows.getPaging(), DEFAULT_OFFSET, DEFAULT_LIMIT, ITEMS.size());
@@ -211,7 +253,7 @@ public class WorkflowManagerImplTest {
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
         RequestSpec requestSpec = new RequestSpec(new PagingRequest(2, 8), null);
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
 
         assertEquals(3, workflows.getItems().size());
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
@@ -228,7 +270,7 @@ public class WorkflowManagerImplTest {
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
         RequestSpec requestSpec = new RequestSpec(new PagingRequest(2, 8), SortingRequest.builder().build());
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
 
         assertEquals(3, workflows.getItems().size());
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
@@ -245,7 +287,7 @@ public class WorkflowManagerImplTest {
         RequestSpec requestSpec = createRequestSpec(0, 5, true);
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
 
         assertEquals(5, workflows.getItems().size());
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
@@ -257,7 +299,7 @@ public class WorkflowManagerImplTest {
         RequestSpec requestSpec = createRequestSpec(0, 3, true);
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
         assertEquals(3, workflows.getItems().size());
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
                 ITEMS.size());
@@ -269,7 +311,7 @@ public class WorkflowManagerImplTest {
         RequestSpec requestSpec = createRequestSpec(3, 1, true);
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
         assertEquals(1, workflows.getItems().size());
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
                 ITEMS.size());
@@ -280,7 +322,7 @@ public class WorkflowManagerImplTest {
         RequestSpec requestSpec = createRequestSpec(0, 10, true);
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
         assertEquals(5, workflows.getItems().size());
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
                 ITEMS.size());
@@ -291,7 +333,7 @@ public class WorkflowManagerImplTest {
         RequestSpec requestSpec = createRequestSpec(6, 3, true);
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
         assertEquals(0, workflows.getItems().size());
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
                 ITEMS.size());
@@ -302,7 +344,7 @@ public class WorkflowManagerImplTest {
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
         RequestSpec requestSpec = createRequestSpec(0, 5555, true);
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
 
         assertEquals(ITEMS.size(), workflows.getItems().size());
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), MAX_LIMIT, ITEMS.size());
@@ -313,7 +355,7 @@ public class WorkflowManagerImplTest {
         RequestSpec requestSpec = createRequestSpec(10, 10, true);
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
         assertEquals(0, workflows.getItems().size());
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
                 ITEMS.size());
@@ -324,7 +366,7 @@ public class WorkflowManagerImplTest {
         RequestSpec requestSpec = createRequestSpec(2, 1, false);
         doReturn(ITEMS).when(itemManagerMock).list(any());
         mockItemToWorkflowMaps();
-        Page<Workflow> workflows = workflowManager.list(null,null, requestSpec);
+        Page<Workflow> workflows = workflowManager.list(null,null,null, requestSpec);
         assertEquals(1, workflows.getItems().size());
         assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
                 ITEMS.size());
index 8b09e15..640d3e8 100644 (file)
@@ -1,11 +1,11 @@
 package org.onap.sdc.workflow.services.impl;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.times;
@@ -15,15 +15,16 @@ import static org.onap.sdc.workflow.services.types.WorkflowVersionState.DRAFT;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
-import java.util.Set;
+
 import org.apache.commons.io.IOUtils;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.InjectMocks;
@@ -39,16 +40,20 @@ import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
 import org.onap.sdc.workflow.services.exceptions.VersionCreationException;
 import org.onap.sdc.workflow.services.exceptions.VersionModificationException;
 import org.onap.sdc.workflow.services.exceptions.VersionStateModificationException;
+import org.onap.sdc.workflow.services.exceptions.VersionStateModificationMissingArtifactException;
+import org.onap.sdc.workflow.services.exceptions.WorkflowModificationException;
 import org.onap.sdc.workflow.services.impl.mappers.VersionMapper;
 import org.onap.sdc.workflow.services.impl.mappers.VersionStateMapper;
 import org.onap.sdc.workflow.services.types.WorkflowVersion;
 import org.onap.sdc.workflow.services.types.WorkflowVersionState;
+import org.openecomp.sdc.versioning.ItemManager;
 import org.openecomp.sdc.versioning.VersioningManager;
 import org.openecomp.sdc.versioning.dao.types.Version;
 import org.openecomp.sdc.versioning.dao.types.VersionState;
 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
+import org.openecomp.sdc.versioning.types.Item;
+import org.openecomp.sdc.versioning.types.ItemStatus;
 import org.openecomp.sdc.versioning.types.VersionCreationMethod;
-import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
 import org.springframework.mock.web.MockMultipartFile;
 
 @RunWith(MockitoJUnitRunner.class)
@@ -58,6 +63,8 @@ public class WorkflowVersionManagerImplTest {
     private static final String VERSION1_ID = "version_id_1";
     private static final String VERSION2_ID = "version_id_2";
 
+    @Mock
+    private ItemManager itemManagerMock;
     @Mock
     private VersioningManager versioningManagerMock;
     @Mock
@@ -68,6 +75,8 @@ public class WorkflowVersionManagerImplTest {
     private VersionMapper versionMapperMock;
     @Mock
     private VersionStateMapper versionStateMapperMock;
+    @Rule
+    public ExpectedException exceptionRule = ExpectedException.none();
     @Spy
     @InjectMocks
     private WorkflowVersionManagerImpl workflowVersionManager;
@@ -79,6 +88,43 @@ public class WorkflowVersionManagerImplTest {
         workflowVersionManager.get(ITEM1_ID, VERSION1_ID);
     }
 
+    @Test(expected = WorkflowModificationException.class)
+    public void shouldThrowExceptionWhenCreatingVersionForArchivedWorkflow() {
+        Item mockItem = new Item();
+        mockItem.setId(ITEM1_ID);
+        mockItem.setStatus(ItemStatus.ARCHIVED);
+        doReturn(mockItem).when(itemManagerMock).get(ITEM1_ID);
+        workflowVersionManager.create(ITEM1_ID, null, new WorkflowVersion(VERSION1_ID));
+    }
+
+    @Test(expected = WorkflowModificationException.class)
+    public void shouldThrowExceptionWhenUpdatingVersionForArchivedWorkflow() {
+        Item mockItem = new Item();
+        mockItem.setId(ITEM1_ID);
+        mockItem.setStatus(ItemStatus.ARCHIVED);
+        doReturn(mockItem).when(itemManagerMock).get(ITEM1_ID);
+        workflowVersionManager.update(ITEM1_ID, new WorkflowVersion(VERSION1_ID));
+    }
+
+    @Test(expected = WorkflowModificationException.class)
+    public void shouldThrowExceptionWhenUploadingArtifactForArchivedWorkflow() {
+        Item mockItem = new Item();
+        mockItem.setId(ITEM1_ID);
+        mockItem.setStatus(ItemStatus.ARCHIVED);
+        doReturn(mockItem).when(itemManagerMock).get(ITEM1_ID);
+        MockMultipartFile mockFile = new MockMultipartFile("data", "filename.txt", "text/plain", "some xml".getBytes());
+        workflowVersionManager.uploadArtifact(ITEM1_ID, VERSION1_ID, mockFile);
+    }
+
+    @Test(expected = WorkflowModificationException.class)
+    public void shouldThrowExceptionWhenDeletingArtifactForArchivedWorkflow() {
+        Item mockItem = new Item();
+        mockItem.setId(ITEM1_ID);
+        mockItem.setStatus(ItemStatus.ARCHIVED);
+        doReturn(mockItem).when(itemManagerMock).get(ITEM1_ID);
+        workflowVersionManager.deleteArtifact(ITEM1_ID, VERSION1_ID);
+    }
+
     @Test
     public void shouldReturnWorkflowVersionWhenExist() {
         Version version = new Version(VERSION1_ID);
@@ -95,7 +141,7 @@ public class WorkflowVersionManagerImplTest {
     public void shouldReturnWorkflowVersionList() {
         Version version1 = new Version(VERSION1_ID);
         Version version2 = new Version(VERSION2_ID);
-        List<Version> versionList = Arrays.asList(version1,version2);
+        List<Version> versionList = Arrays.asList(version1, version2);
         doReturn(versionList).when(versioningManagerMock).list(ITEM1_ID);
         WorkflowVersion workflowVersion1 = new WorkflowVersion();
         workflowVersion1.setId(VERSION1_ID);
@@ -104,8 +150,10 @@ public class WorkflowVersionManagerImplTest {
         workflowVersion2.setId(VERSION2_ID);
         workflowVersion2.setName(VERSION2_ID);
         doReturn(workflowVersion2).when(versionMapperMock).versionToWorkflowVersion(version2);
-        doReturn(Collections.emptyList()).when(parameterRepositoryMock).list(eq(ITEM1_ID),anyString(),eq(ParameterRole.INPUT));
-        doReturn(Collections.emptyList()).when(parameterRepositoryMock).list(eq(ITEM1_ID),anyString(),eq(ParameterRole.OUTPUT));
+        doReturn(Collections.emptyList()).when(parameterRepositoryMock)
+                .list(eq(ITEM1_ID), anyString(), eq(ParameterRole.INPUT));
+        doReturn(Collections.emptyList()).when(parameterRepositoryMock)
+                .list(eq(ITEM1_ID), anyString(), eq(ParameterRole.OUTPUT));
         workflowVersionManager.list(ITEM1_ID, null);
         verify(versioningManagerMock).list(ITEM1_ID);
         verify(versionMapperMock, times(2)).versionToWorkflowVersion(any(Version.class));
@@ -127,14 +175,15 @@ public class WorkflowVersionManagerImplTest {
         workflowVersion2.setName(VERSION2_ID);
         doReturn(workflowVersion1).when(versionMapperMock).versionToWorkflowVersion(version1);
         doReturn(Collections.emptyList()).when(parameterRepositoryMock)
-                                   .list(eq(ITEM1_ID), anyString(), eq(ParameterRole.INPUT));
+                .list(eq(ITEM1_ID), anyString(), eq(ParameterRole.INPUT));
         doReturn(Collections.emptyList()).when(parameterRepositoryMock)
-                                   .list(eq(ITEM1_ID), anyString(), eq(ParameterRole.OUTPUT));
+                .list(eq(ITEM1_ID), anyString(), eq(ParameterRole.OUTPUT));
         doReturn(VersionStatus.Certified).when(versionStateMapperMock)
-                                                                .workflowVersionStateToVersionStatus(
-                                                                       WorkflowVersionState.CERTIFIED);
+                .workflowVersionStateToVersionStatus(
+                        WorkflowVersionState.CERTIFIED);
 
-        assertEquals(1,  workflowVersionManager.list(ITEM1_ID, Collections.singleton(WorkflowVersionState.CERTIFIED)).size());
+        assertEquals(1,
+                workflowVersionManager.list(ITEM1_ID, Collections.singleton(WorkflowVersionState.CERTIFIED)).size());
         verify(versioningManagerMock).list(ITEM1_ID);
         verify(versionMapperMock, times(1)).versionToWorkflowVersion(any(Version.class));
 
@@ -142,6 +191,7 @@ public class WorkflowVersionManagerImplTest {
 
     @Test
     public void shouldUpdateWorkflowVersion() {
+        doNothing().when(workflowVersionManager).validateWorkflowStatus(ITEM1_ID);
         String updatedDescription = "WorkflowVersion description updated";
         Version retrievedVersion = new Version(VERSION1_ID);
         retrievedVersion.setName("1.0");
@@ -160,11 +210,12 @@ public class WorkflowVersionManagerImplTest {
         inputVersion.setInputs(Collections.singleton(toBeCreated));
         ParameterEntity toBeUpdated = new ParameterEntity("Output1");
         inputVersion.setOutputs(Collections.singleton(toBeUpdated));
-        doReturn(Collections.emptyList()).when(parameterRepositoryMock).list(ITEM1_ID,VERSION1_ID,ParameterRole.INPUT);
+        doReturn(Collections.emptyList()).when(parameterRepositoryMock)
+                .list(ITEM1_ID, VERSION1_ID, ParameterRole.INPUT);
         ParameterEntity toBeDeleted = new ParameterEntity("Output2");
         toBeDeleted.setId("parameter_id_1");
         Collection<ParameterEntity> currentOutputs = Arrays.asList(toBeDeleted, toBeUpdated);
-        doReturn(currentOutputs).when(parameterRepositoryMock).list(ITEM1_ID,VERSION1_ID,ParameterRole.OUTPUT);
+        doReturn(currentOutputs).when(parameterRepositoryMock).list(ITEM1_ID, VERSION1_ID, ParameterRole.OUTPUT);
 
         Version mappedInputVersion = new Version(VERSION1_ID);
         mappedInputVersion.setName("1.0");
@@ -181,15 +232,16 @@ public class WorkflowVersionManagerImplTest {
         assertEquals(VersionStatus.Draft, captorVersion.getStatus());
         verify(versioningManagerMock).publish(ITEM1_ID, mappedInputVersion, "Update version");
 
-        verify(parameterRepositoryMock).delete(ITEM1_ID,VERSION1_ID,"parameter_id_1");
-        verify(parameterRepositoryMock).create(ITEM1_ID,VERSION1_ID,ParameterRole.INPUT,toBeCreated);
-        verify(parameterRepositoryMock).update(ITEM1_ID,VERSION1_ID,ParameterRole.OUTPUT,toBeUpdated);
+        verify(parameterRepositoryMock).delete(ITEM1_ID, VERSION1_ID, "parameter_id_1");
+        verify(parameterRepositoryMock).create(ITEM1_ID, VERSION1_ID, ParameterRole.INPUT, toBeCreated);
+        verify(parameterRepositoryMock).update(ITEM1_ID, VERSION1_ID, ParameterRole.OUTPUT, toBeUpdated);
 
     }
 
 
     @Test
     public void shouldCreateWorkflowVersion() {
+        doNothing().when(workflowVersionManager).validateWorkflowStatus(ITEM1_ID);
         Version version = new Version(VERSION1_ID);
         version.setDescription("version desc");
         doReturn(version).when(versioningManagerMock).create(ITEM1_ID, version, VersionCreationMethod.major);
@@ -205,6 +257,7 @@ public class WorkflowVersionManagerImplTest {
 
     @Test(expected = VersionCreationException.class)
     public void shouldTrowExceptionWhenDraftVersionExists() {
+        doNothing().when(workflowVersionManager).validateWorkflowStatus(ITEM1_ID);
         WorkflowVersion versionRequestDto = new WorkflowVersion();
 
         Version baseVersion = new Version(VERSION2_ID);
@@ -217,6 +270,7 @@ public class WorkflowVersionManagerImplTest {
 
     @Test(expected = VersionCreationException.class)
     public void shouldTrowExceptionWhenInputsSupplied() {
+        doNothing().when(workflowVersionManager).validateWorkflowStatus(ITEM1_ID);
         WorkflowVersion versionRequestDto = new WorkflowVersion();
         versionRequestDto.setInputs(Collections.singleton(new ParameterEntity()));
         Version baseVersion = new Version(VERSION2_ID);
@@ -260,32 +314,46 @@ public class WorkflowVersionManagerImplTest {
         workflowVersionManager.updateState(ITEM1_ID, VERSION1_ID, DRAFT);
     }
 
-    @Test(expected = VersionStateModificationException.class)
+    @Test(expected = VersionStateModificationMissingArtifactException.class)
     public void updateStateWhenCertified() {
         Version version = new Version(VERSION1_ID);
         version.setStatus(VersionStatus.Certified);
         doReturn(version).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
         doReturn(CERTIFIED).when(versionStateMapperMock).versionStatusToWorkflowVersionState(version.getStatus());
-        doThrow(new RuntimeException()).when(versioningManagerMock)
-                .submit(eq(ITEM1_ID), eqVersion(VERSION1_ID), anyString());
 
         workflowVersionManager.updateState(ITEM1_ID, VERSION1_ID, CERTIFIED);
     }
 
     @Test
-    public void updateState() {
+    public void shouldFailUpdateStateWhenNoArtifact() {
         Version retrievedVersion = new Version(VERSION1_ID);
         retrievedVersion.setStatus(VersionStatus.Draft);
         doReturn(retrievedVersion).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
         doReturn(DRAFT).when(versionStateMapperMock).versionStatusToWorkflowVersionState(VersionStatus.Draft);
 
+        exceptionRule.expect(VersionStateModificationMissingArtifactException.class);
+        exceptionRule.expectMessage(String.format(
+                VersionStateModificationMissingArtifactException.WORKFLOW_MODIFICATION_STATE_MISSING_ARTIFACT_TEMPLATE,
+                ITEM1_ID, VERSION1_ID, DRAFT, CERTIFIED));
         workflowVersionManager.updateState(ITEM1_ID, VERSION1_ID, CERTIFIED);
 
         verify(versioningManagerMock).submit(eq(ITEM1_ID), eqVersion(VERSION1_ID), anyString());
     }
 
+    @Test
+    public void shouldSuccessUpdateStateWhenArtifactExist() {
+        Version retrievedVersion = new Version(VERSION1_ID);
+        retrievedVersion.setStatus(VersionStatus.Draft);
+        doReturn(retrievedVersion).when(versioningManagerMock).get(eq(ITEM1_ID), eqVersion(VERSION1_ID));
+        doReturn(DRAFT).when(versionStateMapperMock).versionStatusToWorkflowVersionState(VersionStatus.Draft);
+        doReturn(true).when(artifactRepositoryMock).isExist(ITEM1_ID, VERSION1_ID);
+        workflowVersionManager.updateState(ITEM1_ID, VERSION1_ID, CERTIFIED);
+        verify(versioningManagerMock).submit(eq(ITEM1_ID), eqVersion(VERSION1_ID), anyString());
+    }
+
     @Test
     public void shouldUploadArtifact() {
+        doNothing().when(workflowVersionManager).validateWorkflowStatus(ITEM1_ID);
         Version version = new Version(VERSION1_ID);
         version.setStatus(VersionStatus.Draft);
         VersionState versionState = new VersionState();
@@ -321,23 +389,25 @@ public class WorkflowVersionManagerImplTest {
 
     @Test(expected = VersionModificationException.class)
     public void shouldThrowExceptionInDeleteArtifactWhenVersionIsCertified() {
+        doNothing().when(workflowVersionManager).validateWorkflowStatus(ITEM1_ID);
         Version version = new Version(VERSION1_ID);
-        doReturn(version).when(versioningManagerMock).get(ITEM1_ID,version);
+        doReturn(version).when(versioningManagerMock).get(ITEM1_ID, version);
         WorkflowVersion workflowVersion = new WorkflowVersion(VERSION1_ID);
         workflowVersion.setState(WorkflowVersionState.CERTIFIED);
         doReturn(workflowVersion).when(versionMapperMock).versionToWorkflowVersion(version);
-        workflowVersionManager.deleteArtifact(ITEM1_ID,VERSION1_ID);
+        workflowVersionManager.deleteArtifact(ITEM1_ID, VERSION1_ID);
     }
 
     @Test
     public void shouldDeleteArtifact() {
+        doNothing().when(workflowVersionManager).validateWorkflowStatus(ITEM1_ID);
         Version version = new Version(VERSION1_ID);
-        doReturn(version).when(versioningManagerMock).get(ITEM1_ID,version);
+        doReturn(version).when(versioningManagerMock).get(ITEM1_ID, version);
         WorkflowVersion workflowVersion = new WorkflowVersion(VERSION1_ID);
         doReturn(workflowVersion).when(versionMapperMock).versionToWorkflowVersion(version);
-        workflowVersionManager.deleteArtifact(ITEM1_ID,VERSION1_ID);
-        verify(artifactRepositoryMock).delete(ITEM1_ID,VERSION1_ID);
-        verify(versioningManagerMock).publish(ITEM1_ID,version,"Delete Artifact");
+        workflowVersionManager.deleteArtifact(ITEM1_ID, VERSION1_ID);
+        verify(artifactRepositoryMock).delete(ITEM1_ID, VERSION1_ID);
+        verify(versioningManagerMock).publish(ITEM1_ID, version, "Delete Artifact");
     }
 
     private static Version eqVersion(String versionId) {