mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Workflow:
- Pooled task support git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4782 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
import org.dom4j.Element;
|
||||
import org.jbpm.graph.exe.ExecutionContext;
|
||||
import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
|
||||
import org.jbpm.taskmgmt.def.AssignmentHandler;
|
||||
import org.jbpm.taskmgmt.exe.Assignable;
|
||||
|
||||
|
||||
/**
|
||||
* Assignment Handler for assigning Alfresco People and Groups to Tasks
|
||||
* and Swimlanes
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class AlfrescoAssignment implements AssignmentHandler
|
||||
{
|
||||
private static final long serialVersionUID = 1025667849552265719L;
|
||||
|
||||
private Element actor;
|
||||
private Element pooledactors;
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jbpm.taskmgmt.def.AssignmentHandler#assign(org.jbpm.taskmgmt.exe.Assignable, org.jbpm.graph.exe.ExecutionContext)
|
||||
*/
|
||||
public void assign(Assignable assignable, ExecutionContext executionContext) throws Exception
|
||||
{
|
||||
if (actor == null && pooledactors == null)
|
||||
{
|
||||
throw new WorkflowException("no actor or pooled actors has been specified");
|
||||
}
|
||||
|
||||
//
|
||||
// extract actor
|
||||
//
|
||||
|
||||
String assignedActor = null;
|
||||
if (actor != null)
|
||||
{
|
||||
String actorValStr = actor.getTextTrim();
|
||||
if (actorValStr != null && actorValStr.length() > 0)
|
||||
{
|
||||
if (actorValStr.startsWith("#{"))
|
||||
{
|
||||
Object eval = JbpmExpressionEvaluator.evaluate(actorValStr, executionContext);
|
||||
if (eval == null)
|
||||
{
|
||||
throw new WorkflowException("actor expression '" + actorValStr + "' evaluates to null");
|
||||
}
|
||||
|
||||
if (eval instanceof String)
|
||||
{
|
||||
assignedActor = (String)eval;
|
||||
}
|
||||
else if (eval instanceof JBPMNode)
|
||||
{
|
||||
JBPMNode node = (JBPMNode)eval;
|
||||
if (!node.getType().equals(ContentModel.TYPE_PERSON))
|
||||
{
|
||||
throw new WorkflowException("actor expression does not evaluate to a person");
|
||||
}
|
||||
assignedActor = (String)node.getProperties().get(ContentModel.PROP_USERNAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new WorkflowException("actor expression does not evaluate to a person");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assignedActor = actorValStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// extract pooled actors
|
||||
//
|
||||
|
||||
String[] assignedPooledActors = null;
|
||||
if (pooledactors != null)
|
||||
{
|
||||
String pooledactorValStr = pooledactors.getTextTrim();
|
||||
if (pooledactorValStr != null && pooledactorValStr.length() > 0)
|
||||
{
|
||||
if (pooledactorValStr.startsWith("#{"))
|
||||
{
|
||||
Object eval = JbpmExpressionEvaluator.evaluate(pooledactorValStr, executionContext);
|
||||
if (eval == null)
|
||||
{
|
||||
throw new WorkflowException("pooledactors expression '" + pooledactorValStr + "' evaluates to null");
|
||||
}
|
||||
|
||||
if (eval instanceof Collection)
|
||||
{
|
||||
Collection coll = (Collection)eval;
|
||||
assignedPooledActors = new String[coll.size()];
|
||||
|
||||
int i = 0;
|
||||
for (Object obj : coll)
|
||||
{
|
||||
if (!(obj instanceof JBPMNode))
|
||||
{
|
||||
throw new WorkflowException("pooledactors does not refer to a collection of people");
|
||||
}
|
||||
JBPMNode node = (JBPMNode)obj;
|
||||
if (!node.getType().equals(ContentModel.TYPE_PERSON))
|
||||
{
|
||||
throw new WorkflowException("pooledactors expression does not evaluate to a collection of people");
|
||||
}
|
||||
assignedPooledActors[i++] = (String)node.getProperties().get(ContentModel.PROP_USERNAME);
|
||||
}
|
||||
}
|
||||
else if (eval instanceof JBPMNode)
|
||||
{
|
||||
JBPMNode node = (JBPMNode)eval;
|
||||
if (node.getType().equals(ContentModel.TYPE_PERSON))
|
||||
{
|
||||
assignedPooledActors[0] = (String)node.getProperties().get(ContentModel.PROP_USERNAME);
|
||||
}
|
||||
// TODO: Support Group
|
||||
else
|
||||
{
|
||||
throw new WorkflowException("pooledactors expression does not evaluate to a collection of people");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new WorkflowException("pooledactor expression does not evaluate to a group or collection of people");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assignedPooledActors[0] = pooledactorValStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// make the assignment
|
||||
//
|
||||
if (assignedActor != null)
|
||||
{
|
||||
assignable.setActorId(assignedActor);
|
||||
}
|
||||
if (assignedPooledActors != null)
|
||||
{
|
||||
assignable.setPooledActors(assignedPooledActors);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -82,6 +82,7 @@ import org.jbpm.jpdl.par.ProcessArchive;
|
||||
import org.jbpm.jpdl.xml.JpdlXmlReader;
|
||||
import org.jbpm.jpdl.xml.Problem;
|
||||
import org.jbpm.taskmgmt.def.Task;
|
||||
import org.jbpm.taskmgmt.exe.PooledActor;
|
||||
import org.jbpm.taskmgmt.exe.TaskInstance;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springmodules.workflow.jbpm31.JbpmCallback;
|
||||
@@ -1369,9 +1370,9 @@ public class JBPMEngine extends BPMEngine
|
||||
if (pooledActors != null)
|
||||
{
|
||||
List<NodeRef> pooledNodeRefs = new ArrayList<NodeRef>(pooledActors.size());
|
||||
for (String pooledActor : (Set<String>)pooledActors)
|
||||
for (PooledActor pooledActor : (Set<PooledActor>)pooledActors)
|
||||
{
|
||||
NodeRef pooledNodeRef = mapNameToAuthority(pooledActor);
|
||||
NodeRef pooledNodeRef = mapNameToAuthority(pooledActor.getActorId());
|
||||
if (pooledNodeRef != null)
|
||||
{
|
||||
pooledNodeRefs.add(pooledNodeRef);
|
||||
@@ -1746,7 +1747,7 @@ public class JBPMEngine extends BPMEngine
|
||||
if (isMany)
|
||||
{
|
||||
// convert single node ref to list of node refs
|
||||
JBPMNodeList values = new JBPMNodeList();
|
||||
JBPMNodeList values = new JBPMNodeList(serviceRegistry);
|
||||
values.add(new JBPMNode((NodeRef)value, serviceRegistry));
|
||||
value = (Serializable)values;
|
||||
}
|
||||
@@ -1759,7 +1760,7 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
if (isMany)
|
||||
{
|
||||
JBPMNodeList values = new JBPMNodeList();
|
||||
JBPMNodeList values = new JBPMNodeList(serviceRegistry);
|
||||
for (NodeRef nodeRef : (List<NodeRef>)value)
|
||||
{
|
||||
values.add(new JBPMNode(nodeRef, serviceRegistry));
|
||||
|
@@ -1,9 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
import org.alfresco.service.namespace.QNameMap;
|
||||
|
||||
|
||||
/**
|
||||
* List of jBPM Nodes
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class JBPMNodeList extends ArrayList<JBPMNode>
|
||||
{
|
||||
private static final long serialVersionUID = 1376915749912156471L;
|
||||
|
||||
protected ServiceRegistry services;
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param services services
|
||||
*/
|
||||
public JBPMNodeList(ServiceRegistry services)
|
||||
{
|
||||
super();
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor to retrieve a named property on all nodes in the list
|
||||
*
|
||||
* @param propertyName the name of the property to retrieve
|
||||
* @return a collection of property name values
|
||||
*/
|
||||
public Map<String, Collection<Object>> getValues(String propertyName)
|
||||
{
|
||||
ValuesMap<String, Collection<Object>> values = new ValuesMap<String, Collection<Object>>(null);
|
||||
|
||||
for (int i = 0; i < JBPMNodeList.this.size(); i++)
|
||||
{
|
||||
JBPMNode node = JBPMNodeList.this.get(i);
|
||||
Map<String, Object> nodeValues = node.getProperties();
|
||||
for (String key : nodeValues.keySet())
|
||||
{
|
||||
values.put(key, null);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
public class ValuesMap<K, V> extends QNameMap<K, V>
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -6463958742416258009L;
|
||||
|
||||
|
||||
public ValuesMap(NamespacePrefixResolver resolver)
|
||||
{
|
||||
super(resolver);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object get(Object key)
|
||||
{
|
||||
Collection<Object> values = null;
|
||||
if (containsKey(key))
|
||||
{
|
||||
values = new ArrayList<Object>(this.size());
|
||||
|
||||
for (int i = 0; i < JBPMNodeList.this.size(); i++)
|
||||
{
|
||||
JBPMNode node = JBPMNodeList.this.get(i);
|
||||
Object value = node.getProperties().get(key);
|
||||
values.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -83,7 +83,7 @@ public class NodeListConverter extends SerializableToByteArrayConverter
|
||||
BeanFactoryReference factory = jbpmFactoryLocator.useBeanFactory(null);
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry)factory.getFactory().getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
|
||||
JBPMNodeList nodes = new JBPMNodeList();
|
||||
JBPMNodeList nodes = new JBPMNodeList(serviceRegistry);
|
||||
for (NodeRef nodeRef : nodeRefs)
|
||||
{
|
||||
nodes.add(new JBPMNode(nodeRef, serviceRegistry));
|
||||
|
@@ -1,70 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:adhoc">
|
||||
|
||||
<swimlane name="initiator"/>
|
||||
|
||||
<start-state name="start">
|
||||
<task name="wf:submitAdhocTask" swimlane="initiator">
|
||||
<controller>
|
||||
<variable name="assignee" access="write" mapped-name="wf:assignee"/>
|
||||
<variable name="adhocduedate" access="write" mapped-name="wf:adhocDueDate"/>
|
||||
<variable name="adhocpriority" access="write" mapped-name="wf:adhocPriority"/>
|
||||
<variable name="adhocdescription" access="write" mapped-name="wf:adhocDescription"/>
|
||||
<variable name="notify" access="write" mapped-name="wf:notifyMe"/>
|
||||
<variable name="workflowpackage" access="write" mapped-name="bpm:package"/>
|
||||
<variable name="workflowcontext" access="write" mapped-name="bpm:context"/>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="adhoc"/>
|
||||
</start-state>
|
||||
|
||||
<swimlane name="assignee">
|
||||
<assignment actor-id="#{assignee.properties['cm:userName']}"/>
|
||||
</swimlane>
|
||||
|
||||
<task-node name="adhoc">
|
||||
<event type="task-create">
|
||||
<script>
|
||||
taskInstance.dueDate = adhocduedate;
|
||||
taskInstance.priority = adhocpriority;
|
||||
</script>
|
||||
</event>
|
||||
<task name="wf:adhocTask" swimlane="assignee">
|
||||
<controller>
|
||||
<variable name="adhocdescription" access="read" mapped-name="wf:adhocDescription"/>
|
||||
<variable name="workflowpackage" access="read" mapped-name="bpm:package"/>
|
||||
<variable name="workflowcontext" access="read" mapped-name="bpm:context"/>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="completed">
|
||||
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
|
||||
<script>
|
||||
if (notify)
|
||||
{
|
||||
var mail = actions.create("mail");
|
||||
mail.parameters.to = initiator.properties["cm:email"];
|
||||
mail.parameters.subject = "Adhoc Task " + adhocdescription;
|
||||
mail.parameters.from = assignee.properties["cm:email"];
|
||||
mail.parameters.text = "It's done";
|
||||
mail.execute(workflowpackage);
|
||||
}
|
||||
</script>
|
||||
</action>
|
||||
</transition>
|
||||
</task-node>
|
||||
|
||||
<task-node name="completed">
|
||||
<task name="wf:completedAdhocTask" swimlane="initiator">
|
||||
<controller>
|
||||
<variable name="adhocdescription" access="read" mapped-name="wf:adhocDescription"/>
|
||||
<variable name="workflowpackage" access="read" mapped-name="bpm:package"/>
|
||||
<variable name="workflowcontext" access="read" mapped-name="bpm:context"/>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="end"/>
|
||||
</task-node>
|
||||
|
||||
<end-state name="end"/>
|
||||
|
||||
</process-definition>
|
@@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:review">
|
||||
|
||||
<swimlane name="initiator"/>
|
||||
|
||||
<start-state name="start">
|
||||
<task name="wf:submitReviewTask" swimlane="initiator">
|
||||
<controller>
|
||||
<variable name="reviewer" access="write" mapped-name="wf:reviewer"/>
|
||||
<variable name="reviewduedate" access="write" mapped-name="wf:reviewDueDate"/>
|
||||
<variable name="reviewpriority" access="write" mapped-name="wf:reviewPriority"/>
|
||||
<variable name="package" access="write" mapped-name="bpm:package"/>
|
||||
<variable name="context" access="write" mapped-name="bpm:context"/>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="review"/>
|
||||
</start-state>
|
||||
|
||||
<swimlane name="reviewer">
|
||||
<assignment actor-id="#{reviewer.properties['cm:userName']}"/>
|
||||
</swimlane>
|
||||
|
||||
<task-node name="review">
|
||||
<task name="wf:reviewTask" swimlane="reviewer">
|
||||
<event type="task-create">
|
||||
<script>
|
||||
taskInstance.dueDate = reviewduedate;
|
||||
taskInstance.priority = reviewpriority;
|
||||
</script>
|
||||
</event>
|
||||
<controller>
|
||||
<variable name="package" access="read,required" mapped-name="bpm:package"/>
|
||||
<variable name="context" access="read,required" mapped-name="bpm:context"/>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="reject" to="rejected"/>
|
||||
<transition name="approve" to="approved"/>
|
||||
</task-node>
|
||||
|
||||
<task-node name="rejected">
|
||||
<task name="wf:rejectedTask" swimlane="initiator">
|
||||
<controller>
|
||||
<variable name="package" access="read,required" mapped-name="bpm:package"/>
|
||||
<variable name="context" access="read,required" mapped-name="bpm:context"/>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="end"/>
|
||||
</task-node>
|
||||
|
||||
<task-node name="approved">
|
||||
<task name="wf:approvedTask" swimlane="initiator">
|
||||
<controller>
|
||||
<variable name="package" access="read,required" mapped-name="bpm:package"/>
|
||||
<variable name="context" access="read,required" mapped-name="bpm:context"/>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="end"/>
|
||||
</task-node>
|
||||
|
||||
<end-state name="end"/>
|
||||
|
||||
</process-definition>
|
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:pooledtasks">
|
||||
|
||||
<swimlane name="initiator" />
|
||||
|
||||
<start-state name="start">
|
||||
<task name="wf:submitParallelReviewTask" swimlane="initiator" />
|
||||
<transition name="" to="review" />
|
||||
</start-state>
|
||||
|
||||
<swimlane name="reviewer">
|
||||
<assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
|
||||
<pooledactors>#{bpm_assignees}</pooledactors>
|
||||
</assignment>
|
||||
</swimlane>
|
||||
|
||||
<task-node name="review">
|
||||
<task name="wf:reviewTask" swimlane="reviewer"/>
|
||||
<transition name="" to="end" />
|
||||
</task-node>
|
||||
|
||||
<end-state name="end" />
|
||||
|
||||
</process-definition>
|
Reference in New Issue
Block a user