ALF-4485: F107 All relevant REST APIs have the ability to exclude task and workflow types

GET workflow-definitions, GET task-instances and GET workflow-instances all now support the new 'exclude' parameter. This is a comma separated list of types to exclude from the results, for example: "wf:adhocTask,wcmwf:*"

Also fixed the filtering logic used in GET task-instances and GET workflow-instances so that multiple filter parameters now work correctly together.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22046 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Gavin Cornwell
2010-08-27 14:02:06 +00:00
parent aecf8c464b
commit 6dd6f37edc
8 changed files with 356 additions and 157 deletions

View File

@@ -4,7 +4,7 @@
Lists all Workflow Task Instances associated with an authority and of a given State. 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. The list of returned tasks also includes pooled tasks which the specified authority is eligible to claim.
</description> </description>
<url>/api/task-instances?authority={authority?}&amp;state={state?}&amp;priority={priority?}&amp;pooledTasks={pooledTasks?}&amp;dueBefore={dueBefore?}&amp;dueAfter={dueAfter?}&amp;properties={properties?}&amp;detailed={detailed?}&amp;maxItems={maxItems?}&amp;skipCount={skipCount?}</url> <url>/api/task-instances?authority={authority?}&amp;state={state?}&amp;priority={priority?}&amp;pooledTasks={pooledTasks?}&amp;dueBefore={dueBefore?}&amp;dueAfter={dueAfter?}&amp;properties={properties?}&amp;detailed={detailed?}&amp;maxItems={maxItems?}&amp;skipCount={skipCount?}&amp;exclude={exclude?}</url>
<format default="json"/> <format default="json"/>
<authentication>user</authentication> <authentication>user</authentication>
<transaction allow="readonly">required</transaction> <transaction allow="readonly">required</transaction>

View File

@@ -3,7 +3,7 @@
<description> <description>
Returns a simple representation of all deployed workflow definitions. Returns a simple representation of all deployed workflow definitions.
</description> </description>
<url>/api/workflow-definitions</url> <url>/api/workflow-definitions?exclude={exclude?}</url>
<format default="json"/> <format default="json"/>
<authentication>user</authentication> <authentication>user</authentication>
<transaction allow="readonly">required</transaction> <transaction allow="readonly">required</transaction>

View File

@@ -1,8 +1,8 @@
<webscript> <webscript>
<shortname>Get Workflow Instance Collection</shortname> <shortname>Get Workflow Instance Collection</shortname>
<description>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.</description> <description>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.</description>
<url>/api/workflow-instances?state={state?}&amp;initiator={initiator?}&amp;priority={priority?}&amp;dueBefore={dueBefore?}&amp;dueAfter={dueAfter?}&amp;definitionId={workflow_definition_id?}&amp;startedBefore={startedBefore?}&amp;startedAfter={startedAfter?}&amp;completedBefore={completedBefore?}&amp;completedAfter={completedAfter?}&amp;maxItems={maxItems?}&amp;skipCount={skipCount?}</url> <url>/api/workflow-instances?state={state?}&amp;initiator={initiator?}&amp;priority={priority?}&amp;dueBefore={dueBefore?}&amp;dueAfter={dueAfter?}&amp;definitionId={workflow_definition_id?}&amp;startedBefore={startedBefore?}&amp;startedAfter={startedAfter?}&amp;completedBefore={completedBefore?}&amp;completedAfter={completedAfter?}&amp;maxItems={maxItems?}&amp;skipCount={skipCount?}&amp;exclude={exclude?}</url>
<url>/api/workflow-definitions/{workflow_definition_id}/workflow-instances?state={state?}&amp;initiator={initiator?}&amp;priority={priority?}&amp;dueBefore={dueBefore?}&amp;dueAfter={dueAfter?}&amp;startedBefore={startedBefore?}&amp;startedAfter={startedAfter?}&amp;completedBefore={completedBefore?}&amp;completedAfter={completedAfter?}&amp;maxItems={maxItems?}&amp;skipCount={skipCount?}</url> <url>/api/workflow-definitions/{workflow_definition_id}/workflow-instances?state={state?}&amp;initiator={initiator?}&amp;priority={priority?}&amp;dueBefore={dueBefore?}&amp;dueAfter={dueAfter?}&amp;startedBefore={startedBefore?}&amp;startedAfter={startedAfter?}&amp;completedBefore={completedBefore?}&amp;completedAfter={completedAfter?}&amp;maxItems={maxItems?}&amp;skipCount={skipCount?}&amp;exclude={exclude?}</url>
<format default="json"/> <format default="json"/>
<authentication>user</authentication> <authentication>user</authentication>
<transaction allow="readonly">required</transaction> <transaction allow="readonly">required</transaction>

