mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
- Workflow Service
-- addition of get process definition history -- addition of get active timers (for a process definition) -- addition of fire custom workflow events -- addition of get process variables - Workflow Console -- addition of undeploy all versions of a process definition -- addition of list all versions of a process definition -- addition of list workflows for previous version of a process definition -- addition of query tasks -- addition of firing custom workflow event -- addition of list timers -- addition of show process variables git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5754 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -43,9 +43,11 @@ ok> redeploy
|
||||
|
||||
Redeploy the last workflow definition.
|
||||
|
||||
ok> show definitions
|
||||
ok> show definitions [all]
|
||||
|
||||
List all deployed workflow definitions.
|
||||
List latest deployed workflow definitions. Or, display all workflows
|
||||
definitions (including previous versions) with the additional keyword
|
||||
'all'.
|
||||
|
||||
ok> use definition [<workflowDefId>]
|
||||
|
||||
@@ -60,7 +62,14 @@ ok> undeploy definition <workflowDefId>
|
||||
workflows associated with the definition.
|
||||
|
||||
If multiple versions of the definition exist, you will have to undeploy
|
||||
each in turn to remove the definition completely.
|
||||
each in turn to remove the definition completely or issue the 'undeploy
|
||||
definition name' command.
|
||||
|
||||
ok> undeploy definition name <workflowName>
|
||||
|
||||
Undeploy all versions of a workflow definition. As with 'undeploy
|
||||
definition', all "in-flight" workflows associated with each version
|
||||
are terminated.
|
||||
|
||||
##
|
||||
## Variable Commands
|
||||
@@ -140,18 +149,27 @@ ok> start [<varName[=varValue>]]*
|
||||
ok> show workflows [all]
|
||||
|
||||
Display the list of active workflows for the currently selected workflow
|
||||
definition. Or, display the list of all workflows when used with additional
|
||||
keyword 'all'.
|
||||
definition. Or, display the list of all workflows when used with the
|
||||
additional keyword 'all'.
|
||||
|
||||
ok> use workflow <workflowId>
|
||||
|
||||
Use the specified <workflowId>.
|
||||
|
||||
ok> desc workflow <workflowId>
|
||||
|
||||
Describe the specified <workflowId>.
|
||||
|
||||
ok> show paths [<workflowId>]
|
||||
|
||||
Display the workflow paths for the specified <workflowId>. If <workflowId>
|
||||
is omitted, the paths for the currently started workflow are shown.
|
||||
|
||||
ok> desc path <pathId>
|
||||
|
||||
Describe the specified <pathId>. Includes the list of properties associated
|
||||
with the path.
|
||||
|
||||
ok> show transitions [<workflowId>]
|
||||
|
||||
Display all available transitions for the specified <workflowId>. If
|
||||
@@ -163,9 +181,9 @@ ok> signal <pathId> [<transitionName>]
|
||||
Signal transition on specified <pathId>. If <transitionName> is omitted, the
|
||||
default transition is taken.
|
||||
|
||||
ok> desc workflow <workflowId>
|
||||
ok> event <pathId> <eventtype>
|
||||
|
||||
Describe the specified <workflowId>.
|
||||
Fire an event of custom 'eventtype' against the specified path.
|
||||
|
||||
ok> end workflow <workflowId>
|
||||
|
||||
@@ -179,6 +197,16 @@ ok> delete all workflows
|
||||
|
||||
Force deletion of all "in-flight" workflows. Use with care!
|
||||
|
||||
##
|
||||
## Timer Commands
|
||||
##
|
||||
|
||||
ok> show timers [all]
|
||||
|
||||
Display the list of active timers for the currently selected workflow
|
||||
definition. Or, display the list of all timers when used with the
|
||||
additional keyword 'all'.
|
||||
|
||||
##
|
||||
## Task Commands
|
||||
##
|
||||
@@ -223,6 +251,44 @@ ok> end task <taskId> [<transitionName>]
|
||||
End the task identified by <taskId>. If <transitionName> is omitted, the
|
||||
default transition is taken.
|
||||
|
||||
ok> query task [predicate]*
|
||||
|
||||
Query for tasks. If no predicates are provided, all "in-progress" tasks
|
||||
are returned (across all "active" workflows).
|
||||
|
||||
Predicates are:
|
||||
|
||||
taskId=<taskId>
|
||||
taskName=<taskName> e.g. taskName=wf:reviewTask
|
||||
taskState=IN_PROGRESS|COMPLETED
|
||||
taskActor=<actorId> e.g. taskActor=admin
|
||||
task.<propqname>=<propvalue> e.g. task.bpm:outcome=approve
|
||||
processId=<processId>
|
||||
processName=<processName> e.g. processName=wf:review
|
||||
processActive=true|false e.g. processActive=true
|
||||
process.<propqname>=<propvalue> e.g. process.initiator=admin
|
||||
orderBy=<orderBy>* e.g. orderBy=TaskDue_Desc,TaskActor_Asc
|
||||
|
||||
Where <orderBy> is one of:
|
||||
|
||||
TaskId_Asc,
|
||||
TaskId_Desc,
|
||||
TaskCreated_Asc,
|
||||
TaskCreated_Desc,
|
||||
TaskDue_Asc,
|
||||
TaskDue_Desc,
|
||||
TaskName_Asc,
|
||||
TaskName_Desc,
|
||||
TaskActor_Asc,
|
||||
TaskActor_Desc,
|
||||
TaskState_Asc,
|
||||
TaskState_Desc
|
||||
|
||||
e.g. query all in-progress pending submissions for web project X, ordered by pending due date, submitter
|
||||
|
||||
query task taskName=wcmwf:submitpending taskState=IN_PROGRESS \
|
||||
process.wcwmf:webproject=workspace://SpacesStore/projectx orderBy=TaskDue_Desc,TaskActor_Asc
|
||||
|
||||
##
|
||||
## end
|
||||
##
|
||||
|
@@ -35,6 +35,7 @@ import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowInstance;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTimer;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
|
||||
@@ -88,6 +89,14 @@ public interface WorkflowComponent
|
||||
*/
|
||||
public List<WorkflowDefinition> getDefinitions();
|
||||
|
||||
/**
|
||||
* Gets all deployed Workflow Definitions (with all previous versions)
|
||||
*
|
||||
* @return the deployed (and previous) workflow definitions
|
||||
*/
|
||||
@Auditable
|
||||
public List<WorkflowDefinition> getAllDefinitions();
|
||||
|
||||
/**
|
||||
* Gets a Workflow Definition by unique Id
|
||||
*
|
||||
@@ -104,6 +113,15 @@ public interface WorkflowComponent
|
||||
*/
|
||||
public WorkflowDefinition getDefinitionByName(String workflowName);
|
||||
|
||||
/**
|
||||
* Gets all (including previous) Workflow Definitions for the given unique name
|
||||
*
|
||||
* @param workflowName workflow name e.g. jbpm://review
|
||||
* @return the deployed workflow definition (or null if not found)
|
||||
*/
|
||||
@Auditable(parameters = {"workflowName"})
|
||||
public List<WorkflowDefinition> getAllDefinitionsByName(String workflowName);
|
||||
|
||||
/**
|
||||
* Gets a graphical view of the Workflow Definition
|
||||
*
|
||||
@@ -152,6 +170,14 @@ public interface WorkflowComponent
|
||||
*/
|
||||
public List<WorkflowPath> getWorkflowPaths(String workflowId);
|
||||
|
||||
/**
|
||||
* Gets the properties associated with the specified path (and parent paths)
|
||||
*
|
||||
* @param pathId workflow path id
|
||||
* @return map of path properties
|
||||
*/
|
||||
public Map<QName, Serializable> getPathProperties(String pathId);
|
||||
|
||||
/**
|
||||
* Cancel an "in-fligth" Workflow instance
|
||||
*
|
||||
@@ -178,6 +204,15 @@ public interface WorkflowComponent
|
||||
*/
|
||||
public WorkflowPath signal(String pathId, String transitionId);
|
||||
|
||||
/**
|
||||
* Fire custom event against specified path
|
||||
*
|
||||
* @param pathId the workflow path to fire event on
|
||||
* @param event name of event
|
||||
* @return workflow path (it may have been updated as a result of firing the event
|
||||
*/
|
||||
public WorkflowPath fireEvent(String pathId, String event);
|
||||
|
||||
/**
|
||||
* Gets all Tasks associated with the specified path
|
||||
*
|
||||
@@ -186,5 +221,12 @@ public interface WorkflowComponent
|
||||
*/
|
||||
public List<WorkflowTask> getTasksForWorkflowPath(String pathId);
|
||||
|
||||
/**
|
||||
* Gets all active timers for the specified workflow
|
||||
*
|
||||
* @return the list of active timers
|
||||
*/
|
||||
public List<WorkflowTimer> getTimers(String workflowId);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -37,17 +37,17 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.security.authority.AuthorityDAO;
|
||||
import org.alfresco.repo.transaction.TransactionUtil;
|
||||
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
||||
import org.alfresco.service.cmr.avm.AVMService;
|
||||
import org.alfresco.service.cmr.avmsync.AVMDifference;
|
||||
import org.alfresco.service.cmr.avmsync.AVMSyncService;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.security.authority.AuthorityDAO;
|
||||
import org.alfresco.repo.transaction.TransactionUtil;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
@@ -61,7 +61,9 @@ import org.alfresco.service.cmr.workflow.WorkflowInstance;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTimer;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTransition;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
@@ -351,7 +353,22 @@ public class WorkflowInterpreter
|
||||
|
||||
else if (command[1].equals("definitions"))
|
||||
{
|
||||
List<WorkflowDefinition> defs = workflowService.getDefinitions();
|
||||
List<WorkflowDefinition> defs = null;
|
||||
if (command.length == 3)
|
||||
{
|
||||
if (command[2].equals("all"))
|
||||
{
|
||||
defs = workflowService.getAllDefinitions();
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
defs = workflowService.getDefinitions();
|
||||
}
|
||||
for (WorkflowDefinition def : defs)
|
||||
{
|
||||
out.println("id: " + def.id + " , name: " + def.name + " , title: " + def.title + " , version: " + def.version);
|
||||
@@ -379,12 +396,12 @@ public class WorkflowInterpreter
|
||||
|
||||
if (id.equals("all"))
|
||||
{
|
||||
for (WorkflowDefinition def : workflowService.getDefinitions())
|
||||
for (WorkflowDefinition def : workflowService.getAllDefinitions())
|
||||
{
|
||||
List<WorkflowInstance> workflows = workflowService.getActiveWorkflows(def.id);
|
||||
for (WorkflowInstance workflow : workflows)
|
||||
{
|
||||
out.println("id: " + workflow.id + " , desc: " + workflow.description + " , start date: " + workflow.startDate + " , def: " + workflow.definition.title);
|
||||
out.println("id: " + workflow.id + " , desc: " + workflow.description + " , start date: " + workflow.startDate + " , def: " + workflow.definition.name + " v" + workflow.definition.version);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -393,7 +410,7 @@ public class WorkflowInterpreter
|
||||
List<WorkflowInstance> workflows = workflowService.getActiveWorkflows(id);
|
||||
for (WorkflowInstance workflow : workflows)
|
||||
{
|
||||
out.println("id: " + workflow.id + " , desc: " + workflow.description + " , start date: " + workflow.startDate + " , def: " + workflow.definition.title);
|
||||
out.println("id: " + workflow.id + " , desc: " + workflow.description + " , start date: " + workflow.startDate + " , def: " + workflow.definition.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,6 +470,54 @@ public class WorkflowInterpreter
|
||||
}
|
||||
}
|
||||
|
||||
else if (command[1].equals("timers"))
|
||||
{
|
||||
String id = (currentWorkflowDef != null) ? currentWorkflowDef.id : null;
|
||||
if (id == null && command.length == 2)
|
||||
{
|
||||
return "workflow definition not in use. Enter command 'show timers all' or 'use <workflowDefId>'.\n";
|
||||
}
|
||||
if (command.length == 3)
|
||||
{
|
||||
if (command[2].equals("all"))
|
||||
{
|
||||
id = "all";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (id.equals("all"))
|
||||
{
|
||||
for (WorkflowDefinition def : workflowService.getAllDefinitions())
|
||||
{
|
||||
List<WorkflowInstance> workflows = workflowService.getActiveWorkflows(def.id);
|
||||
for (WorkflowInstance workflow : workflows)
|
||||
{
|
||||
List<WorkflowTimer> timers = workflowService.getTimers(workflow.id);
|
||||
for (WorkflowTimer timer : timers)
|
||||
{
|
||||
out.println("id: " + timer.id + " , name: " + timer.name + " , due date: " + timer.dueDate + " , path: " + timer.path.id + " , node: " + timer.path.node.name + " , process: " + timer.path.instance.id + " , task: " + timer.task.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List<WorkflowInstance> workflows = workflowService.getActiveWorkflows(id);
|
||||
for (WorkflowInstance workflow : workflows)
|
||||
{
|
||||
List<WorkflowTimer> timers = workflowService.getTimers(workflow.id);
|
||||
for (WorkflowTimer timer : timers)
|
||||
{
|
||||
out.println("id: " + timer.id + " , name: " + timer.name + " , due date: " + timer.dueDate + " , path: " + timer.path.id + " , node: " + timer.path.node.name + " , process: " + timer.path.instance.id + " , task: " + timer.task.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (command[1].equals("my"))
|
||||
{
|
||||
if (command.length != 3)
|
||||
@@ -550,6 +615,144 @@ public class WorkflowInterpreter
|
||||
out.println("context: " + workflow.context);
|
||||
out.println("package: " + workflow.workflowPackage);
|
||||
}
|
||||
|
||||
else if (command[1].equals("path"))
|
||||
{
|
||||
if (command.length != 3)
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
}
|
||||
Map<QName, Serializable> properties = workflowService.getPathProperties(command[2]);
|
||||
out.println("path: " + command[1]);
|
||||
out.println("properties: " + properties.size());
|
||||
for (Map.Entry<QName, Serializable> prop : properties.entrySet())
|
||||
{
|
||||
out.println(" " + prop.getKey() + " = " + prop.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
}
|
||||
}
|
||||
|
||||
else if (command[0].equals("query"))
|
||||
{
|
||||
if (command.length < 2)
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
}
|
||||
|
||||
if (command[1].equals("task"))
|
||||
{
|
||||
// build query
|
||||
WorkflowTaskQuery query = new WorkflowTaskQuery();
|
||||
Map<QName, Object> taskProps = new HashMap<QName, Object>();
|
||||
Map<QName, Object> procProps = new HashMap<QName, Object>();
|
||||
|
||||
for (int i = 2; i < command.length; i++)
|
||||
{
|
||||
String[] predicate = command[i].split("=");
|
||||
if (predicate.length == 1)
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
}
|
||||
String[] predicateName = predicate[0].split("\\.");
|
||||
if (predicateName.length == 1)
|
||||
{
|
||||
if (predicate[0].equals("taskId"))
|
||||
{
|
||||
query.setTaskId(predicate[1]);
|
||||
}
|
||||
else if (predicate[0].equals("taskState"))
|
||||
{
|
||||
WorkflowTaskState state = WorkflowTaskState.valueOf(predicate[1]);
|
||||
if (state == null)
|
||||
{
|
||||
return "Syntax Error. Unknown task state\n";
|
||||
}
|
||||
query.setTaskState(state);
|
||||
}
|
||||
else if (predicate[0].equals("taskName"))
|
||||
{
|
||||
query.setTaskName(QName.createQName(predicate[1], namespaceService));
|
||||
}
|
||||
else if (predicate[0].equals("taskActor"))
|
||||
{
|
||||
query.setActorId(predicate[1]);
|
||||
}
|
||||
else if (predicate[0].equals("processId"))
|
||||
{
|
||||
query.setProcessId(predicate[1]);
|
||||
}
|
||||
else if (predicate[0].equals("processName"))
|
||||
{
|
||||
query.setProcessName(QName.createQName(predicate[1], namespaceService));
|
||||
}
|
||||
else if (predicate[0].equals("processActive"))
|
||||
{
|
||||
Boolean active = Boolean.valueOf(predicate[1]);
|
||||
query.setActive(active);
|
||||
}
|
||||
else if (predicate[0].equals("orderBy"))
|
||||
{
|
||||
String[] orderBy = predicate[1].split(",");
|
||||
WorkflowTaskQuery.OrderBy[] queryOrderBy = new WorkflowTaskQuery.OrderBy[orderBy.length];
|
||||
for (int iOrderBy = 0; iOrderBy < orderBy.length; iOrderBy++)
|
||||
{
|
||||
queryOrderBy[iOrderBy] = WorkflowTaskQuery.OrderBy.valueOf(orderBy[iOrderBy]);
|
||||
if (queryOrderBy[iOrderBy] == null)
|
||||
{
|
||||
return "Syntax Error. Unknown orderBy.\n";
|
||||
}
|
||||
}
|
||||
query.setOrderBy(queryOrderBy);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Syntax Error. Unknown query predicate.\n";
|
||||
}
|
||||
}
|
||||
else if (predicateName.length == 2)
|
||||
{
|
||||
if (predicateName[0].equals("task"))
|
||||
{
|
||||
taskProps.put(QName.createQName(predicateName[1], namespaceService), predicate[1]);
|
||||
}
|
||||
else if (predicateName[0].equals("process"))
|
||||
{
|
||||
procProps.put(QName.createQName(predicateName[1], namespaceService), predicate[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Syntax Error. Unknown query predicate.\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (taskProps.size() > 0)
|
||||
{
|
||||
query.setTaskCustomProps(taskProps);
|
||||
}
|
||||
if (procProps.size() > 0)
|
||||
{
|
||||
query.setProcessCustomProps(procProps);
|
||||
}
|
||||
|
||||
// execute query
|
||||
List<WorkflowTask> tasks = workflowService.queryTasks(query);
|
||||
out.println("found " + tasks.size() + " tasks.");
|
||||
for (WorkflowTask task : tasks)
|
||||
{
|
||||
out.println("task id: " + task.id + " , name: " + task.name + " , properties: " + task.properties.size() + ", process id: " + task.path.instance);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
@@ -591,14 +794,38 @@ public class WorkflowInterpreter
|
||||
}
|
||||
if (command[1].equals("definition"))
|
||||
{
|
||||
if (command.length != 3)
|
||||
if (command.length == 3)
|
||||
{
|
||||
workflowService.undeployDefinition(command[2]);
|
||||
currentWorkflowDef = null;
|
||||
currentPath = null;
|
||||
out.print(executeCommand("show definitions"));
|
||||
}
|
||||
else if (command.length == 4)
|
||||
{
|
||||
if (command[2].equals("name"))
|
||||
{
|
||||
out.print("undeploying...");
|
||||
List<WorkflowDefinition> defs = workflowService.getAllDefinitionsByName(command[3]);
|
||||
for (WorkflowDefinition def: defs)
|
||||
{
|
||||
workflowService.undeployDefinition(def.id);
|
||||
out.print(" v" + def.version);
|
||||
}
|
||||
out.println("");
|
||||
currentWorkflowDef = null;
|
||||
currentPath = null;
|
||||
out.print(executeCommand("show definitions all"));
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
}
|
||||
workflowService.undeployDefinition(command[2]);
|
||||
currentWorkflowDef = null;
|
||||
currentPath = null;
|
||||
out.print(executeCommand("show definitions"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -610,7 +837,7 @@ public class WorkflowInterpreter
|
||||
{
|
||||
if (command.length == 1)
|
||||
{
|
||||
out.println("definition: " + ((currentWorkflowDef == null) ? "None" : currentWorkflowDef.id + " , name: " + currentWorkflowDef.title));
|
||||
out.println("definition: " + ((currentWorkflowDef == null) ? "None" : currentWorkflowDef.id + " , name: " + currentWorkflowDef.title + " , version: " + currentWorkflowDef.version));
|
||||
out.println("workflow: " + ((currentPath == null) ? "None" : currentPath.instance.id + " , active: " + currentPath.instance.active));
|
||||
out.println("path: " + ((currentPath == null) ? "None" : currentPath.id + " , node: " + currentPath.node.title));
|
||||
}
|
||||
@@ -748,6 +975,17 @@ public class WorkflowInterpreter
|
||||
out.print(interpretCommand("show transitions"));
|
||||
}
|
||||
|
||||
else if (command[0].equals("event"))
|
||||
{
|
||||
if (command.length < 3)
|
||||
{
|
||||
return "Syntax Error.\n";
|
||||
}
|
||||
WorkflowPath path = workflowService.fireEvent(command[1], command[2]);
|
||||
out.println("event " + command[2] + " fired - path id: " + path.id);
|
||||
out.print(interpretCommand("show transitions"));
|
||||
}
|
||||
|
||||
else if (command[0].equals("end"))
|
||||
{
|
||||
if (command.length < 3)
|
||||
@@ -769,7 +1007,6 @@ public class WorkflowInterpreter
|
||||
}
|
||||
workflowService.cancelWorkflow(workflowId);
|
||||
out.println("workflow " + workflowId + " cancelled.");
|
||||
out.print(interpretCommand("show transitions"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -807,7 +1044,7 @@ public class WorkflowInterpreter
|
||||
}
|
||||
if (command[3].equals("imeanit"))
|
||||
{
|
||||
for (WorkflowDefinition def : workflowService.getDefinitions())
|
||||
for (WorkflowDefinition def : workflowService.getAllDefinitions())
|
||||
{
|
||||
List<WorkflowInstance> workflows = workflowService.getActiveWorkflows(def.id);
|
||||
for (WorkflowInstance workflow : workflows)
|
||||
|
@@ -44,6 +44,7 @@ import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTimer;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -159,6 +160,21 @@ public class WorkflowServiceImpl implements WorkflowService
|
||||
return Collections.unmodifiableList(definitions);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#getAllDefinitions()
|
||||
*/
|
||||
public List<WorkflowDefinition> getAllDefinitions()
|
||||
{
|
||||
List<WorkflowDefinition> definitions = new ArrayList<WorkflowDefinition>(10);
|
||||
String[] ids = registry.getWorkflowComponents();
|
||||
for (String id: ids)
|
||||
{
|
||||
WorkflowComponent component = registry.getWorkflowComponent(id);
|
||||
definitions.addAll(component.getAllDefinitions());
|
||||
}
|
||||
return Collections.unmodifiableList(definitions);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#getDefinitionById(java.lang.String)
|
||||
*/
|
||||
@@ -179,6 +195,16 @@ public class WorkflowServiceImpl implements WorkflowService
|
||||
return component.getDefinitionByName(workflowName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#getAllDefinitionsByName(java.lang.String)
|
||||
*/
|
||||
public List<WorkflowDefinition> getAllDefinitionsByName(String workflowName)
|
||||
{
|
||||
String engineId = BPMEngineRegistry.getEngineId(workflowName);
|
||||
WorkflowComponent component = getWorkflowComponent(engineId);
|
||||
return component.getAllDefinitionsByName(workflowName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#getDefinitionImage(java.lang.String)
|
||||
*/
|
||||
@@ -243,6 +269,16 @@ public class WorkflowServiceImpl implements WorkflowService
|
||||
return component.getWorkflowPaths(workflowId);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#getPathProperties(java.lang.String)
|
||||
*/
|
||||
public Map<QName, Serializable> getPathProperties(String pathId)
|
||||
{
|
||||
String engineId = BPMEngineRegistry.getEngineId(pathId);
|
||||
WorkflowComponent component = getWorkflowComponent(engineId);
|
||||
return component.getPathProperties(pathId);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#cancelWorkflow(java.lang.String)
|
||||
*/
|
||||
@@ -281,6 +317,26 @@ public class WorkflowServiceImpl implements WorkflowService
|
||||
return component.signal(pathId, transition);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#fireEvent(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public WorkflowPath fireEvent(String pathId, String event)
|
||||
{
|
||||
String engineId = BPMEngineRegistry.getEngineId(pathId);
|
||||
WorkflowComponent component = getWorkflowComponent(engineId);
|
||||
return component.fireEvent(pathId, event);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#getTimers(java.lang.String)
|
||||
*/
|
||||
public List<WorkflowTimer> getTimers(String workflowId)
|
||||
{
|
||||
String engineId = BPMEngineRegistry.getEngineId(workflowId);
|
||||
WorkflowComponent component = getWorkflowComponent(engineId);
|
||||
return component.getTimers(workflowId);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#getTasksForWorkflowPath(java.lang.String)
|
||||
*/
|
||||
|
@@ -31,8 +31,8 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
@@ -70,6 +70,7 @@ import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTimer;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTransition;
|
||||
import org.alfresco.service.namespace.NamespaceException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
@@ -91,11 +92,14 @@ import org.jbpm.context.exe.VariableInstance;
|
||||
import org.jbpm.db.GraphSession;
|
||||
import org.jbpm.db.TaskMgmtSession;
|
||||
import org.jbpm.file.def.FileDefinition;
|
||||
import org.jbpm.graph.def.Event;
|
||||
import org.jbpm.graph.def.Node;
|
||||
import org.jbpm.graph.def.ProcessDefinition;
|
||||
import org.jbpm.graph.def.Transition;
|
||||
import org.jbpm.graph.exe.ExecutionContext;
|
||||
import org.jbpm.graph.exe.ProcessInstance;
|
||||
import org.jbpm.graph.exe.Token;
|
||||
import org.jbpm.job.Timer;
|
||||
import org.jbpm.jpdl.par.ProcessArchive;
|
||||
import org.jbpm.jpdl.xml.Problem;
|
||||
import org.jbpm.taskmgmt.def.Task;
|
||||
@@ -140,6 +144,14 @@ public class JBPMEngine extends BPMEngine
|
||||
"and ti.isOpen = false " +
|
||||
"and ti.end is not null";
|
||||
|
||||
// Note: jBPM query which is not provided out-of-the-box
|
||||
// TODO: Check jBPMg future and get this implemented in jBPM
|
||||
private final static String PROCESS_TIMERS_QUERY =
|
||||
"select timer " +
|
||||
"from org.jbpm.job.Timer timer " +
|
||||
"where timer.processInstance = :process ";
|
||||
|
||||
|
||||
// Workflow Path Seperators
|
||||
private final static String WORKFLOW_PATH_SEPERATOR = "-";
|
||||
private final static String WORKFLOW_TOKEN_SEPERATOR = "@";
|
||||
@@ -363,6 +375,36 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#getDefinitions()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<WorkflowDefinition> getAllDefinitions()
|
||||
{
|
||||
try
|
||||
{
|
||||
return (List<WorkflowDefinition>)jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
List<ProcessDefinition> processDefs = (List<ProcessDefinition>)graphSession.findAllProcessDefinitions();
|
||||
List<WorkflowDefinition> workflowDefs = new ArrayList<WorkflowDefinition>(processDefs.size());
|
||||
for (ProcessDefinition processDef : processDefs)
|
||||
{
|
||||
WorkflowDefinition workflowDef = createWorkflowDefinition(processDef);
|
||||
workflowDefs.add(workflowDef);
|
||||
}
|
||||
return workflowDefs;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(JbpmException e)
|
||||
{
|
||||
throw new WorkflowException("Failed to retrieve workflow definitions", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#getDefinitionById(java.lang.String)
|
||||
*/
|
||||
@@ -411,6 +453,37 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowComponent#getAllDefinitionsByName(java.lang.String)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<WorkflowDefinition> getAllDefinitionsByName(final String workflowName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (List<WorkflowDefinition>)jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
@SuppressWarnings("synthetic-access")
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
List<ProcessDefinition> processDefs = (List<ProcessDefinition>)graphSession.findAllProcessDefinitionVersions(createLocalId(workflowName));
|
||||
List<WorkflowDefinition> workflowDefs = new ArrayList<WorkflowDefinition>(processDefs.size());
|
||||
for (ProcessDefinition processDef : processDefs)
|
||||
{
|
||||
WorkflowDefinition workflowDef = createWorkflowDefinition(processDef);
|
||||
workflowDefs.add(workflowDef);
|
||||
}
|
||||
return workflowDefs;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(JbpmException e)
|
||||
{
|
||||
throw new WorkflowException("Failed to retrieve all definitions for workflow '" + workflowName + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowComponent#getDefinitionImage(java.lang.String)
|
||||
*/
|
||||
@@ -630,6 +703,55 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowComponent#getPathProperties(java.lang.String)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<QName, Serializable> getPathProperties(final String pathId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (Map<QName, Serializable>) jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public Map<QName, Serializable> doInJbpm(JbpmContext context)
|
||||
{
|
||||
// retrieve jBPM token for workflow position
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
Token token = getWorkflowToken(graphSession, pathId);
|
||||
ContextInstance instanceContext = token.getProcessInstance().getContextInstance();
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(10);
|
||||
while (token != null)
|
||||
{
|
||||
|
||||
TokenVariableMap varMap = instanceContext.getTokenVariableMap(token);
|
||||
if (varMap != null)
|
||||
{
|
||||
Map<String, Object> tokenVars = varMap.getVariablesLocally();
|
||||
for (Map.Entry<String, Object> entry : tokenVars.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
QName qname = mapNameToQName(key);
|
||||
|
||||
if (!properties.containsKey(key))
|
||||
{
|
||||
Serializable value = convertValue(entry.getValue());
|
||||
properties.put(qname, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
token = token.getParent();
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(JbpmException e)
|
||||
{
|
||||
throw new WorkflowException("Failed to retrieve properties of path '" + pathId + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowComponent#cancelWorkflow(java.lang.String)
|
||||
*/
|
||||
@@ -739,6 +861,78 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowComponent#fireEvent(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public WorkflowPath fireEvent(final String pathId, final String event)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (WorkflowPath) jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
// NOTE: Do not allow jBPM built-in events to be fired
|
||||
if (event.equals(Event.EVENTTYPE_AFTER_SIGNAL) ||
|
||||
event.equals(Event.EVENTTYPE_BEFORE_SIGNAL) ||
|
||||
event.equals(Event.EVENTTYPE_NODE_ENTER) ||
|
||||
event.equals(Event.EVENTTYPE_NODE_LEAVE) ||
|
||||
event.equals(Event.EVENTTYPE_PROCESS_END) ||
|
||||
event.equals(Event.EVENTTYPE_PROCESS_START) ||
|
||||
event.equals(Event.EVENTTYPE_SUBPROCESS_CREATED) ||
|
||||
event.equals(Event.EVENTTYPE_SUBPROCESS_END) ||
|
||||
event.equals(Event.EVENTTYPE_SUPERSTATE_ENTER) ||
|
||||
event.equals(Event.EVENTTYPE_SUPERSTATE_LEAVE) ||
|
||||
event.equals(Event.EVENTTYPE_TASK_ASSIGN) ||
|
||||
event.equals(Event.EVENTTYPE_TASK_CREATE) ||
|
||||
event.equals(Event.EVENTTYPE_TASK_END) ||
|
||||
event.equals(Event.EVENTTYPE_TASK_START) ||
|
||||
event.equals(Event.EVENTTYPE_TIMER) ||
|
||||
event.equals(Event.EVENTTYPE_TRANSITION))
|
||||
{
|
||||
throw new WorkflowException("Event " + event + " is not a valid event");
|
||||
}
|
||||
|
||||
// retrieve jBPM token for workflow position
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
Token token = getWorkflowToken(graphSession, pathId);
|
||||
|
||||
ExecutionContext executionContext = new ExecutionContext(token);
|
||||
TaskMgmtSession taskSession = context.getTaskMgmtSession();
|
||||
List<TaskInstance> tasks = taskSession.findTaskInstancesByToken(token.getId());
|
||||
if (tasks.size() == 0)
|
||||
{
|
||||
// fire the event against current node for the token
|
||||
Node node = token.getNode();
|
||||
node.fireEvent(event, executionContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
// fire the event against tasks associated with the node
|
||||
// NOTE: this will also propagate the event to the node
|
||||
for (TaskInstance task : tasks)
|
||||
{
|
||||
executionContext.setTaskInstance(task);
|
||||
task.getTask().fireEvent(event, executionContext);
|
||||
}
|
||||
}
|
||||
|
||||
// save
|
||||
ProcessInstance processInstance = token.getProcessInstance();
|
||||
context.save(processInstance);
|
||||
|
||||
// return new workflow path
|
||||
return createWorkflowPath(token);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(JbpmException e)
|
||||
{
|
||||
throw new WorkflowException("Failed to fire event '" + event + "' on workflow path '" + pathId + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowComponent#getTasksForWorkflowPath(java.lang.String)
|
||||
*/
|
||||
@@ -772,6 +966,44 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowComponent#getTimers(java.lang.String)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<WorkflowTimer> getTimers(final String workflowId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (List<WorkflowTimer>) jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public List<WorkflowTimer> doInJbpm(JbpmContext context)
|
||||
{
|
||||
// retrieve process
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessInstance process = getProcessInstance(graphSession, workflowId);
|
||||
|
||||
// retrieve timers for process
|
||||
Session session = context.getSession();
|
||||
Query query = session.createQuery(PROCESS_TIMERS_QUERY);
|
||||
query.setEntity("process", process);
|
||||
List<Timer> timers = query.list();
|
||||
|
||||
// convert timers to appropriate service response format
|
||||
List<WorkflowTimer> workflowTimers = new ArrayList<WorkflowTimer>(timers.size());
|
||||
for (Timer timer : timers)
|
||||
{
|
||||
WorkflowTimer workflowTimer = createWorkflowTimer(timer);
|
||||
workflowTimers.add(workflowTimer);
|
||||
}
|
||||
return workflowTimers;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(JbpmException e)
|
||||
{
|
||||
throw new JbpmException("Couldn't get timers for process '" + workflowId + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Task Management ...
|
||||
@@ -1562,30 +1794,8 @@ public class JBPMEngine extends BPMEngine
|
||||
// add variable, only if part of task definition or locally defined on task
|
||||
if (taskProperties.containsKey(qname) || taskAssocs.containsKey(qname) || instance.hasVariableLocally(key))
|
||||
{
|
||||
Object value = entry.getValue();
|
||||
|
||||
//
|
||||
// perform data conversions
|
||||
//
|
||||
|
||||
// Convert Nodes to NodeRefs
|
||||
if (value instanceof JBPMNode)
|
||||
{
|
||||
value = ((JBPMNode)value).getNodeRef();
|
||||
}
|
||||
else if (value instanceof JBPMNodeList)
|
||||
{
|
||||
JBPMNodeList nodes = (JBPMNodeList)value;
|
||||
List<NodeRef> nodeRefs = new ArrayList<NodeRef>(nodes.size());
|
||||
for (JBPMNode node : nodes)
|
||||
{
|
||||
nodeRefs.add(node.getNodeRef());
|
||||
}
|
||||
value = (Serializable)nodeRefs;
|
||||
}
|
||||
|
||||
// place task variable in map to return
|
||||
properties.put(qname, (Serializable)value);
|
||||
Serializable value = convertValue(entry.getValue());
|
||||
properties.put(qname, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1982,6 +2192,45 @@ public class JBPMEngine extends BPMEngine
|
||||
return (missingProps == null) ? null : missingProps.toArray(new QName[missingProps.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a jBPM Value to an Alfresco value
|
||||
*
|
||||
* @param value jBPM value
|
||||
* @return alfresco value
|
||||
*/
|
||||
private Serializable convertValue(Object value)
|
||||
{
|
||||
Serializable alfValue = null;
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
else if (value instanceof JBPMNode)
|
||||
{
|
||||
alfValue = ((JBPMNode)value).getNodeRef();
|
||||
}
|
||||
else if (value instanceof JBPMNodeList)
|
||||
{
|
||||
JBPMNodeList nodes = (JBPMNodeList)value;
|
||||
List<NodeRef> nodeRefs = new ArrayList<NodeRef>(nodes.size());
|
||||
for (JBPMNode node : nodes)
|
||||
{
|
||||
nodeRefs.add(node.getNodeRef());
|
||||
}
|
||||
alfValue = (Serializable)nodeRefs;
|
||||
}
|
||||
else if (value instanceof Serializable)
|
||||
{
|
||||
alfValue = (Serializable)value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new WorkflowException("Unable to convert jBPM value " + value + " to Alfresco Value - not serializable");
|
||||
}
|
||||
return alfValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Repository association to JBPMNodeList or JBPMNode
|
||||
*
|
||||
@@ -2187,15 +2436,7 @@ public class JBPMEngine extends BPMEngine
|
||||
workflowNode.name = node.getName();
|
||||
workflowNode.title = getLabel(processName + ".node." + workflowNode.name, TITLE_LABEL, workflowNode.name);
|
||||
workflowNode.description = getLabel(processName + ".node." + workflowNode.name, DESC_LABEL, workflowNode.title);
|
||||
if (node instanceof HibernateProxy)
|
||||
{
|
||||
Node realNode = (Node)((HibernateProxy)node).getHibernateLazyInitializer().getImplementation();
|
||||
workflowNode.type = realNode.getClass().getSimpleName();
|
||||
}
|
||||
else
|
||||
{
|
||||
workflowNode.type = node.getClass().getSimpleName();
|
||||
}
|
||||
workflowNode.type = getRealNode(node).getClass().getSimpleName();
|
||||
// TODO: Is there a formal way of determing if task node?
|
||||
workflowNode.isTaskNode = workflowNode.type.equals("TaskNode");
|
||||
List transitions = node.getLeavingTransitions();
|
||||
@@ -2358,6 +2599,22 @@ public class JBPMEngine extends BPMEngine
|
||||
return deployment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Workflow Timer
|
||||
* @param timer jBPM Timer
|
||||
* @return workflow timer
|
||||
*/
|
||||
protected WorkflowTimer createWorkflowTimer(Timer timer)
|
||||
{
|
||||
WorkflowTimer workflowTimer = new WorkflowTimer();
|
||||
workflowTimer.id = createGlobalId(new Long(timer.getId()).toString());
|
||||
workflowTimer.name = timer.getName();
|
||||
workflowTimer.dueDate = timer.getDueDate();
|
||||
workflowTimer.path = createWorkflowPath(timer.getToken());
|
||||
workflowTimer.task = createWorkflowTask(timer.getTaskInstance());
|
||||
return workflowTimer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Workflow Task State for the specified JBoss JBPM Task
|
||||
*
|
||||
@@ -2376,4 +2633,23 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to retrieve the real jBPM Node
|
||||
*
|
||||
* @param node Node
|
||||
* @return real Node (i.e. the one that's not a Hibernate proxy)
|
||||
*/
|
||||
private Node getRealNode(Node node)
|
||||
{
|
||||
if (node instanceof HibernateProxy)
|
||||
{
|
||||
Node realNode = (Node)((HibernateProxy)node).getHibernateLazyInitializer().getImplementation();
|
||||
return realNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -97,13 +97,21 @@ public interface WorkflowService
|
||||
public void undeployDefinition(String workflowDefinitionId);
|
||||
|
||||
/**
|
||||
* Gets all deployed Workflow Definitions
|
||||
* Gets latest deployed Workflow Definitions
|
||||
*
|
||||
* @return the deployed workflow definitions
|
||||
* @return the latest deployed workflow definitions
|
||||
*/
|
||||
@Auditable
|
||||
public List<WorkflowDefinition> getDefinitions();
|
||||
|
||||
/**
|
||||
* Gets all deployed Workflow Definitions (with all previous versions)
|
||||
*
|
||||
* @return the deployed (and previous) workflow definitions
|
||||
*/
|
||||
@Auditable
|
||||
public List<WorkflowDefinition> getAllDefinitions();
|
||||
|
||||
/**
|
||||
* Gets a Workflow Definition by unique Id
|
||||
*
|
||||
@@ -114,7 +122,7 @@ public interface WorkflowService
|
||||
public WorkflowDefinition getDefinitionById(String workflowDefinitionId);
|
||||
|
||||
/**
|
||||
* Gets a Workflow Definition by unique name
|
||||
* Gets the latest Workflow Definition by unique name
|
||||
*
|
||||
* @param workflowName workflow name e.g. jbpm://review
|
||||
* @return the deployed workflow definition (or null if not found)
|
||||
@@ -122,6 +130,15 @@ public interface WorkflowService
|
||||
@Auditable(parameters = {"workflowName"})
|
||||
public WorkflowDefinition getDefinitionByName(String workflowName);
|
||||
|
||||
/**
|
||||
* Gets all (including previous) Workflow Definitions for the given unique name
|
||||
*
|
||||
* @param workflowName workflow name e.g. jbpm://review
|
||||
* @return the deployed workflow definition (or null if not found)
|
||||
*/
|
||||
@Auditable(parameters = {"workflowName"})
|
||||
public List<WorkflowDefinition> getAllDefinitionsByName(String workflowName);
|
||||
|
||||
/**
|
||||
* Gets a graphical view of the Workflow Definition
|
||||
*
|
||||
@@ -184,6 +201,15 @@ public interface WorkflowService
|
||||
@Auditable(parameters = {"workflowId"})
|
||||
public List<WorkflowPath> getWorkflowPaths(String workflowId);
|
||||
|
||||
/**
|
||||
* Gets the properties associated with the specified path (and parent paths)
|
||||
*
|
||||
* @param pathId workflow path id
|
||||
* @return map of path properties
|
||||
*/
|
||||
@Auditable(parameters = {"pathId"})
|
||||
public Map<QName, Serializable> getPathProperties(String pathId);
|
||||
|
||||
/**
|
||||
* Cancel an "in-fligth" Workflow instance
|
||||
*
|
||||
@@ -215,6 +241,16 @@ public interface WorkflowService
|
||||
@Auditable(parameters = {"pathId", "transitionId"})
|
||||
public WorkflowPath signal(String pathId, String transitionId);
|
||||
|
||||
/**
|
||||
* Fire custom event against specified path
|
||||
*
|
||||
* @param pathId the workflow path to fire event on
|
||||
* @param event name of event
|
||||
* @return workflow path (it may have been updated as a result of firing the event
|
||||
*/
|
||||
@Auditable(parameters = {"pathId", "event"})
|
||||
public WorkflowPath fireEvent(String pathId, String event);
|
||||
|
||||
/**
|
||||
* Gets all Tasks associated with the specified path
|
||||
*
|
||||
@@ -225,6 +261,19 @@ public interface WorkflowService
|
||||
public List<WorkflowTask> getTasksForWorkflowPath(String pathId);
|
||||
|
||||
|
||||
//
|
||||
// Workflow Timer Management
|
||||
//
|
||||
|
||||
/**
|
||||
* Gets all active timers for the specified workflow
|
||||
*
|
||||
* @return the list of active timers
|
||||
*/
|
||||
@Auditable(parameters = {"workflowId"})
|
||||
public List<WorkflowTimer> getTimers(String workflowId);
|
||||
|
||||
|
||||
//
|
||||
// Task Management
|
||||
//
|
||||
@@ -263,7 +312,7 @@ public interface WorkflowService
|
||||
* @param query the filter by which tasks are queried
|
||||
* @return the list of tasks matching the specified query
|
||||
*/
|
||||
@Auditable(parameters = {"filter"})
|
||||
@Auditable(parameters = {"query"})
|
||||
public List<WorkflowTask> queryTasks(WorkflowTaskQuery query);
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.service.cmr.workflow;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class WorkflowTimer
|
||||
{
|
||||
/** Timer Id */
|
||||
public String id;
|
||||
|
||||
/** Transition Name */
|
||||
public String name;
|
||||
|
||||
/** Associated Workflow Path */
|
||||
public WorkflowPath path;
|
||||
|
||||
/** Associated Workflow Task (if any) */
|
||||
public WorkflowTask task;
|
||||
|
||||
/** Due Date */
|
||||
public Date dueDate;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return "WorkflowTimer[id=" + id + ",name=" + name + ",dueDate=" + dueDate + ",path=" + path + ",task=" + task + "]";
|
||||
}
|
||||
|
||||
}
|
36
source/test-resources/jbpmresources/test_customevent.xml
Normal file
36
source/test-resources/jbpmresources/test_customevent.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:testcustomevent">
|
||||
|
||||
<swimlane name="initiator" />
|
||||
|
||||
<start-state name="start">
|
||||
<task name="bpm:startTask" swimlane="initiator" >
|
||||
<event type="where">
|
||||
<script>
|
||||
System.out.println(taskInstance.name);
|
||||
</script>
|
||||
</event>
|
||||
</task>
|
||||
<event type="where">
|
||||
<script>
|
||||
System.out.println(node.name);
|
||||
</script>
|
||||
</event>
|
||||
<transition name="" to="customevent" />
|
||||
</start-state>
|
||||
|
||||
<task-node name="customevent">
|
||||
<task swimlane="initiator">
|
||||
<event type="where">
|
||||
<script>
|
||||
System.out.println(taskInstance.name);
|
||||
</script>
|
||||
</event>
|
||||
</task>
|
||||
<transition name="" to="end" />
|
||||
</task-node>
|
||||
|
||||
<end-state name="end" />
|
||||
|
||||
</process-definition>
|
Reference in New Issue
Block a user