ALF-8613 finished task-query + ALF-8614 + ALF-8617 duedate property

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@27813 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Frederik Heremans
2011-05-13 12:43:02 +00:00
parent 4653b40026
commit eebcfd38fd
20 changed files with 601 additions and 193 deletions

View File

@@ -143,6 +143,11 @@
<bean id="activitiPriorityPropertyHandler" <bean id="activitiPriorityPropertyHandler"
class="org.alfresco.repo.workflow.activiti.properties.ActivitiPriorityPropertyHandler" class="org.alfresco.repo.workflow.activiti.properties.ActivitiPriorityPropertyHandler"
parent="activitiPropertyHandler" /> parent="activitiPropertyHandler" />
<!-- Activiti Due Date Property Handler -->
<bean id="activitiDueDatePropertyHandler"
class="org.alfresco.repo.workflow.activiti.properties.ActivitiDueDatePropertyHandler"
parent="activitiPropertyHandler" />
<!-- Listeners for all activiti-tasks in alfresco --> <!-- Listeners for all activiti-tasks in alfresco -->
<bean id="activitiCompleteTaskListener" <bean id="activitiCompleteTaskListener"

View File

@@ -235,7 +235,7 @@
<prop key="engineId">jbpm</prop> <prop key="engineId">jbpm</prop>
<prop key="location">alfresco/workflow/adhoc_processdefinition.xml</prop> <prop key="location">alfresco/workflow/adhoc_processdefinition.xml</prop>
<prop key="mimetype">text/xml</prop> <prop key="mimetype">text/xml</prop>
<prop key="redeploy">false</prop> <prop key="redeploy">true</prop>
</props> </props>
<!-- Review and Approve workflow definitions --> <!-- Review and Approve workflow definitions -->

View File