View File

@@ -39,9 +39,13 @@ import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException; import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.util.StringUtils;
/** /**
* Base class for all workflow REST API implementations.
*
* @author Nick Smith * @author Nick Smith
* @author Gavin Cornwell
* @since 3.4 * @since 3.4
*/ */
public abstract class AbstractWorkflowWebscript extends DeclarativeWebScript public abstract class AbstractWorkflowWebscript extends DeclarativeWebScript
@@ -51,6 +55,7 @@ public abstract class AbstractWorkflowWebscript extends DeclarativeWebScript
public static final String PARAM_MAX_ITEMS = "maxItems"; public static final String PARAM_MAX_ITEMS = "maxItems";
public static final String PARAM_SKIP_COUNT = "skipCount"; public static final String PARAM_SKIP_COUNT = "skipCount";
public static final String PARAM_EXCLUDE = "exclude";
// used for results pagination: indicates that all items from list should be returned // used for results pagination: indicates that all items from list should be returned
public static final int DEFAULT_MAX_ITEMS = -1; public static final int DEFAULT_MAX_ITEMS = -1;
@@ -272,4 +277,126 @@ public abstract class AbstractWorkflowWebscript extends DeclarativeWebScript
return pagingResults; return pagingResults;
} }
/**
* Determines whether the given date is a match for the given filter value.
*
* @param date The date to check against
* @param filterValue The value of the filter, either an empty String or a Date object
* @param dateBeforeFilter true to test the date is before the filterValue,
* false to test the date is after the filterValue
* @return true if the date is a match for the filterValue
*/
protected boolean isDateMatchForFilter(Date date, Object filterValue, boolean dateBeforeFilter)
{
boolean match = true;
if (filterValue.equals(EMPTY))
{
if (date != null)
{
match = false;
}
}
else
{
if (date == null)
{
match = false;
}
else
{
if (dateBeforeFilter)
{
if (((Date)date).getTime() >= ((Date)filterValue).getTime())
{
match = false;
}
}
else
{
if (((Date)date).getTime() <= ((Date)filterValue).getTime())
{
match = false;
}
}
}
}
return match;
}
/**
* Helper class to check for excluded items.
*/
public class ExcludeFilter
{
private static final String WILDCARD = "*";
private List<String> exactFilters;
private List<String> wilcardFilters;
private boolean containsWildcards = false;
/**
* Creates a new ExcludeFilter
*
* @param filters Comma separated list of filters which can optionally
* contain wildcards
*/
public ExcludeFilter(String filters)
{
// tokenize the filters
String[] filterArray = StringUtils.tokenizeToStringArray(filters, ",");
// create a list of exact filters and wildcard filters
this.exactFilters = new ArrayList<String>(filterArray.length);
this.wilcardFilters = new ArrayList<String>(filterArray.length);
for (String filter : filterArray)
{
if (filter.endsWith(WILDCARD))
{
// at least one wildcard is present
this.containsWildcards = true;
// add the filter without the wildcard
this.wilcardFilters.add(filter.substring(0,
(filter.length()-WILDCARD.length())));
}
else
{
// add the exact filter
this.exactFilters.add(filter);
}
}
}
/**
* Determines whether the given item matches one of
* the filters.
*
* @param item The item to check
* @return true if the item matches one of the filters
*/
public boolean isMatch(String item)
{
// see whether there is an exact match
boolean match = this.exactFilters.contains(item);
// if there wasn't an exact match and wildcards are present
if (item != null && !match && this.containsWildcards)
{
for (String wildcardFilter : this.wilcardFilters)
{
if (item.startsWith(wildcardFilter))
{
match = true;
break;
}
}
}
return match;
}
}
} }

