diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instances.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instances.get.desc.xml index 80ae37060b..42db149bce 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instances.get.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instances.get.desc.xml @@ -4,7 +4,7 @@ Lists all Workflow Task Instances associated with an authority and of a given State. The list of returned tasks also includes pooled tasks which the specified authority is eligible to claim. - /api/task-instances?authority={authority?}&state={state?}&priority={priority?}&dueBefore={dueBefore?}&dueAfter={dueAfter?}&properties={properties?}&detailed={detailed?}&maxItems={maxItems?}&skipCount={skipCount?} + /api/task-instances?authority={authority?}&state={state?}&priority={priority?}&pooledTasks={pooledTasks?}&dueBefore={dueBefore?}&dueAfter={dueAfter?}&properties={properties?}&detailed={detailed?}&maxItems={maxItems?}&skipCount={skipCount?} user required diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-instances.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-instances.get.desc.xml index c71e183383..9de97412a9 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-instances.get.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-instances.get.desc.xml @@ -1,7 +1,7 @@ Get Workflow Instance Collection Retrieves all workflow instances, the returned list can be optionally filtered by the state of the workflow instance and by the authority that initiated the workflow instance. - /api/workflow-instances?state={state?}&initiator={initiator?}&priority={priority?}&dueBefore={dueBefore?}&dueAfter={dueAfter?}&startedBefore={startedBefore?}&startedAfter={startedAfter?}&completedBefore={completedBefore?}&completedAfter={completedAfter?}&maxItems={maxItems?}&skipCount={skipCount?} + /api/workflow-instances?state={state?}&initiator={initiator?}&priority={priority?}&dueBefore={dueBefore?}&dueAfter={dueAfter?}&definitionId={workflow_definition_id?}&startedBefore={startedBefore?}&startedAfter={startedAfter?}&completedBefore={completedBefore?}&completedAfter={completedAfter?}&maxItems={maxItems?}&skipCount={skipCount?} /api/workflow-definitions/{workflow_definition_id}/workflow-instances?state={state?}&initiator={initiator?}&priority={priority?}&dueBefore={dueBefore?}&dueAfter={dueAfter?}&startedBefore={startedBefore?}&startedAfter={startedAfter?}&completedBefore={completedBefore?}&completedAfter={completedAfter?}&maxItems={maxItems?}&skipCount={skipCount?} user diff --git a/source/java/org/alfresco/repo/web/scripts/workflow/AbstractWorkflowWebscript.java b/source/java/org/alfresco/repo/web/scripts/workflow/AbstractWorkflowWebscript.java index 05f858812c..6bbccf6652 100644 --- a/source/java/org/alfresco/repo/web/scripts/workflow/AbstractWorkflowWebscript.java +++ b/source/java/org/alfresco/repo/web/scripts/workflow/AbstractWorkflowWebscript.java @@ -46,6 +46,9 @@ import org.springframework.extensions.webscripts.WebScriptRequest; */ public abstract class AbstractWorkflowWebscript extends DeclarativeWebScript { + public static final String NULL = "null"; + public static final String EMPTY = ""; + public static final String PARAM_MAX_ITEMS = "maxItems"; public static final String PARAM_SKIP_COUNT = "skipCount"; @@ -119,6 +122,36 @@ public abstract class AbstractWorkflowWebscript extends DeclarativeWebScript WebScriptRequest req, Status status, Cache cache); + + /** + * Processes the given date filter parameter from the provided webscript request. + * + * If the parameter is present but set to an empty string or to "null" the + * date is added to the given filters Map as "", if the parameter + * contains an ISO8601 date it's added as a Date object to the filters. + * + * @param req The WebScript request + * @param paramName The name of the parameter to look for + * @param filters Map of filters to add the date to + */ + protected void processDateFilter(WebScriptRequest req, String paramName, Map filters) + { + // TODO: support other keywords i.e. today, tomorrow + + String dateParam = req.getParameter(paramName); + if (dateParam != null) + { + Object date = EMPTY; + + if (!EMPTY.equals(dateParam) && !NULL.equals(dateParam)) + { + date = getDateParameter(req, paramName); + } + + filters.put(paramName, date); + } + } + /** * Retrieves the named paramter as a date. * diff --git a/source/java/org/alfresco/repo/web/scripts/workflow/TaskInstancesGet.java b/source/java/org/alfresco/repo/web/scripts/workflow/TaskInstancesGet.java index 9bacb94374..a9fa288d0a 100644 --- a/source/java/org/alfresco/repo/web/scripts/workflow/TaskInstancesGet.java +++ b/source/java/org/alfresco/repo/web/scripts/workflow/TaskInstancesGet.java @@ -49,6 +49,7 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript public static final String PARAM_DUE_BEFORE = "dueBefore"; public static final String PARAM_DUE_AFTER = "dueAfter"; public static final String PARAM_PROPERTIES = "properties"; + public static final String PARAM_POOLED_TASKS = "pooledTasks"; public static final String PARAM_DETAILED = "detailed"; @Override @@ -58,24 +59,47 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript // authority is not included into filters list as it will be taken into account before filtering String authority = getAuthority(req); + // state is also not included into filters list, for the same reason WorkflowTaskState state = getState(req); - filters.put(PARAM_PRIORITY, req.getParameter(PARAM_PRIORITY)); - filters.put(PARAM_DUE_BEFORE, getDateParameter(req, PARAM_DUE_BEFORE)); - filters.put(PARAM_DUE_AFTER, getDateParameter(req, PARAM_DUE_AFTER)); - + + Boolean pooledTasksOnly = getPooledTasks(req); List properties = getProperties(req); boolean detailed = "true".equals(req.getParameter(PARAM_DETAILED)); - + + // get filter param values + filters.put(PARAM_PRIORITY, req.getParameter(PARAM_PRIORITY)); + processDateFilter(req, PARAM_DUE_BEFORE, filters); + processDateFilter(req, PARAM_DUE_AFTER, filters); + List allTasks; if (authority != null) { List tasks = workflowService.getAssignedTasks(authority, state); List pooledTasks = workflowService.getPooledTasks(authority); - allTasks = new ArrayList(tasks.size() + pooledTasks.size()); - allTasks.addAll(tasks); - allTasks.addAll(pooledTasks); + if (pooledTasksOnly != null) + { + if (pooledTasksOnly.booleanValue()) + { + // only return pooled tasks the user can claim + allTasks = new ArrayList(pooledTasks.size()); + allTasks.addAll(pooledTasks); + } + else + { + // only return tasks assigned to the user + allTasks = new ArrayList(tasks.size()); + allTasks.addAll(tasks); + } + } + else + { + // include both assigned and unassigned tasks + allTasks = new ArrayList(tasks.size() + pooledTasks.size()); + allTasks.addAll(tasks); + allTasks.addAll(pooledTasks); + } } else { @@ -107,6 +131,12 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript return createResultModel(modelBuilder, req, "taskInstances", results); } + /** + * Retrieves the list of property names to include in the response. + * + * @param req The WebScript request + * @return List of property names + */ private List getProperties(WebScriptRequest req) { String propertiesStr = req.getParameter(PARAM_PROPERTIES); @@ -116,7 +146,26 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript } return null; } - + + /** + * Retrieves the pooledTasks parameter. + * + * @param req The WebScript request + * @return null if not present, Boolean object otherwise + */ + private Boolean getPooledTasks(WebScriptRequest req) + { + Boolean result = null; + String includePooledTasks = req.getParameter(PARAM_POOLED_TASKS); + + if (includePooledTasks != null) + { + result = Boolean.valueOf(includePooledTasks); + } + + return result; + } + /** * Gets the specified {@link WorkflowTaskState}, defaults to IN_PROGRESS. * @param req @@ -186,18 +235,38 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript { Serializable dueDate = task.getProperties().get(WorkflowModel.PROP_DUE_DATE); - if (dueDate == null || ((Date) dueDate).getTime() <= ((Date) filterValue).getTime()) + if (filterValue.equals(EMPTY)) { - matches = true; + if (dueDate == null) + { + matches = true; + } + } + else + { + if (dueDate == null || ((Date) dueDate).getTime() <= ((Date) filterValue).getTime()) + { + matches = true; + } } } else if (key.equals(PARAM_DUE_AFTER)) { Serializable dueDate = task.getProperties().get(WorkflowModel.PROP_DUE_DATE); - if (dueDate == null || ((Date) dueDate).getTime() >= ((Date) filterValue).getTime()) + if (filterValue.equals(EMPTY)) { - matches = true; + if (dueDate == null) + { + matches = true; + } + } + else + { + if (dueDate == null || ((Date) dueDate).getTime() >= ((Date) filterValue).getTime()) + { + matches = true; + } } } else if (key.equals(PARAM_PRIORITY)) @@ -214,5 +283,4 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript return result; } - } diff --git a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstancesGet.java b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstancesGet.java index 579e4e213d..5d604aa224 100644 --- a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstancesGet.java +++ b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstancesGet.java @@ -51,7 +51,8 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript public static final String PARAM_STARTED_AFTER = "startedAfter"; public static final String PARAM_COMPLETED_BEFORE = "completedBefore"; public static final String PARAM_COMPLETED_AFTER = "completedAfter"; - public static final String PARAM_DEFINITION_ID = "workflow_definition_id"; + public static final String PARAM_DEFINITION_ID = "definitionId"; + public static final String VAR_DEFINITION_ID = "workflow_definition_id"; @Override protected Map buildModel(WorkflowModelBuilder modelBuilder, WebScriptRequest req, Status status, Cache cache) @@ -63,14 +64,21 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript filters.put(PARAM_STATE, req.getParameter(PARAM_STATE)); filters.put(PARAM_INITIATOR, req.getParameter(PARAM_INITIATOR)); filters.put(PARAM_PRIORITY, req.getParameter(PARAM_PRIORITY)); - filters.put(PARAM_DUE_BEFORE, getDateParameter(req, PARAM_DUE_BEFORE)); - filters.put(PARAM_DUE_AFTER, getDateParameter(req, PARAM_DUE_AFTER)); - filters.put(PARAM_STARTED_BEFORE, getDateParameter(req, PARAM_STARTED_BEFORE)); - filters.put(PARAM_STARTED_AFTER, getDateParameter(req, PARAM_STARTED_AFTER)); - filters.put(PARAM_COMPLETED_BEFORE, getDateParameter(req, PARAM_COMPLETED_BEFORE)); - filters.put(PARAM_COMPLETED_AFTER, getDateParameter(req, PARAM_COMPLETED_AFTER)); + + // process all the date related parameters + processDateFilter(req, PARAM_DUE_BEFORE, filters); + processDateFilter(req, PARAM_DUE_AFTER, filters); + processDateFilter(req, PARAM_STARTED_BEFORE, filters); + processDateFilter(req, PARAM_STARTED_AFTER, filters); + processDateFilter(req, PARAM_COMPLETED_BEFORE, filters); + processDateFilter(req, PARAM_COMPLETED_AFTER, filters); - String workflowDefinitionId = params.get(PARAM_DEFINITION_ID); + // determine if there is a definition id to filter by + String workflowDefinitionId = params.get(VAR_DEFINITION_ID); + if (workflowDefinitionId == null) + { + workflowDefinitionId = req.getParameter(PARAM_DEFINITION_ID); + } List workflows = new ArrayList(); @@ -148,9 +156,19 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript WorkflowTask startTask = modelBuilder.getStartTaskForWorkflow(workflowInstance); Serializable dueDate = startTask.getProperties().get(WorkflowModel.PROP_WORKFLOW_DUE_DATE); - if (dueDate == null || ((Date) dueDate).getTime() <= ((Date) filterValue).getTime()) + if (filterValue.equals(EMPTY)) { - matches = true; + if (dueDate == null) + { + matches = true; + } + } + else + { + if (dueDate != null && ((Date) dueDate).getTime() <= ((Date) filterValue).getTime()) + { + matches = true; + } } } else if (key.equals(PARAM_DUE_AFTER)) @@ -158,51 +176,101 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript WorkflowTask startTask = modelBuilder.getStartTaskForWorkflow(workflowInstance); Serializable dueDate = startTask.getProperties().get(WorkflowModel.PROP_WORKFLOW_DUE_DATE); - if (dueDate == null || ((Date) dueDate).getTime() >= ((Date) filterValue).getTime()) + if (filterValue.equals(EMPTY)) { - matches = true; + if (dueDate == null) + { + matches = true; + } + } + else + { + if (dueDate != null && ((Date) dueDate).getTime() >= ((Date) filterValue).getTime()) + { + matches = true; + } } } else if (key.equals(PARAM_STARTED_BEFORE)) { Date startDate = workflowInstance.getStartDate(); - if (startDate == null || startDate.getTime() <= ((Date) filterValue).getTime()) + if (filterValue.equals(EMPTY)) { - matches = true; + if (startDate == null) + { + matches = true; + } + } + else + { + if (startDate != null && startDate.getTime() <= ((Date) filterValue).getTime()) + { + matches = true; + } } } else if (key.equals(PARAM_STARTED_AFTER)) { Date startDate = workflowInstance.getStartDate(); - if (startDate == null || startDate.getTime() >= ((Date) filterValue).getTime()) + if (filterValue.equals(EMPTY)) { - matches = true; + if (startDate == null) + { + matches = true; + } + } + else + { + if (startDate != null && startDate.getTime() >= ((Date) filterValue).getTime()) + { + matches = true; + } } } else if (key.equals(PARAM_COMPLETED_BEFORE)) { Date endDate = workflowInstance.getEndDate(); - if (endDate == null || endDate.getTime() <= ((Date) filterValue).getTime()) + if (filterValue.equals(EMPTY)) { - matches = true; + if (endDate == null) + { + matches = true; + } + } + else + { + if (endDate != null && endDate.getTime() <= ((Date) filterValue).getTime()) + { + matches = true; + } } } else if (key.equals(PARAM_COMPLETED_AFTER)) { Date endDate = workflowInstance.getEndDate(); - if (endDate == null || endDate.getTime() >= ((Date) filterValue).getTime()) + if (filterValue.equals(EMPTY)) { - matches = true; + if (endDate == null) + { + matches = true; + } + } + else + { + if (endDate != null && endDate.getTime() >= ((Date) filterValue).getTime()) + { + matches = true; + } } } else if (key.equals(PARAM_INITIATOR)) { - if (workflowInstance.getInitiator() != null && nodeService.exists(workflowInstance.getInitiator()) - && filterValue.equals(nodeService.getProperty(workflowInstance.getInitiator(), ContentModel.PROP_USERNAME))) + if (workflowInstance.getInitiator() != null && nodeService.exists(workflowInstance.getInitiator()) && + filterValue.equals(nodeService.getProperty(workflowInstance.getInitiator(), ContentModel.PROP_USERNAME))) { matches = true; } @@ -216,6 +284,7 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript matches = true; } } + // update global result result = result || matches; } diff --git a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowRestApiTest.java b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowRestApiTest.java index 92dd81a1f0..3517c3344f 100644 --- a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowRestApiTest.java +++ b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowRestApiTest.java @@ -435,6 +435,7 @@ public class WorkflowRestApiTest extends BaseWebScriptTest assertTrue(tasks.length() > 1); } + @SuppressWarnings("deprecation") public void testWorkflowInstancesGet() throws Exception { //Start workflow as USER1 and assign task to USER2. @@ -443,15 +444,15 @@ public class WorkflowRestApiTest extends BaseWebScriptTest Map params = new HashMap(); params.put(WorkflowModel.ASSOC_ASSIGNEE, personManager.get(USER2)); Date dueDate = new Date(); - params.put(WorkflowModel.PROP_DUE_DATE, dueDate); + params.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, dueDate); params.put(WorkflowModel.PROP_WORKFLOW_PRIORITY, 1); params.put(WorkflowModel.ASSOC_PACKAGE, packageRef); params.put(WorkflowModel.PROP_CONTEXT, packageRef); WorkflowPath adhocPath = workflowService.startWorkflow(adhocDef.getId(), params); WorkflowTask startTask = workflowService.getTasksForWorkflowPath(adhocPath.getId()).get(0); - WorkflowInstance adhocInstance = startTask.getPath().getInstance(); + workflowService.endTask(startTask.getId(), null); // Get Workflow Instance Collection Response response = sendRequest(new GetRequest(URL_WORKFLOW_INSTANCES), 200); @@ -489,7 +490,9 @@ public class WorkflowRestApiTest extends BaseWebScriptTest checkFiltering(URL_WORKFLOW_INSTANCES + "?startedBefore=" + ISO8601DateFormat.format(adhocInstance.getStartDate())); // filter by dueAfter - checkFiltering(URL_WORKFLOW_INSTANCES + "?dueAfter=" + ISO8601DateFormat.format(dueDate)); + Date anHourAgo = new Date(dueDate.getTime()); + anHourAgo.setHours(anHourAgo.getHours()-1); + checkFiltering(URL_WORKFLOW_INSTANCES + "?dueAfter=" + ISO8601DateFormat.format(anHourAgo)); // filter by dueBefore checkFiltering(URL_WORKFLOW_INSTANCES + "?dueBefore=" + ISO8601DateFormat.format(dueDate));