Merged BRANCHES/DEV/BELARUS/HEAD_2010_08_17 to HEAD:

21853: ALF-4304 : F101 All relevant REST APIs have filtering capabilities i.e. authority, state, priority and date range
               ALF-3902: F77 REST API to get all task instances

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21899 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Gavin Cornwell
2010-08-20 12:31:58 +00:00
parent 55bd4fc42e
commit 79c700b6fb
5 changed files with 413 additions and 216 deletions

View File

@@ -2,9 +2,9 @@
<shortname>List Workflow Tasks</shortname>
<description>
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>
<url>/api/task-instances?authority={authority?}&amp;state={state?}&amp;properties={properties?}&amp;detailed={detailed?}</url>
<url>/api/task-instances?authority={authority?}&amp;state={state?}&amp;priority={priority?}&amp;dueBefore={dueBefore?}&amp;dueAfter={dueAfter?}&amp;properties={properties?}&amp;detailed={detailed?}</url>
<format default="json"/>
<authentication>user</authentication>
<transaction allow="readonly">required</transaction>

View File

@@ -1,8 +1,8 @@
<webscript>
<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>
<url>/api/workflow-instances?state={state?}&amp;initiator={initiator?}&amp;priority={priority?}</url>
<url>/api/workflow-definitions/{workflow_definition_id}/workflow-instances?state={state?}&amp;initiator={initiator?}&amp;date={date?}&amp;priority={priority?}</url>
<url>/api/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?}</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?}</url>
<format default="json"/>
<authentication>user</authentication>
<transaction allow="readonly">required</transaction>

View File

