提交 46e98396 编写于 作者: M Marcus Klimstra

Implemented ACT-1585: Linking process instances and users.

上级 7fd47012
......@@ -24,6 +24,8 @@ import org.activiti.engine.runtime.NativeExecutionQuery;
import org.activiti.engine.runtime.NativeProcessInstanceQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType;
/** Service which provides access to {@link Deployment}s,
......@@ -268,6 +270,24 @@ public interface RuntimeService {
*/
void signal(String executionId, Map<String, Object> processVariables);
// Identity Links ///////////////////////////////////////////////////////////////
/**
* Involves a user with a process instance. The type of identity link is defined by the
* given identityLinkType.
* @param processInstanceId id of the process instance, cannot be null.
* @param userId id of the user involve, cannot be null.
* @param identityLinkType type of identityLink, cannot be null (@see {@link IdentityLinkType}).
* @throws ActivitiObjectNotFoundException when the process instance doesn't exist.
*/
void addUserIdentityLink(String processInstanceId, String userId, String identityLinkType);
/**
* Retrieves the {@link IdentityLink}s associated with the given process instance.
* Such an {@link IdentityLink} informs how a certain user is involved with a process instance.
*/
List<IdentityLink> getIdentityLinksForProcessInstance(String instanceId);
// Variables ////////////////////////////////////////////////////////////////////
/** All variables visible from the given execution scope (including parent scopes).
......@@ -514,5 +534,5 @@ public interface RuntimeService {
* @throws ActivitiException if the execution has not subscribed to the signal
*/
void messageEventReceived(String messageName, String executionId, Map<String, Object> processVariables);
}
\ No newline at end of file
......@@ -43,6 +43,7 @@ public class ProcessInstanceQueryImpl extends AbstractVariableQueryImpl<ProcessI
protected String processDefinitionKey;
protected String superProcessInstanceId;
protected String subProcessInstanceId;
protected String involvedUser;
protected SuspensionState suspensionState;
// Unused, see dynamic query
......@@ -122,6 +123,13 @@ public class ProcessInstanceQueryImpl extends AbstractVariableQueryImpl<ProcessI
return this;
}
public ProcessInstanceQuery involvedUser(String involvedUser) {
if (involvedUser == null) {
throw new ActivitiIllegalArgumentException("Involved user is null");
}
this.involvedUser = involvedUser;
return this;
}
public ProcessInstanceQuery orderByProcessInstanceId() {
this.orderProperty = ProcessInstanceQueryProperty.PROCESS_INSTANCE_ID;
......@@ -195,6 +203,9 @@ public class ProcessInstanceQueryImpl extends AbstractVariableQueryImpl<ProcessI
public String getSubProcessInstanceId() {
return subProcessInstanceId;
}
public String getInvolvedUser() {
return involvedUser;
}
public SuspensionState getSuspensionState() {
return suspensionState;
}
......
......@@ -18,15 +18,16 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.form.FormData;
import org.activiti.engine.impl.cmd.ActivateProcessInstanceCmd;
import org.activiti.engine.impl.cmd.AddIdentityLinkForProcessInstanceCmd;
import org.activiti.engine.impl.cmd.DeleteProcessInstanceCmd;
import org.activiti.engine.impl.cmd.FindActiveActivityIdsCmd;
import org.activiti.engine.impl.cmd.GetExecutionVariableCmd;
import org.activiti.engine.impl.cmd.GetExecutionVariablesCmd;
import org.activiti.engine.impl.cmd.GetIdentityLinksForProcessInstanceCmd;
import org.activiti.engine.impl.cmd.GetStartFormCmd;
import org.activiti.engine.impl.cmd.MessageEventReceivedCmd;
import org.activiti.engine.impl.cmd.RemoveExecutionVariablesCmd;
......@@ -41,6 +42,7 @@ import org.activiti.engine.runtime.NativeExecutionQuery;
import org.activiti.engine.runtime.NativeProcessInstanceQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.IdentityLink;
/**
* @author Tom Baeyens
......@@ -175,6 +177,14 @@ public class RuntimeServiceImpl extends ServiceImpl implements RuntimeService {
commandExecutor.execute(new SignalCmd(executionId, null, null, processVariables));
}
public void addUserIdentityLink(String processInstanceId, String userId, String identityLinkType) {
commandExecutor.execute(new AddIdentityLinkForProcessInstanceCmd(processInstanceId, userId, identityLinkType));
}
public List<IdentityLink> getIdentityLinksForProcessInstance(String processInstanceId) {
return commandExecutor.execute(new GetIdentityLinksForProcessInstanceCmd(processInstanceId));
}
public ProcessInstanceQuery createProcessInstanceQuery() {
return new ProcessInstanceQueryImpl(commandExecutor);
}
......
......@@ -74,13 +74,10 @@ public class AddIdentityLinkCmd extends NeedsActiveTaskCmd<Void> {
task.addIdentityLink(userId, groupId, type);
}
if(assignedToNoOne)
{
if (assignedToNoOne) {
// ACT-1317: Special handling when assignee is set to NULL, a CommentEntity notifying of assignee-delete should be created
commandContext.getHistoryManager().createIdentityLinkComment(taskId, userId, groupId, type, false, true);
}
else
{
} else {
commandContext.getHistoryManager().createIdentityLinkComment(taskId, userId, groupId, type, true);
}
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.engine.impl.cmd;
import java.io.Serializable;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
/**
* @author Marcus Klimstra
*/
public class AddIdentityLinkForProcessInstanceCmd implements Command<Void>, Serializable {
private static final long serialVersionUID = 1L;
protected String processInstanceId;
protected String userId;
protected String type;
public AddIdentityLinkForProcessInstanceCmd(String processInstanceId, String userId, String type) {
validateParams(processInstanceId, userId);
this.processInstanceId = processInstanceId;
this.userId = userId;
this.type = type;
}
protected void validateParams(String processInstanceId, String userId) {
if (processInstanceId == null) {
throw new ActivitiIllegalArgumentException("processInstanceId is null");
}
if (userId == null) {
throw new ActivitiIllegalArgumentException("userId cannot be null");
}
}
public Void execute(CommandContext commandContext) {
ExecutionEntity processInstance = Context
.getCommandContext()
.getExecutionEntityManager()
.findExecutionById(processInstanceId);
if (processInstance == null) {
throw new ActivitiObjectNotFoundException("Cannot find process instance with id " + processInstanceId, ExecutionEntity.class);
}
processInstance.addIdentityLink(userId, type);
return null;
}
}
......@@ -15,7 +15,6 @@ package org.activiti.engine.impl.cmd;
import java.io.Serializable;
import java.util.List;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.engine.impl.cmd;
import java.io.Serializable;
import java.util.List;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.task.IdentityLink;
/**
* @author Marcus Klimstra
*/
public class GetIdentityLinksForProcessInstanceCmd implements Command<List<IdentityLink>>, Serializable {
private static final long serialVersionUID = 1L;
protected String processInstanceId;
public GetIdentityLinksForProcessInstanceCmd(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
@SuppressWarnings({"unchecked", "rawtypes"})
public List<IdentityLink> execute(CommandContext commandContext) {
ExecutionEntity processInstance = Context
.getCommandContext()
.getExecutionEntityManager()
.findExecutionById(processInstanceId);
if (processInstance == null) {
throw new ActivitiObjectNotFoundException("Cannot find process definition with id " + processInstanceId, ExecutionEntity.class);
}
return (List) processInstance.getIdentityLinks();
}
}
......@@ -131,6 +131,7 @@ public class ExecutionEntity extends VariableScopeImpl implements ActivityExecut
protected List<EventSubscriptionEntity> eventSubscriptions;
protected List<JobEntity> jobs;
protected List<TaskEntity> tasks;
protected List<IdentityLinkEntity> identityLinks;
protected int cachedEntityState;
// cascade deletion ////////////////////////////////////////////////////////
......@@ -831,6 +832,9 @@ public class ExecutionEntity extends VariableScopeImpl implements ActivityExecut
// remove event scopes:
removeEventScopes();
// remove identity links
removeIdentityLinks();
// finally delete this execution
Context.getCommandContext()
......@@ -1180,7 +1184,48 @@ public class ExecutionEntity extends VariableScopeImpl implements ActivityExecut
getTasksInternal().remove(task);
}
// identity links ///////////////////////////////////////////////////////////
public List<IdentityLinkEntity> getIdentityLinks() {
if (identityLinks == null) {
identityLinks = Context
.getCommandContext()
.getIdentityLinkEntityManager()
.findIdentityLinksByProcessInstanceId(id);
}
return identityLinks;
}
public IdentityLinkEntity addIdentityLink(String userId, String type) {
IdentityLinkEntity identityLinkEntity = IdentityLinkEntity.createAndInsert();
getIdentityLinks().add(identityLinkEntity);
identityLinkEntity.setProcessInstance(this);
identityLinkEntity.setUserId(userId);
identityLinkEntity.setType(type);
return identityLinkEntity;
}
/**
* Adds an IdentityLink for this user with the specified type,
* but only if the user is not associated with this instance yet.
**/
public IdentityLinkEntity involveUser(String userId, String type) {
for (IdentityLinkEntity identityLink : getIdentityLinks()) {
if (identityLink.getUserId().equals(userId)) {
return identityLink;
}
}
return addIdentityLink(userId, type);
}
public void removeIdentityLinks() {
Context
.getCommandContext()
.getIdentityLinkEntityManager()
.deleteIdentityLinksByProcInstance(id);
}
// getters and setters //////////////////////////////////////////////////////
......
......@@ -37,10 +37,14 @@ public class IdentityLinkEntity implements Serializable, IdentityLink, Persisten
protected String taskId;
protected String processInstanceId;
protected String processDefId;
protected TaskEntity task;
protected ExecutionEntity processInstance;
protected ProcessDefinitionEntity processDef;
public Object getPersistentState() {
......@@ -109,6 +113,14 @@ public class IdentityLinkEntity implements Serializable, IdentityLink, Persisten
void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getProcessInstanceId() {
return processInstanceId;
}
public void setProcessInstanceId(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
public String getProcessDefId() {
return processDefId;
......@@ -132,6 +144,21 @@ public class IdentityLinkEntity implements Serializable, IdentityLink, Persisten
this.task = task;
this.taskId = task.getId();
}
public ExecutionEntity getProcessInstance() {
if ((processInstance == null) && (processInstanceId != null)) {
this.processInstance = Context
.getCommandContext()
.getExecutionEntityManager()
.findExecutionById(processInstanceId);
}
return processInstance;
}
public void setProcessInstance(ExecutionEntity processInstance) {
this.processInstance = processInstance;
this.processInstanceId = processInstance.getId();
}
public ProcessDefinitionEntity getProcessDef() {
if ((processDef == null) && (processDefId != null)) {
......
......@@ -35,6 +35,11 @@ public class IdentityLinkEntityManager extends AbstractManager {
return getDbSqlSession().selectList("selectIdentityLinksByTask", taskId);
}
@SuppressWarnings("unchecked")
public List<IdentityLinkEntity> findIdentityLinksByProcessInstanceId(String processInstanceId) {
return getDbSqlSession().selectList("selectIdentityLinksByProcessInstance", processInstanceId);
}
@SuppressWarnings("unchecked")
public List<IdentityLinkEntity> findIdentityLinksByProcessDefinitionId(String processDefinitionId) {
return getDbSqlSession().selectList("selectIdentityLinksByProcessDefinition", processDefinitionId);
......@@ -65,9 +70,13 @@ public class IdentityLinkEntityManager extends AbstractManager {
deleteIdentityLink(identityLink);
}
}
public void deleteIdentityLinksByProcInstance(String processInstanceId) {
getDbSqlSession().delete("deleteIdentityLinksByProcInstance", processInstanceId);
}
public void deleteIdentityLinksByProcDef(String processDefId) {
getDbSqlSession().delete("deleteIdentityLinkByProcDef", processDefId);
}
}
......@@ -84,11 +84,14 @@ public class ProcessDefinitionEntity extends ProcessDefinitionImpl implements Pr
// Reset the process instance in order to have the db-generated process instance id available
processInstance.setProcessInstance(processInstance);
String authenticatedUserId = Authentication.getAuthenticatedUserId();
String initiatorVariableName = (String) getProperty(BpmnParse.PROPERTYNAME_INITIATOR_VARIABLE_NAME);
if (initiatorVariableName!=null) {
String authenticatedUserId = Authentication.getAuthenticatedUserId();
processInstance.setVariable(initiatorVariableName, authenticatedUserId);
}
if (authenticatedUserId != null) {
processInstance.addIdentityLink(authenticatedUserId, IdentityLinkType.STARTER);
}
Context.getCommandContext().getHistoryManager()
.recordProcessInstanceStart(processInstance);
......
......@@ -32,6 +32,7 @@ import org.activiti.engine.impl.db.DbSqlSession;
import org.activiti.engine.impl.db.HasRevision;
import org.activiti.engine.impl.db.PersistentObject;
import org.activiti.engine.impl.delegate.TaskListenerInvocation;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.pvm.delegate.ActivityExecution;
import org.activiti.engine.impl.task.TaskDefinition;
......@@ -129,13 +130,8 @@ public class TaskEntity extends VariableScopeImpl implements Task, DelegateTask,
dbSqlSession.update(this);
}
/** new task. Embedded state and create time will be initialized.
* But this task still will have to be persisted with
* TransactionContext
* .getCurrent()
* .getPersistenceSession()
* .insert(task);
*/
/** Creates a new task. Embedded state and create time will be initialized.
* But this task still will have to be persisted. See {@link #insert(ExecutionEntity)}. */
public static TaskEntity create() {
TaskEntity task = new TaskEntity();
task.isIdentityLinksInitialized = true;
......@@ -146,6 +142,10 @@ public class TaskEntity extends VariableScopeImpl implements Task, DelegateTask,
public void complete() {
fireEvent(TaskListener.EVENTNAME_COMPLETE);
if (Authentication.getAuthenticatedUserId() != null) {
getProcessInstance().involveUser(Authentication.getAuthenticatedUserId(), IdentityLinkType.PARTICIPANT);
}
Context
.getCommandContext()
.getTaskEntityManager()
......@@ -271,6 +271,7 @@ public class TaskEntity extends VariableScopeImpl implements Task, DelegateTask,
identityLinkEntity.setUserId(userId);
identityLinkEntity.setGroupId(groupId);
identityLinkEntity.setType(type);
getProcessInstance().involveUser(owner, IdentityLinkType.PARTICIPANT);
return identityLinkEntity;
}
......@@ -420,16 +421,16 @@ public class TaskEntity extends VariableScopeImpl implements Task, DelegateTask,
this.assignee = assignee;
CommandContext commandContext = Context.getCommandContext();
// if there is no command context, then it means that the user is calling the
// setAssignee outside a service method. E.g. while creating a new task.
if (commandContext!=null) {
commandContext
.getHistoryManager()
.recordTaskAssigneeChange(id, assignee);
// if there is no command context, then it means that the user is calling the
// setAssignee outside a service method. E.g. while creating a new task.
if (commandContext!=null) {
fireEvent(TaskListener.EVENTNAME_ASSIGNMENT);
}
getProcessInstance().involveUser(assignee, IdentityLinkType.PARTICIPANT);
fireEvent(TaskListener.EVENTNAME_ASSIGNMENT);
}
}
......@@ -452,6 +453,8 @@ public class TaskEntity extends VariableScopeImpl implements Task, DelegateTask,
commandContext
.getHistoryManager()
.recordTaskOwnerChange(id, owner);
getProcessInstance().involveUser(owner, IdentityLinkType.PARTICIPANT);
}
}
......@@ -636,6 +639,12 @@ public class TaskEntity extends VariableScopeImpl implements Task, DelegateTask,
this.executionId = executionId;
}
public ExecutionEntity getProcessInstance() {
if (processInstance == null) {
processInstance = Context
.getCommandContext()
.getExecutionEntityManager()
.findExecutionById(processInstanceId);
}
return processInstance;
}
public void setProcessInstance(ExecutionEntity processInstance) {
......
......@@ -46,7 +46,7 @@ public interface ProcessInstanceQuery extends Query<ProcessInstanceQuery, Proces
ProcessInstanceQuery processDefinitionKey(String processDefinitionKey);
/**
* Selects the process instances which are defined by a process definition
* Select the process instances which are defined by a process definition
* with the given id.
*/
ProcessInstanceQuery processDefinitionId(String processDefinitionId);
......@@ -64,6 +64,11 @@ public interface ProcessInstanceQuery extends Query<ProcessInstanceQuery, Proces
*/
ProcessInstanceQuery subProcessInstanceId(String subProcessInstanceId);
/**
* Select the process instances with which the user with the given id is involved.
*/
ProcessInstanceQuery involvedUser(String userId);
/**
* Only select process instances which have a global variable with the given value. The type
* of variable is determined based on the value, using types configured in
......@@ -165,14 +170,14 @@ public interface ProcessInstanceQuery extends Query<ProcessInstanceQuery, Proces
ProcessInstanceQuery variableValueLike(String name, String value);
/**
* Only selects process instances which are suspended, either because the
* Only select process instances which are suspended, either because the
* process instance itself is suspended or because the corresponding process
* definition is suspended
*/
ProcessInstanceQuery suspended();
/**
* Only selects process instances which are active, which means that
* Only select process instances which are active, which means that
* neither the process instance nor the corresponding process definition
* are suspended.
*/
......
......@@ -34,4 +34,8 @@ public class IdentityLinkType {
public static final String OWNER = "owner";
public static final String STARTER = "starter";
public static final String PARTICIPANT = "participant";
}
......@@ -129,6 +129,7 @@ create table ACT_RU_IDENTITYLINK (
TYPE_ varchar(255),
USER_ID_ varchar(255),
TASK_ID_ varchar(64),
PROC_INST_ID_ varchar(64),
PROC_DEF_ID_ varchar(64),
primary key (ID_)
);
......
......@@ -129,6 +129,7 @@ create table ACT_RU_IDENTITYLINK (
TYPE_ nvarchar(255),
USER_ID_ nvarchar(255),
TASK_ID_ nvarchar(64),
PROC_INST_ID_ varchar(64),
PROC_DEF_ID_ nvarchar(64),
primary key (ID_)
);
......
......@@ -130,6 +130,7 @@ create table ACT_RU_IDENTITYLINK (
TYPE_ varchar(255),
USER_ID_ varchar(255),
TASK_ID_ varchar(64),
PROC_INST_ID_ varchar(64),
PROC_DEF_ID_ varchar(64),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
......
......@@ -129,6 +129,7 @@ create table ACT_RU_IDENTITYLINK (
TYPE_ NVARCHAR2(255),
USER_ID_ NVARCHAR2(255),
TASK_ID_ NVARCHAR2(64),
PROC_INST_ID_ varchar(64),
PROC_DEF_ID_ NVARCHAR2(64),
primary key (ID_)
);
......
......@@ -130,6 +130,7 @@ create table ACT_RU_IDENTITYLINK (
TYPE_ varchar(255),
USER_ID_ varchar(255),
TASK_ID_ varchar(64),
PROC_INST_ID_ varchar(64),
PROC_DEF_ID_ varchar (64),
primary key (ID_)
);
......
......@@ -105,7 +105,7 @@
<include refid="selectExecutionsByQueryCriteriaSql"/>
</select>
<!-- same as selectExecutionByQueryCriteria, but with different parameterType -->
<!-- same as selectExecutionsByQueryCriteria, but with different parameterType -->
<select id="selectProcessInstanceByQueryCriteria" parameterType="org.activiti.engine.impl.ProcessInstanceQueryImpl" resultMap="executionResultMap">
${limitBefore}
select RES.* ${limitBetween}, P.KEY_ as ProcessDefinitionKey, P.ID_ as ProcessDefinitionId
......@@ -121,6 +121,9 @@
<sql id="selectExecutionsByQueryCriteriaSql">
from ${prefix}ACT_RU_EXECUTION RES
<if test="involvedUser != null">
inner join ${prefix}ACT_RU_IDENTITYLINK I on I.PROC_INST_ID_ = RES.ID_
</if>
<foreach collection="queryVariableValues" index="index" item="queryVariableValue">
<choose>
<when test="queryVariableValue.local">
......@@ -181,6 +184,9 @@
and (RES.SUSPENSION_STATE_ = 2)
</if>
</if>
<if test="involvedUser != null">
and I.USER_ID_ = #{involvedUser}
</if>
<!-- PLEASE NOTE: If you change anything have a look into the HistoricVariableInstance & HistoricProcessInstance, the same query object is used there! -->
<foreach collection="queryVariableValues" index="index" item="queryVariableValue">
<if test="!queryVariableValue.local">
......
......@@ -7,13 +7,14 @@
<!-- INSERT IDENTITY LINK -->
<insert id="insertIdentityLink" parameterType="org.activiti.engine.impl.persistence.entity.IdentityLinkEntity">
insert into ${prefix}ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_DEF_ID_)
insert into ${prefix}ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_)
values (#{id, jdbcType=VARCHAR},
1,
#{type, jdbcType=VARCHAR},
#{userId, jdbcType=VARCHAR},
#{groupId, jdbcType=VARCHAR},
#{taskId, jdbcType=VARCHAR},
#{processInstanceId, jdbcType=VARCHAR},
#{processDefId, jdbcType=VARCHAR})
</insert>
......@@ -24,6 +25,10 @@
delete from ${prefix}ACT_RU_IDENTITYLINK where ID_ = #{id}
</delete>
<delete id="deleteIdentityLinksByProcInstance" parameterType="string">
delete from ${prefix}ACT_RU_IDENTITYLINK where PROC_INST_ID_ = #{id}
</delete>
<delete id="deleteIdentityLinkByProcDef" parameterType="string">
delete from ${prefix}ACT_RU_IDENTITYLINK where PROC_DEF_ID_ = #{id}
</delete>
......@@ -37,6 +42,7 @@
<result property="userId" column="USER_ID_" jdbcType="VARCHAR" />
<result property="groupId" column="GROUP_ID_" jdbcType="VARCHAR" />
<result property="taskId" column="TASK_ID_" jdbcType="VARCHAR" />
<result property="processInstanceId" column="PROC_INST_ID_" jdbcType="VARCHAR" />
<result property="processDefId" column="PROCESS_DEF_ID_" jdbcType="VARCHAR" />
</resultMap>
......@@ -50,6 +56,10 @@
select * from ${prefix}ACT_RU_IDENTITYLINK where TASK_ID_ = #{parameter}
</select>
<select id="selectIdentityLinksByProcessInstance" parameterType="org.activiti.engine.impl.db.ListQueryParameterObject" resultMap="identityLinkResultMap">
select * from ${prefix}ACT_RU_IDENTITYLINK where PROC_INST_ID_ = #{parameter}
</select>
<select id="selectIdentityLinksByProcessDefinition" parameterType="org.activiti.engine.impl.db.ListQueryParameterObject" resultMap="identityLinkResultMap">
select * from ${prefix}ACT_RU_IDENTITYLINK where PROC_DEF_ID_ = #{parameter}
</select>
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.engine.test.api.runtime;
import java.util.List;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
/**
* @author Marcus Klimstra
*/
public class InstanceInvolvementTest extends PluggableActivitiTestCase {
@Deployment(resources={
"org/activiti/engine/test/api/runtime/threeParallelTasks.bpmn20.xml"})
public void testInvolvements() {
// "user1", "user2", "user3" and "user4 should not be involved with any process instance
assertNoInvolvement("user1");
assertNoInvolvement("user2");
assertNoInvolvement("user3");
assertNoInvolvement("user4");
// start a new process instance as "user1"
String instanceId = startProcessAsUser("threeParallelTasks", "user1");
// there are supposed to be 3 tasks
List<Task> tasks = taskService.createTaskQuery().processInstanceId(instanceId).list();
assertEquals(3, tasks.size());
// "user1" should now be involved as the starter of the new process instance. "user2" is still not involved.
assertInvolvement("user1", instanceId);
assertNoInvolvement("user2");
// "user2" should be involved with the new process instance after claiming a task
taskService.claim(tasks.get(0).getId(), "user2");
assertInvolvement("user2", instanceId);
// "user2" should still be involved with the new process instance even after completing his task
taskService.complete(tasks.get(0).getId());
assertInvolvement("user2", instanceId);
// "user3" should be involved after completing a task even without claiming it
completeTaskAsUser(tasks.get(1).getId(), "user3");
assertInvolvement("user3", instanceId);
// "user4" should be involved after manually adding an identity link
runtimeService.addUserIdentityLink(instanceId, "user4", "custom");
assertInvolvement("user4", instanceId);
// verify all identity links for this instance
// note that since "user1" already is the starter, he is not involved as a participant as well
List<IdentityLink> identityLinks = runtimeService.getIdentityLinksForProcessInstance(instanceId);
assertTrue(containsIdentityLink(identityLinks, "user1", "starter"));
assertTrue(containsIdentityLink(identityLinks, "user2", "participant"));
assertTrue(containsIdentityLink(identityLinks, "user3", "participant"));
assertTrue(containsIdentityLink(identityLinks, "user4", "custom"));
assertEquals(4, identityLinks.size());
// "user1" completes the remaining task, ending the process
completeTaskAsUser(tasks.get(2).getId(), "user1");
// none of the users should now be involved with any process instance
assertNoInvolvement("user1");
assertNoInvolvement("user2");
assertNoInvolvement("user3");
assertNoInvolvement("user4");
}
@Deployment(resources={
"org/activiti/engine/test/api/runtime/threeParallelTasks.bpmn20.xml"})
public void testInstanceRemoval() {
String instanceId = startProcessAsUser("threeParallelTasks", "user1");
assertInvolvement("user1", instanceId);
runtimeService.deleteProcessInstance(instanceId, "Testing instance removal");
assertNoInvolvement("user1");
// this will fail with a "DB NOT CLEAN" if the identity links are not removed
}
private void assertNoInvolvement(String userId) {
assertEquals(0L, runtimeService.createProcessInstanceQuery().involvedUser(userId).count());
}
private void assertInvolvement(String userId, String instanceId) {
ProcessInstance involvedInstance = runtimeService
.createProcessInstanceQuery()
.involvedUser(userId)
.singleResult();
assertEquals(instanceId, involvedInstance.getId());
}
private String startProcessAsUser(String processId, String userId) {
try {
identityService.setAuthenticatedUserId(userId);
return runtimeService.startProcessInstanceByKey(processId).getId();
}
finally {
identityService.setAuthenticatedUserId(null);
}
}
private void completeTaskAsUser(String taskId, String userId) {
try {
identityService.setAuthenticatedUserId(userId);
taskService.complete(taskId);
}
finally {
identityService.setAuthenticatedUserId(null);
}
}
private boolean containsIdentityLink(List<IdentityLink> identityLinks, String userId, String type) {
for (IdentityLink identityLink : identityLinks) {
if (userId.equals(identityLink.getUserId()) && type.equals(identityLink.getType())) {
return true;
}
}
return false;
}
}
......@@ -1224,7 +1224,7 @@ public class ProcessInstanceQueryTest extends PluggableActivitiTestCase {
@Deployment(resources={
"org/activiti/engine/test/api/oneTaskProcess.bpmn20.xml"})
public void testClashingValues() throws Exception {
public void testClashingValues() throws Exception {
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("var", 1234L);
......
<?xml version="1.0" encoding="UTF-8"?>
<definitions id="definitions"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="org.activiti.enginge.test.api.runtime">
<process id="threeParallelTasks">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />
<parallelGateway id="fork" />
<sequenceFlow sourceRef="fork" targetRef="task1" />
<sequenceFlow sourceRef="fork" targetRef="task2" />
<sequenceFlow sourceRef="fork" targetRef="task3" />
<userTask id="task1" name="Task 1" />
<userTask id="task2" name="Task 2" />
<userTask id="task3" name="Task 3" />
<sequenceFlow sourceRef="task1" targetRef="join" />
<sequenceFlow sourceRef="task2" targetRef="join" />
<sequenceFlow sourceRef="task3" targetRef="join" />
<parallelGateway id="join" />
<sequenceFlow sourceRef="join" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册