mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-21 18:09:20 +00:00
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:
@@ -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?}&state={state?}&priority={priority?}&pooledTasks={pooledTasks?}&dueBefore={dueBefore?}&dueAfter={dueAfter?}&properties={properties?}&detailed={detailed?}&maxItems={maxItems?}&skipCount={skipCount?}</url>
|
<url>/api/task-instances?authority={authority?}&state={state?}&priority={priority?}&pooledTasks={pooledTasks?}&dueBefore={dueBefore?}&dueAfter={dueAfter?}&properties={properties?}&detailed={detailed?}&maxItems={maxItems?}&skipCount={skipCount?}&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>
|
||||||
|
@@ -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>
|
||||||
|
@@ -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?}&initiator={initiator?}&priority={priority?}&dueBefore={dueBefore?}&dueAfter={dueAfter?}&definitionId={workflow_definition_id?}&startedBefore={startedBefore?}&startedAfter={startedAfter?}&completedBefore={completedBefore?}&completedAfter={completedAfter?}&maxItems={maxItems?}&skipCount={skipCount?}</url>
|
<url>/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?}&exclude={exclude?}</url>
|
||||||
<url>/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?}</url>
|
<url>/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?}&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>
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Webscript impelementation to return workflow task instances.
|
||||||
|
*
|
||||||
* @author Nick Smith
|
* @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)
|
|
||||||
{
|
{
|
||||||
result = false;
|
ExcludeFilter excludeFilter = (ExcludeFilter)filterValue;
|
||||||
firstFilter = false;
|
String type = task.getDefinition().getMetadata().getName().toPrefixString(this.namespaceService);
|
||||||
}
|
if (excludeFilter.isMatch(type))
|
||||||
|
|
||||||
boolean matches = false;
|
|
||||||
|
|
||||||
if (key.equals(PARAM_DUE_BEFORE))
|
|
||||||
{
|
|
||||||
Serializable dueDate = task.getProperties().get(WorkflowModel.PROP_DUE_DATE);
|
|
||||||
|
|
||||||
if (filterValue.equals(EMPTY))
|
|
||||||
{
|
{
|
||||||
if (dueDate == null)
|
result = false;
|
||||||
{
|
break;
|
||||||
matches = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else if (key.equals(PARAM_DUE_BEFORE))
|
||||||
|
{
|
||||||
|
Date dueDate = (Date)task.getProperties().get(WorkflowModel.PROP_DUE_DATE);
|
||||||
|
|
||||||
|
if (!isDateMatchForFilter(dueDate, filterValue, true))
|
||||||
{
|
{
|
||||||
if (dueDate == null || ((Date) dueDate).getTime() <= ((Date) filterValue).getTime())
|
result = false;
|
||||||
{
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,12 +34,20 @@ 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();
|
||||||
|
|
||||||
@@ -47,7 +55,11 @@ public class WorkflowDefinitionsGet extends AbstractWorkflowWebscript
|
|||||||
|
|
||||||
for (WorkflowDefinition workflowDefinition : workflowDefinitions)
|
for (WorkflowDefinition workflowDefinition : workflowDefinitions)
|
||||||
{
|
{
|
||||||
results.add(modelBuilder.buildSimple(workflowDefinition));
|
// if present, filter out excluded definitions
|
||||||
|
if (excludeFilter == null || !excludeFilter.isMatch(workflowDefinition.getName()))
|
||||||
|
{
|
||||||
|
results.add(modelBuilder.buildSimple(workflowDefinition));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> model = new HashMap<String, Object>();
|
Map<String, Object> model = new HashMap<String, Object>();
|
||||||
|
@@ -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.
|
||||||
|
*
|
||||||
|
* @author Gavin Cornwell
|
||||||
* @since 3.4
|
* @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);
|
||||||
@@ -72,7 +78,7 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
|
|||||||
processDateFilter(req, PARAM_STARTED_AFTER, filters);
|
processDateFilter(req, PARAM_STARTED_AFTER, filters);
|
||||||
processDateFilter(req, PARAM_COMPLETED_BEFORE, filters);
|
processDateFilter(req, PARAM_COMPLETED_BEFORE, filters);
|
||||||
processDateFilter(req, PARAM_COMPLETED_AFTER, filters);
|
processDateFilter(req, PARAM_COMPLETED_AFTER, filters);
|
||||||
|
|
||||||
// determine if there is a definition id to filter by
|
// determine if there is a definition id to filter by
|
||||||
String workflowDefinitionId = params.get(VAR_DEFINITION_ID);
|
String workflowDefinitionId = params.get(VAR_DEFINITION_ID);
|
||||||
if (workflowDefinitionId == null)
|
if (workflowDefinitionId == null)
|
||||||
@@ -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)
|
|
||||||
{
|
{
|
||||||
result = false;
|
ExcludeFilter excludeFilter = (ExcludeFilter)filterValue;
|
||||||
firstFilter = false;
|
String type = workflowInstance.getDefinition().getName();
|
||||||
|
|
||||||
|
if (excludeFilter.isMatch(type))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if (key.equals(PARAM_STATE))
|
||||||
boolean matches = false;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
@@ -479,19 +555,21 @@ 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
|
||||||
|
Reference in New Issue
Block a user