@@ -18,17 +18,21 @@
*/
package org.alfresco.repo.web.scripts.workflow;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.springframework.extensions.surf.util.ISO8601DateFormat;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
@@ -41,38 +45,63 @@ import org.springframework.extensions.webscripts.WebScriptRequest;
public class TaskInstancesGet extends AbstractWorkflowWebscript
{
public static final String PARAM_AUTHORITY = "authority";
public static final String PARAM_STATUS= "status";
public static final String PARAM_PROPERTIES= "properties";
public static final String PARAM_DETAILED= "detailed";
public static final String PARAM_STATE = "state";
public static final String PARAM_PRIORITY = "priority";
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_DETAILED = "detailed";
@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)
{
Map<String, Object> filters = new HashMap<String, Object>(4);
// 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));
List<String> properties = getProperties(req);
boolean detailed = "true".equals(req.getParameter(PARAM_DETAILED));
//TODO Handle possible thrown exceptions here?
List<WorkflowTask> tasks = workflowService.getAssignedTasks(authority, state);
List<WorkflowTask> pooledTasks= workflowService.getPooledTasks(authority);
ArrayList<WorkflowTask> allTasks = new ArrayList<WorkflowTask>(tasks.size() + pooledTasks.size());
allTasks.addAll(tasks);
allTasks.addAll(pooledTasks);
ArrayList<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
for (WorkflowTask task : allTasks)
List<WorkflowTask> allTasks;
if (authority != null)
{
if (detailed)
List<WorkflowTask> tasks = workflowService.getAssignedTasks(authority, state);
List<WorkflowTask> pooledTasks = workflowService.getPooledTasks(authority);
allTasks = new ArrayList<WorkflowTask>(tasks.size() + pooledTasks.size());
allTasks.addAll(tasks);
allTasks.addAll(pooledTasks);
}
else
{
// authority was not provided -> return all active tasks in the system
WorkflowTaskQuery taskQuery = new WorkflowTaskQuery();
taskQuery.setTaskState(state);
allTasks = workflowService.queryTasks(taskQuery);
}
ArrayList<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
for (WorkflowTask task : allTasks)
{
if (matches(task, filters))
{
results.add(modelBuilder.buildDetailed(task));
}
else {
results.add(modelBuilder.buildSimple(task, properties));
if (detailed)
{
results.add(modelBuilder.buildDetailed(task));
}
else
{
results.add(modelBuilder.buildSimple(task, properties));
}
}
}
Map<String, Object> model = new HashMap<String, Object>();
model.put("taskInstances", results);
return model;
@@ -81,7 +110,7 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
private List<String> getProperties(WebScriptRequest req)
{
String propertiesStr = req.getParameter(PARAM_PROPERTIES);
if(propertiesStr != null)
if (propertiesStr != null)
{
return Arrays.asList(propertiesStr.split(","));
}
@@ -95,16 +124,16 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
*/
private WorkflowTaskState getState(WebScriptRequest req)
{
String stateName= req.getParameter(PARAM_STATUS);
if(stateName != null)
String stateName = req.getParameter(PARAM_STATE);
if (stateName != null)
{
try
{
return WorkflowTaskState.valueOf(stateName.toUpperCase());
}
catch(IllegalArgumentException e)
catch (IllegalArgumentException e)
{
String msg = "Unrecognised State parameter: "+stateName;
String msg = "Unrecognised State parameter: " + stateName;
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
@@ -120,11 +149,89 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
private String getAuthority(WebScriptRequest req)
{
String authority = req.getParameter(PARAM_AUTHORITY);
if(authority == null)
if (authority == null || authority.length() == 0)
{
authority = AuthenticationUtil.getFullyAuthenticatedUser();
authority = null;
}
return authority;
}
private Date getDateParameter(WebScriptRequest req, String name)
{
String dateString = req.getParameter(name);
if (dateString != null)
{
try
{
return ISO8601DateFormat.parse(dateString.replaceAll(" ", "+"));
}
catch (Exception e)
{
String msg = "Invalid date value: " + dateString;
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
return null;
}
/*
* If workflow task matches at list one filter value or if no filter was specified, then it will be included in response
*/
private boolean matches(WorkflowTask task, Map<String, Object> filters)
{
// by default we assume that workflow task should be included to response
boolean result = true;
boolean firstFilter = true;
for (String key : filters.keySet())
{
Object filterValue = filters.get(key);
// skip null filters (null value means that filter was not specified)
if (filterValue != null)
{
// some of the filter was specified, so the decision to include or not task to response
// based on matching to filter parameter (by default false)
if (firstFilter)
{
result = false;
firstFilter = false;
}
boolean matches = false;
if (key.equals(PARAM_DUE_BEFORE))
{
Serializable dueDate = task.getProperties().get(WorkflowModel.PROP_DUE_DATE);
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())
{
matches = true;
}
}
else if (key.equals(PARAM_PRIORITY))
{
if (filterValue.equals(task.getProperties().get(WorkflowModel.PROP_PRIORITY).toString()))
{
matches = true;
}
}
// update global result
result = result || matches;
}
}
return result;
}
}

View File

@@ -18,11 +18,15 @@
*/
package org.alfresco.repo.web.scripts.workflow;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
@@ -31,6 +35,7 @@ import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.springframework.extensions.surf.util.ISO8601DateFormat;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
@@ -43,26 +48,36 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
public static final String PARAM_STATE = "state";
public static final String PARAM_INITIATOR = "initiator";
public static final String PARAM_DATE = "date";
public static final String PARAM_PRIORITY = "priority";
public static final String PARAM_DUE_BEFORE = "dueBefore";
public static final String PARAM_DUE_AFTER = "dueAfter";
public static final String PARAM_STARTED_BEFORE = "startedBefore";
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";
@Override
protected Map<String, Object> buildModel(WorkflowModelBuilder modelBuilder, WebScriptRequest req, Status status, Cache cache)
{
Map<String, String> params = req.getServiceMatch().getTemplateVars();
// get request parameters
Map<String, String> filters = new HashMap<String, String>(4);
Map<String, Object> filters = new HashMap<String, Object>(9);
filters.put(PARAM_STATE, req.getParameter(PARAM_STATE));
filters.put(PARAM_INITIATOR, req.getParameter(PARAM_INITIATOR));
filters.put(PARAM_DATE, req.getParameter(PARAM_DATE));
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));
String workflowDefinitionId = params.get(PARAM_DEFINITION_ID);
List<WorkflowInstance> workflows = new ArrayList<WorkflowInstance>();
if (workflowDefinitionId != null)
{
// list workflows for specified workflow definition
@@ -71,17 +86,17 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
else
{
List<WorkflowDefinition> workflowDefinitions = workflowService.getAllDefinitions();
// list workflows for all definitions
for (WorkflowDefinition workflowDefinition : workflowDefinitions)
{
workflows.addAll(workflowService.getWorkflows(workflowDefinition.getId()));
}
}
// filter result
List<Map<String, Object>> results = new ArrayList<Map<String,Object>>(workflows.size());
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>(workflows.size());
for (WorkflowInstance workflow : workflows)
{
if (matches(workflow, filters, modelBuilder))
@@ -89,18 +104,18 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
results.add(modelBuilder.buildSimple(workflow));
}
}
Map<String, Object> model = new HashMap<String, Object>();
// build the model for ftl
model.put("workflowInstances", results);
return model;
}
/*
* If workflow instance matches at list one filter value or if no filter was specified, then it will included in response
* If workflow instance matches at list one filter value or if no filter was specified, then it will be included in response
*/
private boolean matches(WorkflowInstance workflowInstance, Map<String, String> 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
boolean result = true;
@@ -108,7 +123,7 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
for (String key : filters.keySet())
{
String filterValue = filters.get(key);
Object filterValue = filters.get(key);
// skip null filters (null value means that filter was not specified)
if (filterValue != null)
@@ -125,7 +140,7 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
if (key.equals(PARAM_STATE))
{
WorkflowState filter = WorkflowState.getState(filterValue);
WorkflowState filter = WorkflowState.getState(filterValue.toString());
if (filter != null)
{
@@ -135,17 +150,66 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
}
}
}
else if (key.equals(PARAM_DATE))
else if (key.equals(PARAM_DUE_BEFORE))
{
// only workflows that was started after specified time are returned
if (workflowInstance.getStartDate().getTime() >= ISO8601DateFormat.parse(filterValue.replaceAll(" ", "+")).getTime())
WorkflowTask startTask = modelBuilder.getStartTaskForWorkflow(workflowInstance);
Serializable dueDate = startTask.getProperties().get(WorkflowModel.PROP_WORKFLOW_DUE_DATE);
if (dueDate == null || ((Date) dueDate).getTime() <= ((Date) filterValue).getTime())
{
matches = true;
}
}
else if (key.equals(PARAM_DUE_AFTER))
{
WorkflowTask startTask = modelBuilder.getStartTaskForWorkflow(workflowInstance);
Serializable dueDate = startTask.getProperties().get(WorkflowModel.PROP_WORKFLOW_DUE_DATE);
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())
{
matches = true;
}
}
else if (key.equals(PARAM_STARTED_AFTER))
{
Date startDate = workflowInstance.getStartDate();
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())
{
matches = true;
}
}
else if (key.equals(PARAM_COMPLETED_AFTER))
{
Date endDate = workflowInstance.getEndDate();
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;
}
@@ -163,22 +227,41 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
result = result || matches;
}
}
return result;
}
private Date getDateParameter(WebScriptRequest req, String name)
{
String dateString = req.getParameter(name);
if (dateString != null)
{
try
{
return ISO8601DateFormat.parse(dateString.replaceAll(" ", "+"));
}
catch (Exception e)
{
String msg = "Invalid date value: " + dateString;
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
return null;
}
private enum WorkflowState
{
{
ACTIVE ("active"),
COMPLETED ("completed");
String value;
WorkflowState(String value)
{
this.value = value;
}
static WorkflowState getState(String value)
{
for (WorkflowState state : WorkflowState.values())
@@ -188,7 +271,7 @@ public class WorkflowInstancesGet extends AbstractWorkflowWebscript
return state;
}
}
return null;
}
}

View File

@@ -56,9 +56,9 @@ import org.json.JSONObject;
import org.springframework.context.ApplicationContext;
import org.springframework.extensions.surf.util.ISO8601DateFormat;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.TestWebScriptServer.DeleteRequest;
import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest;
import org.springframework.extensions.webscripts.TestWebScriptServer.PutRequest;
import org.springframework.extensions.webscripts.TestWebScriptServer.DeleteRequest;
import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
/**
@@ -69,84 +69,98 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
{
private final static String USER1 = "Bob" + GUID.generate();
private final static String USER2 = "Jane" + GUID.generate();
private final static String USER3 = "Nick" + GUID.generate();
private final static String USER3 = "Nick" + GUID.generate();
private static final String URL_TASKS = "api/task-instances";
private static final String URL_USER_TASKS = "api/task-instances?authority={0}";
private static final String URL_WORKFLOW_DEFINITIONS = "api/workflow-definitions";
private static final String URL_WORKFLOW_INSTANCES = "api/workflow-instances";
private static final String URL_WORKFLOW_INSTANCES_FOR_DEFINITION = "api/workflow-definitions/{0}/workflow-instances";
private static final String URL_WORKFLOW_INSTANCES_FOR_NODE = "api/node/{0}/{1}/{2}/workflow-instances";
private static final String COMPANY_HOME = "/app:company_home";
private static final String TEST_CONTENT = "TestContent";
private TestPersonManager personManager;
private WorkflowService workflowService;
private NodeService nodeService;
private NamespaceService namespaceService;
private NodeRef packageRef;
private NodeRef contentNodeRef;
public void testTaskInstancesGet() throws Exception
{
// Check USER2 starts with no tasks.
personManager.setUser(USER2);
Response response = sendRequest(new GetRequest(URL_TASKS), 200);
Response response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER2)), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
String jsonStr = response.getContentAsString();
JSONObject json = new JSONObject(jsonStr);
JSONArray results = json.getJSONArray("data");
assertNotNull(results);
assertTrue(results.length() == 0);
// Start workflow as USER1 and assign task to USER2.
personManager.setUser(USER1);
WorkflowDefinition adhocDef = workflowService.getDefinitionByName("jbpm$wf:adhoc");
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
params.put(WorkflowModel.ASSOC_ASSIGNEE, personManager.get(USER2));
params.put(WorkflowModel.PROP_DUE_DATE, new Date());
Date dueDate = new Date();
params.put(WorkflowModel.PROP_DUE_DATE, dueDate);
params.put(WorkflowModel.PROP_PRIORITY, 1);
params.put(WorkflowModel.ASSOC_PACKAGE, packageRef);
WorkflowPath adhocPath = workflowService.startWorkflow(adhocDef.id, params);
WorkflowTask startTask = workflowService.getTasksForWorkflowPath(adhocPath.id).get(0);
workflowService.endTask(startTask.id, null);
// Check USER2 now has one task.
List<WorkflowTask> tasks = workflowService.getAssignedTasks(USER2, WorkflowTaskState.IN_PROGRESS);
WorkflowTask task = tasks.get(0);
personManager.setUser(USER2);
response = sendRequest(new GetRequest(URL_TASKS), 200);
response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER2)), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
jsonStr = response.getContentAsString();
System.out.println(jsonStr);
json = new JSONObject(jsonStr);
results = json.getJSONArray("data");
assertNotNull(results);
assertTrue(results.length() == tasks.size());
JSONObject result = results.getJSONObject(0);
String expUrl = "api/task-instances/" + task.id;
assertEquals(expUrl, result.getString("url"));
assertEquals(task.name, result.getString("name"));
assertEquals(task.title, result.getString("title"));
assertEquals(task.description, result.getString("description"));
assertEquals(task.state.name(), result.getString("state"));
assertEquals(task.definition.metadata.getTitle(), result.getString("typeDefinitionTitle"));
assertEquals(false, result.getBoolean("isPooled"));
assertEquals(task.definition.metadata.getName().toPrefixString(this.namespaceService),
result.getString("type"));
assertEquals( "api/workflow-paths/" + adhocPath.getId(), result.getString("path"));
assertFalse(result.getBoolean("isPooled"));
assertTrue(result.getBoolean("isEditable"));
assertTrue(result.getBoolean("isReassignable"));
assertFalse(result.getBoolean("isClaimable"));
assertFalse(result.getBoolean("isReleasable"));
JSONObject owner = result.getJSONObject("owner");
assertEquals(USER2, owner.getString("userName"));
assertEquals(personManager.getFirstName(USER2), owner.getString("firstName"));
assertEquals(personManager.getLastName(USER2), owner.getString("lastName"));
JSONObject properties = result.getJSONObject("properties");
assertNotNull(properties);
JSONObject instance = result.getJSONObject("workflowInstance");
assertNotNull(instance);
// TODO: Add more tests to check property filtering and pooled actors.
// filtering
checkFiltering(URL_TASKS + "?priority=2");
checkFiltering(URL_TASKS + "?dueAfter=" + ISO8601DateFormat.format(dueDate));
checkFiltering(URL_TASKS + "?dueBefore=" + ISO8601DateFormat.format(dueDate));
}
public void testTaskInstanceGet() throws Exception
@@ -177,7 +191,7 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
assertEquals(startTask.description, result.getString("description"));
assertEquals(startTask.state.name(), result.getString("state"));
assertEquals(startTask.name, result.getString("type"));
assertEquals( "api/workflow-paths/" + adhocPath.getId(), result.getString("path"));
assertEquals("api/workflow-paths/" + adhocPath.getId(), result.getString("path"));
assertFalse(result.getBoolean("isPooled"));
assertTrue(result.getBoolean("isEditable"));
assertTrue(result.getBoolean("isReassignable"));
@@ -194,12 +208,12 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
assertTrue(properties.has("bpm_priority"));
assertTrue(properties.has("bpm_description"));
assertTrue(properties.has("bpm_reassignable"));
JSONObject instance = result.getJSONObject("workflowInstance");
WorkflowInstance startInstance = startTask.path.instance;
assertNotNull(instance);
assertEquals(startInstance.id, instance.getString("id"));
assertTrue(instance.has("url"));
assertEquals(startInstance.definition.name, instance.getString("name"));
@@ -207,13 +221,13 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
assertEquals(startInstance.definition.description, instance.getString("description"));
assertEquals(startInstance.active, instance.getBoolean("isActive"));
assertTrue(instance.has("startDate"));
JSONObject initiator = instance.getJSONObject("initiator");
assertEquals(USER1, initiator.getString("userName"));
assertEquals(personManager.getFirstName(USER1), initiator.getString("firstName"));
assertEquals(personManager.getLastName(USER1), initiator.getString("lastName"));
JSONObject definition = result.getJSONObject("definition");
WorkflowTaskDefinition startDefinitiont = startTask.definition;
@@ -264,7 +278,7 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
}
}
public void testTaskInstancePut() throws Exception
{
// Start workflow as USER1 and assign task to USER2.
@@ -278,18 +292,18 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
WorkflowPath adhocPath = workflowService.startWorkflow(adhocDef.id, params);
WorkflowTask startTask = workflowService.getTasksForWorkflowPath(adhocPath.id).get(0);
Response getResponse = sendRequest(new GetRequest(URL_TASKS + "/" + startTask.id), 200);
Response getResponse = sendRequest(new GetRequest(URL_TASKS + "/" + startTask.id), 200);
JSONObject jsonProperties = new JSONObject(getResponse.getContentAsString()).getJSONObject("data").getJSONObject("properties");
// make some changes
jsonProperties.remove(qnameToString(WorkflowModel.ASSOC_PACKAGE));
jsonProperties.put(qnameToString(WorkflowModel.PROP_COMMENT), "Edited comment");
jsonProperties.put(qnameToString(WorkflowModel.PROP_DUE_DATE), ISO8601DateFormat.format(new Date()));
jsonProperties.put(qnameToString(WorkflowModel.PROP_DESCRIPTION), "Edited description");
jsonProperties.put(qnameToString(WorkflowModel.PROP_PRIORITY), 1);
// test USER3 can not update the task
personManager.setUser(USER3);
Response unauthResponse = sendRequest(new PutRequest(URL_TASKS + "/" + startTask.id, jsonProperties.toString(), "application/json"), 401);
@@ -298,26 +312,26 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
// test USER1 (the task owner) can update the task
personManager.setUser(USER1);
Response putResponse = sendRequest(new PutRequest(URL_TASKS + "/" + startTask.id, jsonProperties.toString(), "application/json"), 200);
assertEquals(Status.STATUS_OK, putResponse.getStatus());
String jsonStr = putResponse.getContentAsString();
JSONObject json = new JSONObject(jsonStr);
JSONObject result = json.getJSONObject("data");
assertNotNull(result);
JSONObject editedJsonProperties = result.getJSONObject("properties");
compareProperties(jsonProperties, editedJsonProperties);
// get the next task where USER2 is the owner
workflowService.endTask(startTask.id, null);
List<WorkflowPath> paths = workflowService.getWorkflowPaths(adhocPath.getInstance().getId());
WorkflowTask nextTask = workflowService.getTasksForWorkflowPath(paths.get(0).getId()).get(0);
// make sure USER1 (the workflow initiator) can update
putResponse = sendRequest(new PutRequest(URL_TASKS + "/" + nextTask.id, jsonProperties.toString(), "application/json"), 200);
}
public void testWorkflowDefinitionsGet() throws Exception
{
Response response = sendRequest(new GetRequest(URL_WORKFLOW_DEFINITIONS), 200);
@@ -325,30 +339,30 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
JSONObject json = new JSONObject(response.getContentAsString());
JSONArray results = json.getJSONArray("data");
assertNotNull(results);
for (int i = 0; i < results.length(); i++)
{
JSONObject workflowDefinitionJSON = results.getJSONObject(i);
assertTrue(workflowDefinitionJSON.has("id"));
assertTrue(workflowDefinitionJSON.getString("id").length() > 0);
assertTrue(workflowDefinitionJSON.has("url"));
String url = workflowDefinitionJSON.getString("url");
assertTrue(url.length() > 0);
assertTrue(url.startsWith("api/workflow-definitions/"));
assertTrue(workflowDefinitionJSON.has("name"));
assertTrue(workflowDefinitionJSON.getString("name").length() > 0);
assertTrue(workflowDefinitionJSON.has("title"));
assertTrue(workflowDefinitionJSON.getString("title").length() > 0);
assertTrue(workflowDefinitionJSON.has("description"));
assertTrue(workflowDefinitionJSON.getString("description").length() > 0);
}
}
public void testWorkflowInstanceGet() throws Exception
{
//Start workflow as USER1 and assign task to USER2.
@@ -365,16 +379,16 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
WorkflowPath adhocPath = workflowService.startWorkflow(adhocDef.id, params);
WorkflowTask startTask = workflowService.getTasksForWorkflowPath(adhocPath.id).get(0);
startTask = workflowService.endTask(startTask.id, null);
WorkflowInstance adhocInstance = startTask.path.instance;
Response response = sendRequest(new GetRequest(URL_WORKFLOW_INSTANCES + "/" + adhocInstance.id + "?includeTasks=true"), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
String jsonStr = response.getContentAsString();
JSONObject json = new JSONObject(jsonStr);
JSONObject result = json.getJSONObject("data");
assertNotNull(result);
assertEquals(adhocInstance.id, result.getString("id"));
assertEquals(adhocInstance.definition.name, result.getString("name"));
assertEquals(adhocInstance.definition.title, result.getString("title"));
@@ -385,20 +399,20 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
assertNotNull(result.getString("endDate"));
assertEquals(2, result.getInt("priority"));
JSONObject initiator = result.getJSONObject("initiator");
assertEquals(USER1, initiator.getString("userName"));
assertEquals(personManager.getFirstName(USER1), initiator.getString("firstName"));
assertEquals(personManager.getLastName(USER1), initiator.getString("lastName"));
assertEquals(adhocInstance.context.toString(), result.getString("context"));
assertEquals(adhocInstance.workflowPackage.toString(), result.getString("package"));
assertNotNull(result.getString("startTaskInstanceId"));
JSONObject jsonDefinition = result.getJSONObject("definition");
WorkflowDefinition adhocDefinition = adhocInstance.definition;
assertNotNull(jsonDefinition);
assertEquals(adhocDefinition.id, jsonDefinition.getString("id"));
assertEquals(adhocDefinition.name, jsonDefinition.getString("name"));
assertEquals(adhocDefinition.title, jsonDefinition.getString("title"));
@@ -406,11 +420,11 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
assertEquals(adhocDefinition.version, jsonDefinition.getString("version"));
assertEquals(adhocDefinition.getStartTaskDefinition().metadata.getName().toPrefixString(namespaceService), jsonDefinition.getString("startTaskDefinitionType"));
assertTrue(jsonDefinition.has("taskDefinitions"));
JSONArray tasks = result.getJSONArray("tasks");
assertTrue(tasks.length() > 1);
}
public void testWorkflowInstancesGet() throws Exception
{
//Start workflow as USER1 and assign task to USER2.
@@ -426,9 +440,9 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
WorkflowPath adhocPath = workflowService.startWorkflow(adhocDef.getId(), params);
WorkflowTask startTask = workflowService.getTasksForWorkflowPath(adhocPath.getId()).get(0);
WorkflowInstance adhocInstance = startTask.getPath().getInstance();
WorkflowInstance adhocInstance = startTask.getPath().getInstance();
// Get Workflow Instance Collection
Response response = sendRequest(new GetRequest(URL_WORKFLOW_INSTANCES), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
@@ -436,74 +450,55 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
JSONObject json = new JSONObject(jsonStr);
JSONArray result = json.getJSONArray("data");
assertNotNull(result);
for (int i = 0; i < result.length(); i++)
{
checkSimpleWorkflowInstanceResponse(result.getJSONObject(i));
}
Response forDefinitionResponse = sendRequest(new GetRequest(MessageFormat.format(URL_WORKFLOW_INSTANCES_FOR_DEFINITION, adhocDef.getId())), 200);
assertEquals(Status.STATUS_OK, forDefinitionResponse.getStatus());
String forDefinitionJsonStr = forDefinitionResponse.getContentAsString();
JSONObject forDefinitionJson = new JSONObject(forDefinitionJsonStr);
JSONArray forDefinitionResult = forDefinitionJson.getJSONArray("data");
assertNotNull(forDefinitionResult);
for (int i = 0; i < forDefinitionResult.length(); i++)
{
checkSimpleWorkflowInstanceResponse(forDefinitionResult.getJSONObject(i));
}
// filter by initiator
String initiatorFilter = "?initiator=" + USER1;
Response initiatorFilteredResponse = sendRequest(new GetRequest(URL_WORKFLOW_INSTANCES + initiatorFilter), 200);
assertEquals(Status.STATUS_OK, initiatorFilteredResponse.getStatus());
String initiatorFilteredJsonStr = initiatorFilteredResponse.getContentAsString();
JSONObject initiatorFilteredJson = new JSONObject(initiatorFilteredJsonStr);
JSONArray initiatorFilteredResult = initiatorFilteredJson.getJSONArray("data");
assertNotNull(initiatorFilteredResult);
assertEquals(1, initiatorFilteredResult.length());
assertEquals(adhocInstance.getId(), initiatorFilteredResult.getJSONObject(0).getString("id"));
// filter by date
String dateFilter = "?date=" + ISO8601DateFormat.format(adhocInstance.startDate);
Response dateFilteredResponse = sendRequest(new GetRequest(URL_WORKFLOW_INSTANCES + dateFilter), 200);
assertEquals(Status.STATUS_OK, dateFilteredResponse.getStatus());
String dateFilteredJsonStr = dateFilteredResponse.getContentAsString();
JSONObject dateFilteredJson = new JSONObject(dateFilteredJsonStr);
JSONArray dateFilteredResult = dateFilteredJson.getJSONArray("data");
assertNotNull(dateFilteredResult);
assertTrue(dateFilteredResult.length() > 0);
// filter by priority
String priorityFilter = "?priority=1";
Response priorityFilteredResponse = sendRequest(new GetRequest(URL_WORKFLOW_INSTANCES + priorityFilter), 200);
assertEquals(Status.STATUS_OK, priorityFilteredResponse.getStatus());
String priorityFilteredJsonStr = priorityFilteredResponse.getContentAsString();
JSONObject priorityFilteredJson = new JSONObject(priorityFilteredJsonStr);
JSONArray priorityFilteredResult = priorityFilteredJson.getJSONArray("data");
assertNotNull(priorityFilteredResult);
assertTrue(priorityFilteredResult.length() > 0);
checkFiltering(URL_WORKFLOW_INSTANCES + "?initiator=" + USER1);
// filter by startedAfter
checkFiltering(URL_WORKFLOW_INSTANCES + "?startedAfter=" + ISO8601DateFormat.format(adhocInstance.getStartDate()));
// filter by startedBefore
checkFiltering(URL_WORKFLOW_INSTANCES + "?startedBefore=" + ISO8601DateFormat.format(adhocInstance.getStartDate()));
// filter by dueAfter
checkFiltering(URL_WORKFLOW_INSTANCES + "?dueAfter=" + ISO8601DateFormat.format(dueDate));
// filter by dueBefore
checkFiltering(URL_WORKFLOW_INSTANCES + "?dueBefore=" + ISO8601DateFormat.format(dueDate));
if (adhocInstance.getEndDate() != null)
{
// filter by completedAfter
checkFiltering(URL_WORKFLOW_INSTANCES + "?completedAfter=" + ISO8601DateFormat.format(adhocInstance.getEndDate()));
// filter by completedBefore
checkFiltering(URL_WORKFLOW_INSTANCES + "?completedBefore=" + ISO8601DateFormat.format(adhocInstance.getEndDate()));
}
// filter by priority
checkFiltering(URL_WORKFLOW_INSTANCES + "?priority=1");
// filter by state
String stateFilter = "?state=active";
Response stateFilteredResponse = sendRequest(new GetRequest(URL_WORKFLOW_INSTANCES + stateFilter), 200);
assertEquals(Status.STATUS_OK, stateFilteredResponse.getStatus());
String stateFilteredJsonStr = stateFilteredResponse.getContentAsString();
JSONObject stateFilteredJson = new JSONObject(stateFilteredJsonStr);
JSONArray stateFilteredResult = stateFilteredJson.getJSONArray("data");
assertNotNull(stateFilteredResult);
assertTrue(stateFilteredResult.length() > 1);
checkFiltering(URL_WORKFLOW_INSTANCES + "?state=active");
}
public void testWorkflowInstancesForNodeGet() throws Exception
{
//Start workflow as USER1 and assign task to USER2.
@@ -514,38 +509,38 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
params.put(WorkflowModel.PROP_DUE_DATE, new Date());
params.put(WorkflowModel.PROP_PRIORITY, 1);
params.put(WorkflowModel.ASSOC_PACKAGE, packageRef);
nodeService.addChild(packageRef, contentNodeRef,
WorkflowModel.ASSOC_PACKAGE_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,
QName.createValidLocalName((String)nodeService.getProperty(
contentNodeRef, ContentModel.PROP_NAME))));
WorkflowPath adhocPath = workflowService.startWorkflow(adhocDef.id, params);
WorkflowPath adhocPath = workflowService.startWorkflow(adhocDef.id, params);
String url = MessageFormat.format(URL_WORKFLOW_INSTANCES_FOR_NODE, contentNodeRef.getStoreRef().getProtocol(), contentNodeRef.getStoreRef().getIdentifier(), contentNodeRef.getId());
Response response = sendRequest(new GetRequest(url), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
String jsonStr = response.getContentAsString();
JSONObject json = new JSONObject(jsonStr);
JSONArray result = json.getJSONArray("data");
assertNotNull(result);
assertTrue(result.length() > 0);
workflowService.cancelWorkflow(adhocPath.getInstance().getId());
Response afterCancelResponse = sendRequest(new GetRequest(url), 200);
assertEquals(Status.STATUS_OK, afterCancelResponse.getStatus());
String afterCancelJsonStr = afterCancelResponse.getContentAsString();
JSONObject afterCancelJson = new JSONObject(afterCancelJsonStr);
JSONArray afterCancelResult = afterCancelJson.getJSONArray("data");
assertNotNull(afterCancelResult);
assertTrue(afterCancelResult.length() == 0);
}
public void testWorkflowInstanceDelete() throws Exception
{
//Start workflow as USER1 and assign task to USER2.
@@ -567,7 +562,7 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
Response response = sendRequest(new DeleteRequest(URL_WORKFLOW_INSTANCES + "/" + adhocInstance.getId()), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
assertNull(workflowService.getWorkflowById(adhocInstance.getId()));
}
@@ -576,32 +571,31 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
{
super.setUp();
ApplicationContext appContext = getServer().getApplicationContext();
namespaceService = (NamespaceService)appContext.getBean("NamespaceService");
workflowService = (WorkflowService)appContext.getBean("WorkflowService");
MutableAuthenticationService authenticationService = (MutableAuthenticationService)appContext.getBean("AuthenticationService");
PersonService personService = (PersonService)appContext.getBean("PersonService");
SearchService searchService = (SearchService)appContext.getBean("SearchService");
FileFolderService fileFolderService = (FileFolderService)appContext.getBean("FileFolderService");
nodeService = (NodeService)appContext.getBean("NodeService");
namespaceService = (NamespaceService) appContext.getBean("NamespaceService");
workflowService = (WorkflowService) appContext.getBean("WorkflowService");
MutableAuthenticationService authenticationService = (MutableAuthenticationService) appContext.getBean("AuthenticationService");
PersonService personService = (PersonService) appContext.getBean("PersonService");
SearchService searchService = (SearchService) appContext.getBean("SearchService");
FileFolderService fileFolderService = (FileFolderService) appContext.getBean("FileFolderService");
nodeService = (NodeService) appContext.getBean("NodeService");
personManager = new TestPersonManager(authenticationService, personService, nodeService);
personManager.createPerson(USER1);
personManager.createPerson(USER2);
personManager.createPerson(USER3);
packageRef = workflowService.createPackage(null);
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
NodeRef companyHome = searchService.selectNodes(nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE),
COMPANY_HOME, null, namespaceService, false).get(0);
NodeRef companyHome = searchService.selectNodes(nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE), COMPANY_HOME, null, namespaceService, false).get(0);
contentNodeRef = fileFolderService.create(companyHome, TEST_CONTENT + System.currentTimeMillis(), ContentModel.TYPE_CONTENT).getNodeRef();
AuthenticationUtil.clearCurrentSecurityContext();
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
@@ -611,14 +605,14 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
super.tearDown();
personManager.clearPeople();
}
private String qnameToString(QName qName)
{
String separator = Character.toString(QName.NAMESPACE_PREFIX);
return qName.toPrefixString(namespaceService).replaceFirst(separator, "_");
}
private void compareProperties(JSONObject before, JSONObject after) throws JSONException
{
for (String name : JSONObject.getNames(after))
@@ -629,7 +623,7 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
{
for (int i = 0; i < before.getJSONArray(name).length(); i++)
{
assertEquals(before.getJSONArray(name).get(i), after.getJSONArray(name).get(i));
assertEquals(before.getJSONArray(name).get(i), after.getJSONArray(name).get(i));
}
}
else
@@ -639,41 +633,54 @@ public class WorkflowRestApiTest extends BaseWebScriptTest
}
}
}
private void checkSimpleWorkflowInstanceResponse(JSONObject json) throws JSONException
{
assertTrue(json.has("id"));
assertTrue(json.getString("id").length() > 0);
assertTrue(json.has("url"));
assertTrue(json.getString("url").startsWith(URL_WORKFLOW_INSTANCES));
assertTrue(json.has("name"));
assertTrue(json.getString("name").length() > 0);
assertTrue(json.has("title"));
assertTrue(json.getString("title").length() > 0);
assertTrue(json.has("description"));
assertTrue(json.getString("description").length() > 0);
assertTrue(json.has("isActive"));
assertTrue(json.has("isActive"));
assertTrue(json.has("startDate"));
assertTrue(json.getString("startDate").length() > 0);
assertTrue(json.has("endDate"));
assertTrue(json.has("endDate"));
assertTrue(json.has("initiator"));
Object initiator = json.get("initiator");
if (!initiator.equals(JSONObject.NULL))
{
assertTrue(((JSONObject)initiator).has("userName"));
assertTrue(((JSONObject)initiator).has("firstName"));
assertTrue(((JSONObject)initiator).has("lastName"));
assertTrue(((JSONObject) initiator).has("userName"));
assertTrue(((JSONObject) initiator).has("firstName"));
assertTrue(((JSONObject) initiator).has("lastName"));
}
assertTrue(json.has("definitionUrl"));
assertTrue(json.getString("definitionUrl").startsWith(URL_WORKFLOW_DEFINITIONS));
}
private void checkFiltering(String url) throws Exception
{
Response response = sendRequest(new GetRequest(url), 200);
assertEquals(Status.STATUS_OK, response.getStatus());
String jsonStr = response.getContentAsString();
JSONObject json = new JSONObject(jsonStr);
JSONArray result = json.getJSONArray("data");
assertNotNull(result);
assertTrue(result.length() > 0);
}
}