/*
* 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.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.StringTokenizer;
import org.hibernate.Session;
import org.jbpm.api.Execution;
import org.jbpm.api.JbpmException;
import org.jbpm.api.activity.ActivityExecution;
import org.jbpm.api.cmd.Environment;
import org.jbpm.api.job.Job;
import org.jbpm.api.job.Timer;
import org.jbpm.api.listener.EventListenerExecution;
import org.jbpm.api.model.Event;
import org.jbpm.api.model.OpenExecution;
import org.jbpm.api.task.Assignable;
import org.jbpm.api.task.AssignmentHandler;
import org.jbpm.internal.log.Log;
import org.jbpm.pvm.internal.client.ClientProcessDefinition;
import org.jbpm.pvm.internal.client.ClientProcessInstance;
import org.jbpm.pvm.internal.env.Context;
import org.jbpm.pvm.internal.env.EnvironmentImpl;
import org.jbpm.pvm.internal.env.ExecutionContext;
import org.jbpm.pvm.internal.history.HistoryEvent;
import org.jbpm.pvm.internal.history.events.ActivityEnd;
import org.jbpm.pvm.internal.history.events.ActivityStart;
import org.jbpm.pvm.internal.history.events.AutomaticEnd;
import org.jbpm.pvm.internal.history.events.DecisionEnd;
import org.jbpm.pvm.internal.history.events.ProcessInstanceCreate;
import org.jbpm.pvm.internal.history.events.ProcessInstanceEnd;
import org.jbpm.pvm.internal.id.DbidGenerator;
import org.jbpm.pvm.internal.id.IdComposer;
import org.jbpm.pvm.internal.job.JobImpl;
import org.jbpm.pvm.internal.job.MessageImpl;
import org.jbpm.pvm.internal.model.op.AtomicOperation;
import org.jbpm.pvm.internal.model.op.MoveToChildActivity;
import org.jbpm.pvm.internal.model.op.Signal;
import org.jbpm.pvm.internal.script.ScriptManager;
import org.jbpm.pvm.internal.session.DbSession;
import org.jbpm.pvm.internal.session.MessageSession;
import org.jbpm.pvm.internal.session.RepositorySession;
import org.jbpm.pvm.internal.session.TimerSession;
import org.jbpm.pvm.internal.task.AssignableDefinitionImpl;
import org.jbpm.pvm.internal.task.SwimlaneDefinitionImpl;
import org.jbpm.pvm.internal.task.SwimlaneImpl;
import org.jbpm.pvm.internal.type.Variable;
import org.jbpm.pvm.internal.util.EqualsUtil;
import org.jbpm.pvm.internal.util.Priority;
import org.jbpm.pvm.internal.wire.usercode.UserCodeReference;
/**
* @author Tom Baeyens
*/
public class ExecutionImpl extends ScopeInstanceImpl
implements ClientProcessInstance,
ActivityExecution,
EventListenerExecution,
Serializable {
private static final long serialVersionUID = 1L;
private static final Log log = Log.getLog(ExecutionImpl.class.getName());
/** an optional name for this execution. can be used to
* differentiate concurrent paths of execution like e.g.
* the 'shipping' and 'billing' paths. */
protected String name;
/** a key for this execution. typically this is an externally provided reference
* that is unique within the scope of the process definition. */
protected String key;
/** a unique id for this execution. */
protected String id;
/** are concurrent executions that related to this execution. */
protected Collection<ExecutionImpl> executions = new ArrayList<ExecutionImpl>();
/** the parent child relation of executions is convenient for some forms of
* concurrency. */
protected ExecutionImpl parent = null;
protected ExecutionImpl processInstance;
/** the super process link in case this is a sub process execution */
protected ExecutionImpl superProcessExecution;
/** the sub process link in case of sub process execution */
protected ExecutionImpl subProcessInstance;
/** swimlanes */
protected Map<String, SwimlaneImpl> swimlanes = new HashMap<String, SwimlaneImpl>();
/** reference to the current activity instance history record */
protected Long historyActivityInstanceDbid;
/** start time of the activity for history purposes (not persisted) */
protected Date historyActivityStart;
protected int priority = Priority.NORMAL;
protected Map<String, Variable> systemVariables = new HashMap<String, Variable>();
// persistent indicators of the current position ////////////////////////////
/** persistent process definition reference */
protected String processDefinitionId;
/** persistent activity reference */
protected String activityName;
// transient cached indicators of the current position //////////////////////
/** transient cached process definition. persistence is managed in {@link #processDefinitionId} */
protected ProcessDefinitionImpl processDefinition;
/** transient cached current activity pointer. persistence is managed in {@link #activityName} */
private ActivityImpl activity;
/** transition is not to be made persistable by default */
protected TransitionImpl transition;
protected EventImpl event;
protected AtomicOperation eventCompletedOperation;
protected int eventListenerIndex;
protected ObservableElementImpl eventSource;
// cached named executions //////////////////////////////////////////////////
/** caches the child executions by execution name. This member might be
* null and is only created from the executions in case its needed. Note
* that not all executions are forced to have a name and duplicates are allowed.
* In case the {@link #executions} change, the executionsMap can be nulled or
* also updated (but a check needs to be added whether it exists). */
protected transient Map<String, Execution> executionsMap = null;
/** the queue of atomic operations to be performed for this execution. */
protected Queue<AtomicOperation> atomicOperations;
public enum Propagation {
UNSPECIFIED, WAIT, EXPLICIT
}
protected Propagation propagation = null;
// construction /////////////////////////////////////////////////////////////
public void initializeProcessInstance(ProcessDefinitionImpl processDefinition, String key) {
setProcessDefinition(processDefinition);
setActivity ( (ActivityImpl) processDefinition.getInitial() );
this.processInstance = this;
this.state = STATE_CREATED;
this.key = key;
save();
composeIds();
HistoryEvent.fire(new ProcessInstanceCreate(), this);
}
protected void save() {
this.dbid = DbidGenerator.getDbidGenerator().getNextId();
DbSession dbSession = EnvironmentImpl.getFromCurrent(DbSession.class, false);
if (dbSession!=null) {
dbSession.save(this);
}
}
protected void composeIds() {
this.id = IdComposer.getIdComposer().createId(processDefinition, parent, this);
}
// execution method : start /////////////////////////////////////////////////
public