Workflow Service - addition of task query

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5720 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2007-05-18 12:35:22 +00:00
parent 6a5a8cbe75
commit 801ec46791
6 changed files with 552 additions and 0 deletions

View File

@@ -30,6 +30,7 @@ import java.util.Map;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.QName;
@@ -67,6 +68,14 @@ public interface TaskComponent
*/
public List<WorkflowTask> getPooledTasks(List<String> authorities);
/**
* Query for tasks
*
* @param query the filter by which tasks are queried
* @return the list of tasks matching the specified query
*/
public List<WorkflowTask> queryTasks(WorkflowTaskQuery query);
/**
* Update the Properties and Associations of a Task
*

View File

@@ -42,6 +42,7 @@ import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
@@ -327,6 +328,46 @@ public class WorkflowServiceImpl implements WorkflowService
return Collections.unmodifiableList(tasks);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.workflow.WorkflowService#queryTasks(org.alfresco.service.cmr.workflow.WorkflowTaskFilter)
*/
public List<WorkflowTask> queryTasks(WorkflowTaskQuery query)
{
// extract task component to perform query
String engineId = null;
String processId = query.getProcessId();
if (processId != null)
{
engineId = BPMEngineRegistry.getEngineId(processId);
}
String taskId = query.getTaskId();
if (taskId != null)
{
String taskEngineId = BPMEngineRegistry.getEngineId(taskId);
if (engineId != null && !engineId.equals(taskEngineId))
{
throw new WorkflowException("Cannot query for tasks across multiple task components: " + engineId + ", " + taskEngineId);
}
engineId = taskEngineId;
}
// perform query
List<WorkflowTask> tasks = new ArrayList<WorkflowTask>(10);
String[] ids = registry.getTaskComponents();
for (String id: ids)
{
TaskComponent component = registry.getTaskComponent(id);
// NOTE: don't bother asking task component if specific task or process id
// are in the filter and do not correspond to the component
if (engineId != null && !engineId.equals(id))
{
continue;
}
tasks.addAll(component.queryTasks(query));
}
return Collections.unmodifiableList(tasks);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.workflow.WorkflowService#updateTask(java.lang.String, java.util.Map, java.util.Map, java.util.Map)
*/

View File

@@ -40,6 +40,9 @@ import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseSpringTest;
@@ -94,6 +97,29 @@ public class WorkflowServiceImplTest extends BaseSpringTest
assertTrue(nodeService.hasAspect(nodeRef, WorkflowModel.ASPECT_WORKFLOW_PACKAGE));
}
public void testQueryTasks()
{
WorkflowTaskQuery filter = new WorkflowTaskQuery();
filter.setTaskName(QName.createQName("{http://www.alfresco.org/model/wcmworkflow/1.0}submitpendingTask"));
filter.setTaskState(WorkflowTaskState.COMPLETED);
Map<QName, Object> taskProps = new HashMap<QName, Object>();
taskProps.put(QName.createQName("{http://www.alfresco.org/model/bpm/1.0}workflowDescription"), "Test5");
filter.setTaskCustomProps(taskProps);
filter.setProcessId("jbpm$48");
filter.setProcessName(QName.createQName("{http://www.alfresco.org/model/wcmworkflow/1.0}submit"));
Map<QName, Object> procProps = new HashMap<QName, Object>();
procProps.put(QName.createQName("{http://www.alfresco.org/model/bpm/1.0}workflowDescription"), "Test5");
procProps.put(QName.createQName("companyhome"), new NodeRef("workspace://SpacesStore/3df8a9d0-ff04-11db-98da-a3c3f3149ea5"));
filter.setProcessCustomProps(procProps);
filter.setOrderBy(new WorkflowTaskQuery.OrderBy[] { WorkflowTaskQuery.OrderBy.TaskName_Asc, WorkflowTaskQuery.OrderBy.TaskState_Asc });
List<WorkflowTask> tasks = workflowService.queryTasks(filter);
System.out.println("Found " + tasks.size() + " tasks.");
for (WorkflowTask task : tasks)
{
System.out.println(task.toString());
}
}
public void testAssociateWorkflowPackage()
{
// create workflow package

View File

@@ -68,18 +68,26 @@ import org.alfresco.service.cmr.workflow.WorkflowNode;
import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.cmr.workflow.WorkflowTransition;
import org.alfresco.service.namespace.NamespaceException;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.proxy.HibernateProxy;
import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
import org.jbpm.context.exe.ContextInstance;
import org.jbpm.context.exe.TokenVariableMap;
import org.jbpm.context.exe.VariableInstance;
import org.jbpm.db.GraphSession;
import org.jbpm.db.TaskMgmtSession;
import org.jbpm.file.def.FileDefinition;
@@ -869,6 +877,229 @@ public class JBPMEngine extends BPMEngine
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.workflow.TaskComponent#queryTasks(org.alfresco.service.cmr.workflow.WorkflowTaskFilter)
*/
@SuppressWarnings("unchecked")
public List<WorkflowTask> queryTasks(final WorkflowTaskQuery query)
{
try
{
return (List<WorkflowTask>) jbpmTemplate.execute(new JbpmCallback()
{
public List<WorkflowTask> doInJbpm(JbpmContext context)
{
Session session = context.getSession();
Criteria criteria = createTaskQueryCriteria(session, query);
List<TaskInstance> tasks = criteria.list();
// convert tasks to appropriate service response format
List<WorkflowTask> workflowTasks = new ArrayList<WorkflowTask>(tasks.size());
for (TaskInstance task : tasks)
{
WorkflowTask workflowTask = createWorkflowTask(task);
workflowTasks.add(workflowTask);
}
return workflowTasks;
}
});
}
catch(JbpmException e)
{
throw new WorkflowException("Failed to query tasks", e);
}
}
/**
* Construct a JBPM Hibernate query based on the Task Query provided
*
* @param session
* @param query
* @return jbpm hiberate query criteria
*/
private Criteria createTaskQueryCriteria(Session session, WorkflowTaskQuery query)
{
Criteria process = null;
Criteria task = session.createCriteria(TaskInstance.class);
// task id
if (query.getTaskId() != null)
{
task.add(Restrictions.eq("id", getJbpmId(query.getTaskId())));
}
// task state
if (query.getTaskState() != null)
{
WorkflowTaskState state = query.getTaskState();
if (state == WorkflowTaskState.IN_PROGRESS)
{
task.add(Restrictions.eq("isOpen", true));
task.add(Restrictions.isNull("end"));
}
else if (state == WorkflowTaskState.COMPLETED)
{
task.add(Restrictions.eq("isOpen", false));
task.add(Restrictions.isNotNull("end"));
}
}
// task name
if (query.getTaskName() != null)
{
task.add(Restrictions.eq("name", query.getTaskName().toPrefixString(namespaceService)));
}
// task actor
if (query.getActorId() != null)
{
task.add(Restrictions.eq("actorId", query.getActorId()));
}
// task custom properties
if (query.getTaskCustomProps() != null)
{
Map<QName, Object> props = query.getTaskCustomProps();
if (props.size() > 0)
{
Criteria variables = task.createCriteria("variableInstances");
Disjunction values = Restrictions.disjunction();
for (Map.Entry<QName, Object> prop : props.entrySet())
{
Conjunction value = Restrictions.conjunction();
value.add(Restrictions.eq("name", mapQNameToName(prop.getKey())));
value.add(Restrictions.eq("value", prop.getValue().toString()));
values.add(value);
}
variables.add(values);
}
}
// process active?
if (query.isActive() != null)
{
process = (process == null) ? task.createCriteria("processInstance") : process;
if (query.isActive())
{
process.add(Restrictions.isNull("end"));
}
else
{
process.add(Restrictions.isNotNull("end"));
}
}
// process id
if (query.getProcessId() != null)
{
process = (process == null) ? task.createCriteria("processInstance") : process;
process.add(Restrictions.eq("id", getJbpmId(query.getProcessId())));
}
// process name
if (query.getProcessName() != null)
{
process = (process == null) ? task.createCriteria("processInstance") : process;
Criteria processDef = process.createCriteria("processDefinition");
processDef.add(Restrictions.eq("name", query.getProcessName().toPrefixString(namespaceService)));
}
// process custom properties
if (query.getProcessCustomProps() != null)
{
// TODO: Due to Hibernate bug http://opensource.atlassian.com/projects/hibernate/browse/HHH-957
// it's not possible to perform a sub-select with the criteria api. For now issue a
// secondary query and create an IN clause.
Map<QName, Object> props = query.getProcessCustomProps();
if (props.size() > 0)
{
// create criteria for process variables
Criteria variables = session.createCriteria(VariableInstance.class);
variables.setProjection(Property.forName("processInstance"));
Disjunction values = Restrictions.disjunction();
for (Map.Entry<QName, Object> prop : props.entrySet())
{
Conjunction value = Restrictions.conjunction();
value.add(Restrictions.eq("name", mapQNameToName(prop.getKey())));
value.add(Restrictions.eq("value", prop.getValue().toString()));
values.add(value);
}
variables.add(values);
// retrieve list of processes matching specified variables
List<ProcessInstance> processList = variables.list();
Object[] processIds = null;
if (processList.size() == 0)
{
processIds = new Object[] { new Long(-1) };
}
else
{
processIds = new Object[processList.size()];
for (int i = 0; i < processList.size(); i++)
{
processIds[i] = processList.get(i).getId();
}
}
// constrain tasks by process list
process = (process == null) ? task.createCriteria("processInstance") : process;
process.add(Restrictions.in("id", processIds));
}
}
// order by
if (query.getOrderBy() != null)
{
WorkflowTaskQuery.OrderBy[] orderBy = query.getOrderBy();
for (WorkflowTaskQuery.OrderBy orderByPart : orderBy)
{
if (orderByPart == WorkflowTaskQuery.OrderBy.TaskActor_Asc)
{
task.addOrder(Order.asc("actorId"));
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskActor_Desc)
{
task.addOrder(Order.desc("actorId"));
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskCreated_Asc)
{
task.addOrder(Order.asc("create"));
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskCreated_Desc)
{
task.addOrder(Order.desc("create"));
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskId_Asc)
{
task.addOrder(Order.asc("id"));
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskId_Desc)
{
task.addOrder(Order.desc("id"));
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskName_Asc)
{
task.addOrder(Order.asc("name"));
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskName_Desc)
{
task.addOrder(Order.desc("name"));
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskState_Asc)
{
task.addOrder(Order.asc("end"));
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskState_Desc)
{
task.addOrder(Order.desc("end"));
}
}
}
return task;
}
/**
* Gets a jBPM Task Instance
* @param taskSession jBPM task session