diff --git a/config/alfresco/activiti-context.xml b/config/alfresco/activiti-context.xml
index 9d8566e264..337a606f4e 100644
--- a/config/alfresco/activiti-context.xml
+++ b/config/alfresco/activiti-context.xml
@@ -143,6 +143,11 @@
+
+
+
jbpm
alfresco/workflow/adhoc_processdefinition.xml
text/xml
- false
+ true
diff --git a/source/java/org/alfresco/repo/workflow/AbstractWorkflowServiceIntegrationTest.java b/source/java/org/alfresco/repo/workflow/AbstractWorkflowServiceIntegrationTest.java
index 309577873f..a8c3b0b40f 100644
--- a/source/java/org/alfresco/repo/workflow/AbstractWorkflowServiceIntegrationTest.java
+++ b/source/java/org/alfresco/repo/workflow/AbstractWorkflowServiceIntegrationTest.java
@@ -575,16 +575,16 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
// Adhoc task should only be returned
QName taskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "adhocTask");
- checkTaskNameQuery(taskName, Arrays.asList(theTask.getId()), WorkflowTaskState.COMPLETED);
+ checkTaskNameQuery(taskName, Arrays.asList(theTask.getId()), WorkflowTaskState.COMPLETED, null);
// Completed adhocTask is assigned to USER2
- checkActorIdQuery(USER2, Arrays.asList(theTask.getId()), WorkflowTaskState.COMPLETED);
+ checkActorIdQuery(USER2, Arrays.asList(theTask.getId()), WorkflowTaskState.COMPLETED, null);
// Workflow is still active, both tasks will be returned
- checkIsActiveQuery(expectedTasks, WorkflowTaskState.COMPLETED);
+ checkIsActiveQuery(expectedTasks, WorkflowTaskState.COMPLETED, null);
// Both tasks have custom property set
- checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED);
+ checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED, null);
}
protected void testTaskQueryInProgress(String workflowInstanceId, WorkflowTask expectedTask)
@@ -595,10 +595,11 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
checkTaskIdQuery(expectedTask.getId(), WorkflowTaskState.IN_PROGRESS);
QName taskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "adhocTask");
- checkTaskNameQuery(taskName, expectedTasks, WorkflowTaskState.IN_PROGRESS);
- checkActorIdQuery(USER2, expectedTasks, WorkflowTaskState.IN_PROGRESS);
- checkIsActiveQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS);
- checkTaskPropsQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS);
+ checkTaskNameQuery(taskName, expectedTasks, WorkflowTaskState.IN_PROGRESS, null);
+ checkActorIdQuery(USER2, expectedTasks, WorkflowTaskState.IN_PROGRESS, null);
+ checkIsActiveQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS, null);
+ checkTaskPropsQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS, null);
+ checkProcessPropsQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS);
}
protected void testTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask) {
@@ -608,10 +609,10 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
checkTaskIdQuery(startTask.getId(), WorkflowTaskState.COMPLETED);
QName startTaskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "submitAdhocTask");
- checkTaskNameQuery(startTaskName, expectedTasks, WorkflowTaskState.COMPLETED);
- checkActorIdQuery(USER1, expectedTasks, WorkflowTaskState.COMPLETED);
- checkIsActiveQuery(expectedTasks, WorkflowTaskState.COMPLETED);
- checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED);
+ checkTaskNameQuery(startTaskName, expectedTasks, WorkflowTaskState.COMPLETED, null);
+ checkActorIdQuery(USER1, expectedTasks, WorkflowTaskState.COMPLETED, null);
+ checkIsActiveQuery(expectedTasks, WorkflowTaskState.COMPLETED, null);
+ checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED, null);
}
public void testGetWorkflows() throws Exception
@@ -767,14 +768,23 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
}
}
- protected void checkTaskNameQuery(QName taskName, List expectedTaskIds, WorkflowTaskState state) {
+ protected void checkTaskNameQuery(QName taskName, List expectedTaskIds, WorkflowTaskState state,
+ String optionalProcessId) {
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state);
taskQuery.setTaskName(taskName);
+ if(optionalProcessId != null)
+ {
+ taskQuery.setProcessId(optionalProcessId);
+ }
checkTasksFoundUsingQuery(expectedTaskIds, taskQuery);
QName unexistingTaskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "unexistingTask");
taskQuery = createWorkflowTaskQuery(state);
taskQuery.setTaskName(unexistingTaskName);
+ if(optionalProcessId != null)
+ {
+ taskQuery.setProcessId(optionalProcessId);
+ }
checkNoTasksFoundUsingQuery(taskQuery);
}
@@ -800,29 +810,48 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
checkNoTasksFoundUsingQuery(taskQuery);
}
- protected void checkIsActiveQuery(List expectedTaskIds, WorkflowTaskState state)
+ protected void checkIsActiveQuery(List expectedTaskIds, WorkflowTaskState state,
+ String optionalProcessId)
{
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state);
taskQuery.setActive(true);
+ if(optionalProcessId != null)
+ {
+ taskQuery.setProcessId(optionalProcessId);
+ }
checkTasksFoundUsingQuery(expectedTaskIds, taskQuery);
taskQuery = createWorkflowTaskQuery(state);
taskQuery.setActive(false);
+ if(optionalProcessId != null)
+ {
+ taskQuery.setProcessId(optionalProcessId);
+ }
checkNoTasksFoundUsingQuery(taskQuery);
}
- protected void checkActorIdQuery(String actorId, List expectedTaskIds, WorkflowTaskState state)
+ protected void checkActorIdQuery(String actorId, List expectedTaskIds, WorkflowTaskState state,
+ String optionalProcessId)
{
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state);
taskQuery.setActorId(actorId);
+ if(optionalProcessId != null)
+ {
+ taskQuery.setProcessId(optionalProcessId);
+ }
checkTasksFoundUsingQuery(expectedTaskIds, taskQuery);
taskQuery = createWorkflowTaskQuery(state);
taskQuery.setActorId(USER3);
+ if(optionalProcessId != null)
+ {
+ taskQuery.setProcessId(optionalProcessId);
+ }
checkNoTasksFoundUsingQuery(taskQuery);
}
- protected void checkTaskPropsQuery(List expectedTaskIds, WorkflowTaskState state)
+ protected void checkTaskPropsQuery(List expectedTaskIds, WorkflowTaskState state,
+ String optionalProcessId)
{
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state);
QName customStringProp = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "customStringProp");
@@ -831,6 +860,10 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
taskProps.put(customStringProp, "stringValue");
taskQuery.setTaskCustomProps(taskProps);
+ if(optionalProcessId != null)
+ {
+ taskQuery.setProcessId(optionalProcessId);
+ }
checkTasksFoundUsingQuery(expectedTaskIds, taskQuery);
taskProps = new HashMap();
@@ -838,6 +871,10 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
taskQuery = createWorkflowTaskQuery(state);
taskQuery.setTaskCustomProps(taskProps);
+ if(optionalProcessId != null)
+ {
+ taskQuery.setProcessId(optionalProcessId);
+ }
checkNoTasksFoundUsingQuery(taskQuery);
}
diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiTaskComponentTest.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiTaskComponentTest.java
index 0cc16c63cd..e9a674a3ea 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiTaskComponentTest.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiTaskComponentTest.java
@@ -240,8 +240,7 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
WorkflowTask finishedTask = workflowEngine.getTaskById(finishedTaskId);
assertNotNull(finishedTask);
- // TODO: revive once http://jira.codehaus.org/browse/ACT-485 is fixed
- // Assert.assertEquals("Task description", finishedTask.getDescription());
+ Assert.assertEquals("Task description", finishedTask.getDescription());
Assert.assertEquals(finishedTaskId, finishedTask.getId());
Assert.assertEquals("bpm_foo_task", finishedTask.getName());
@@ -446,8 +445,31 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
Assert.assertNotNull(tasks);
Assert.assertEquals(0, tasks.size());
- // TODO: test using process-name, not yet implemented now
- // TODO: test using task-name
+ // Test query by process-name
+ taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
+ taskQuery.setProcessName(QName.createQName("testTask"));
+ tasks = workflowEngine.queryTasks(taskQuery);
+
+ Assert.assertNotNull(tasks);
+ Assert.assertEquals(1, tasks.size());
+
+ taskQuery.setProcessName(QName.createQName("unexistingTaskName"));
+ tasks = workflowEngine.queryTasks(taskQuery);
+ Assert.assertNotNull(tasks);
+ Assert.assertEquals(0, tasks.size());
+
+ // Test query by task-name
+ taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
+ taskQuery.setTaskName(QName.createQName("bpm_foo_task"));
+ tasks = workflowEngine.queryTasks(taskQuery);
+
+ Assert.assertNotNull(tasks);
+ Assert.assertEquals(1, tasks.size());
+
+ taskQuery.setTaskName(QName.createQName("unexisting_task_name"));
+ tasks = workflowEngine.queryTasks(taskQuery);
+ Assert.assertNotNull(tasks);
+ Assert.assertEquals(0, tasks.size());
// Test querying task variables, using all possible (and allowed) types of variables
Map variables = new HashMap();
@@ -499,29 +521,51 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
ActivitiScriptNode otherNode = new ActivitiScriptNode(testUserNode, serviceRegistry);
checkTaskVariableNoMatch(WorkflowTaskState.IN_PROGRESS, QName.createQName("scriptNodeVar"), otherNode);
- // TODO: test using process variables
+
+ // Query task based on process variable
+ runtime.setVariable(task.getExecutionId(), "processVar", "testing");
+ taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
+ Map props = new HashMap();
+ props.put(QName.createQName("processVar"), "testing");
+ taskQuery.setProcessCustomProps(props);
+
+ tasks = workflowEngine.queryTasks(taskQuery);
+ assertNotNull(tasks);
+ assertEquals(1, tasks.size());
+
+ props.put(QName.createQName("processVar"), "notmatching");
+
+ tasks = workflowEngine.queryTasks(taskQuery);
+ assertNotNull(tasks);
+ assertEquals(0, tasks.size());
}
@Test
public void testQueryTasksCompleted() throws Exception {
- // Testing all query functionality for WorkflowTaskState.IN_PROGRESS
+ // Testing all query functionality for WorkflowTaskState.COMPLETED
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), new HashMap());
Task task = taskService.createTaskQuery()
.executionId(BPMEngineRegistry.getLocalId(path.getId()))
.singleResult();
+
+ taskService.setVariableLocal(task.getId(), "taskVar", "theValue");
assertNotNull("Task should exist!", task);
String globalTaskId = createGlobalId(task.getId());
// Set the actor
taskService.setAssignee(task.getId(), TEST_USER);
+ // Set process prop
+ runtime.setVariable(task.getExecutionId(), "processVar", "testing");
+
// End the task
workflowEngine.endTask(globalTaskId, null);
// Test query by taskId
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
+ taskQuery.setActive(Boolean.FALSE); // Set to false, since workflow this task is in, has finished
taskQuery.setTaskId(globalTaskId);
List tasks = workflowEngine.queryTasks(taskQuery);
@@ -540,6 +584,7 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
// Test query by process ID, this should also return the start-task
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
taskQuery.setProcessId(createGlobalId(task.getProcessInstanceId()));
+ taskQuery.setActive(Boolean.FALSE);
tasks = workflowEngine.queryTasks(taskQuery);
Assert.assertNotNull(tasks);
@@ -572,6 +617,7 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
// Test query by actor
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
taskQuery.setActorId(TEST_USER);
+ taskQuery.setActive(Boolean.FALSE);
tasks = workflowEngine.queryTasks(taskQuery);
Assert.assertNotNull(tasks);
@@ -585,11 +631,53 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
Assert.assertNotNull(tasks);
Assert.assertEquals(0, tasks.size());
- // TODO: test using process-name, not yet implemented now
- // TODO: test using task-name
+ // Test query by process-name
+ taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
+ taskQuery.setProcessName(QName.createQName("testTask"));
+ taskQuery.setActive(Boolean.FALSE);
+ tasks = workflowEngine.queryTasks(taskQuery);
- // TODO: test using task variables
- // TODO: test using process variables
+ Assert.assertNotNull(tasks);
+ Assert.assertEquals(1, tasks.size());
+
+ taskQuery.setProcessName(QName.createQName("unexistingTaskName"));
+ tasks = workflowEngine.queryTasks(taskQuery);
+ Assert.assertNotNull(tasks);
+ Assert.assertEquals(0, tasks.size());
+
+ // Query task based on task variable
+ taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
+ Map props = new HashMap();
+ props.put(QName.createQName("taskVar"), "theValue");
+ taskQuery.setActive(false);
+ taskQuery.setTaskCustomProps(props);
+
+ tasks = workflowEngine.queryTasks(taskQuery);
+ assertNotNull(tasks);
+ assertEquals(1, tasks.size());
+
+ props.put(QName.createQName("processVar"), "notmatching");
+
+ tasks = workflowEngine.queryTasks(taskQuery);
+ assertNotNull(tasks);
+ assertEquals(0, tasks.size());
+
+ // Query task based on process variable
+ taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
+ props = new HashMap();
+ props.put(QName.createQName("processVar"), "testing");
+ taskQuery.setActive(false);
+ taskQuery.setProcessCustomProps(props);
+
+ tasks = workflowEngine.queryTasks(taskQuery);
+ assertNotNull(tasks);
+ assertEquals(1, tasks.size());
+
+ props.put(QName.createQName("processVar"), "notmatching");
+
+ tasks = workflowEngine.queryTasks(taskQuery);
+ assertNotNull(tasks);
+ assertEquals(0, tasks.size());
}
diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiTaskTypeManager.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiTaskTypeManager.java
index 03b4d89725..6792a45519 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiTaskTypeManager.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiTaskTypeManager.java
@@ -24,7 +24,7 @@ import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.form.FormData;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.impl.form.TaskFormHandler;
-import org.activiti.engine.impl.task.TaskEntity;
+import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.task.Task;
import org.alfresco.repo.workflow.WorkflowObjectFactory;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiTimerExecutionTest.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiTimerExecutionTest.java
index 6cb3bd1576..5b87d6fcb6 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiTimerExecutionTest.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiTimerExecutionTest.java
@@ -26,7 +26,7 @@ import java.util.List;
import java.util.Map;
import org.activiti.engine.ProcessEngine;
-import org.activiti.engine.impl.runtime.TimerEntity;
+import org.activiti.engine.impl.persistence.entity.TimerEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Job;
import org.alfresco.model.ContentModel;
diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiUtil.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiUtil.java
index 772acc1efe..993027c96a 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiUtil.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiUtil.java
@@ -32,8 +32,8 @@ import org.activiti.engine.form.StartFormData;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
+import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.ReadOnlyProcessDefinition;
-import org.activiti.engine.impl.repository.ProcessDefinitionEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java
index bbe87eb207..056fce192f 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java
@@ -51,11 +51,11 @@ import org.activiti.engine.impl.bpmn.deployer.BpmnDeployer;
import org.activiti.engine.impl.form.DefaultTaskFormHandler;
import org.activiti.engine.impl.form.TaskFormHandler;
import org.activiti.engine.impl.identity.Authentication;
+import org.activiti.engine.impl.persistence.entity.TimerEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.ReadOnlyProcessDefinition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
-import org.activiti.engine.impl.runtime.TimerEntity;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
@@ -1369,7 +1369,6 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
@Override
public List queryTasks(WorkflowTaskQuery query)
{
- // TODO: complete, only small part is implemented
ArrayList result = new ArrayList();
WorkflowTaskState taskState = query.getTaskState();
if(WorkflowTaskState.COMPLETED.equals(taskState) == false)
@@ -1407,9 +1406,8 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
if(query.getProcessName() != null)
{
- // String processName = getProcessNameMTSafe(query.getProcessName());
- // TODO: Method added in http://jira.codehaus.org/browse/ACT-459
- // taskQuery.processDefinitionName(processName);
+ String processName = getProcessNameMTSafe(query.getProcessName());
+ taskQuery.processDefinitionKey(processName);
}
@@ -1447,7 +1445,11 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
private void addProcessPropertiesToQuery(
Map processCustomProps, TaskQuery taskQuery) {
- // TODO: implement
+ for(Entry customProperty : processCustomProps.entrySet())
+ {
+ String name =factory.mapQNameToName(customProperty.getKey());
+ taskQuery.processVariableValueEquals(name, customProperty.getValue());
+ }
}
protected String getProcessNameMTSafe(QName processNameQName)
@@ -1517,13 +1519,11 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
{
if (orderByPart == WorkflowTaskQuery.OrderBy.TaskActor_Asc)
{
- // TODO: add in activiti
- // taskQuery.orderByTaskAssignee().asc();
+ taskQuery.orderByTaskAssignee().asc();
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskActor_Desc)
{
- // TODO: add in activiti
- // taskQuery.orderByTaskAssignee().desc();
+ taskQuery.orderByTaskAssignee().desc();
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskCreated_Asc)
{
@@ -1543,13 +1543,11 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskId_Asc)
{
- // TODO: add in activiti
- // taskQuery.orderByTaskId().asc();
+ taskQuery.orderByTaskId().asc();
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskId_Desc)
{
- // TODO: add in activiti
- // taskQuery.orderByTaskId().desc();
+ taskQuery.orderByTaskId().desc();
}
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskName_Asc)
{
@@ -1581,7 +1579,6 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
private List queryHistoricTasks(WorkflowTaskQuery query)
{
- // TODO: Implement complete query
HistoricTaskInstanceQuery historicQuery = historyService
.createHistoricTaskInstanceQuery()
.finished();
@@ -1609,12 +1606,30 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
if(query.getProcessName() != null)
{
- // String processName = getProcessNameMTSafe(query.getProcessName());
- // TODO: add to query
+ String processName = getProcessNameMTSafe(query.getProcessName());
+ historicQuery.processDefinitionKey(processName);
}
- // TODO: task properties from history query
- // TODO: process properties
+ if(query.getTaskCustomProps() != null)
+ {
+ addTaskPropertiesToQuery(query.getTaskCustomProps(), historicQuery);
+ }
+
+ if(query.getProcessCustomProps() != null)
+ {
+ addProcessPropertiesToQuery(query.getProcessCustomProps(), historicQuery);
+ }
+
+ if(query.isActive() != null)
+ {
+ if(query.isActive()) {
+ historicQuery.processUnfinished();
+ }
+ else
+ {
+ historicQuery.processFinished();
+ }
+ }
// Order query
if(query.getOrderBy() != null)
@@ -1638,10 +1653,26 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
}
+ private void addTaskPropertiesToQuery(Map taskCustomProps,
+ HistoricTaskInstanceQuery taskQuery) {
+ for(Entry customProperty : taskCustomProps.entrySet())
+ {
+ String name =factory.mapQNameToName(customProperty.getKey());
+ taskQuery.taskVariableValueEquals(name, customProperty.getValue());
+ }
+ }
+
+ private void addProcessPropertiesToQuery(Map processCustomProps,
+ HistoricTaskInstanceQuery taskQuery) {
+ for(Entry customProperty : processCustomProps.entrySet())
+ {
+ String name =factory.mapQNameToName(customProperty.getKey());
+ taskQuery.processVariableValueEquals(name, customProperty.getValue());
+ }
+ }
+
private List queryStartTasks(WorkflowTaskQuery query)
{
-
- // TODO: implement further
List startTasks = new ArrayList();
String processInstanceId = null;
@@ -1683,6 +1714,18 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
private boolean isStartTaskMatching(WorkflowTask workflowTask,
WorkflowTaskQuery query) {
+ if(query.isActive() != null)
+ {
+ if(query.isActive() && !workflowTask.getPath().isActive())
+ {
+ return false;
+ }
+ if(!query.isActive() && workflowTask.getPath().isActive())
+ {
+ return false;
+ }
+ }
+
if(query.getActorId() != null && !query.getActorId().equals(workflowTask.getProperties().get(ContentModel.PROP_OWNER)))
{
return false;
@@ -1755,7 +1798,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
{
for(Map.Entry entry : expectedProperties.entrySet())
{
- if(props.containsKey(entry.getValue()))
+ if(props.containsKey(entry.getKey()))
{
Object requiredValue = entry.getValue();
Object actualValue = props.get(entry.getKey());
@@ -1766,6 +1809,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
{
return false;
}
+ break;
}
else
{
@@ -1773,6 +1817,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
{
return false;
}
+ break;
}
}
if(entry.getValue() != null)
diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java
index 45de1b7cec..e06dd2fb9c 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java
@@ -20,6 +20,7 @@
package org.alfresco.repo.workflow.activiti;
import java.io.Serializable;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -30,6 +31,8 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowPath;
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;
@@ -78,11 +81,63 @@ public class ActivitiWorkflowServiceIntegrationTest extends AbstractWorkflowServ
Serializable outcome = result.getProperties().get(WorkflowModel.PROP_OUTCOME);
assertEquals("Approve", outcome);
}
+
+ protected void testTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask)
+ {
+ // In activiti, start-tasks only show up when the workflowInstanceId or taskId is passed
+ List expectedTasks = Arrays.asList(startTask.getId());
+
+ checkProcessIdQuery(workflowInstanceId, expectedTasks, WorkflowTaskState.COMPLETED);
+ checkTaskIdQuery(startTask.getId(), WorkflowTaskState.COMPLETED);
+
+ // Check additional filtering, when workflowInstanceId is passed
+ QName startTaskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "submitAdhocTask");
+ checkTaskNameQuery(startTaskName, expectedTasks, WorkflowTaskState.COMPLETED, workflowInstanceId);
+ checkActorIdQuery(USER1, expectedTasks, WorkflowTaskState.COMPLETED, workflowInstanceId);
+ checkIsActiveQuery(expectedTasks, WorkflowTaskState.COMPLETED, workflowInstanceId);
+ checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED, workflowInstanceId);
+ }
- @Override
- public void testQueryTasks() {
- // TODO: Revive test once all pieces of queryTasks() are finished on ActivitiWorkflowEngine
- }
+ protected void testTaskQueryTaskCompleted(String workflowInstanceId,
+ WorkflowTask theTask, WorkflowTask startTask)
+ {
+ List bothTasks = Arrays.asList(theTask.getId(), startTask.getId());
+ List withoutStartTask = Arrays.asList(theTask.getId());
+
+ checkProcessIdQuery(workflowInstanceId, bothTasks, WorkflowTaskState.COMPLETED);
+
+ // Adhoc task should only be returned
+ QName taskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "adhocTask");
+ checkTaskNameQuery(taskName, withoutStartTask, WorkflowTaskState.COMPLETED, null);
+
+ // Completed adhocTask is assigned to USER2
+ checkActorIdQuery(USER2, withoutStartTask, WorkflowTaskState.COMPLETED, null);
+
+ // Workflow is still active, but in activiti, active start-task is not returned when
+ // no process-instance ID is provided
+ checkIsActiveQuery(withoutStartTask, WorkflowTaskState.COMPLETED, null);
+
+ // Task has custom property set
+ checkTaskPropsQuery(withoutStartTask, WorkflowTaskState.COMPLETED, null);
+
+ // Process properties
+ checkProcessPropsQuery(withoutStartTask, WorkflowTaskState.COMPLETED);
+ }
+
+ protected void testQueryTasksInactiveWorkflow(String workflowInstanceId) {
+ WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
+ taskQuery.setActive(false);
+
+ List tasks = workflowService.queryTasks(taskQuery);
+ assertNotNull(tasks);
+
+ // Activiti doesn't return start-task when no process/task id is set in query, so only 2 tasks will be returned
+ assertEquals(2, tasks.size());
+
+ taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
+ taskQuery.setActive(true);
+ checkNoTasksFoundUsingQuery(taskQuery);
+ }
@Override
protected String getEngine()
diff --git a/source/java/org/alfresco/repo/workflow/activiti/AddTaskListenerParseListener.java b/source/java/org/alfresco/repo/workflow/activiti/AddTaskListenerParseListener.java
index acc8b1ae7b..e835f7bf41 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/AddTaskListenerParseListener.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/AddTaskListenerParseListener.java
@@ -18,14 +18,14 @@
*/
package org.alfresco.repo.workflow.activiti;
+import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.parser.BpmnParseListener;
+import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
-import org.activiti.engine.impl.pvm.delegate.TaskListener;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ScopeImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
-import org.activiti.engine.impl.repository.ProcessDefinitionEntity;
import org.activiti.engine.impl.util.xml.Element;
import org.activiti.engine.impl.variable.VariableDeclaration;
diff --git a/source/java/org/alfresco/repo/workflow/activiti/AuthenticatedTimerJobHandler.java b/source/java/org/alfresco/repo/workflow/activiti/AuthenticatedTimerJobHandler.java
index 8b022f98fa..f40767200e 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/AuthenticatedTimerJobHandler.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/AuthenticatedTimerJobHandler.java
@@ -22,8 +22,8 @@ package org.alfresco.repo.workflow.activiti;
import org.activiti.engine.impl.TaskQueryImpl;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.jobexecutor.JobHandler;
+import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
-import org.activiti.engine.impl.runtime.ExecutionEntity;
import org.activiti.engine.task.Task;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
diff --git a/source/java/org/alfresco/repo/workflow/activiti/listener/ScriptExecutionListener.java b/source/java/org/alfresco/repo/workflow/activiti/listener/ScriptExecutionListener.java
index 68c67696b5..fa491e56b8 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/listener/ScriptExecutionListener.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/listener/ScriptExecutionListener.java
@@ -19,115 +19,55 @@
package org.alfresco.repo.workflow.activiti.listener;
-import java.util.HashMap;
import java.util.Map;
-import java.util.Map.Entry;
import org.activiti.engine.delegate.DelegateExecution;
-import org.activiti.engine.impl.pvm.delegate.ExecutionListener;
+import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.impl.pvm.delegate.ExecutionListenerExecution;
-import org.alfresco.model.ContentModel;
-import org.alfresco.repo.security.authentication.AuthenticationUtil;
-import org.alfresco.repo.workflow.WorkflowQNameConverter;
import org.alfresco.repo.workflow.activiti.ActivitiConstants;
-import org.alfresco.repo.workflow.activiti.ActivitiScriptNode;
-import org.alfresco.repo.workflow.activiti.script.ActivitiScriptBase;
-import org.alfresco.service.ServiceRegistry;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.repo.workflow.activiti.script.DelegateExecutionScriptBase;
+import org.alfresco.service.cmr.repository.ScriptService;
/**
+ * An {@link ExecutionListener} that runs a script against the {@link ScriptService}.
+ *
+ * The script that is executed can be set using field 'script'. A non-default
+ * script-processor can be set in the field 'scriptProcessor'. Optionally, you can run
+ * the script as a different user than the default by setting the field 'runAs'.
+ * By default, the user this script as the current logged-in user. If no user is
+ * currently logged in (eg. flow triggered by timer) the system user will be used instead.
*
* @author Nick Smith
* @author Frederik Heremans
* @since 3.4.e
*/
-public class ScriptExecutionListener extends ActivitiScriptBase implements ExecutionListener
+public class ScriptExecutionListener extends DelegateExecutionScriptBase implements ExecutionListener
{
+
private static final String DELETED_FLAG = "deleted";
private static final String CANCELLED_FLAG = "cancelled";
-
+
@Override
- public void notify(ExecutionListenerExecution execution) throws Exception {
- if(script != null)
- {
- String scriptString = getStringValue(script, execution);
- String scriptProcessorName = getStringValue(scriptProcessor, execution);
- String runAsUser = getStringValue(runAs, execution);
-
- // Make sure there is an authenticated user for the current thread, so when
- // the script is executed using no 'runAs' from a job-executor thread, the workflow
- // owner us used
- boolean clearAuthenticationContext = checkFullyAuthenticatedUser(execution);
-
- // Get all activiti-defined objects
- Map scriptModel = getInputMap(execution, runAsUser);
-
- // Add core alfresco objects to the input-map
- getServiceRegistry().getScriptService().buildCoreModel(scriptModel);
-
- try
- {
- Object scriptOutput = executeScript(scriptString, scriptModel, scriptProcessorName, runAsUser);
-
- // TODO: What to do with the script-output?
- if(scriptOutput != null)
- {
- // delegateTask.setVariableLocal("scriptOutput", scriptOutput);
- }
- }
- finally
- {
- if(clearAuthenticationContext)
- {
- // If the current user has been set to the Task's assignee, we should clear it agian
- AuthenticationUtil.clearCurrentSecurityContext();
- }
- }
- }
- else
- {
- throw new IllegalArgumentException("The field 'script' should be set on the TaskListener");
- }
+ public void notify(DelegateExecution execution) throws Exception {
+ runScript(execution);
}
- protected Map getInputMap(ExecutionListenerExecution execution, String runAsUser)
- {
- HashMap scriptModel = new HashMap(1);
-
- // Add current logged-in user and it's user home
- ActivitiScriptNode personNode = getPersonNode(runAsUser);
- if(personNode != null)
- {
- ServiceRegistry registry = getServiceRegistry();
- scriptModel.put(PERSON_BINDING_NAME, personNode);
- NodeRef userHomeNode = (NodeRef) registry.getNodeService().getProperty(personNode.getNodeRef(), ContentModel.PROP_HOMEFOLDER);
- if (userHomeNode != null)
- {
- scriptModel.put(USERHOME_BINDING_NAME, new ActivitiScriptNode(userHomeNode, registry));
- }
- }
-
- // Add activiti-specific objects
- scriptModel.put(EXECUTION_BINDING_NAME, execution);
-
- // Add all workflow variables to model
- Map variables = execution.getVariables();
-
- for(Entry varEntry : variables.entrySet())
- {
- scriptModel.put(varEntry.getKey(), varEntry.getValue());
- }
-
- // Add deleted/cancelled flags
+ @Override
+ protected Map getInputMap(DelegateExecution execution,
+ String runAsUser) {
+ Map scriptModel = super.getInputMap(execution, runAsUser);
+
+ ExecutionListenerExecution listenerExecution = (ExecutionListenerExecution) execution;
+
+ // Add deleted/cancelled flags
boolean cancelled = false;
boolean deleted = false;
- if(ActivitiConstants.DELETE_REASON_DELETED.equals(execution.getDeleteReason()))
+ if(ActivitiConstants.DELETE_REASON_DELETED.equals(listenerExecution.getDeleteReason()))
{
deleted = true;
}
- else if(ActivitiConstants.DELETE_REASON_CANCELLED.equals(execution.getDeleteReason()))
+ else if(ActivitiConstants.DELETE_REASON_CANCELLED.equals(listenerExecution.getDeleteReason()))
{
cancelled = true;
}
@@ -136,28 +76,4 @@ public class ScriptExecutionListener extends ActivitiScriptBase implements Execu
return scriptModel;
}
-
- /**
- * Checks a valid Fully Authenticated User is set.
- * If none is set then attempts to set the workflow owner
- * @param execution the execution
- * @return true
if the Fully Authenticated User was changed, otherwise false
.
- */
- private boolean checkFullyAuthenticatedUser(final DelegateExecution execution) {
- if(AuthenticationUtil.getFullyAuthenticatedUser() == null)
- {
- NamespaceService namespaceService = getServiceRegistry().getNamespaceService();
- WorkflowQNameConverter qNameConverter = new WorkflowQNameConverter(namespaceService);
- String ownerVariableName = qNameConverter.mapQNameToName(ContentModel.PROP_OWNER);
-
- String userName = (String) execution.getVariable(ownerVariableName);
- if (userName != null)
- {
- AuthenticationUtil.setFullyAuthenticatedUser(userName);
- return true;
- }
- }
- return false;
- }
-
}
diff --git a/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiDueDatePropertyHandler.java b/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiDueDatePropertyHandler.java
new file mode 100644
index 0000000000..735dfd15ac
--- /dev/null
+++ b/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiDueDatePropertyHandler.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+package org.alfresco.repo.workflow.activiti.properties;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.activiti.engine.delegate.DelegateTask;
+import org.activiti.engine.task.Task;
+import org.alfresco.repo.workflow.WorkflowModel;
+import org.alfresco.repo.workflow.activiti.ActivitiTaskPropertyHandler;
+import org.alfresco.service.cmr.dictionary.TypeDefinition;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * @since 3.5
+ * @author Frederik Heremans
+ *
+ */
+public class ActivitiDueDatePropertyHandler extends ActivitiTaskPropertyHandler
+{
+
+ /**
+ * {@inheritDoc}
+ */
+
+ @Override
+ protected Object handleTaskProperty(Task task, TypeDefinition type, QName key, Serializable value)
+ {
+ checkType(key, value, Date.class);
+ task.setDueDate((Date) value);
+ return DO_NOT_ADD;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Object handleDelegateTaskProperty(DelegateTask task, TypeDefinition type, QName key, Serializable value)
+ {
+ checkType(key, value, Date.class);
+ task.setDueDate((Date) value);
+ return DO_NOT_ADD;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+
+ @Override
+ protected QName getKey()
+ {
+ return WorkflowModel.PROP_DUE_DATE;
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPooledActorsPropertyHandler.java b/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPooledActorsPropertyHandler.java
index cfe000bc7d..7f9a51c17c 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPooledActorsPropertyHandler.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPooledActorsPropertyHandler.java
@@ -28,8 +28,8 @@ import java.util.List;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.DelegateTask;
-import org.activiti.engine.impl.task.IdentityLinkEntity;
-import org.activiti.engine.impl.task.TaskEntity;
+import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity;
+import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType;
import org.activiti.engine.task.Task;
diff --git a/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPropertyConverter.java b/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPropertyConverter.java
index e43c428f41..4c60e684f8 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPropertyConverter.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPropertyConverter.java
@@ -38,8 +38,8 @@ import org.activiti.engine.history.HistoricDetailQuery;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableUpdate;
+import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.ReadOnlyProcessDefinition;
-import org.activiti.engine.impl.task.TaskEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType;
@@ -148,8 +148,7 @@ public class ActivitiPropertyConverter
properties.put(WorkflowModel.PROP_START_DATE, task.getCreateTime());
// Due date is present on the process instance
- String dueDateKey = factory.mapQNameToName(WorkflowModel.PROP_DUE_DATE);
- properties.put(WorkflowModel.PROP_DUE_DATE, (Serializable) variables.get(dueDateKey));
+ properties.put(WorkflowModel.PROP_DUE_DATE, task.getDueDate());
// Since this is a runtime-task, it's not completed yet
properties.put(WorkflowModel.PROP_COMPLETION_DATE, null);
@@ -260,12 +259,8 @@ public class ActivitiPropertyConverter
// Since the task is never started explicitally, we use the create time
properties.put(WorkflowModel.PROP_START_DATE, task.getCreateTime());
- // Due date is present on the process instance
- String dueDateKey = factory.mapQNameToName(WorkflowModel.PROP_DUE_DATE);
- if(properties.containsKey(WorkflowModel.PROP_DUE_DATE)==false)
- {
- properties.put(WorkflowModel.PROP_DUE_DATE, (Serializable) variables.get(dueDateKey));
- }
+ // Due date
+ properties.put(WorkflowModel.PROP_DUE_DATE, task.getDueDate());
// Since this is a runtime-task, it's not completed yet
properties.put(WorkflowModel.PROP_COMPLETION_DATE, null);
@@ -302,12 +297,10 @@ public class ActivitiPropertyConverter
// Since the task is never started explicitly, we use the create time
properties.put(WorkflowModel.PROP_START_DATE, historicTask.getStartTime());
- Object dueDateKey = factory.mapQNameToName(WorkflowModel.PROP_DUE_DATE);
- properties.put(WorkflowModel.PROP_DUE_DATE, (Serializable) variables.get(dueDateKey));
+ properties.put(WorkflowModel.PROP_DUE_DATE, historicTask.getDueDate());
properties.put(WorkflowModel.PROP_COMPLETION_DATE, historicTask.getEndTime());
- // TODO: Put task priority in history - http://jira.codehaus.org/browse/ACT-484
- // properties.put(WorkflowModel.PROP_PRIORITY, historicTask.getPriority());
+ properties.put(WorkflowModel.PROP_PRIORITY, historicTask.getPriority());
properties.put(ContentModel.PROP_CREATED, historicTask.getStartTime());
properties.put(ContentModel.PROP_OWNER, historicTask.getAssignee());
@@ -447,7 +440,6 @@ public class ActivitiPropertyConverter
// Map activiti task instance fields to properties
properties.put(WorkflowModel.PROP_TASK_ID, ActivitiConstants.START_TASK_PREFIX + historicProcessInstance.getId());
- // properties.put(WorkflowModel.PROP_DESCRIPTION, historicTask.getDescription());
properties.put(WorkflowModel.PROP_START_DATE, historicProcessInstance.getStartTime());
diff --git a/source/java/org/alfresco/repo/workflow/activiti/script/AlfrescoScriptDelegate.java b/source/java/org/alfresco/repo/workflow/activiti/script/AlfrescoScriptDelegate.java
new file mode 100644
index 0000000000..5e75e47391
--- /dev/null
+++ b/source/java/org/alfresco/repo/workflow/activiti/script/AlfrescoScriptDelegate.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+package org.alfresco.repo.workflow.activiti.script;
+
+import org.activiti.engine.delegate.DelegateExecution;
+import org.activiti.engine.delegate.JavaDelegate;
+import org.alfresco.service.cmr.repository.ScriptService;
+
+/**
+ * A {@link JavaDelegate} that executes a script against the {@link ScriptService}.
+ *
+ * The script that is executed can be set using field 'script'. A non-default
+ * script-processor can be set in the field 'scriptProcessor'. Optionally, you can run
+ * the script as a different user than the default by setting the field 'runAs'.
+ * By default, the user this script as the current logged-in user. If no user is
+ * currently logged in (eg. flow triggered by timer) the system user will be used instead.
+ *
+ * @author Frederik Heremans
+ * @since 3.5
+ */
+public class AlfrescoScriptDelegate extends DelegateExecutionScriptBase implements JavaDelegate {
+
+ @Override
+ public void execute(DelegateExecution execution) throws Exception {
+ runScript(execution);
+ }
+}
diff --git a/source/java/org/alfresco/repo/workflow/activiti/script/DelegateExecutionScriptBase.java b/source/java/org/alfresco/repo/workflow/activiti/script/DelegateExecutionScriptBase.java
new file mode 100644
index 0000000000..feaf198337
--- /dev/null
+++ b/source/java/org/alfresco/repo/workflow/activiti/script/DelegateExecutionScriptBase.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+package org.alfresco.repo.workflow.activiti.script;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.activiti.engine.delegate.DelegateExecution;
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.workflow.WorkflowQNameConverter;
+import org.alfresco.repo.workflow.activiti.ActivitiScriptNode;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.ScriptService;
+import org.alfresco.service.namespace.NamespaceService;
+
+
+/**
+ * Base class for running scripts against the {@link ScriptService}, in activiti's
+ * {@link DelegateExecution} context.
+ *
+ * @author Frederik Heremans
+ *
+ */
+public class DelegateExecutionScriptBase extends ActivitiScriptBase {
+
+ /**
+ * Run the script that is configured, using the given execution.
+ */
+ protected void runScript(DelegateExecution execution) throws Exception {
+ if(script != null)
+ {
+ String scriptString = getStringValue(script, execution);
+ String scriptProcessorName = getStringValue(scriptProcessor, execution);
+ String runAsUser = getStringValue(runAs, execution);
+
+ // Make sure there is an authenticated user for the current thread, so when
+ // the script is executed using no 'runAs' from a job-executor thread, the workflow
+ // owner us used
+ boolean clearAuthenticationContext = checkFullyAuthenticatedUser(execution);
+
+ // Get all activiti-defined objects
+ Map scriptModel = getInputMap(execution, runAsUser);
+
+ // Add core alfresco objects to the input-map
+ getServiceRegistry().getScriptService().buildCoreModel(scriptModel);
+
+ try
+ {
+ Object scriptOutput = executeScript(scriptString, scriptModel, scriptProcessorName, runAsUser);
+
+ // TODO: What to do with the script-output?
+ if(scriptOutput != null)
+ {
+ // delegateTask.setVariableLocal("scriptOutput", scriptOutput);
+ }
+ }
+ finally
+ {
+ if(clearAuthenticationContext)
+ {
+ // If the current user has been set to the Task's assignee, we should clear it agian
+ AuthenticationUtil.clearCurrentSecurityContext();
+ }
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("The field 'script' should be set on the TaskListener");
+ }
+ }
+
+ protected Map getInputMap(DelegateExecution execution, String runAsUser)
+ {
+ HashMap scriptModel = new HashMap(1);
+
+ // Add current logged-in user and it's user home
+ ActivitiScriptNode personNode = getPersonNode(runAsUser);
+ if(personNode != null)
+ {
+ ServiceRegistry registry = getServiceRegistry();
+ scriptModel.put(PERSON_BINDING_NAME, personNode);
+ NodeRef userHomeNode = (NodeRef) registry.getNodeService().getProperty(personNode.getNodeRef(), ContentModel.PROP_HOMEFOLDER);
+ if (userHomeNode != null)
+ {
+ scriptModel.put(USERHOME_BINDING_NAME, new ActivitiScriptNode(userHomeNode, registry));
+ }
+ }
+
+ // Add activiti-specific objects
+ scriptModel.put(EXECUTION_BINDING_NAME, execution);
+
+ // Add all workflow variables to model
+ Map variables = execution.getVariables();
+
+ for(Entry varEntry : variables.entrySet())
+ {
+ scriptModel.put(varEntry.getKey(), varEntry.getValue());
+ }
+
+ return scriptModel;
+ }
+
+ /**
+ * Checks a valid Fully Authenticated User is set.
+ * If none is set then attempts to set the workflow owner
+ * @param execution the execution
+ * @return true
if the Fully Authenticated User was changed, otherwise false
.
+ */
+ private boolean checkFullyAuthenticatedUser(final DelegateExecution execution) {
+ if(AuthenticationUtil.getFullyAuthenticatedUser() == null)
+ {
+ NamespaceService namespaceService = getServiceRegistry().getNamespaceService();
+ WorkflowQNameConverter qNameConverter = new WorkflowQNameConverter(namespaceService);
+ String ownerVariableName = qNameConverter.mapQNameToName(ContentModel.PROP_OWNER);
+
+ String userName = (String) execution.getVariable(ownerVariableName);
+ if (userName != null)
+ {
+ AuthenticationUtil.setFullyAuthenticatedUser(userName);
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/workflow/activiti/tasklistener/ScriptTaskListener.java b/source/java/org/alfresco/repo/workflow/activiti/tasklistener/ScriptTaskListener.java
index 830b0d530c..ce33e19523 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/tasklistener/ScriptTaskListener.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/tasklistener/ScriptTaskListener.java
@@ -24,18 +24,25 @@ import java.util.Map;
import java.util.Map.Entry;
import org.activiti.engine.delegate.DelegateTask;
-import org.activiti.engine.impl.pvm.delegate.TaskListener;
+import org.activiti.engine.delegate.TaskListener;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.workflow.activiti.ActivitiScriptNode;
import org.alfresco.repo.workflow.activiti.script.ActivitiScriptBase;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.ScriptService;
/**
- * A {@link TaskListener} that runs the script in property 'script'
- * using scripting-language specified by 'language'
- *
+ * A {@link TaskListener} that runs the script against the {@link ScriptService}.
+ *
+ * The script that is executed can be set using field 'script'. A non-default
+ * script-processor can be set in the field 'scriptProcessor'. Optionally, you can run
+ * the script as a different user than the default by setting the field 'runAs'.
+ * By default, the user this script is executed with is the task's assignee. If no
+ * assignee is set, the current logged-in user is used. If no user is currently logged in
+ * (eg. flow triggered by timer) the system user will be used instead.
+ *
* @author Frederik Heremans
* @since 3.4.e
*/
diff --git a/source/java/org/alfresco/repo/workflow/activiti/tasklistener/TaskCompleteListener.java b/source/java/org/alfresco/repo/workflow/activiti/tasklistener/TaskCompleteListener.java
index cb23755e52..2d6fec5cd5 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/tasklistener/TaskCompleteListener.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/tasklistener/TaskCompleteListener.java
@@ -25,9 +25,9 @@ import java.util.List;
import java.util.Map;
import org.activiti.engine.delegate.DelegateTask;
-import org.activiti.engine.impl.pvm.delegate.TaskListener;
-import org.activiti.engine.impl.task.IdentityLinkEntity;
-import org.activiti.engine.impl.task.TaskEntity;
+import org.activiti.engine.delegate.TaskListener;
+import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity;
+import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.task.IdentityLink;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.repo.workflow.WorkflowQNameConverter;
diff --git a/source/java/org/alfresco/repo/workflow/activiti/tasklistener/TaskCreateListener.java b/source/java/org/alfresco/repo/workflow/activiti/tasklistener/TaskCreateListener.java
index 766db7ecde..cdab33c3fb 100644
--- a/source/java/org/alfresco/repo/workflow/activiti/tasklistener/TaskCreateListener.java
+++ b/source/java/org/alfresco/repo/workflow/activiti/tasklistener/TaskCreateListener.java
@@ -20,10 +20,10 @@
package org.alfresco.repo.workflow.activiti.tasklistener;
import org.activiti.engine.delegate.DelegateTask;
+import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.form.FormData;
import org.activiti.engine.impl.form.TaskFormHandler;
-import org.activiti.engine.impl.pvm.delegate.TaskListener;
-import org.activiti.engine.impl.task.TaskEntity;
+import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.alfresco.repo.workflow.activiti.ActivitiConstants;
import org.alfresco.repo.workflow.activiti.properties.ActivitiPropertyConverter;