View File

@@ -18,7 +18,6 @@
*/ */
package org.alfresco.repo.web.scripts.workflow; package org.alfresco.repo.web.scripts.workflow;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
@@ -38,8 +37,10 @@ import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptRequest;
/** /**
* @author Nick Smith * Webscript impelementation to return workflow task instances.
* *
* @author Nick Smith
* @author Gavin Cornwell
*/ */
public class TaskInstancesGet extends AbstractWorkflowWebscript public class TaskInstancesGet extends AbstractWorkflowWebscript
{ {
@@ -72,6 +73,12 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
processDateFilter(req, PARAM_DUE_BEFORE, filters); processDateFilter(req, PARAM_DUE_BEFORE, filters);
processDateFilter(req, PARAM_DUE_AFTER, filters); processDateFilter(req, PARAM_DUE_AFTER, filters);
String excludeParam = req.getParameter(PARAM_EXCLUDE);
if (excludeParam != null && excludeParam.length() > 0)
{
filters.put(PARAM_EXCLUDE, new ExcludeFilter(excludeParam));
}
List<WorkflowTask> allTasks; List<WorkflowTask> allTasks;
if (authority != null) if (authority != null)
@@ -205,14 +212,17 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
return authority; return authority;
} }
/* /**
* If workflow task matches at list one filter value or if no filter was specified, then it will be included in response * Determine if the given task should be included in the response.
*
* @param task The task to check
* @param filters The list of filters the task must match to be included
* @return true if the task matches and should therefore be returned
*/ */
private boolean matches(WorkflowTask task, Map<String, Object> filters) private boolean matches(WorkflowTask task, Map<String, Object> filters)
{ {
// by default we assume that workflow task should be included to response // by default we assume that workflow task should be included
boolean result = true; boolean result = true;
boolean firstFilter = true;
for (String key : filters.keySet()) for (String key : filters.keySet())
{ {
@@ -221,63 +231,44 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
// skip null filters (null value means that filter was not specified) // skip null filters (null value means that filter was not specified)
if (filterValue != null) if (filterValue != null)
{ {
// some of the filter was specified, so the decision to include or not task to response if (key.equals(PARAM_EXCLUDE))
// based on matching to filter parameter (by default false) {
if (firstFilter) ExcludeFilter excludeFilter = (ExcludeFilter)filterValue;
String type = task.getDefinition().getMetadata().getName().toPrefixString(this.namespaceService);
if (excludeFilter.isMatch(type))
{ {
result = false; result = false;
firstFilter = false; break;
} }
}
else if (key.equals(PARAM_DUE_BEFORE))
{
Date dueDate = (Date)task.getProperties().get(WorkflowModel.PROP_DUE_DATE);
boolean matches = false; if (!isDateMatchForFilter(dueDate, filterValue, true))
if (key.equals(PARAM_DUE_BEFORE))
{ {
Serializable dueDate = task.getProperties().get(WorkflowModel.PROP_DUE_DATE); result = false;
break;
if (filterValue.equals(EMPTY))
{
if (dueDate == null)
{
matches = true;
}
}
else
{
if (dueDate == null || ((Date) dueDate).getTime() <= ((Date) filterValue).getTime())
{
matches = true;
}
} }
} }
else if (key.equals(PARAM_DUE_AFTER)) else if (key.equals(PARAM_DUE_AFTER))
{ {
Serializable dueDate = task.getProperties().get(WorkflowModel.PROP_DUE_DATE); Date dueDate = (Date)task.getProperties().get(WorkflowModel.PROP_DUE_DATE);
if (filterValue.equals(EMPTY)) if (!isDateMatchForFilter(dueDate, filterValue, false))
{ {
if (dueDate == null) result = false;
{ break;
matches = true;
}
}
else
{
if (dueDate == null || ((Date) dueDate).getTime() >= ((Date) filterValue).getTime())
{
matches = true;
}
} }
} }
else if (key.equals(PARAM_PRIORITY)) else if (key.equals(PARAM_PRIORITY))
{ {
if (filterValue.equals(task.getProperties().get(WorkflowModel.PROP_PRIORITY).toString())) if (!filterValue.equals(task.getProperties().get(WorkflowModel.PROP_PRIORITY).toString()))
{ {
matches = true; result = false;
break;
} }
} }
// update global result
result = result || matches;
} }
} }

View File

@@ -34,21 +34,33 @@ import org.springframework.extensions.webscripts.WebScriptRequest;
* *
* @author Gavin Cornwell * @author Gavin Cornwell
* @author Nick Smith * @author Nick Smith
* @since 3.4
*/ */
public class WorkflowDefinitionsGet extends AbstractWorkflowWebscript public class WorkflowDefinitionsGet extends AbstractWorkflowWebscript
{ {
@Override @Override
protected Map<String, Object> buildModel(WorkflowModelBuilder modelBuilder, WebScriptRequest req, Status status, Cache cache) protected Map<String, Object> buildModel(WorkflowModelBuilder modelBuilder, WebScriptRequest req, Status status, Cache cache)
{ {
ExcludeFilter excludeFilter = null;
String excludeParam = req.getParameter(PARAM_EXCLUDE);
if (excludeParam != null && excludeParam.length() > 0)
{
excludeFilter = new ExcludeFilter(excludeParam);
}
// list all workflow's definitions simple representation // list all workflow's definitions simple representation
List<WorkflowDefinition> workflowDefinitions = workflowService.getDefinitions(); List<WorkflowDefinition> workflowDefinitions = workflowService.getDefinitions();
ArrayList<Map<String, Object>> results = new ArrayList<Map<String, Object>>(); ArrayList<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
for (WorkflowDefinition workflowDefinition : workflowDefinitions) for (WorkflowDefinition workflowDefinition : workflowDefinitions)
{
// if present, filter out excluded definitions
if (excludeFilter == null || !excludeFilter.isMatch(workflowDefinition.getName()))
{ {
results.add(modelBuilder.buildSimple(workflowDefinition)); results.add(modelBuilder.buildSimple(workflowDefinition));
} }
}
Map<String, Object> model = new HashMap<String, Object>(); Map<String, Object> model = new HashMap<String, Object>();
model.put("workflowDefinitions", results); model.put("workflowDefinitions", results);

View File

@@ -18,7 +18,6 @@
*/ */
package org.alfresco.repo.web.scripts.workflow; package org.alfresco.repo.web.scripts.workflow;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
@@ -27,6 +26,7 @@ import java.util.Map;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowDefinition; import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowInstance; import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowTask; import org.alfresco.service.cmr.workflow.WorkflowTask;
@@ -35,13 +35,13 @@ import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptRequest;
/** /**
* @author unknown * Java backed implementation for REST API to retrieve workflow instances.
* @since 3.4
* *
* @author Gavin Cornwell
* @since 3.4
*/ */
public class WorkflowInstancesGet extends AbstractWorkflowWebscript public class WorkflowInstancesGet extends AbstractWorkflowWebscript
{ {
public static final String PARAM_STATE = "state"; public static final String PARAM_STATE = "state";
public static final String PARAM_INITIATOR = "initiator"; public static final String PARAM_INITIATOR = "initiator";
public static final String PARAM_PRIORITY = "priority"; public static final String PARAM_PRIORITY = "priority";
@@ -59,12 +59,18 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
{ {
Map<String, String> params = req.getServiceMatch().getTemplateVars(); Map<String, String> params = req.getServiceMatch().getTemplateVars();
// get request parameters // get filter param values
Map<String, Object> filters = new HashMap<String, Object>(9); Map<String, Object> filters = new HashMap<String, Object>(9);
filters.put(PARAM_STATE, req.getParameter(PARAM_STATE)); filters.put(PARAM_STATE, req.getParameter(PARAM_STATE));
filters.put(PARAM_INITIATOR, req.getParameter(PARAM_INITIATOR)); filters.put(PARAM_INITIATOR, req.getParameter(PARAM_INITIATOR));
filters.put(PARAM_PRIORITY, req.getParameter(PARAM_PRIORITY)); filters.put(PARAM_PRIORITY, req.getParameter(PARAM_PRIORITY));
String excludeParam = req.getParameter(PARAM_EXCLUDE);
if (excludeParam != null && excludeParam.length() > 0)
{
filters.put(PARAM_EXCLUDE, new ExcludeFilter(excludeParam));
}
// process all the date related parameters // process all the date related parameters
processDateFilter(req, PARAM_DUE_BEFORE, filters); processDateFilter(req, PARAM_DUE_BEFORE, filters);
processDateFilter(req, PARAM_DUE_AFTER, filters); processDateFilter(req, PARAM_DUE_AFTER, filters);
@@ -113,14 +119,17 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
return createResultModel(modelBuilder, req, "workflowInstances", results); return createResultModel(modelBuilder, req, "workflowInstances", results);
} }
/* /**
* If workflow instance matches at list one filter value or if no filter was specified, then it will be included in response * Determine if the given workflow instance should be included in the response.
*
* @param workflowInstance The workflow instance to check
* @param filters The list of filters the task must match to be included
* @return true if the workflow matches and should therefore be returned
*/ */
private boolean matches(WorkflowInstance workflowInstance, Map<String, Object> filters, WorkflowModelBuilder modelBuilder) private boolean matches(WorkflowInstance workflowInstance, Map<String, Object> filters, WorkflowModelBuilder modelBuilder)
{ {
// by default we assume that workflow instance should be included to response // by default we assume that workflow instance should be included
boolean result = true; boolean result = true;
boolean firstFilter = true;
for (String key : filters.keySet()) for (String key : filters.keySet())
{ {
@@ -129,164 +138,122 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
// skip null filters (null value means that filter was not specified) // skip null filters (null value means that filter was not specified)
if (filterValue != null) if (filterValue != null)
{ {
// some of the filter was specified, so the decision to include or not workflow to response if (key.equals(PARAM_EXCLUDE))
// based on matching to filter parameter (by default false) {
if (firstFilter) ExcludeFilter excludeFilter = (ExcludeFilter)filterValue;
String type = workflowInstance.getDefinition().getName();
if (excludeFilter.isMatch(type))
{ {
result = false; result = false;
firstFilter = false; break;
} }
}
boolean matches = false; else if (key.equals(PARAM_STATE))
if (key.equals(PARAM_STATE))
{ {
WorkflowState filter = WorkflowState.getState(filterValue.toString()); WorkflowState filter = WorkflowState.getState(filterValue.toString());
if (filter != null) if (filter != null)
{ {
if (filter.equals(WorkflowState.COMPLETED) && !workflowInstance.isActive() || filter.equals(WorkflowState.ACTIVE) && workflowInstance.isActive()) if (filter.equals(WorkflowState.COMPLETED) && workflowInstance.isActive() ||
filter.equals(WorkflowState.ACTIVE) && !workflowInstance.isActive())
{ {
matches = true; result = false;
break;
} }
} }
} }
else if (key.equals(PARAM_DUE_BEFORE)) else if (key.equals(PARAM_DUE_BEFORE))
{ {
WorkflowTask startTask = modelBuilder.getStartTaskForWorkflow(workflowInstance); WorkflowTask startTask = modelBuilder.getStartTaskForWorkflow(workflowInstance);
Serializable dueDate = startTask.getProperties().get(WorkflowModel.PROP_WORKFLOW_DUE_DATE); Date dueDate = (Date)startTask.getProperties().get(WorkflowModel.PROP_WORKFLOW_DUE_DATE);
if (filterValue.equals(EMPTY)) if (!isDateMatchForFilter(dueDate, filterValue, true))
{ {
if (dueDate == null) result = false;
{ break;
matches = true;
}
}
else
{
if (dueDate != null && ((Date) dueDate).getTime() <= ((Date) filterValue).getTime())
{
matches = true;
}
} }
} }
else if (key.equals(PARAM_DUE_AFTER)) else if (key.equals(PARAM_DUE_AFTER))
{ {
WorkflowTask startTask = modelBuilder.getStartTaskForWorkflow(workflowInstance); WorkflowTask startTask = modelBuilder.getStartTaskForWorkflow(workflowInstance);
Serializable dueDate = startTask.getProperties().get(WorkflowModel.PROP_WORKFLOW_DUE_DATE); Date dueDate = (Date)startTask.getProperties().get(WorkflowModel.PROP_WORKFLOW_DUE_DATE);
if (filterValue.equals(EMPTY)) if (!isDateMatchForFilter(dueDate, filterValue, false))
{ {
if (dueDate == null) result = false;
{ break;
matches = true;
}
}
else
{
if (dueDate != null && ((Date) dueDate).getTime() >= ((Date) filterValue).getTime())
{
matches = true;
}
} }
} }
else if (key.equals(PARAM_STARTED_BEFORE)) else if (key.equals(PARAM_STARTED_BEFORE))
{ {
Date startDate = workflowInstance.getStartDate(); Date startDate = workflowInstance.getStartDate();
if (filterValue.equals(EMPTY)) if (!isDateMatchForFilter(startDate, filterValue, true))
{ {
if (startDate == null) result = false;
{ break;
matches = true;
}
}
else
{
if (startDate != null && startDate.getTime() <= ((Date) filterValue).getTime())
{
matches = true;
}
} }
} }
else if (key.equals(PARAM_STARTED_AFTER)) else if (key.equals(PARAM_STARTED_AFTER))
{ {
Date startDate = workflowInstance.getStartDate(); Date startDate = workflowInstance.getStartDate();
if (filterValue.equals(EMPTY)) if (!isDateMatchForFilter(startDate, filterValue, false))
{ {
if (startDate == null) result = false;
{ break;
matches = true;
}
}
else
{
if (startDate != null && startDate.getTime() >= ((Date) filterValue).getTime())
{
matches = true;
}
} }
} }
else if (key.equals(PARAM_COMPLETED_BEFORE)) else if (key.equals(PARAM_COMPLETED_BEFORE))
{ {
Date endDate = workflowInstance.getEndDate(); Date endDate = workflowInstance.getEndDate();
if (filterValue.equals(EMPTY)) if (!isDateMatchForFilter(endDate, filterValue, true))
{ {
if (endDate == null) result = false;
{ break;
matches = true;
}
}
else
{
if (endDate != null && endDate.getTime() <= ((Date) filterValue).getTime())
{
matches = true;
}
} }
} }
else if (key.equals(PARAM_COMPLETED_AFTER)) else if (key.equals(PARAM_COMPLETED_AFTER))
{ {
Date endDate = workflowInstance.getEndDate(); Date endDate = workflowInstance.getEndDate();
if (filterValue.equals(EMPTY)) if (!isDateMatchForFilter(endDate, filterValue, false))
{ {
if (endDate == null) result = false;
{ break;
matches = true;
}
}
else
{
if (endDate != null && endDate.getTime() >= ((Date) filterValue).getTime())
{
matches = true;
}
} }
} }
else if (key.equals(PARAM_INITIATOR)) else if (key.equals(PARAM_INITIATOR))
{ {
if (workflowInstance.getInitiator() != null && nodeService.exists(workflowInstance.getInitiator()) && NodeRef initiator = workflowInstance.getInitiator();
filterValue.equals(nodeService.getProperty(workflowInstance.getInitiator(), ContentModel.PROP_USERNAME)))
if (initiator == null)
{ {
matches = true; result = false;
break;
}
else
{
if (!nodeService.exists(initiator) ||
!filterValue.equals(nodeService.getProperty(workflowInstance.getInitiator(), ContentModel.PROP_USERNAME)))
{
result = false;
break;
}
} }
} }
else if (key.equals(PARAM_PRIORITY)) else if (key.equals(PARAM_PRIORITY))
{ {
WorkflowTask startTask = modelBuilder.getStartTaskForWorkflow(workflowInstance); WorkflowTask startTask = modelBuilder.getStartTaskForWorkflow(workflowInstance);
if (startTask != null && filterValue.equals(startTask.getProperties().get(WorkflowModel.PROP_WORKFLOW_PRIORITY).toString())) if (startTask == null || !filterValue.equals(startTask.getProperties().get(WorkflowModel.PROP_WORKFLOW_PRIORITY).toString()))
{ {
matches = true; result = false;
break;
} }
} }
// update global result
result = result || matches;
} }
} }

View File

@@ -170,6 +170,30 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
{ {
checkPaging(MessageFormat.format(URL_USER_TASKS, USER2) + "&maxItems=" + maxItems + "&skipCount=" + skipCount, totalItems, maxItems, skipCount); checkPaging(MessageFormat.format(URL_USER_TASKS, USER2) + "&maxItems=" + maxItems + "&skipCount=" + skipCount, totalItems, maxItems, skipCount);
} }
// check the exclude filtering
String exclude = "wf:submitAdhocTask";
response = sendRequest(new GetRequest(URL_TASKS + "?exclude=" + exclude), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
jsonStr = response.getContentAsString();
json = new JSONObject(jsonStr);
results = json.getJSONArray("data");
assertNotNull(results);
boolean adhocTasksPresent = false;
for (int i = 0; i < results.length(); i++)
{
JSONObject taskJSON = results.getJSONObject(i);
String type = taskJSON.getString("type");
if (exclude.equals(type))
{
adhocTasksPresent = true;
break;
}
}
assertFalse("Found wf:submitAdhocTask when they were supposed to be excluded", adhocTasksPresent);
} }
public void testTaskInstanceGet() throws Exception public void testTaskInstanceGet() throws Exception
@@ -348,6 +372,7 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
JSONObject json = new JSONObject(response.getContentAsString()); JSONObject json = new JSONObject(response.getContentAsString());
JSONArray results = json.getJSONArray("data"); JSONArray results = json.getJSONArray("data");
assertNotNull(results); assertNotNull(results);
assertTrue(results.length() > 0);
for (int i = 0; i < results.length(); i++) for (int i = 0; i < results.length(); i++)
{ {
@@ -370,6 +395,57 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
assertTrue(workflowDefinitionJSON.has("description")); assertTrue(workflowDefinitionJSON.has("description"));
assertTrue(workflowDefinitionJSON.getString("description").length() > 0); assertTrue(workflowDefinitionJSON.getString("description").length() > 0);
} }
// filter the workflow definitions and check they are not returned
String exclude = "jbpm$wf:adhoc";
response = sendRequest(new GetRequest(URL_WORKFLOW_DEFINITIONS + "?exclude=" + exclude), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
json = new JSONObject(response.getContentAsString());
results = json.getJSONArray("data");
assertNotNull(results);
boolean adhocWorkflowPresent = false;
for (int i = 0; i < results.length(); i++)
{
JSONObject workflowDefinitionJSON = results.getJSONObject(i);
String name = workflowDefinitionJSON.getString("name");
if (exclude.equals(name))
{
adhocWorkflowPresent = true;
break;
}
}
assertFalse("Found adhoc workflow when it was supposed to be excluded", adhocWorkflowPresent);
// filter with a wildcard and ensure they all get filtered out
exclude = "jbpm$wf:adhoc, jbpm$wcmwf:*";
response = sendRequest(new GetRequest(URL_WORKFLOW_DEFINITIONS + "?exclude=" + exclude), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
json = new JSONObject(response.getContentAsString());
results = json.getJSONArray("data");
assertNotNull(results);
adhocWorkflowPresent = false;
boolean wcmWorkflowsPresent = false;
for (int i = 0; i < results.length(); i++)
{
JSONObject workflowDefinitionJSON = results.getJSONObject(i);
String name = workflowDefinitionJSON.getString("name");
if (name.equals("jbpm$wf:adhoc"))
{
adhocWorkflowPresent = true;
}
if (name.startsWith("jbpm$wcmwf:"))
{
wcmWorkflowsPresent = true;
}
}
assertFalse("Found adhoc workflow when it was supposed to be excluded", adhocWorkflowPresent);
assertFalse("Found a WCM workflow when they were supposed to be excluded", wcmWorkflowsPresent);
} }
public void testWorkflowInstanceGet() throws Exception public void testWorkflowInstanceGet() throws Exception
@@ -480,18 +556,20 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
checkSimpleWorkflowInstanceResponse(forDefinitionResult.getJSONObject(i)); checkSimpleWorkflowInstanceResponse(forDefinitionResult.getJSONObject(i));
} }
// create a date an hour ago to test filtering
Date anHourAgo = new Date(dueDate.getTime());
anHourAgo.setHours(anHourAgo.getHours()-1);
// filter by initiator // filter by initiator
checkFiltering(URL_WORKFLOW_INSTANCES + "?initiator=" + USER1); checkFiltering(URL_WORKFLOW_INSTANCES + "?initiator=" + USER1);
// filter by startedAfter // filter by startedAfter
checkFiltering(URL_WORKFLOW_INSTANCES + "?startedAfter=" + ISO8601DateFormat.format(adhocInstance.getStartDate())); checkFiltering(URL_WORKFLOW_INSTANCES + "?startedAfter=" + ISO8601DateFormat.format(anHourAgo));
// filter by startedBefore // filter by startedBefore
checkFiltering(URL_WORKFLOW_INSTANCES + "?startedBefore=" + ISO8601DateFormat.format(adhocInstance.getStartDate())); checkFiltering(URL_WORKFLOW_INSTANCES + "?startedBefore=" + ISO8601DateFormat.format(adhocInstance.getStartDate()));
// filter by dueAfter // filter by dueAfter
Date anHourAgo = new Date(dueDate.getTime());
anHourAgo.setHours(anHourAgo.getHours()-1);
checkFiltering(URL_WORKFLOW_INSTANCES + "?dueAfter=" + ISO8601DateFormat.format(anHourAgo)); checkFiltering(URL_WORKFLOW_INSTANCES + "?dueAfter=" + ISO8601DateFormat.format(anHourAgo));
// filter by dueBefore // filter by dueBefore
@@ -518,6 +596,30 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
{ {
checkPaging(URL_WORKFLOW_INSTANCES + "?maxItems=" + maxItems + "&skipCount=" + skipCount, totalItems, maxItems, skipCount); checkPaging(URL_WORKFLOW_INSTANCES + "?maxItems=" + maxItems + "&skipCount=" + skipCount, totalItems, maxItems, skipCount);
} }
// check the exclude filtering
String exclude = "jbpm$wf:adhoc";
response = sendRequest(new GetRequest(URL_WORKFLOW_INSTANCES + "?exclude=" + exclude), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
jsonStr = response.getContentAsString();
json = new JSONObject(jsonStr);
JSONArray results = json.getJSONArray("data");
assertNotNull(results);
boolean adhocWorkflowPresent = false;
for (int i = 0; i < results.length(); i++)
{
JSONObject workflowInstanceJSON = results.getJSONObject(i);
String type = workflowInstanceJSON.getString("type");
if (exclude.equals(type))
{
adhocWorkflowPresent = true;
break;
}
}
assertFalse("Found adhoc workflows when they were supposed to be excluded", adhocWorkflowPresent);
} }
public void testWorkflowInstancesForNodeGet() throws Exception public void testWorkflowInstancesForNodeGet() throws Exception