@@ -575,16 +575,16 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
// Adhoc task should only be returned // Adhoc task should only be returned
QName taskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "adhocTask"); 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 // 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 // Workflow is still active, both tasks will be returned
checkIsActiveQuery(expectedTasks, WorkflowTaskState.COMPLETED); checkIsActiveQuery(expectedTasks, WorkflowTaskState.COMPLETED, null);
// Both tasks have custom property set // Both tasks have custom property set
checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED); checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED, null);
} }
protected void testTaskQueryInProgress(String workflowInstanceId, WorkflowTask expectedTask) protected void testTaskQueryInProgress(String workflowInstanceId, WorkflowTask expectedTask)
@@ -595,10 +595,11 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
checkTaskIdQuery(expectedTask.getId(), WorkflowTaskState.IN_PROGRESS); checkTaskIdQuery(expectedTask.getId(), WorkflowTaskState.IN_PROGRESS);
QName taskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "adhocTask"); QName taskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "adhocTask");
checkTaskNameQuery(taskName, expectedTasks, WorkflowTaskState.IN_PROGRESS); checkTaskNameQuery(taskName, expectedTasks, WorkflowTaskState.IN_PROGRESS, null);
checkActorIdQuery(USER2, expectedTasks, WorkflowTaskState.IN_PROGRESS); checkActorIdQuery(USER2, expectedTasks, WorkflowTaskState.IN_PROGRESS, null);
checkIsActiveQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS); checkIsActiveQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS, null);
checkTaskPropsQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS); checkTaskPropsQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS, null);
checkProcessPropsQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS);
} }
protected void testTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask) { protected void testTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask) {
@@ -608,10 +609,10 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
checkTaskIdQuery(startTask.getId(), WorkflowTaskState.COMPLETED); checkTaskIdQuery(startTask.getId(), WorkflowTaskState.COMPLETED);
QName startTaskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "submitAdhocTask"); QName startTaskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "submitAdhocTask");
checkTaskNameQuery(startTaskName, expectedTasks, WorkflowTaskState.COMPLETED); checkTaskNameQuery(startTaskName, expectedTasks, WorkflowTaskState.COMPLETED, null);
checkActorIdQuery(USER1, expectedTasks, WorkflowTaskState.COMPLETED); checkActorIdQuery(USER1, expectedTasks, WorkflowTaskState.COMPLETED, null);
checkIsActiveQuery(expectedTasks, WorkflowTaskState.COMPLETED); checkIsActiveQuery(expectedTasks, WorkflowTaskState.COMPLETED, null);
checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED); checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED, null);
} }
public void testGetWorkflows() throws Exception public void testGetWorkflows() throws Exception
@@ -767,14 +768,23 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
} }
} }
protected void checkTaskNameQuery(QName taskName, List<String> expectedTaskIds, WorkflowTaskState state) { protected void checkTaskNameQuery(QName taskName, List<String> expectedTaskIds, WorkflowTaskState state,
String optionalProcessId) {
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state); WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state);
taskQuery.setTaskName(taskName); taskQuery.setTaskName(taskName);
if(optionalProcessId != null)
{
taskQuery.setProcessId(optionalProcessId);
}
checkTasksFoundUsingQuery(expectedTaskIds, taskQuery); checkTasksFoundUsingQuery(expectedTaskIds, taskQuery);
QName unexistingTaskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "unexistingTask"); QName unexistingTaskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "unexistingTask");
taskQuery = createWorkflowTaskQuery(state); taskQuery = createWorkflowTaskQuery(state);
taskQuery.setTaskName(unexistingTaskName); taskQuery.setTaskName(unexistingTaskName);
if(optionalProcessId != null)
{
taskQuery.setProcessId(optionalProcessId);
}
checkNoTasksFoundUsingQuery(taskQuery); checkNoTasksFoundUsingQuery(taskQuery);
} }
@@ -800,29 +810,48 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
checkNoTasksFoundUsingQuery(taskQuery); checkNoTasksFoundUsingQuery(taskQuery);
} }
protected void checkIsActiveQuery(List<String> expectedTaskIds, WorkflowTaskState state) protected void checkIsActiveQuery(List<String> expectedTaskIds, WorkflowTaskState state,
String optionalProcessId)
{ {
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state); WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state);
taskQuery.setActive(true); taskQuery.setActive(true);
if(optionalProcessId != null)
{
taskQuery.setProcessId(optionalProcessId);
}
checkTasksFoundUsingQuery(expectedTaskIds, taskQuery); checkTasksFoundUsingQuery(expectedTaskIds, taskQuery);
taskQuery = createWorkflowTaskQuery(state); taskQuery = createWorkflowTaskQuery(state);
taskQuery.setActive(false); taskQuery.setActive(false);
if(optionalProcessId != null)
{
taskQuery.setProcessId(optionalProcessId);
}
checkNoTasksFoundUsingQuery(taskQuery); checkNoTasksFoundUsingQuery(taskQuery);
} }
protected void checkActorIdQuery(String actorId, List<String> expectedTaskIds, WorkflowTaskState state) protected void checkActorIdQuery(String actorId, List<String> expectedTaskIds, WorkflowTaskState state,
String optionalProcessId)
{ {
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state); WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state);
taskQuery.setActorId(actorId); taskQuery.setActorId(actorId);
if(optionalProcessId != null)
{
taskQuery.setProcessId(optionalProcessId);
}
checkTasksFoundUsingQuery(expectedTaskIds, taskQuery); checkTasksFoundUsingQuery(expectedTaskIds, taskQuery);
taskQuery = createWorkflowTaskQuery(state); taskQuery = createWorkflowTaskQuery(state);
taskQuery.setActorId(USER3); taskQuery.setActorId(USER3);
if(optionalProcessId != null)
{
taskQuery.setProcessId(optionalProcessId);
}
checkNoTasksFoundUsingQuery(taskQuery); checkNoTasksFoundUsingQuery(taskQuery);
} }
protected void checkTaskPropsQuery(List<String> expectedTaskIds, WorkflowTaskState state) protected void checkTaskPropsQuery(List<String> expectedTaskIds, WorkflowTaskState state,
String optionalProcessId)
{ {
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state); WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state);
QName customStringProp = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "customStringProp"); 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"); taskProps.put(customStringProp, "stringValue");
taskQuery.setTaskCustomProps(taskProps); taskQuery.setTaskCustomProps(taskProps);
if(optionalProcessId != null)
{
taskQuery.setProcessId(optionalProcessId);
}
checkTasksFoundUsingQuery(expectedTaskIds, taskQuery); checkTasksFoundUsingQuery(expectedTaskIds, taskQuery);
taskProps = new HashMap<QName, Object>(); taskProps = new HashMap<QName, Object>();
@@ -838,6 +871,10 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
taskQuery = createWorkflowTaskQuery(state); taskQuery = createWorkflowTaskQuery(state);
taskQuery.setTaskCustomProps(taskProps); taskQuery.setTaskCustomProps(taskProps);
if(optionalProcessId != null)
{
taskQuery.setProcessId(optionalProcessId);
}
checkNoTasksFoundUsingQuery(taskQuery); checkNoTasksFoundUsingQuery(taskQuery);
} }

