mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
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:
@@ -144,6 +144,11 @@
|
||||
class="org.alfresco.repo.workflow.activiti.properties.ActivitiPriorityPropertyHandler"
|
||||
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 -->
|
||||
<bean id="activitiCompleteTaskListener"
|
||||
class="org.alfresco.repo.workflow.activiti.tasklistener.TaskCompleteListener"
|
||||
|
@@ -235,7 +235,7 @@
|
||||
<prop key="engineId">jbpm</prop>
|
||||
<prop key="location">alfresco/workflow/adhoc_processdefinition.xml</prop>
|
||||
<prop key="mimetype">text/xml</prop>
|
||||
<prop key="redeploy">false</prop>
|
||||
<prop key="redeploy">true</prop>
|
||||
</props>
|
||||
|
||||
<!-- Review and Approve workflow definitions -->
|
||||
|
@@ -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<String> expectedTaskIds, WorkflowTaskState state) {
|
||||
protected void checkTaskNameQuery(QName taskName, List<String> 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<String> expectedTaskIds, WorkflowTaskState state)
|
||||
protected void checkIsActiveQuery(List<String> 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<String> expectedTaskIds, WorkflowTaskState state)
|
||||
protected void checkActorIdQuery(String actorId, List<String> 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<String> expectedTaskIds, WorkflowTaskState state)
|
||||
protected void checkTaskPropsQuery(List<String> 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<QName, Object>();
|
||||
@@ -838,6 +871,10 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT
|
||||
|
||||
taskQuery = createWorkflowTaskQuery(state);
|
||||
taskQuery.setTaskCustomProps(taskProps);
|
||||
if(optionalProcessId != null)
|
||||
{
|
||||
taskQuery.setProcessId(optionalProcessId);
|
||||
}
|
||||
checkNoTasksFoundUsingQuery(taskQuery);
|
||||
}
|
||||
|
||||
|
@@ -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<String, Object> variables = new HashMap<String, Object>();
|
||||
@@ -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<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
|
||||
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>());
|
||||
|
||||
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<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
|
||||
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<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());
|
||||
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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<WorkflowTask> queryTasks(WorkflowTaskQuery query)
|
||||
{
|
||||
// TODO: complete, only small part is implemented
|
||||
ArrayList<WorkflowTask> result = new ArrayList<WorkflowTask>();
|
||||
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<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)
|
||||
@@ -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<WorkflowTask> 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<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)
|
||||
{
|
||||
|
||||
// TODO: implement further
|
||||
List<WorkflowTask> startTasks = new ArrayList<WorkflowTask>();
|
||||
|
||||
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<QName, Object> 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)
|
||||
|
@@ -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;
|
||||
|
||||
@@ -79,9 +82,61 @@ public class ActivitiWorkflowServiceIntegrationTest extends AbstractWorkflowServ
|
||||
assertEquals("Approve", outcome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testQueryTasks() {
|
||||
// TODO: Revive test once all pieces of queryTasks() are finished on ActivitiWorkflowEngine
|
||||
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);
|
||||
}
|
||||
|
||||
protected void testTaskQueryTaskCompleted(String workflowInstanceId,
|
||||
WorkflowTask theTask, WorkflowTask startTask)
|
||||
{
|
||||
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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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<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");
|
||||
}
|
||||
public void notify(DelegateExecution execution) throws Exception {
|
||||
runScript(execution);
|
||||
}
|
||||
|
||||
protected Map<String, Object> getInputMap(ExecutionListenerExecution execution, String runAsUser)
|
||||
{
|
||||
HashMap<String, Object> scriptModel = new HashMap<String, Object>(1);
|
||||
@Override
|
||||
protected Map<String, Object> getInputMap(DelegateExecution execution,
|
||||
String runAsUser) {
|
||||
Map<String, Object> scriptModel = super.getInputMap(execution, runAsUser);
|
||||
|
||||
// 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());
|
||||
}
|
||||
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 <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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
|
@@ -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());
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
@@ -24,17 +24,24 @@ 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
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user