/*
|
* JBoss, Home of Professional Open Source
|
* Copyright 2005, JBoss Inc., and individual contributors as indicated
|
* by the @authors tag. See the copyright.txt in the distribution for a
|
* full listing of individual contributors.
|
*
|
* This 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 2.1 of
|
* the License, or (at your option) any later version.
|
*
|
* This software 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 this software; if not, write to the Free
|
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
*/
|
package org.jbpm.pvm.internal.task;
|
|
import java.io.Serializable;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.HashSet;
|
import java.util.Set;
|
|
import org.jbpm.api.Execution;
|
import org.jbpm.api.JbpmException;
|
import org.jbpm.api.model.Event;
|
import org.jbpm.api.task.Assignable;
|
import org.jbpm.api.task.Participation;
|
import org.jbpm.api.task.Swimlane;
|
import org.jbpm.api.task.Task;
|
import org.jbpm.pvm.internal.client.ClientExecution;
|
import org.jbpm.pvm.internal.env.EnvironmentImpl;
|
import org.jbpm.pvm.internal.history.HistoryEvent;
|
import org.jbpm.pvm.internal.history.events.TaskComplete;
|
import org.jbpm.pvm.internal.history.events.TaskDelete;
|
import org.jbpm.pvm.internal.model.ExecutionImpl;
|
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
|
import org.jbpm.pvm.internal.model.ScopeInstanceImpl;
|
import org.jbpm.pvm.internal.session.DbSession;
|
import org.jbpm.pvm.internal.util.EqualsUtil;
|
import org.jbpm.pvm.internal.util.Priority;
|
|
/**
|
* is one task instance that can be assigned to an actor (read: put in someone's task list) and that
|
* can trigger the continuation of execution of the token upon completion.
|
*/
|
public class TaskImpl extends ScopeInstanceImpl implements Serializable, OpenTask, Assignable {
|
|
private static final long serialVersionUID = 1L;
|
|
// private static Log log = Log.getLog(TaskImpl.class.getName());
|
|
protected boolean isNew;
|
protected String name;
|
protected String description;
|
|
protected String assignee;
|
protected Set<ParticipationImpl> participations = new HashSet<ParticipationImpl>();
|
|
protected String formResourceName;
|
protected Date createTime;
|
protected Date duedate;
|
protected Integer progress;
|
protected boolean isSignalling;
|
|
protected int priority = Priority.NORMAL;
|
|
protected String state = Task.STATE_OPEN;
|
|
protected String taskDefinitionName;
|
protected TaskDefinitionImpl taskDefinition;
|
|
protected ExecutionImpl execution;
|
protected ExecutionImpl processInstance;
|
|
// local storage of the execution id such that it
|
// can be lazily loaded when not needed.
|
protected String executionId;
|
|
protected String activityName;
|
|
protected SwimlaneImpl swimlane;
|
|
protected TaskImpl superTask;
|
protected Set<TaskImpl> subTasks;
|
|
protected Long executionDbid;
|
protected Long superTaskDbid;
|
|
public TaskImpl() {
|
}
|
|
// parent for variable lookup ///////////////////////////////////////////////
|
|
public ScopeInstanceImpl getParentVariableScope() {
|
return execution;
|
}
|
|
public TaskImpl getTask() {
|
return this;
|
}
|
|
// assignment ///////////////////////////////////////////////////////////////
|
|
public void take(String userId) {
|
if (assignee != null) {
|
throw new JbpmException("task already taken by " + this.assignee);
|
}
|
setAssignee(userId, true);
|
}
|
|
public void setAssignee(String userId) {
|
setAssignee(userId, false);
|
}
|
|
public void setAssignee(String assignee, boolean propagateToSwimlane) {
|
this.assignee = assignee;
|
if (propagateToSwimlane) {
|
propagateAssigneeToSwimlane();
|
}
|
if (execution != null) {
|
execution.fire(Event.ASSIGN, execution.getActivity());
|
}
|
}
|
|
protected void propagateAssigneeToSwimlane() {
|
if (swimlane != null) {
|
swimlane.setAssignee(assignee);
|
}
|
}
|
|
// participations /////////////////////////////////////////////////////////////
|
|
// TODO: Why does it return the impl. not the interface?
|
public Set<ParticipationImpl> getParticipations() {
|
return participations;
|
}
|
|
public Set<ParticipationImpl> getAllParticipants() {
|
Set<ParticipationImpl> allRoles = new HashSet<ParticipationImpl>();
|
if (!participations.isEmpty()) {
|
allRoles = new HashSet<ParticipationImpl>(participations);
|
}
|
if (swimlane != null) {
|
allRoles.addAll((Set) swimlane.getParticipations());
|
}
|
return allRoles;
|
}
|
|
public void addCandidateGroup(String groupId) {
|
addParticipation(null, groupId, Participation.CANDIDATE);
|
}
|
|
public void addCandidateUser(String userId) {
|
addParticipation(userId, null, Participation.CANDIDATE);
|
}
|
|
public Participation addParticipation(String userId, String groupId, String type) {
|
return addParticipant(new ParticipationImpl(userId, groupId, type));
|
}
|
|
private Participation addParticipant(ParticipationImpl participation) {
|
participation.setTask(this);
|
participations.add(participation);
|
return participation;
|
}
|
|
public void removeParticipant(ParticipationImpl participation) {
|
if (participation == null) {
|
throw new JbpmException("participant is null");
|
}
|
if (participations.remove(participation)) {
|
participation.setTask(null);
|
}
|
}
|
|
// completion ///////////////////////////////////////////////////////////////
|
|
public void complete() {
|
complete(TaskConstants.NO_TASK_OUTCOME_SPECIFIED);
|
}
|
|
public void complete(String outcome) {
|
historyTaskComplete(outcome);
|
|
if (isSignalling()) {
|
ClientExecution execution = (ClientExecution) getExecution();
|
execution.signal(outcome);
|
}
|
|
if (superTask != null) {
|
superTask.subTaskComplete(this, outcome);
|
}
|
}
|
|
protected void subTaskComplete(TaskImpl subTask, String outcome) {
|
}
|
|
public void delete(String reason) {
|
historyTaskDelete(reason);
|
}
|
|
// state ////////////////////////////////////////////////////////////////////
|
|
public boolean isCompleted() {
|
if (Task.STATE_COMPLETED.equals(state)) {
|
return true;
|
}
|
if ((Task.STATE_OPEN.equals(state)) || (Task.STATE_SUSPENDED.equals(state))) {
|
return false;
|
}
|
return true;
|
}
|
|
// subtasks /////////////////////////////////////////////////////////////////
|
|
public Set<Task> getSubTasks() {
|
if (subTasks == null) {
|
return Collections.emptySet();
|
}
|
return (Set) subTasks;
|
}
|
|
public TaskImpl createSubTask() {
|
DbSession dbSession = EnvironmentImpl.getFromCurrent(DbSession.class);
|
TaskImpl subTask = (TaskImpl) dbSession.createTask();
|
if (subTasks == null) {
|
subTasks = new HashSet<TaskImpl>();
|
}
|
addSubTask(subTask);
|
return subTask;
|
}
|
|
public TaskImpl createSubTask(String name) {
|
// TODO look up the task definition in the current task's
|
// subtask definitions and in the process's task definitions
|
TaskImpl subtask = createSubTask();
|
subtask.setName(name);
|
return subtask;
|
}
|
|
public TaskImpl addSubTask(TaskImpl subtask) {
|
if (subTasks == null) {
|
subTasks = new HashSet<TaskImpl>();
|
}
|
subtask.setSuperTask(this);
|
subTasks.add(subtask);
|
return subtask;
|
}
|
|
public void removeSubTask(Task subtask) {
|
if (subtask == null) {
|
throw new JbpmException("subtask is null");
|
}
|
if ((subTasks != null) && (subTasks.remove(subtask))) {
|
((TaskImpl) subtask).setSuperTask(null);
|
}
|
}
|
|
// equals ///////////////////////////////////////////////////////////////////
|
// hack to support comparing hibernate proxies against the real objects
|
// since this always falls back to ==, we don't need to overwrite the hashcode
|
public boolean equals(Object o) {
|
return EqualsUtil.equals(this, o);
|
}
|
|
public String toString() {
|
return "Task(" + name + ")";
|
}
|
|
public String getLifeCycleResource() {
|
// the default lifecycle can be overridden in subclasses
|
return "jbpm.task.lifecycle.xml";
|
}
|
|
// modified getters and setters /////////////////////////////////////////////
|
public void setProgress(Integer progress) {
|
if ((progress < 0) || (progress > 100)) {
|
throw new JbpmException(
|
"task progress is a percentage (integer) and must be expressed between 0 and 100");
|
}
|
this.progress = progress;
|
}
|
|
public void cancelExecution(String signal) {
|
if (execution != null) {
|
execution.end("cancel");
|
}
|
}
|
|
public void historyTaskDelete(String reason) {
|
if (execution != null) {
|
HistoryEvent.fire(new TaskDelete(this, reason), execution);
|
}
|
}
|
|
public void historyTaskComplete(String outcome) {
|
if (execution != null) {
|
HistoryEvent.fire(new TaskComplete(outcome), execution);
|
}
|
}
|
|
public void signalExecution(String signalName) {
|
if (execution != null) {
|
execution.signal(signalName);
|
}
|
}
|
|
// special getters and setters //////////////////////////////////////////////
|
|
public TaskDefinitionImpl getTaskDefinition() {
|
if ((taskDefinition == null) && (taskDefinitionName != null) && (execution != null)) {
|
ProcessDefinitionImpl processDefinition = execution.getProcessDefinition();
|
taskDefinition = processDefinition.getTaskDefinition(taskDefinitionName);
|
}
|
|
return taskDefinition;
|
}
|
|
// customized getters and setters //////////////////////////////////////////
|
|
public String getId() {
|
return Long.toString(dbid);
|
}
|
|
public void setTaskDefinition(TaskDefinitionImpl taskDefinition) {
|
this.taskDefinition = taskDefinition;
|
this.taskDefinitionName = taskDefinition.getName();
|
}
|
|
public void setExecution(ExecutionImpl execution) {
|
this.execution = execution;
|
this.executionId = execution.getId();
|
this.activityName = execution.getActivityName();
|
}
|
|
// getters and setters //////////////////////////////////////////////////////
|
|
public String getName() {
|
return name;
|
}
|
|
public void setName(String name) {
|
this.name = name;
|
}
|
|
public String getDescription() {
|
return description;
|
}
|
|
public void setDescription(String description) {
|
this.description = description;
|
}
|
|
public int getPriority() {
|
return priority;
|
}
|
|
public void setPriority(int priority) {
|
this.priority = priority;
|
}
|
|
public Date getCreateTime() {
|
return createTime;
|
}
|
|
public void setCreateTime(Date create) {
|
this.createTime = create;
|
}
|
|
public Date getDuedate() {
|
return duedate;
|
}
|
|
public void setDuedate(Date duedate) {
|
this.duedate = duedate;
|
}
|
|
public ExecutionImpl getExecution() {
|
return execution;
|
}
|
|
public void setExecution(Execution execution) {
|
this.execution = (ExecutionImpl) execution;
|
}
|
|
public String getState() {
|
return state;
|
}
|
|
public String getAssignee() {
|
return assignee;
|
}
|
|
public Swimlane getSwimlane() {
|
return swimlane;
|
}
|
|
public void setSwimlane(SwimlaneImpl swimlane) {
|
this.swimlane = swimlane;
|
}
|
|
public TaskImpl getSuperTask() {
|
return superTask;
|
}
|
|
public void setSuperTask(TaskImpl superTask) {
|
this.superTask = superTask;
|
}
|
|
public Integer getProgress() {
|
return progress;
|
}
|
|
public Long getExecutionDbid() {
|
return executionDbid;
|
}
|
|
public void setExecutionDbid(Long executionDbid) {
|
this.executionDbid = executionDbid;
|
}
|
|
public Long getSuperTaskDbid() {
|
return superTaskDbid;
|
}
|
|
public void setSuperTaskDbid(Long parentTaskDbid) {
|
this.superTaskDbid = parentTaskDbid;
|
}
|
|
public void setParticipations(Set<ParticipationImpl> participations) {
|
this.participations = participations;
|
}
|
|
public void setState(String state) {
|
this.state = state;
|
}
|
|
public String getExecutionId() {
|
return executionId;
|
}
|
|
public String getActivityName() {
|
return activityName;
|
}
|
|
public void setActivityName(String activityName) {
|
this.activityName = activityName;
|
}
|
|
public void setSubTasks(Set<TaskImpl> subTasks) {
|
this.subTasks = subTasks;
|
}
|
|
public ExecutionImpl getProcessInstance() {
|
return processInstance;
|
}
|
|
public void setProcessInstance(ExecutionImpl processInstance) {
|
this.processInstance = processInstance;
|
}
|
|
public boolean isSignalling() {
|
return isSignalling;
|
}
|
|
public void setSignalling(boolean isSignalling) {
|
this.isSignalling = isSignalling;
|
}
|
|
public String getFormResourceName() {
|
return formResourceName;
|
}
|
|
public void setFormResourceName(String form) {
|
this.formResourceName = form;
|
}
|
public boolean isNew() {
|
return isNew;
|
}
|
public void setNew(boolean isNew) {
|
this.isNew = isNew;
|
}
|
|
public void setDbid(long dbid) {
|
this.dbid = dbid;
|
}
|
}
|