View File

@@ -240,8 +240,7 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
WorkflowTask finishedTask = workflowEngine.getTaskById(finishedTaskId); WorkflowTask finishedTask = workflowEngine.getTaskById(finishedTaskId);
assertNotNull(finishedTask); 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(finishedTaskId, finishedTask.getId());
Assert.assertEquals("bpm_foo_task", finishedTask.getName()); Assert.assertEquals("bpm_foo_task", finishedTask.getName());
@@ -446,8 +445,31 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
Assert.assertNotNull(tasks); Assert.assertNotNull(tasks);
Assert.assertEquals(0, tasks.size()); Assert.assertEquals(0, tasks.size());
// TODO: test using process-name, not yet implemented now // Test query by process-name
// TODO: test using task-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 // Test querying task variables, using all possible (and allowed) types of variables
Map<String, Object> variables = new HashMap<String, Object>(); Map<String, Object> variables = new HashMap<String, Object>();
@@ -499,29 +521,51 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
ActivitiScriptNode otherNode = new ActivitiScriptNode(testUserNode, serviceRegistry); ActivitiScriptNode otherNode = new ActivitiScriptNode(testUserNode, serviceRegistry);
checkTaskVariableNoMatch(WorkflowTaskState.IN_PROGRESS, QName.createQName("scriptNodeVar"), otherNode); 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<QName, Object> props = new HashMap<QName, Object>();
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 @Test
public void testQueryTasksCompleted() throws Exception { 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<QName, Serializable>()); WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), new HashMap<QName, Serializable>());
Task task = taskService.createTaskQuery() Task task = taskService.createTaskQuery()
.executionId(BPMEngineRegistry.getLocalId(path.getId())) .executionId(BPMEngineRegistry.getLocalId(path.getId()))
.singleResult(); .singleResult();
taskService.setVariableLocal(task.getId(), "taskVar", "theValue");
assertNotNull("Task should exist!", task); assertNotNull("Task should exist!", task);
String globalTaskId = createGlobalId(task.getId()); String globalTaskId = createGlobalId(task.getId());
// Set the actor // Set the actor
taskService.setAssignee(task.getId(), TEST_USER); taskService.setAssignee(task.getId(), TEST_USER);
// Set process prop
runtime.setVariable(task.getExecutionId(), "processVar", "testing");
// End the task // End the task
workflowEngine.endTask(globalTaskId, null); workflowEngine.endTask(globalTaskId, null);
// Test query by taskId // Test query by taskId
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED); WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
taskQuery.setActive(Boolean.FALSE); // Set to false, since workflow this task is in, has finished
taskQuery.setTaskId(globalTaskId); taskQuery.setTaskId(globalTaskId);
List<WorkflowTask> tasks = workflowEngine.queryTasks(taskQuery); List<WorkflowTask> 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 // Test query by process ID, this should also return the start-task
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED); taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
taskQuery.setProcessId(createGlobalId(task.getProcessInstanceId())); taskQuery.setProcessId(createGlobalId(task.getProcessInstanceId()));
taskQuery.setActive(Boolean.FALSE);
tasks = workflowEngine.queryTasks(taskQuery); tasks = workflowEngine.queryTasks(taskQuery);
Assert.assertNotNull(tasks); Assert.assertNotNull(tasks);
@@ -572,6 +617,7 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
// Test query by actor // Test query by actor
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED); taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
taskQuery.setActorId(TEST_USER); taskQuery.setActorId(TEST_USER);
taskQuery.setActive(Boolean.FALSE);
tasks = workflowEngine.queryTasks(taskQuery); tasks = workflowEngine.queryTasks(taskQuery);
Assert.assertNotNull(tasks); Assert.assertNotNull(tasks);
@@ -585,11 +631,53 @@ public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
Assert.assertNotNull(tasks); Assert.assertNotNull(tasks);
Assert.assertEquals(0, tasks.size()); Assert.assertEquals(0, tasks.size());
// TODO: test using process-name, not yet implemented now // Test query by process-name
// TODO: test using task-name taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
taskQuery.setProcessName(QName.createQName("testTask"));
taskQuery.setActive(Boolean.FALSE);
tasks = workflowEngine.queryTasks(taskQuery);
// TODO: test using task variables Assert.assertNotNull(tasks);
// TODO: test using process variables 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<QName, Object> props = new HashMap<QName, Object>();
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<QName, Object>();
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());
} }

