mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged 5.2.N (5.2.1) to HEAD (5.2)
130404 jkaabimofrad: SHA-1598: Added support to Get Task Instances API to filter result, based on the given property. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@130935 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?}&maxItems={maxItems?}&skipCount={skipCount?}&exclude={exclude?}</url>
|
<url>/api/task-instances?authority={authority?}&state={state?}&priority={priority?}&pooledTasks={pooledTasks?}&dueBefore={dueBefore?}&dueAfter={dueAfter?}&properties={properties?}&maxItems={maxItems?}&skipCount={skipCount?}&exclude={exclude?}&property={propQName/propValue?}</url>
|
||||||
<url>/api/workflow-instances/{workflow_instance_id}/task-instances?authority={authority?}&state={state?}&priority={priority?}&dueBefore={isoDate?}&dueAfter={isoDate?}&properties={prop1, prop2, prop3...?}&maxItems={maxItems?}&skipCount={skipCount?}&exclude={exclude?}</url>
|
<url>/api/workflow-instances/{workflow_instance_id}/task-instances?authority={authority?}&state={state?}&priority={priority?}&dueBefore={isoDate?}&dueAfter={isoDate?}&properties={prop1, prop2, prop3...?}&maxItems={maxItems?}&skipCount={skipCount?}&exclude={exclude?}</url>
|
||||||
<format default="json"/>
|
<format default="json"/>
|
||||||
<authentication>user</authentication>
|
<authentication>user</authentication>
|
||||||
@@ -55,6 +55,10 @@
|
|||||||
<shortname>workflow_instance_id</shortname>
|
<shortname>workflow_instance_id</shortname>
|
||||||
<description>Restricts the returned tasks to those that belong to the given workflow process instance id.</description>
|
<description>Restricts the returned tasks to those that belong to the given workflow process instance id.</description>
|
||||||
</arg>
|
</arg>
|
||||||
|
<arg>
|
||||||
|
<shortname>property</shortname>
|
||||||
|
<description>Restricts the returned tasks to only those that match the given property. The property name should be a valid QName format followed by '/' then the property value. E.g. bpm:description/myDescription</description>
|
||||||
|
</arg>
|
||||||
</args>
|
</args>
|
||||||
<responses>
|
<responses>
|
||||||
<response>
|
<response>
|
||||||
|
@@ -1,30 +1,31 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Remote API
|
* Alfresco Remote API
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
*
|
*
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
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.Collections;
|
import java.util.Collections;
|
||||||
@@ -41,6 +42,8 @@ import org.alfresco.service.cmr.workflow.WorkflowTask;
|
|||||||
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
|
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
|
||||||
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery.OrderBy;
|
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery.OrderBy;
|
||||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||||
|
import org.alfresco.service.namespace.NamespaceException;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.ModelUtil;
|
import org.alfresco.util.ModelUtil;
|
||||||
import org.springframework.extensions.webscripts.Cache;
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
import org.springframework.extensions.webscripts.Status;
|
import org.springframework.extensions.webscripts.Status;
|
||||||
@@ -63,6 +66,7 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
|
|||||||
public static final String PARAM_DUE_AFTER = "dueAfter";
|
public static final String PARAM_DUE_AFTER = "dueAfter";
|
||||||
public static final String PARAM_PROPERTIES = "properties";
|
public static final String PARAM_PROPERTIES = "properties";
|
||||||
public static final String PARAM_POOLED_TASKS = "pooledTasks";
|
public static final String PARAM_POOLED_TASKS = "pooledTasks";
|
||||||
|
public static final String PARAM_PROPERTY = "property";
|
||||||
public static final String VAR_WORKFLOW_INSTANCE_ID = "workflow_instance_id";
|
public static final String VAR_WORKFLOW_INSTANCE_ID = "workflow_instance_id";
|
||||||
|
|
||||||
private WorkflowTaskDueAscComparator taskComparator = new WorkflowTaskDueAscComparator();
|
private WorkflowTaskDueAscComparator taskComparator = new WorkflowTaskDueAscComparator();
|
||||||
@@ -96,6 +100,7 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
|
|||||||
|
|
||||||
// get filter param values
|
// get filter param values
|
||||||
filters.put(PARAM_PRIORITY, req.getParameter(PARAM_PRIORITY));
|
filters.put(PARAM_PRIORITY, req.getParameter(PARAM_PRIORITY));
|
||||||
|
filters.put(PARAM_PROPERTY, req.getParameter(PARAM_PROPERTY));
|
||||||
processDateFilter(req, PARAM_DUE_BEFORE, filters);
|
processDateFilter(req, PARAM_DUE_BEFORE, filters);
|
||||||
processDateFilter(req, PARAM_DUE_AFTER, filters);
|
processDateFilter(req, PARAM_DUE_AFTER, filters);
|
||||||
|
|
||||||
@@ -104,7 +109,7 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
|
|||||||
{
|
{
|
||||||
filters.put(PARAM_EXCLUDE, new ExcludeFilter(excludeParam));
|
filters.put(PARAM_EXCLUDE, new ExcludeFilter(excludeParam));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<WorkflowTask> allTasks;
|
List<WorkflowTask> allTasks;
|
||||||
|
|
||||||
if (workflowInstanceId != null)
|
if (workflowInstanceId != null)
|
||||||
@@ -179,20 +184,18 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
|
|||||||
ArrayList<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
|
ArrayList<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
|
||||||
|
|
||||||
// Filter results
|
// Filter results
|
||||||
WorkflowTask task = null;
|
for (WorkflowTask task : allTasks)
|
||||||
for(int i=0; i<allTasks.size(); i++)
|
|
||||||
{
|
{
|
||||||
task = allTasks.get(i);
|
if (matches(task, filters))
|
||||||
if (matches(task, filters))
|
|
||||||
{
|
{
|
||||||
// Total-count needs to be based on matching tasks only, so we can't just use allTasks.size() for this
|
// Total-count needs to be based on matching tasks only, so we can't just use allTasks.size() for this
|
||||||
totalCount++;
|
totalCount++;
|
||||||
if(totalCount > skipCount && (maxItems < 0 || maxItems > results.size()))
|
if(totalCount > skipCount && (maxItems < 0 || maxItems > results.size()))
|
||||||
{
|
{
|
||||||
// Only build the actual detail if it's in the range of items we need. This will
|
// Only build the actual detail if it's in the range of items we need. This will
|
||||||
// drastically improve performance over paging after building the model
|
// drastically improve performance over paging after building the model
|
||||||
results.add(modelBuilder.buildSimple(task, properties));
|
results.add(modelBuilder.buildSimple(task, properties));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,12 +344,35 @@ public class TaskInstancesGet extends AbstractWorkflowWebscript
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(key.equals(PARAM_PROPERTY))
|
||||||
|
{
|
||||||
|
String[] propertyValuePair = filterValue.toString().split("/");
|
||||||
|
if (propertyValuePair.length != 2)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QName propertyQName;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
propertyQName = QName.createQName(propertyValuePair[0], namespaceService);
|
||||||
|
}
|
||||||
|
catch (NamespaceException ne)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Serializable value = task.getProperties().get(propertyQName);
|
||||||
|
if (value != null && !value.equals(propertyValuePair[1]))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comparator to sort workflow tasks by due date in ascending order.
|
* Comparator to sort workflow tasks by due date in ascending order.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,28 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Remote API
|
* Alfresco Remote API
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
*
|
*
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
package org.alfresco.repo.web.scripts.workflow;
|
package org.alfresco.repo.web.scripts.workflow;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -305,7 +305,90 @@ public abstract class AbstractWorkflowRestApiTest extends BaseWebScriptTest
|
|||||||
JSONArray resultArray = json.getJSONArray("data");
|
JSONArray resultArray = json.getJSONArray("data");
|
||||||
assertEquals(0, resultArray.length());
|
assertEquals(0, resultArray.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testTaskInstancesGetWithFiltering() throws Exception
|
||||||
|
{
|
||||||
|
// Check USER2 starts with no tasks.
|
||||||
|
personManager.setUser(USER2);
|
||||||
|
Response response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER2)), 200);
|
||||||
|
getJsonArray(response, 0);
|
||||||
|
|
||||||
|
// Start workflow as USER1 and assign the task to GROUP.
|
||||||
|
personManager.setUser(USER1);
|
||||||
|
WorkflowDefinition wfDefinition = workflowService.getDefinitionByName(getReviewPooledWorkflowDefinitionName());
|
||||||
|
Map<QName, Serializable> params = new HashMap<>(3);
|
||||||
|
params.put(WorkflowModel.ASSOC_GROUP_ASSIGNEE, groupManager.get(GROUP));
|
||||||
|
params.put(WorkflowModel.ASSOC_PACKAGE, packageRef);
|
||||||
|
params.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "descTest1");
|
||||||
|
|
||||||
|
WorkflowPath wfPath = workflowService.startWorkflow(wfDefinition.getId(), params);
|
||||||
|
String workflowId = wfPath.getInstance().getId();
|
||||||
|
workflows.add(workflowId);
|
||||||
|
|
||||||
|
WorkflowTask startTask = workflowService.getStartTask(workflowId);
|
||||||
|
workflowService.endTask(startTask.getId(), null);
|
||||||
|
|
||||||
|
// Start another workflow as USER1 and assign the task to GROUP.
|
||||||
|
wfDefinition = workflowService.getDefinitionByName(getReviewPooledWorkflowDefinitionName());
|
||||||
|
params.put(WorkflowModel.ASSOC_GROUP_ASSIGNEE, groupManager.get(GROUP));
|
||||||
|
params.put(WorkflowModel.ASSOC_PACKAGE, workflowService.createPackage(null));
|
||||||
|
params.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "descTest2");
|
||||||
|
|
||||||
|
wfPath = workflowService.startWorkflow(wfDefinition.getId(), params);
|
||||||
|
workflowId = wfPath.getInstance().getId();
|
||||||
|
workflows.add(workflowId);
|
||||||
|
|
||||||
|
startTask = workflowService.getStartTask(workflowId);
|
||||||
|
workflowService.endTask(startTask.getId(), null);
|
||||||
|
|
||||||
|
// Check USER2's tasks without filtering. It should return two tasks as USER2 is a member of the GROUP
|
||||||
|
personManager.setUser(USER2);
|
||||||
|
response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER2)), 200);
|
||||||
|
getJsonArray(response, 2);
|
||||||
|
|
||||||
|
//Check USER2's tasks With filtering where property bpm:description should match "descTest1"
|
||||||
|
response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER2) + "&property=bpm:description/descTest1"), 200);
|
||||||
|
JSONArray results = getJsonArray(response, 1);
|
||||||
|
JSONObject result = results.getJSONObject(0);
|
||||||
|
assertNotNull(result);
|
||||||
|
JSONObject properties = result.getJSONObject("properties");
|
||||||
|
assertNotNull(properties);
|
||||||
|
assertEquals("descTest1", properties.getString("bpm_description"));
|
||||||
|
|
||||||
|
//Check USER2's tasks With filtering where property bpm:description should match "descTest2"
|
||||||
|
response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER2) + "&property=bpm:description/descTest2"), 200);
|
||||||
|
results = getJsonArray(response, 1);
|
||||||
|
result = results.getJSONObject(0);
|
||||||
|
assertNotNull(result);
|
||||||
|
properties = result.getJSONObject("properties");
|
||||||
|
assertNotNull(properties);
|
||||||
|
assertEquals("descTest2", properties.getString("bpm_description"));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* -ve tests
|
||||||
|
*/
|
||||||
|
// Mismatched property value - There is no task with the description "somePropValue"
|
||||||
|
response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER2) + "&property=bpm:description/somePropValue"), 200);
|
||||||
|
getJsonArray(response, 0);
|
||||||
|
|
||||||
|
//Unregistered namespace prefix (ignores "property" parameter)
|
||||||
|
response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER2) + "&property=unknownPrefix:description/test"), 200);
|
||||||
|
getJsonArray(response, 2);
|
||||||
|
|
||||||
|
// Nonexistent property (ignores "property" parameter)
|
||||||
|
response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER2) + "&property=bpm:nonexistentProp/test"), 200);
|
||||||
|
getJsonArray(response, 2);
|
||||||
|
|
||||||
|
// Not well-formed parameter
|
||||||
|
response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER2) + "&property=bpm:description/"), 200);
|
||||||
|
getJsonArray(response, 2);
|
||||||
|
|
||||||
|
// Check USER3's tasks without filtering. It should return 0 task as USER3 is not a member of the GROUP
|
||||||
|
personManager.setUser(USER3);
|
||||||
|
response = sendRequest(new GetRequest(MessageFormat.format(URL_USER_TASKS, USER3)), 200);
|
||||||
|
getJsonArray(response, 0);
|
||||||
|
}
|
||||||
|
|
||||||
public void testWorkflowPermissions() throws Exception
|
public void testWorkflowPermissions() throws Exception
|
||||||
{
|
{
|
||||||
// Start workflow as USER1 and assign task to USER1.
|
// Start workflow as USER1 and assign task to USER1.
|
||||||
@@ -1785,7 +1868,17 @@ public abstract class AbstractWorkflowRestApiTest extends BaseWebScriptTest
|
|||||||
assertEquals(maxItems, paging.getInt("maxItems"));
|
assertEquals(maxItems, paging.getInt("maxItems"));
|
||||||
assertEquals(skipCount, paging.getInt("skipCount"));
|
assertEquals(skipCount, paging.getInt("skipCount"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JSONArray getJsonArray(Response response, int expectedLength) throws Exception
|
||||||
|
{
|
||||||
|
String jsonStr = response.getContentAsString();
|
||||||
|
JSONObject json = new JSONObject(jsonStr);
|
||||||
|
JSONArray results = json.getJSONArray("data");
|
||||||
|
assertNotNull(results);
|
||||||
|
assertEquals(expectedLength, results.length());
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract String getEngine();
|
protected abstract String getEngine();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user