/*
* 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.db;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.jbpm.JbpmException;
import org.jbpm.command.ChangeProcessInstanceVersionCommand;
import org.jbpm.graph.action.Script;
import org.jbpm.graph.def.Action;
import org.jbpm.graph.def.GraphElement;
import org.jbpm.graph.def.Node;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.ProcessInstanceExpedient;
import org.jbpm.graph.exe.Token;
import org.jbpm.graph.log.ActionLog;
import org.jbpm.graph.log.SignalLog;
import org.jbpm.graph.log.TransitionLog;
import org.jbpm.graph.node.ProcessState;
import org.jbpm.instantiation.Delegation;
import org.jbpm.job.Job;
import org.jbpm.logging.log.CompositeLog;
import org.jbpm.logging.log.ProcessLog;
import org.jbpm.scheduler.def.CancelTimerAction;
import org.jbpm.scheduler.def.CreateTimerAction;
import org.jbpm.taskmgmt.def.Task;
import org.jbpm.taskmgmt.def.TaskController;
import org.jbpm.taskmgmt.def.TaskMgmtDefinition;
import org.jbpm.taskmgmt.exe.TaskInstance;
/**
* are the graph related database operations.
*/
@SuppressWarnings({ "deprecation", "unchecked", "rawtypes" })
public class GraphSession {
public static Map<Long, Set<ProcessInstanceExpedient>> errorsDelete = new HashMap<Long, Set<ProcessInstanceExpedient>>();
JbpmSession jbpmSession = null;
Session session = null;
public GraphSession(JbpmSession jbpmSession) {
this.jbpmSession = jbpmSession;
this.session = jbpmSession.getSession();
}
public GraphSession(Session session) {
this.session = session;
this.jbpmSession = new JbpmSession(session);
}
// process definitions
// //////////////////////////////////////////////////////
public void deployProcessDefinition(ProcessDefinition processDefinition) {
String processDefinitionName = processDefinition.getName();
// if the process definition has a name (process versioning only applies
// to named process definitions)
if (processDefinitionName != null) {
// find the current latest process definition
ProcessDefinition previousLatestVersion = findLatestProcessDefinition(processDefinitionName);
// if there is a current latest process definition
if (previousLatestVersion != null) {
// take the next version number
processDefinition.setVersion(previousLatestVersion.getVersion() + 1);
} else {
// start from 1
processDefinition.setVersion(1);
}
session.save(processDefinition);
} else {
throw new JbpmException("process definition does not have a name");
}
}
/**
* saves the process definitions. this method does not assign a version number. that is the responsibility of the
* {@link #deployProcessDefinition(ProcessDefinition)
* deployProcessDefinition} method.
*/
public void saveProcessDefinition(ProcessDefinition processDefinition) {
try {
session.save(processDefinition);
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't save process definition '" + processDefinition + "'", e);
}
}
/**
* loads a process definition from the database by the identifier.
*
* @throws JbpmException
* in case the referenced process definition doesn't exist.
*/
public ProcessDefinition loadProcessDefinition(long processDefinitionId) {
try {
return (ProcessDefinition) session.load(ProcessDefinition.class, new Long(processDefinitionId));
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't load process definition '" + processDefinitionId + "'", e);
}
}
/**
* gets a process definition from the database by the identifier.
*
* @return the referenced process definition or null in case it doesn't
* exist.
*/
public ProcessDefinition getProcessDefinition(long processDefinitionId) {
try {
return (ProcessDefinition) session.get(ProcessDefinition.class, new Long(processDefinitionId));
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't get process definition '" + processDefinitionId + "'", e);
}
}
/**
* queries the database for a process definition with the given name and
* version.
*/
public ProcessDefinition findProcessDefinition(String name, int version) {
ProcessDefinition processDefinition = null;
try {
Query query = session.getNamedQuery("GraphSession.findProcessDefinitionByNameAndVersion");
query.setString("name", name);
query.setInteger("version", version);
processDefinition = (ProcessDefinition) query.uniqueResult();
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException(
"couldn't get process definition with name '" + name + "' and version '" + version + "'", e);
}
return processDefinition;
}
/**
* queries the database for the latest version of a process definition with
* the given name.
*/
public ProcessDefinition findLatestProcessDefinition(String name) {
ProcessDefinition processDefinition = null;
try {
Query query = session.getNamedQuery("GraphSession.findLatestProcessDefinitionQuery");
query.setString("name", name);
query.setMaxResults(1);
processDefinition = (ProcessDefinition) query.uniqueResult();
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't find process definition '" + name + "'", e);
}
return processDefinition;
}
/**
* queries the database for the latest version of each process definition.
* Process definitions are distinct by name.
*/
public List findLatestProcessDefinitions() {
List processDefinitions = new ArrayList();
Map processDefinitionsByName = new HashMap();
try {
Query query = session.getNamedQuery("GraphSession.findAllProcessDefinitions");
Iterator iter = query.list().iterator();
while (iter.hasNext()) {
ProcessDefinition processDefinition = (ProcessDefinition) iter.next();
String processDefinitionName = processDefinition.getName();
ProcessDefinition previous = (ProcessDefinition) processDefinitionsByName.get(processDefinitionName);
if ((previous == null) || (previous.getVersion() < processDefinition.getVersion())) {
processDefinitionsByName.put(processDefinitionName, processDefinition);
}
}
processDefinitions = new ArrayList(processDefinitionsByName.values());
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't find latest versions of process definitions", e);
}
return processDefinitions;
}
/**
* queries the database for all process definitions, ordered by name
* (ascending), then by version (descending).
*/
public List findAllProcessDefinitions() {
try {
Query query = session.getNamedQuery("GraphSession.findAllProcessDefinitions");
return query.list();
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't find all process definitions", e);
}
}
/**
* queries the database for all versions of process definitions with the
* given name, ordered by version (descending).
*/
public List findAllProcessDefinitionVersions(String name) {
try {
Query query = session.getNamedQuery("GraphSession.findAllProcessDefinitionVersions");
query.setString("name", name);
return query.list();
} catch (HibernateException e) {
log.error(e);
throw new JbpmException("couldn't find all versions of process definition '" + name + "'", e);
}
}
public void deleteProcessDefinition(long processDefinitionId) {
deleteProcessDefinition(loadProcessDefinition(processDefinitionId));
}
public void deleteProcessDefinition(ProcessDefinition processDefinition) {
if (processDefinition == null) {
throw new JbpmException("processDefinition is null");
}
Set<ProcessInstanceExpedient> expedientsError = new HashSet<ProcessInstanceExpedient>();
try {
// delete all the process instances of this definition
for (ProcessInstance processInstance; ((processInstance = findNextProcessInstance(processDefinition)) != null);) {
deleteProcessInstance(processInstance);
}
// CODI DE LA FUNCIONALITAT DE BORRAT DE DEFINICIONS DE PROCÉS -- Inici
// INICI MODIFICACIONS per a poder eliminar DefProc que han tingut expedients ------------------------------------------------
// Canviam tasques "orfes", encara referenciades per la definició de procés antiga
log.debug(" - Eliminam la definició de procés " + processDefinition.getName() + "(" + processDefinition.getId() + ")");
log.debug(" |- Modificam els TaskInstances relacionats amb la definició de procés antiga:");
// Set<TaskMgmtDefinition> tmdBorrar = new HashSet<TaskMgmtDefinition>();
for (TaskInstance ti : findReferencedDPTaskInstances(processDefinition.getId())) {
log.debug(" ||- TasckInstance: " + ti.getName() + "(" + ti.getId() + ")");
Task oldTask = ti.getTask();
Node oldNode = oldTask.getTaskNode();
Task newTask = findReplacementTask(ti.getProcessInstance().getProcessDefinition(), oldNode, oldTask);
log.debug(" |||- Actualitzam Task:");
log.debug(" ||||- Task antiga: " + oldTask.getName() + "(" + oldTask.getId() + ")");
if (newTask != null) {
log.debug(" ||||- Task nova: " + newTask.getName() + "(" + newTask.getId() + ")");
ti.setTask(newTask);
session.save(ti);
// Task Managment
TaskMgmtDefinition newTmd = newTask.getTaskMgmtDefinition();
TaskMgmtDefinition oldTmd = ti.getTaskMgmtInstance().getTaskMgmtDefinition();
if (oldTmd.getProcessDefinition().equals(processDefinition)) {
log.debug(" |||- Actualitzam TaskMgmtDefinition del TaskMgmtinstance:");
log.debug(" ||||- TaskMgmtDefinition Antiga: " + newTmd.getName() + "(" + newTmd.getId() + ")");
log.debug(" ||||- TaskMgmtDefinition Nova: " + oldTmd.getName() + "(" + oldTmd.getId() + ")");
ti.getTaskMgmtInstance().setTaskMgmtDefinition(newTmd);
session.save(ti.getTaskMgmtInstance());
// tmdBorrar.add(oldTmd);
}
} else {
log.debug(" ||||- Task nova: NO S'HA TROBAT AQUESTA TASCA EN LA NOVA DEFINICIÓ DE PROCÉS.");
// errors.add(new Object[]{
// DeleteErrorType.TASK,
// ti.getProcessInstance().getExpedient(),
// ti.getName(),
// ti.getId()});
// errorsDelete.put(processDefinition.getId(), errors);
expedientsError.add(ti.getProcessInstance().getExpedient());
errorsDelete.put(processDefinition.getId(), expedientsError);
throw new JbpmException("S'han torbat tasques lligades a la definició de procés, que no tenen un substitut en la definició de procés del seu expedient.");
}
log.debug(" ||| ");
log.debug(" || ");
log.debug(" | ");
}
// Canviam el processDefinition dels tasksMgmtInstance dels tasksInstance de la versió que s'intenta esborrar a la de la tasca.
log.debug(" |- Modificam els TaskMgmtDefinition:");
for (TaskInstance ti : findReferencedTaskInstances(processDefinition.getId())) {
log.debug(" ||- TasckInstance: " + ti.getName() + "(" + ti.getId() + ")");
TaskMgmtDefinition oldTmd = ti.getTaskMgmtInstance().getTaskMgmtDefinition();
TaskMgmtDefinition newTmd = ti.getProcessInstance().getProcessDefinition().getTaskMgmtDefinition();
if (oldTmd.getProcessDefinition().equals(processDefinition)) {
log.debug(" |||- TaskMgmtDefinition Antiga: " + oldTmd.getName() + "(" + oldTmd.getId() + ")");
log.debug(" |||- TaskMgmtDefinition Nova: " + newTmd.getName() + "(" + newTmd.getId() + ")");
ti.getTaskMgmtInstance().setTaskMgmtDefinition(newTmd);
session.save(ti.getTaskMgmtInstance());
// tmdBorrar.add(oldTmd);
}
// tmd.setProcessDefinition(ti.getProcessInstance().getProcessDefinition());
// if (tmd.getStartTask() != null) {
// tmd.setStartTask(ti.getProcessInstance().getProcessDefinition().getTaskMgmtDefinition().getStartTask());
// }
// session.save(tmd);
log.debug(" || ");
}
log.debug(" | ");
// // Eliminam les StartStates que referencien la DefProc antiga
// for (Task task: findReferencingStartStates(processDefinition.getId())) {
// task.setStartState(null);
// session.save(task);
// }
// for (Iterator iter = processDefinition.getNodes().iterator(); iter.hasNext();) {
// Node node = (Node)iter.next();
// if (node instanceof TaskNode)
// iter.remove();
// }
List<Long> taskIds = new ArrayList<Long>();
log.debug(" |- Dereferenciam les tasques:");
for (Task task: findReferencedTask(processDefinition.getId())) {
log.debug(" ||- " + task.getName() + "(" + task.getId() + ")");
taskIds.add(task.getId());
task.setStartState(null);
task.setAssignmentDelegation(null);
task.setTaskController(null);
task.setProcessDefinition(null);
session.save(task);
// session.delete(task);
}
log.debug(" | ");
session.flush();
// Eliminam les delegacions
// for (Task task : findReferencingDelegatingTasks(processDefinition.getId())) {
// task.setAssignmentDelegation(null);
// session.save(task);
//// session.flush();
// }
log.debug(" |- Dereferenciam els jobs:");
for (Job job : findReferencedJobs(processDefinition.getId())) {
log.debug(" ||- " + job.getId());
Action oldAction = (Action)job.getClass().getMethod("getAction").invoke(job);
Action newAction = job.getProcessInstance().getProcessDefinition().getAction(oldAction.getName());
if (newAction != null) {
job.getClass().getMethod("setAction", Action.class).invoke(job, newAction);
session.save(job);
} else {
if (job.getRetries() <= 0) {
session.delete(job);
} else {
// errors.add(new Object[]{
// DeleteErrorType.JOB,
// job.getProcessInstance().getExpedient(),
// oldAction.toString(),
// oldAction.getId(),
// job.getId()});
// errorsDelete.put(processDefinition.getId(), errors);
expedientsError.add(job.getProcessInstance().getExpedient());
errorsDelete.put(processDefinition.getId(), expedientsError);
// throw new JbpmException("S'han torbat jobs lligades a la definició de procés, que no tenen una acció substituta en la definició de procés del seu expedient.");
}
}
// session.delete(action);
// session.flush();
}
log.debug(" | ");
log.debug(" |- Dereferenciam les accions:");
//for (Action action : findReferencingDelegatingActions(processDefinition.getId())) {
List<Action> accions = findReferencedActions(processDefinition.getId());
for (Action action : accions) {
action.setActionDelegation(null);
session.save(action);
// session.delete(action);
// session.flush();
log.debug(" ||- " + action.getName() + "(" + action.getId() + ")");
}
log.debug(" | ");
log.debug(" |- Dereferenciam les accions del logs:");
// if (!processDefinition.getEvents().isEmpty()) {
//for (ActionLog al : findReferencingEventActions(processDefinition)) {
// Mapa de reemplaç de accions
Map<Long, Action> reAccions = new HashMap<Long, Action>();
for (ActionLog al : findReferencedActionLogs(accions)) {
log.debug(" ||- Log: " + al.getId() + ", Action: " + al.getAction().getId());
ProcessDefinition newProcessDefinition = al.getToken().getProcessInstance().getProcessDefinition();
Action oldAction = al.getAction();
Action newAction = null;
if (reAccions.containsKey(oldAction.getId())) {
newAction = reAccions.get(oldAction.getId());
} else {
newAction = findReplacementEventAction(oldAction, newProcessDefinition);
reAccions.put(oldAction.getId(), newAction);
}
if (newAction != null) {
al.setAction(newAction);
} else {
log.debug(" |||- No s'ha trobat substitut per aquesta acció");
// errors.add(new Object[]{
// DeleteErrorType.ACTION,
// al.getToken().getProcessInstance().getExpedient(),
// oldAction.toString(),
// oldAction.getId(),
// al.getId()});
// errorsDelete.put(processDefinition.getId(), errors);
expedientsError.add(al.getToken().getProcessInstance().getExpedient());
errorsDelete.put(processDefinition.getId(), expedientsError);
}
}
// }
log.debug(" | ");
log.debug(" |- Dereferenciam les transicions dels logs:");
// Mapa de reemplaç de transicions
Map<Long, Transition> reTransicions = new HashMap<Long, Transition>();
List<CompositeLog> logs = findReferencedTransitionLogs(processDefinition.getId());
for (CompositeLog cl : logs) {
TransitionLog tl = null;
SignalLog sl = null;
Transition oldTransition = null;
if (cl instanceof TransitionLog) {
tl = (TransitionLog)cl;
oldTransition = tl.getTransition();
} else {
sl = (SignalLog)cl;
oldTransition = sl.getTransition();
}
log.debug(" ||- Log: " + cl.getId() + ", Transition: " + oldTransition.getId());
ProcessDefinition newProcessDefinition = cl.getToken().getProcessInstance().getProcessDefinition();
Transition newTransition = null;
if (reTransicions.containsKey(oldTransition.getId())) {
newTransition = reTransicions.get(oldTransition.getId());
} else {
newTransition = findReplacementTransition(newProcessDefinition, oldTransition);
reTransicions.put(oldTransition.getId(), newTransition);
}
if (newTransition != null) {
if (tl != null) {
tl.setTransition(newTransition);
tl.setSourceNode(newTransition.getFrom());
tl.setDestinationNode(newTransition.getTo());
} else {
sl.setTransition(newTransition);
}
} else {
log.debug(" |||- No s'ha trobat substitut per aquesta transició");
// errors.add(new Object[]{
// DeleteErrorType.TRANSITION,
// tl.getToken().getProcessInstance().getExpedient(),
// oldTransition.toString(),
// oldTransition.getId(),
// tl.getId()});
// errorsDelete.put(processDefinition.getId(), errors);
expedientsError.add(cl.getToken().getProcessInstance().getExpedient());
errorsDelete.put(processDefinition.getId(), expedientsError);
}
}
log.debug(" | ");
log.debug(" |- Eliminam els taskControllers:");
for (TaskController tc : findReferencedTaskController(processDefinition.getId())) {
// tc.setTaskControllerDelegation(null);
// session.save(tc);
log.debug(" ||- " + tc.getId());
session.delete(tc);
// session.flush();
}
log.debug(" | ");
session.flush();
log.debug(" |- Eliminam les delegacions:");
for (Delegation delegation : findReferencedDelegations(processDefinition.getId())) {
log.debug(" ||- " + delegation.getId());
session.delete(delegation);
session.flush();
}
log.debug(" | ");
// ---------------------------------------------------------------------------------------------------------------------------
// CODI DE LA FUNCIONALITAT DE BORRAT DE DEFINICIONS DE PROCÉS -- Fi
// Eliminam els StartStates de les tasques de la definició de procés a esborrar
List referencingProcessStates = findReferencingProcessStates(processDefinition);
for (Iterator iter = referencingProcessStates.iterator(); iter.hasNext();) {
ProcessState processState = (ProcessState) iter.next();
processState.setSubProcessDefinition(null);
}
// CODI DE LA FUNCIONALITAT DE BORRAT DE DEFINICIONS DE PROCÉS -- Inici
session.flush();
// CODI DE LA FUNCIONALITAT DE BORRAT DE DEFINICIONS DE PROCÉS -- Fi
// then delete the process definition
session.delete(processDefinition);
// CODI DE LA FUNCIONALITAT DE BORRAT DE DEFINICIONS DE PROCÉS -- Inici
// ---------------------------------------------------------------------------------------------------------------------------
// Eliminam les tasques que hagin quedat orfes
log.debug(" |- Eliminam les tasques");
log.debug(" ||- " + taskIds.toString());
session.createQuery(
"delete from org.jbpm.taskmgmt.def.Task t "
+ " where t.id in :taskIds")
.setParameterList("taskIds", taskIds)
.executeUpdate();
log.debug(" | ");
// log.debug(" |- Eliminam els taskMgmtDefinition:");
// for (TaskMgmtDefinition tmd: tmdBorrar)
// session.delete(tmd);
// log.debug(" | ");
// FI MODIFICACIONS per a poder eliminar DefProc que han tingut expedients ---------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------------
// CODI DE LA FUNCIONALITAT DE BORRAT DE DEFINICIONS DE PROCÉS -- Fi
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
for (ProcessInstanceExpedient expedient: expedientsError) {
expedient.getIdentificador();
// expedient.getId();
}
throw new JbpmException("couldn't delete process definition '" + processDefinition.getId() + "'", e);
}
}
protected ProcessInstance findNextProcessInstance(ProcessDefinition processDefinition) {
return (ProcessInstance) session.createCriteria(ProcessInstance.class)
.add(Restrictions.eq("processDefinition", processDefinition)).setMaxResults(1).uniqueResult();
}
protected List findReferencingProcessStates(ProcessDefinition subProcessDefinition) {
Query query = session.getNamedQuery("GraphSession.findReferencingProcessStates");
query.setEntity("subProcessDefinition", subProcessDefinition);
return query.list();
}
// CODI DE LA FUNCIONALITAT DE BORRAT DE DEFINICIONS DE PROCÉS -- Inici
protected List<Task> findReferencedTask(Long processDefinitionId) {
Query q = session.createQuery(
"from org.jbpm.taskmgmt.def.Task t "
+ "where t.processDefinition.id = :processDefinitionId");
q.setLong("processDefinitionId", processDefinitionId);
return (List<Task>)q.list();
}
protected List<TaskInstance> findReferencedTaskInstances(Long processDefinitionId) {
Query q = session.createQuery(
"from org.jbpm.taskmgmt.exe.TaskInstance ti "
+ "where ti.taskMgmtInstance.taskMgmtDefinition.processDefinition.id = :processDefinitionId ");
q.setLong("processDefinitionId", processDefinitionId);
return (List<TaskInstance>)q.list();
}
protected List<TaskInstance> findReferencedDPTaskInstances(Long processDefinitionId) {
Query q = session.createQuery(
"from org.jbpm.taskmgmt.exe.TaskInstance ti "
+ "where ti.task.processDefinition.id = :processDefinitionId ");
q.setLong("processDefinitionId", processDefinitionId);
return (List<TaskInstance>)q.list();
}
protected List<Task> findReferencingStartStates(Long processDefinitionId) {
Query query = session.createQuery(
" from org.jbpm.taskmgmt.def.Task t "
+ "where t.processDefinition.id = :processDefinitionId "
+ " and t.startState is not null");
query.setLong("processDefinitionId", processDefinitionId);
return (List<Task>)query.list();
}
// protected List<Task> findReferencingDelegatingTasks(Long processDefinitionId) {
// Query query = session.createQuery(
// " from org.jbpm.taskmgmt.def.Task t "
// + "where t.processDefinition.id = :processDefinitionId "
// + " and t.assignmentDelegation is not null");
// query.setLong("processDefinitionId", processDefinitionId);
// return (List<Task>)query.list();
// }
protected List<Job> findReferencedJobs(Long processDefinitionId) {
List<Job> jobs = new ArrayList<Job>();
Query q = session.createQuery(
"from org.jbpm.job.Timer t "
+ "where t.action.processDefinition.id = :processDefinitionId ");
q.setLong("processDefinitionId", processDefinitionId);
jobs.addAll(q.list());
q = session.createQuery(
"from org.jbpm.job.ExecuteActionJob ea "
+ "where ea.action.processDefinition.id = :processDefinitionId ");
q.setLong("processDefinitionId", processDefinitionId);
jobs.addAll(q.list());
return jobs;
}
protected List<Action> findReferencedActions(Long processDefinitionId) {
List<Action> referencedActions = null;
// Action -> ActionDelegation -> ProcessDefinition
Query query = session.createQuery(
" select a "
+ " from org.jbpm.graph.def.Action a, "
+ " org.jbpm.instantiation.Delegation d "
+ "where d.processDefinition.id = :processDefinitionId "
+ " and a.actionDelegation.id = d.id");
query.setLong("processDefinitionId", processDefinitionId);
referencedActions = (List<Action>)query.list();
// Action -> Event -> Transition / Node -> ProcessDefinition
// query = session.createQuery(
// " select a "
// + " from org.jbpm.graph.def.Action a "
// + "where a.event.graphElement.processDefinition.id = :processDefinitionId");
//query.setLong("processDefinitionId", processDefinitionId);
query = session.createSQLQuery(
"select a.* "
+ " from jbpm_action a, "
+ " jbpm_event e, "
+ " jbpm_task t"
+ " where a.EVENT_ = e.ID_ "
+ " and e.TYPE_ = 'A' "
+ " and e.GRAPHELEMENT_ = t.ID_ "
+ " and t.PROCESSDEFINITION_ = :processDefinitionId")
.addEntity(Action.class)
.setLong("processDefinitionId", processDefinitionId);
referencedActions.addAll((List<Action>)query.list());
query = session.createSQLQuery(
"select a.* "
+ " from jbpm_action a, "
+ " jbpm_event e, "
+ " jbpm_transition t"
+ " where a.EVENT_ = e.ID_ "
+ " and e.TYPE_ = 'T' "
+ " and e.GRAPHELEMENT_ = t.ID_ "
+ " and t.PROCESSDEFINITION_ = :processDefinitionId")
.addEntity(Action.class)
.setLong("processDefinitionId", processDefinitionId);
referencedActions.addAll((List<Action>)query.list());
query = session.createSQLQuery(
"select a.* "
+ " from jbpm_action a, "
+ " jbpm_event e "
// + " jbpm_processDefinition p"
+ " where a.EVENT_ = e.ID_ "
+ " and e.TYPE_ = 'P' "
// + " and e.GRAPHELEMENT_ = t.ID_ "
+ " and e.PROCESSDEFINITION_ = :processDefinitionId")
.addEntity(Action.class)
.setLong("processDefinitionId", processDefinitionId);
referencedActions.addAll((List<Action>)query.list());
query = session.createSQLQuery(
"select a.* "
+ " from jbpm_action a, "
+ " jbpm_event e, "
+ " jbpm_node n "
+ " where a.EVENT_ = e.ID_"
+ " and e.TYPE_ not in ('A', 'T', 'P') "
+ " and e.GRAPHELEMENT_ = n.ID_ "
+ " and n.PROCESSDEFINITION_ = :processDefinitionId")
.addEntity(Action.class)
.setLong("processDefinitionId", processDefinitionId);
referencedActions.addAll((List<Action>)query.list());
return referencedActions;
}
protected List<Action> findReferencingDelegatingActions(Long processDefinitionId) {
Query query = session.createQuery(
" select a "
+ " from org.jbpm.graph.def.Action a, "
+ " org.jbpm.instantiation.Delegation d "
+ "where d.processDefinition.id = :processDefinitionId "
+ " and a.actionDelegation.id = d.id");
query.setLong("processDefinitionId", processDefinitionId);
return (List<Action>)query.list();
}
// protected List<ActionLog> findReferencingEventActions(ProcessDefinition processDefinition) {
// Query query = session.createQuery(
// " select al "
// + " from org.jbpm.graph.log.ActionLog al "
// + "where al.action in ("
// + " select a "
// + " from org.jbpm.graph.def.Action a "
// + " where a.event in :events)");
// query.setParameterList("events", processDefinition.getEvents().values());
// return (List<ActionLog>)query.list();
// }
protected List<ActionLog> findReferencedActionLogs(List<Action> accions) {
Query query = session.createQuery(
" select al "
+ " from org.jbpm.graph.log.ActionLog al "
+ "where al.action in (:accions)");
query.setParameterList("accions", accions);
return (List<ActionLog>)query.list();
}
private Action findReplacementEventAction(Action oldAction, ProcessDefinition newProcessDefinition) {
// Query query = session.createQuery(
// " from org.jbpm.scheduler.def.CreateTimerAction ta "
// + "where ta.timerName = :timerName "
// + " and ta.event.graphElement.name = :nodeName "
// + " and ta.event.graphElement.processDefinition.id = :processDefinitionId)");
// query.setLong("processDefinitionId", newProcessDefinition.getId());
// List<Action> accions = (List<Action>)query.list();
// return accions.isEmpty() ? null : accions.get(0);
Boolean evalCreateTimer = false;
Boolean evalCancelTimer = false;
Boolean evalScript = false;
CreateTimerAction oldCreateTimer = null;
CancelTimerAction oldCancelTimer = null;
Script oldScript = null;
if (oldAction instanceof CreateTimerAction) {
oldCreateTimer = (CreateTimerAction)oldAction;
evalCreateTimer = oldCreateTimer.getTimerName() != null && !oldCreateTimer.getTimerName().isEmpty();
} else if (oldAction instanceof CancelTimerAction) {
oldCancelTimer = (CancelTimerAction)oldAction;
evalCancelTimer = oldCancelTimer.getTimerName() != null && !oldCancelTimer.getTimerName().isEmpty();
} else if (oldAction instanceof Script) {
oldScript = (Script)oldAction;
evalScript = oldScript.getExpression() != null && !oldScript.getExpression().isEmpty();
}
List<Action> novesAccions = findReferencedActions(newProcessDefinition.getId());
for (Action novaAccio: novesAccions) {
if (oldAction.getName() != null && !oldAction.getName().isEmpty()) {
if (oldAction.getName().equals(novaAccio.getName()))
return novaAccio;
} else {
if (evalCreateTimer) {
if (novaAccio instanceof CreateTimerAction) {
CreateTimerAction ncta = (CreateTimerAction)novaAccio;
if (oldCreateTimer.getTimerName().equals(ncta.getTimerName()))
return novaAccio;
}
} else if (evalCancelTimer) {
if (novaAccio instanceof CancelTimerAction) {
CancelTimerAction ncta = (CancelTimerAction)novaAccio;
if (oldCancelTimer.getTimerName().equals(ncta.getTimerName()))
return novaAccio;
}
} else if (evalScript) {
if (novaAccio instanceof Script) {
Script ns = (Script)novaAccio;
if (oldScript.getExpression().equals(ns.getExpression()))
return novaAccio;
}
}
}
}
// String nom = oldCreateTimer != null ? oldCreateTimer.getTimerName() :
// oldCancelTimer != null ? oldCancelTimer.getTimerName() :
// oldScript != null ? oldScript.getExpression() : oldAction.getName();
// throw new JbpmException("Action ='" + nom + "' (" + oldAction.getId() + ")" + " not found in new process definition");
return null;
}
protected List<TaskController> findReferencedTaskController(Long processDefinitionId) {
Query query = session.createQuery(
" select tc "
+ " from org.jbpm.taskmgmt.def.TaskController tc, "
+ " org.jbpm.instantiation.Delegation d "
+ "where d.processDefinition.id = :processDefinitionId "
+ " and tc.taskControllerDelegation.id = d.id");
query.setLong("processDefinitionId", processDefinitionId);
return (List<TaskController>)query.list();
}
// protected List<Task> findReferencingTaskControllerTasks(Long processDefinitionId, List<TaskController> taskControllers) {
// Query query = session.createQuery(
// " from org.jbpm.taskmgmt.def.Task t "
// + "where t.processDefinition.id = :processDefinitionId "
// + " and t.taskController in :taskController");
// query.setLong("processDefinitionId", processDefinitionId);
// query.setParameterList("taskControllers", taskControllers);
// return (List<Task>)query.list();
// }
protected List<Delegation> findReferencedDelegations(Long processDefinitionId) {
Query query = session.createQuery(
" from org.jbpm.instantiation.Delegation d "
+ "where d.processDefinition.id = :processDefinitionId");
query.setLong("processDefinitionId", processDefinitionId);
return (List<Delegation>)query.list();
}
protected List<CompositeLog> findReferencedTransitionLogs(Long processDefinitionId) {
// Query query = session.createSQLQuery(
// "select l.* "
// + " from jbpm_log l, "
// + " jbpm_transition t "
// + " where l.TRANSITION_ = t.ID_ "
// + " and t.PROCESSDEFINITION_ = :processDefinitionId")
// .addEntity(TransitionLog.class)
List<CompositeLog> logs = null;
Query query = session.createQuery(
"select tl " +
" from org.jbpm.graph.log.TransitionLog as tl " +
" where tl.transition.processDefinition.id = :processDefinitionId")
.setLong("processDefinitionId", processDefinitionId);
logs = (List<CompositeLog>)query.list();
query = session.createQuery(
"select sl " +
" from org.jbpm.graph.log.SignalLog as sl " +
" where sl.transition.processDefinition.id = :processDefinitionId")
.setLong("processDefinitionId", processDefinitionId);
logs.addAll((List<CompositeLog>)query.list());
return logs;
}
private Transition findReplacementTransition(ProcessDefinition newDef, Transition oldTransition) {
Transition newTransition = null;
Node newNodeFrom = findReplacementNode(newDef, oldTransition.getFrom());
if (newNodeFrom != null) {
Node newNodeTo = findReplacementNode(newDef, oldTransition.getTo());
if (newNodeTo != null) {
Query q = session.createQuery(
"from org.jbpm.graph.def.Transition t "
+ "where t.from = :nodeFrom "
+ " and t.to = :nodeTo");
q.setEntity("nodeFrom", newNodeFrom);
q.setEntity("nodeTo", newNodeTo);
List<Transition> transicions = (List<Transition>)q.list();
if (!transicions.isEmpty()) {
if (transicions.size() == 1)
newTransition = transicions.get(0);
else {
for (Transition t: transicions) {
if (oldTransition.getName() == null) {
if (t.getName() == null)
newTransition = t;
} else if (t.getName() != null && t.getName().equals(oldTransition.getName())) {
newTransition = t;
break;
}
}
}
}
}
}
return newTransition;
}
private Task findReplacementTask(ProcessDefinition newDef, Node oldNode, Task oldTask) {
Task newTask = null;
String replacementTaskName = oldTask.getName();
Node newTaskNode = findReplacementNode(newDef, oldNode);
if (newTaskNode != null) {
Query q = session.getNamedQuery("TaskMgmtSession.findTaskForNode");
q.setString("taskName", replacementTaskName);
q.setLong("taskNodeId", newTaskNode.getId());
newTask = (Task) q.uniqueResult();
}
return newTask;
}
private Node findReplacementNode(ProcessDefinition newDef, GraphElement oldNode) {
String name = getReplacementNodeName(oldNode);
log.debug("get replacement for node with name '" + name + "'");
// Node newNode = newDef.findNode(name);
Node newNode = ChangeProcessInstanceVersionCommand.findNode(newDef, name);
return newNode;
}
private String getReplacementNodeName(GraphElement oldNode) {
return (oldNode instanceof Node ? ((Node) oldNode).getFullyQualifiedName() : oldNode.getName());
}
// CODI DE LA FUNCIONALITAT DE BORRAT DE DEFINICIONS DE PROCÉS -- Fi
// process instances
// ////////////////////////////////////////////////////////
/**
* @deprecated use {@link org.jbpm.JbpmContext#save(ProcessInstance)}
* instead.
* @throws UnsupportedOperationException
*/
public void saveProcessInstance(ProcessInstance processInstance) {
throw new UnsupportedOperationException("use JbpmContext.save(ProcessInstance) instead");
}
/**
* loads a process instance from the database by the identifier. This throws
* an exception in case the process instance doesn't exist.
*
* @see #getProcessInstance(long)
* @throws JbpmException
* in case the process instance doesn't exist.
*/
public ProcessInstance loadProcessInstance(long processInstanceId) {
try {
ProcessInstance processInstance = (ProcessInstance) session.load(ProcessInstance.class,
new Long(processInstanceId));
return processInstance;
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't load process instance '" + processInstanceId + "'", e);
}
}
/**
* gets a process instance from the database by the identifier. This method
* returns null in case the given process instance doesn't exist.
*/
public ProcessInstance getProcessInstance(long processInstanceId) {
try {
ProcessInstance processInstance = (ProcessInstance) session.get(ProcessInstance.class,
new Long(processInstanceId));
return processInstance;
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't get process instance '" + processInstanceId + "'", e);
}
}
/**
* loads a token from the database by the identifier.
*
* @return the token.
* @throws JbpmException
* in case the referenced token doesn't exist.
*/
public Token loadToken(long tokenId) {
try {
Token token = (Token) session.load(Token.class, new Long(tokenId));
return token;
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't load token '" + tokenId + "'", e);
}
}
/**
* gets a token from the database by the identifier.
*
* @return the token or null in case the token doesn't exist.
*/
public Token getToken(long tokenId) {
try {
Token token = (Token) session.get(Token.class, new Long(tokenId));
return token;
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't get token '" + tokenId + "'", e);
}
}
/**
* locks a process instance in the database.
*/
public void lockProcessInstance(long processInstanceId) {
lockProcessInstance(loadProcessInstance(processInstanceId));
}
/**
* locks a process instance in the database.
*/
public void lockProcessInstance(ProcessInstance processInstance) {
try {
session.lock(processInstance, LockMode.UPGRADE);
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't lock process instance '" + processInstance.getId() + "'", e);
}
}
/**
* fetches all processInstances for the given process definition from the
* database. The returned list of process instances is sorted start date,
* youngest first.
*/
public List findProcessInstances(long processDefinitionId) {
List processInstances = null;
try {
Query query = session.getNamedQuery("GraphSession.findAllProcessInstancesForADefinition");
query.setLong("processDefinitionId", processDefinitionId);
processInstances = query.list();
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException(
"couldn't load process instances for process definition '" + processDefinitionId + "'", e);
}
return processInstances;
}
public void deleteProcessInstance(long processInstanceId) {
deleteProcessInstance(loadProcessInstance(processInstanceId));
}
public void deleteProcessInstance(ProcessInstance processInstance) {
deleteProcessInstance(processInstance, true, true);
}
public void deleteProcessInstance(ProcessInstance processInstance, boolean includeTasks, boolean includeJobs) {
if (processInstance == null)
throw new JbpmException("processInstance is null in JbpmSession.deleteProcessInstance()");
log.debug("deleting process instance " + processInstance.getId());
try {
// jobs
if (includeJobs) {
log.debug("deleting jobs for process instance " + processInstance.getId());
Query query = session.getNamedQuery("GraphSession.deleteJobsForProcessInstance");
query.setEntity("processInstance", processInstance);
query.executeUpdate();
}
// tasks
if (includeTasks) {
Query query = session.getNamedQuery("GraphSession.findTaskInstanceIdsForProcessInstance");
query.setEntity("processInstance", processInstance);
List taskInstanceIds = query.list();
if ((taskInstanceIds != null) && (!taskInstanceIds.isEmpty())) {
log.debug("deleting tasks " + taskInstanceIds + " for process instance " + processInstance.getId());
query = session.getNamedQuery("GraphSession.deleteTaskInstancesById");
query.setParameterList("taskInstanceIds", taskInstanceIds);
}
}
// delete the logs
log.debug("deleting logs for process instance " + processInstance.getId());
deleteLogs(processInstance);
List<Token> tokens = new ArrayList<Token>();
Query qTok = session
.createQuery("select token from org.jbpm.graph.exe.Token token where token.processInstance.id=?")
.setLong(0, processInstance.getId());
tokens.addAll(qTok.list());
// delete the tokens and subprocess instances
log.debug("deleting subprocesses for process instance " + processInstance.getId());
deleteSubProcesses(processInstance.getRootToken());
// null out the parent process token
Token superProcessToken = processInstance.getSuperProcessToken();
if (superProcessToken != null) {
log.debug("nulling property subProcessInstance in superProcessToken " + superProcessToken.getId()
+ " which is referencing the process instance " + processInstance.getId()
+ " which is being deleted");
superProcessToken.setSubProcessInstance(null);
}
for (Token token : tokens) {
token.setProcessInstance(null);
session.delete(token);
}
// add the process instance
log.debug("hibernate session delete for process instance " + processInstance.getId());
session.delete(processInstance);
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't delete process instance '" + processInstance.getId() + "'", e);
}
}
void deleteLogs(ProcessInstance processInstance) {
Query query = session.getNamedQuery("GraphSession.findLogsForProcessInstance");
query.setEntity("processInstance", processInstance);
List logs = query.list();
Iterator iter = logs.iterator();
while (iter.hasNext()) {
ProcessLog processLog = (ProcessLog) iter.next();
session.delete(processLog);
}
}
void deleteSubProcesses(Token token) {
if (token != null) {
Query query = session.getNamedQuery("GraphSession.findSubProcessInstances");
query.setEntity("processInstance", token.getProcessInstance());
List processInstances = query.list();
if (processInstances == null || processInstances.isEmpty()) {
log.debug("no subprocesses to delete for token " + token.getId());
return;
}
Iterator iter = processInstances.iterator();
while (iter.hasNext()) {
ProcessInstance subProcessInstance = (ProcessInstance) iter.next();
subProcessInstance.getSuperProcessToken().setSubProcessInstance(null);
subProcessInstance.setSuperProcessToken(null);
token.setSubProcessInstance(null);
log.debug("deleting sub process " + subProcessInstance.getId());
deleteProcessInstance(subProcessInstance);
}
}
}
public static class AverageNodeTimeEntry {
private long nodeId;
private String nodeName;
private int count;
private long averageDuration;
private long minDuration;
private long maxDuration;
public long getNodeId() {
return nodeId;
}
public void setNodeId(final long nodeId) {
this.nodeId = nodeId;
}
public String getNodeName() {
return nodeName;
}
public void setNodeName(final String nodeName) {
this.nodeName = nodeName;
}
public int getCount() {
return count;
}
public void setCount(final int count) {
this.count = count;
}
public long getAverageDuration() {
return averageDuration;
}
public void setAverageDuration(final long averageDuration) {
this.averageDuration = averageDuration;
}
public long getMinDuration() {
return minDuration;
}
public void setMinDuration(final long minDuration) {
this.minDuration = minDuration;
}
public long getMaxDuration() {
return maxDuration;
}
public void setMaxDuration(final long maxDuration) {
this.maxDuration = maxDuration;
}
}
public List calculateAverageTimeByNode(final long processDefinitionId, final long minumumDurationMillis) {
List results = null;
try {
Query query = session.getNamedQuery("GraphSession.calculateAverageTimeByNode");
query.setLong("processDefinitionId", processDefinitionId);
query.setDouble("minimumDuration", minumumDurationMillis);
List listResults = query.list();
if (listResults != null) {
results = new ArrayList();
Iterator iter = listResults.iterator();
while (iter.hasNext()) {
Object[] values = (Object[]) iter.next();
AverageNodeTimeEntry averageNodeTimeEntry = new AverageNodeTimeEntry();
averageNodeTimeEntry.setNodeId(((Number) values[0]).longValue());
averageNodeTimeEntry.setNodeName((String) values[1]);
averageNodeTimeEntry.setCount(((Number) values[2]).intValue());
averageNodeTimeEntry.setAverageDuration(((Number) values[3]).longValue());
averageNodeTimeEntry.setMinDuration(((Number) values[4]).longValue());
averageNodeTimeEntry.setMaxDuration(((Number) values[5]).longValue());
results.add(averageNodeTimeEntry);
}
}
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException(
"couldn't load process instances for process definition '" + processDefinitionId + "'", e);
}
return results;
}
public List findActiveNodesByProcessInstance(ProcessInstance processInstance) {
List results = null;
try {
Query query = session.getNamedQuery("GraphSession.findActiveNodesByProcessInstance");
query.setEntity("processInstance", processInstance);
results = query.list();
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't active nodes for process instance '" + processInstance + "'", e);
}
return results;
}
public ProcessInstance getProcessInstance(ProcessDefinition processDefinition, String key) {
ProcessInstance processInstance = null;
try {
Query query = session.getNamedQuery("GraphSession.findProcessInstanceByKey");
query.setEntity("processDefinition", processDefinition);
query.setString("key", key);
processInstance = (ProcessInstance) query.uniqueResult();
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't get process instance with key '" + key + "'", e);
}
return processInstance;
}
public ProcessInstance loadProcessInstance(ProcessDefinition processDefinition, String key) {
ProcessInstance processInstance = null;
try {
Query query = session.getNamedQuery("GraphSession.findProcessInstanceByKey");
query.setEntity("processDefinition", processDefinition);
query.setString("key", key);
processInstance = (ProcessInstance) query.uniqueResult();
if (processInstance == null) {
throw new JbpmException("no process instance was found with key " + key);
}
} catch (Exception e) {
log.error(e);
jbpmSession.handleException();
throw new JbpmException("couldn't load process instance with key '" + key + "'", e);
}
return processInstance;
}
private static final Log log = LogFactory.getLog(GraphSession.class);
}