View File

@@ -24,7 +24,7 @@ import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.form.FormData; import org.activiti.engine.form.FormData;
import org.activiti.engine.form.TaskFormData; import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.impl.form.TaskFormHandler; 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.activiti.engine.task.Task;
import org.alfresco.repo.workflow.WorkflowObjectFactory; import org.alfresco.repo.workflow.WorkflowObjectFactory;
import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition;

View File

@@ -26,7 +26,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.activiti.engine.ProcessEngine; 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.repository.ProcessDefinition;
import org.activiti.engine.runtime.Job; import org.activiti.engine.runtime.Job;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;

View File

@@ -32,8 +32,8 @@ import org.activiti.engine.form.StartFormData;
import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl; 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.pvm.ReadOnlyProcessDefinition;
import org.activiti.engine.impl.repository.ProcessDefinitionEntity;
import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution; import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.runtime.ProcessInstance;

View File

@@ -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.DefaultTaskFormHandler;
import org.activiti.engine.impl.form.TaskFormHandler; import org.activiti.engine.impl.form.TaskFormHandler;
import org.activiti.engine.impl.identity.Authentication; 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.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition; import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.ReadOnlyProcessDefinition; import org.activiti.engine.impl.pvm.ReadOnlyProcessDefinition;
import org.activiti.engine.impl.pvm.process.ActivityImpl; 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.Deployment;
import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution; import org.activiti.engine.runtime.Execution;
@@ -1369,7 +1369,6 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
@Override @Override
public List<WorkflowTask> queryTasks(WorkflowTaskQuery query) public List<WorkflowTask> queryTasks(WorkflowTaskQuery query)
{ {
// TODO: complete, only small part is implemented
ArrayList<WorkflowTask> result = new ArrayList<WorkflowTask>(); ArrayList<WorkflowTask> result = new ArrayList<WorkflowTask>();
WorkflowTaskState taskState = query.getTaskState(); WorkflowTaskState taskState = query.getTaskState();
if(WorkflowTaskState.COMPLETED.equals(taskState) == false) if(WorkflowTaskState.COMPLETED.equals(taskState) == false)
@@ -1407,9 +1406,8 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
if(query.getProcessName() != null) if(query.getProcessName() != null)
{ {
// String processName = getProcessNameMTSafe(query.getProcessName()); String processName = getProcessNameMTSafe(query.getProcessName());
// TODO: Method added in http://jira.codehaus.org/browse/ACT-459 taskQuery.processDefinitionKey(processName);
// taskQuery.processDefinitionName(processName);
} }
@@ -1447,7 +1445,11 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
private void addProcessPropertiesToQuery( private void addProcessPropertiesToQuery(
Map<QName, Object> processCustomProps, TaskQuery taskQuery) { Map<QName, Object> processCustomProps, TaskQuery taskQuery) {
// TODO: implement for(Entry<QName, Object> customProperty : processCustomProps.entrySet())
{
String name =factory.mapQNameToName(customProperty.getKey());
taskQuery.processVariableValueEquals(name, customProperty.getValue());
}
} }
protected String getProcessNameMTSafe(QName processNameQName) protected String getProcessNameMTSafe(QName processNameQName)
@@ -1517,13 +1519,11 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
{ {
if (orderByPart == WorkflowTaskQuery.OrderBy.TaskActor_Asc) if (orderByPart == WorkflowTaskQuery.OrderBy.TaskActor_Asc)
{ {
// TODO: add in activiti taskQuery.orderByTaskAssignee().asc();
// taskQuery.orderByTaskAssignee().asc();
} }
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskActor_Desc) else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskActor_Desc)
{ {
// TODO: add in activiti taskQuery.orderByTaskAssignee().desc();
// taskQuery.orderByTaskAssignee().desc();
} }
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskCreated_Asc) 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) else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskId_Asc)
{ {
// TODO: add in activiti taskQuery.orderByTaskId().asc();
// taskQuery.orderByTaskId().asc();
} }
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskId_Desc) else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskId_Desc)
{ {
// TODO: add in activiti taskQuery.orderByTaskId().desc();
// taskQuery.orderByTaskId().desc();
} }
else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskName_Asc) else if (orderByPart == WorkflowTaskQuery.OrderBy.TaskName_Asc)
{ {
@@ -1581,7 +1579,6 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
private List<WorkflowTask> queryHistoricTasks(WorkflowTaskQuery query) private List<WorkflowTask> queryHistoricTasks(WorkflowTaskQuery query)
{ {
// TODO: Implement complete query
HistoricTaskInstanceQuery historicQuery = historyService HistoricTaskInstanceQuery historicQuery = historyService
.createHistoricTaskInstanceQuery() .createHistoricTaskInstanceQuery()
.finished(); .finished();
@@ -1609,12 +1606,30 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
if(query.getProcessName() != null) if(query.getProcessName() != null)
{ {
// String processName = getProcessNameMTSafe(query.getProcessName()); String processName = getProcessNameMTSafe(query.getProcessName());
// TODO: add to query historicQuery.processDefinitionKey(processName);
} }
// TODO: task properties from history query if(query.getTaskCustomProps() != null)
// TODO: process properties {
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 // Order query
if(query.getOrderBy() != null) if(query.getOrderBy() != null)
@@ -1638,10 +1653,26 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
} }
private void addTaskPropertiesToQuery(Map<QName, Object> taskCustomProps,
HistoricTaskInstanceQuery taskQuery) {
for(Entry<QName, Object> customProperty : taskCustomProps.entrySet())
{
String name =factory.mapQNameToName(customProperty.getKey());
taskQuery.taskVariableValueEquals(name, customProperty.getValue());
}
}
private void addProcessPropertiesToQuery(Map<QName, Object> processCustomProps,
HistoricTaskInstanceQuery taskQuery) {
for(Entry<QName, Object> customProperty : processCustomProps.entrySet())
{
String name =factory.mapQNameToName(customProperty.getKey());
taskQuery.processVariableValueEquals(name, customProperty.getValue());
}
}
private List<WorkflowTask> queryStartTasks(WorkflowTaskQuery query) private List<WorkflowTask> queryStartTasks(WorkflowTaskQuery query)
{ {
// TODO: implement further
List<WorkflowTask> startTasks = new ArrayList<WorkflowTask>(); List<WorkflowTask> startTasks = new ArrayList<WorkflowTask>();
String processInstanceId = null; String processInstanceId = null;
@@ -1683,6 +1714,18 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
private boolean isStartTaskMatching(WorkflowTask workflowTask, private boolean isStartTaskMatching(WorkflowTask workflowTask,
WorkflowTaskQuery query) { 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))) if(query.getActorId() != null && !query.getActorId().equals(workflowTask.getProperties().get(ContentModel.PROP_OWNER)))
{ {
return false; return false;
@@ -1755,7 +1798,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
{ {
for(Map.Entry<QName, Object> entry : expectedProperties.entrySet()) for(Map.Entry<QName, Object> entry : expectedProperties.entrySet())
{ {
if(props.containsKey(entry.getValue())) if(props.containsKey(entry.getKey()))
{ {
Object requiredValue = entry.getValue(); Object requiredValue = entry.getValue();
Object actualValue = props.get(entry.getKey()); Object actualValue = props.get(entry.getKey());
@@ -1766,6 +1809,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
{ {
return false; return false;
} }
break;
} }
else else
{ {
@@ -1773,6 +1817,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
{ {
return false; return false;
} }
break;
} }
} }
if(entry.getValue() != null) if(entry.getValue() != null)

View File

@@ -20,6 +20,7 @@
package org.alfresco.repo.workflow.activiti; package org.alfresco.repo.workflow.activiti;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; 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.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowPath; import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowTask; 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.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
@@ -78,11 +81,63 @@ public class ActivitiWorkflowServiceIntegrationTest extends AbstractWorkflowServ
Serializable outcome = result.getProperties().get(WorkflowModel.PROP_OUTCOME); Serializable outcome = result.getProperties().get(WorkflowModel.PROP_OUTCOME);
assertEquals("Approve", 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<String> 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 protected void testTaskQueryTaskCompleted(String workflowInstanceId,
public void testQueryTasks() { WorkflowTask theTask, WorkflowTask startTask)
// TODO: Revive test once all pieces of queryTasks() are finished on ActivitiWorkflowEngine {
} List<String> bothTasks = Arrays.asList(theTask.getId(), startTask.getId());
List<String> 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<WorkflowTask> 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 @Override
protected String getEngine() protected String getEngine()

View File

@@ -18,14 +18,14 @@
*/ */
package org.alfresco.repo.workflow.activiti; 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.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.parser.BpmnParseListener; 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.ActivityBehavior;
import org.activiti.engine.impl.pvm.delegate.TaskListener;
import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ScopeImpl; import org.activiti.engine.impl.pvm.process.ScopeImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl; 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.util.xml.Element;
import org.activiti.engine.impl.variable.VariableDeclaration; import org.activiti.engine.impl.variable.VariableDeclaration;

View File

@@ -22,8 +22,8 @@ package org.alfresco.repo.workflow.activiti;
import org.activiti.engine.impl.TaskQueryImpl; import org.activiti.engine.impl.TaskQueryImpl;
import org.activiti.engine.impl.interceptor.CommandContext; import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.jobexecutor.JobHandler; 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.pvm.PvmActivity;
import org.activiti.engine.impl.runtime.ExecutionEntity;
import org.activiti.engine.task.Task; import org.activiti.engine.task.Task;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;

View File

@@ -19,115 +19,55 @@
package org.alfresco.repo.workflow.activiti.listener; package org.alfresco.repo.workflow.activiti.listener;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import org.activiti.engine.delegate.DelegateExecution; 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.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.ActivitiConstants;
import org.alfresco.repo.workflow.activiti.ActivitiScriptNode; import org.alfresco.repo.workflow.activiti.script.DelegateExecutionScriptBase;
import org.alfresco.repo.workflow.activiti.script.ActivitiScriptBase; import org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
/** /**
* 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 Nick Smith
* @author Frederik Heremans * @author Frederik Heremans
* @since 3.4.e * @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 DELETED_FLAG = "deleted";
private static final String CANCELLED_FLAG = "cancelled"; private static final String CANCELLED_FLAG = "cancelled";
@Override @Override
public void notify(ExecutionListenerExecution execution) throws Exception { public void notify(DelegateExecution execution) throws Exception {
if(script != null) runScript(execution);
{
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<String, Object> 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<String, Object> getInputMap(ExecutionListenerExecution execution, String runAsUser) @Override
{ protected Map<String, Object> getInputMap(DelegateExecution execution,
HashMap<String, Object> scriptModel = new HashMap<String, Object>(1); String runAsUser) {
Map<String, Object> scriptModel = super.getInputMap(execution, runAsUser);
// Add current logged-in user and it's user home
ActivitiScriptNode personNode = getPersonNode(runAsUser); ExecutionListenerExecution listenerExecution = (ExecutionListenerExecution) execution;
if(personNode != null)
{ // Add deleted/cancelled flags
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<String, Object> variables = execution.getVariables();
for(Entry<String, Object> varEntry : variables.entrySet())
{
scriptModel.put(varEntry.getKey(), varEntry.getValue());
}
// Add deleted/cancelled flags
boolean cancelled = false; boolean cancelled = false;
boolean deleted = false; boolean deleted = false;
if(ActivitiConstants.DELETE_REASON_DELETED.equals(execution.getDeleteReason())) if(ActivitiConstants.DELETE_REASON_DELETED.equals(listenerExecution.getDeleteReason()))
{ {
deleted = true; deleted = true;
} }
else if(ActivitiConstants.DELETE_REASON_CANCELLED.equals(execution.getDeleteReason())) else if(ActivitiConstants.DELETE_REASON_CANCELLED.equals(listenerExecution.getDeleteReason()))
{ {
cancelled = true; cancelled = true;
} }
@@ -136,28 +76,4 @@ public class ScriptExecutionListener extends ActivitiScriptBase implements Execu
return scriptModel; 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 <code>true</code> if the Fully Authenticated User was changed, otherwise <code>false</code>.
*/
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;
}
} }

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@@ -28,8 +28,8 @@ import java.util.List;
import org.activiti.engine.TaskService; import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.DelegateTask; import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.impl.task.IdentityLinkEntity; import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity;
import org.activiti.engine.impl.task.TaskEntity; import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.task.IdentityLink; import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType; import org.activiti.engine.task.IdentityLinkType;
import org.activiti.engine.task.Task; import org.activiti.engine.task.Task;

View File

@@ -38,8 +38,8 @@ import org.activiti.engine.history.HistoricDetailQuery;
import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableUpdate; 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.pvm.ReadOnlyProcessDefinition;
import org.activiti.engine.impl.task.TaskEntity;
import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.IdentityLink; import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType; import org.activiti.engine.task.IdentityLinkType;
@@ -148,8 +148,7 @@ public class ActivitiPropertyConverter
properties.put(WorkflowModel.PROP_START_DATE, task.getCreateTime()); properties.put(WorkflowModel.PROP_START_DATE, task.getCreateTime());
// Due date is present on the process instance // Due date is present on the process instance
String dueDateKey = factory.mapQNameToName(WorkflowModel.PROP_DUE_DATE); properties.put(WorkflowModel.PROP_DUE_DATE, task.getDueDate());
properties.put(WorkflowModel.PROP_DUE_DATE, (Serializable) variables.get(dueDateKey));
// Since this is a runtime-task, it's not completed yet // Since this is a runtime-task, it's not completed yet
properties.put(WorkflowModel.PROP_COMPLETION_DATE, null); 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 // Since the task is never started explicitally, we use the create time
properties.put(WorkflowModel.PROP_START_DATE, task.getCreateTime()); properties.put(WorkflowModel.PROP_START_DATE, task.getCreateTime());
// Due date is present on the process instance // Due date
String dueDateKey = factory.mapQNameToName(WorkflowModel.PROP_DUE_DATE); properties.put(WorkflowModel.PROP_DUE_DATE, task.getDueDate());
if(properties.containsKey(WorkflowModel.PROP_DUE_DATE)==false)
{
properties.put(WorkflowModel.PROP_DUE_DATE, (Serializable) variables.get(dueDateKey));
}
// Since this is a runtime-task, it's not completed yet // Since this is a runtime-task, it's not completed yet
properties.put(WorkflowModel.PROP_COMPLETION_DATE, null); 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 // Since the task is never started explicitly, we use the create time
properties.put(WorkflowModel.PROP_START_DATE, historicTask.getStartTime()); properties.put(WorkflowModel.PROP_START_DATE, historicTask.getStartTime());
Object dueDateKey = factory.mapQNameToName(WorkflowModel.PROP_DUE_DATE); properties.put(WorkflowModel.PROP_DUE_DATE, historicTask.getDueDate());
properties.put(WorkflowModel.PROP_DUE_DATE, (Serializable) variables.get(dueDateKey));
properties.put(WorkflowModel.PROP_COMPLETION_DATE, historicTask.getEndTime()); 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_CREATED, historicTask.getStartTime());
properties.put(ContentModel.PROP_OWNER, historicTask.getAssignee()); properties.put(ContentModel.PROP_OWNER, historicTask.getAssignee());
@@ -447,7 +440,6 @@ public class ActivitiPropertyConverter
// Map activiti task instance fields to properties // Map activiti task instance fields to properties
properties.put(WorkflowModel.PROP_TASK_ID, ActivitiConstants.START_TASK_PREFIX + historicProcessInstance.getId()); 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()); properties.put(WorkflowModel.PROP_START_DATE, historicProcessInstance.getStartTime());

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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<String, Object> 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<String, Object> getInputMap(DelegateExecution execution, String runAsUser)
{
HashMap<String, Object> scriptModel = new HashMap<String, Object>(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<String, Object> variables = execution.getVariables();
for(Entry<String, Object> 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 <code>true</code> if the Fully Authenticated User was changed, otherwise <code>false</code>.
*/
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;
}
}

View File

@@ -24,18 +24,25 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.activiti.engine.delegate.DelegateTask; 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.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.workflow.activiti.ActivitiScriptNode; import org.alfresco.repo.workflow.activiti.ActivitiScriptNode;
import org.alfresco.repo.workflow.activiti.script.ActivitiScriptBase; import org.alfresco.repo.workflow.activiti.script.ActivitiScriptBase;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.ScriptService;
/** /**
* A {@link TaskListener} that runs the script in property 'script' * A {@link TaskListener} that runs the script against the {@link ScriptService}.
* using scripting-language specified by 'language' *
* * 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 * @author Frederik Heremans
* @since 3.4.e * @since 3.4.e
*/ */

View File

@@ -25,9 +25,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.activiti.engine.delegate.DelegateTask; import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.impl.pvm.delegate.TaskListener; import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.impl.task.IdentityLinkEntity; import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity;
import org.activiti.engine.impl.task.TaskEntity; import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.task.IdentityLink; import org.activiti.engine.task.IdentityLink;
import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.repo.workflow.WorkflowQNameConverter; import org.alfresco.repo.workflow.WorkflowQNameConverter;

View File

@@ -20,10 +20,10 @@
package org.alfresco.repo.workflow.activiti.tasklistener; package org.alfresco.repo.workflow.activiti.tasklistener;
import org.activiti.engine.delegate.DelegateTask; import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.form.FormData; import org.activiti.engine.form.FormData;
import org.activiti.engine.impl.form.TaskFormHandler; import org.activiti.engine.impl.form.TaskFormHandler;
import org.activiti.engine.impl.pvm.delegate.TaskListener; import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.task.TaskEntity;
import org.alfresco.repo.workflow.activiti.ActivitiConstants; import org.alfresco.repo.workflow.activiti.ActivitiConstants;
import org.alfresco.repo.workflow.activiti.properties.ActivitiPropertyConverter; import org.alfresco.repo.workflow.activiti.properties.ActivitiPropertyConverter;