mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
ALF-2764 Fixed an issue with the ForEachFork incorrectly naming the paths it creates resulting in attempts to cancel the path failing.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22693 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,87 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:parallelreview">
|
||||||
|
|
||||||
|
<swimlane name="initiator" />
|
||||||
|
|
||||||
|
<start-state name="start">
|
||||||
|
<task name="wf:submitParallelReviewTask" swimlane="initiator" />
|
||||||
|
<transition name="" to="startreview"/>
|
||||||
|
</start-state>
|
||||||
|
|
||||||
|
<node name="startreview">
|
||||||
|
<action class="org.alfresco.repo.workflow.jbpm.ForEachFork">
|
||||||
|
<foreach>#{bpm_assignees}</foreach>
|
||||||
|
<var>reviewer</var>
|
||||||
|
</action>
|
||||||
|
<event type="node-enter">
|
||||||
|
<script>
|
||||||
|
<variable name="wf_approveCount" access="write" />
|
||||||
|
<expression>
|
||||||
|
wf_approveCount = 0;
|
||||||
|
</expression>
|
||||||
|
</script>
|
||||||
|
</event>
|
||||||
|
<transition name="review" to="review" />
|
||||||
|
</node>
|
||||||
|
|
||||||
|
<task-node name="review">
|
||||||
|
<task name="wf:reviewTask">
|
||||||
|
<assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
|
||||||
|
<actor>#{reviewer}</actor>
|
||||||
|
</assignment>
|
||||||
|
<event type="task-create">
|
||||||
|
<script>
|
||||||
|
if (bpm_workflowDueDate != void) taskInstance.dueDate = bpm_workflowDueDate;
|
||||||
|
if (bpm_workflowPriority != void) taskInstance.priority = bpm_workflowPriority;
|
||||||
|
</script>
|
||||||
|
</event>
|
||||||
|
</task>
|
||||||
|
<transition name="approve" to="endreview">
|
||||||
|
<script>
|
||||||
|
<variable name="wf_approveCount" access="read,write" />
|
||||||
|
<expression>
|
||||||
|
wf_approveCount = wf_approveCount +1;
|
||||||
|
</expression>
|
||||||
|
</script>
|
||||||
|
</transition>
|
||||||
|
<transition name="reject" to="endreview" />
|
||||||
|
</task-node>
|
||||||
|
|
||||||
|
<join name="endreview">
|
||||||
|
<transition to="isapproved" />
|
||||||
|
</join>
|
||||||
|
|
||||||
|
<decision name="isapproved">
|
||||||
|
<event type="node-enter">
|
||||||
|
<script>
|
||||||
|
<variable name="wf_reviewerCount" access="write"/>
|
||||||
|
<variable name="wf_requiredPercent" access="write"/>
|
||||||
|
<variable name="wf_actualPercent" access="write"/>
|
||||||
|
<expression>
|
||||||
|
wf_requiredPercent = wf_requiredApprovePercent;
|
||||||
|
wf_reviewerCount = bpm_assignees.size();
|
||||||
|
wf_actualPercent = ((wf_approveCount * 100) / wf_reviewerCount);
|
||||||
|
</expression>
|
||||||
|
</script>
|
||||||
|
</event>
|
||||||
|
<transition name="reject" to="rejected" />
|
||||||
|
<transition name="approve" to="approved">
|
||||||
|
<condition>#{wf_actualPercent >= wf_requiredApprovePercent}</condition>
|
||||||
|
</transition>
|
||||||
|
</decision>
|
||||||
|
|
||||||
|
<task-node name="rejected">
|
||||||
|
<task name="wf:rejectedParallelTask" swimlane="initiator" />
|
||||||
|
<transition to="startreview" name="again" />
|
||||||
|
<transition to="end" />
|
||||||
|
</task-node>
|
||||||
|
|
||||||
|
<task-node name="approved">
|
||||||
|
<task name="wf:approvedParallelTask" swimlane="initiator" />
|
||||||
|
<transition to="end" />
|
||||||
|
</task-node>
|
||||||
|
|
||||||
|
<end-state name="end"/>
|
||||||
|
|
||||||
|
</process-definition>
|
@@ -66,6 +66,7 @@ public interface WorkflowModel
|
|||||||
static final QName PROP_WORKFLOW_PRIORITY = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPriority");
|
static final QName PROP_WORKFLOW_PRIORITY = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPriority");
|
||||||
static final QName PROP_WORKFLOW_DUE_DATE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDueDate");
|
static final QName PROP_WORKFLOW_DUE_DATE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDueDate");
|
||||||
static final QName ASSOC_ASSIGNEE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "assignee");
|
static final QName ASSOC_ASSIGNEE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "assignee");
|
||||||
|
static final QName ASSOC_ASSIGNEES = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "assignees");
|
||||||
|
|
||||||
// workflow package
|
// workflow package
|
||||||
static final QName ASPECT_WORKFLOW_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPackage");
|
static final QName ASPECT_WORKFLOW_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPackage");
|
||||||
|
@@ -20,6 +20,7 @@ package org.alfresco.repo.workflow.jbpm;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -47,7 +48,6 @@ public class ForEachFork extends JBPMSpringActionHandler
|
|||||||
private Element foreach;
|
private Element foreach;
|
||||||
private String var;
|
private String var;
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler#initialiseHandler(org.springframework.beans.factory.BeanFactory)
|
* @see org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler#initialiseHandler(org.springframework.beans.factory.BeanFactory)
|
||||||
*/
|
*/
|
||||||
@@ -63,7 +63,6 @@ public class ForEachFork extends JBPMSpringActionHandler
|
|||||||
* @param executionContext
|
* @param executionContext
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void execute(final ExecutionContext executionContext)
|
public void execute(final ExecutionContext executionContext)
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
@@ -76,57 +75,7 @@ public class ForEachFork extends JBPMSpringActionHandler
|
|||||||
throw new WorkflowException("forEach has not been provided");
|
throw new WorkflowException("forEach has not been provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
// build "for each" collection
|
// Collection<?> forEachColl = buildForEachCollection(executionContext);
|
||||||
List forEachColl = null;
|
|
||||||
String forEachCollStr = foreach.getTextTrim();
|
|
||||||
if (forEachCollStr != null)
|
|
||||||
{
|
|
||||||
if (forEachCollStr.startsWith("#{"))
|
|
||||||
{
|
|
||||||
String expression = forEachCollStr.substring(2, forEachCollStr.length() -1);
|
|
||||||
Object eval = AlfrescoJavaScript.executeScript(executionContext, services, expression, null);
|
|
||||||
if (eval == null)
|
|
||||||
{
|
|
||||||
throw new WorkflowException("forEach expression '" + forEachCollStr + "' evaluates to null");
|
|
||||||
}
|
|
||||||
|
|
||||||
// expression evaluates to string
|
|
||||||
if (eval instanceof String)
|
|
||||||
{
|
|
||||||
String[] forEachStrs = ((String)eval).trim().split(",");
|
|
||||||
forEachColl = new ArrayList(forEachStrs.length);
|
|
||||||
for (String forEachStr : forEachStrs)
|
|
||||||
{
|
|
||||||
forEachColl.add(forEachStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// expression evaluates to Node array
|
|
||||||
else if (eval instanceof Serializable[])
|
|
||||||
{
|
|
||||||
Serializable[] nodes = (Serializable[])eval;
|
|
||||||
forEachColl = new ArrayList(nodes.length);
|
|
||||||
for (Serializable node : nodes)
|
|
||||||
{
|
|
||||||
if (node instanceof NodeRef)
|
|
||||||
{
|
|
||||||
forEachColl.add(new JBPMNode((NodeRef)node, services));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// expression evaluates to collection
|
|
||||||
else if (eval instanceof Collection)
|
|
||||||
{
|
|
||||||
forEachColl = (List)eval;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
forEachColl = (List)FieldInstantiator.getValue(List.class, foreach);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (var == null || var.length() == 0)
|
if (var == null || var.length() == 0)
|
||||||
{
|
{
|
||||||
@@ -137,31 +86,30 @@ public class ForEachFork extends JBPMSpringActionHandler
|
|||||||
// create forked paths
|
// create forked paths
|
||||||
//
|
//
|
||||||
|
|
||||||
Token rootToken = executionContext.getToken();
|
|
||||||
Node node = executionContext.getNode();
|
Node node = executionContext.getNode();
|
||||||
List<ForkedTransition> forkTransitions = new ArrayList<ForkedTransition>();
|
List<ForkedTransition> forkTransitions = new ArrayList<ForkedTransition>();
|
||||||
|
|
||||||
// first, create a new token and execution context for each item in list
|
Collection<?> forEachColl = buildForEachCollection(executionContext);
|
||||||
for (int i = 0; i < node.getLeavingTransitions().size(); i++)
|
|
||||||
{
|
|
||||||
Transition transition = (Transition) node.getLeavingTransitions().get(i);
|
|
||||||
|
|
||||||
for (int iVar = 0; iVar < forEachColl.size(); iVar++)
|
// Create a new token and execution context for each node transition and item in list
|
||||||
|
List<Transition> nodeTransitions = node.getLeavingTransitions();
|
||||||
|
for (Transition noderansition : nodeTransitions)
|
||||||
|
{
|
||||||
|
int iVar = 0;
|
||||||
|
for (Object item: forEachColl)
|
||||||
{
|
{
|
||||||
// create child token to represent new path
|
// create child token to represent new path
|
||||||
String tokenName = getTokenName(rootToken, transition.getName(), iVar);
|
Token loopToken = buildChildToken(executionContext, noderansition, iVar);
|
||||||
Token loopToken = new Token(rootToken, tokenName);
|
iVar++;
|
||||||
loopToken.setTerminationImplicit(true);
|
|
||||||
executionContext.getJbpmContext().getSession().save(loopToken);
|
|
||||||
|
|
||||||
// assign variable within path
|
// assign variable within path
|
||||||
final ExecutionContext newExecutionContext = new ExecutionContext(loopToken);
|
final ExecutionContext newExecutionContext = new ExecutionContext(loopToken);
|
||||||
newExecutionContext.getContextInstance().createVariable(var, forEachColl.get(iVar), loopToken);
|
newExecutionContext.getContextInstance().createVariable(var, item, loopToken);
|
||||||
|
|
||||||
// record path & transition
|
// record path & transition
|
||||||
ForkedTransition forkTransition = new ForkedTransition();
|
ForkedTransition forkTransition = new ForkedTransition();
|
||||||
forkTransition.executionContext = newExecutionContext;
|
forkTransition.executionContext = newExecutionContext;
|
||||||
forkTransition.transition = transition;
|
forkTransition.transition = noderansition;
|
||||||
forkTransitions.add(forkTransition);
|
forkTransitions.add(forkTransition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,6 +123,74 @@ public class ForEachFork extends JBPMSpringActionHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Token buildChildToken(final ExecutionContext executionContext, Transition noderansition,
|
||||||
|
int iVar)
|
||||||
|
{
|
||||||
|
Token rootToken = executionContext.getToken();
|
||||||
|
String tokenName = getTokenName(rootToken, noderansition.getName(), iVar);
|
||||||
|
Token loopToken = new Token(rootToken, tokenName);
|
||||||
|
loopToken.setTerminationImplicit(true);
|
||||||
|
executionContext.getJbpmContext().getSession().save(loopToken);
|
||||||
|
return loopToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<?> buildForEachCollection(final ExecutionContext executionContext)
|
||||||
|
{
|
||||||
|
// build "for each" collection
|
||||||
|
String text = foreach.getTextTrim();
|
||||||
|
if (text != null && text.startsWith("#{"))
|
||||||
|
{
|
||||||
|
return evaluateForEachExpression(executionContext, text);
|
||||||
|
}
|
||||||
|
return (Collection<?>) FieldInstantiator.getValue(List.class, foreach);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<?> evaluateForEachExpression(final ExecutionContext executionContext, String forEachText)
|
||||||
|
{
|
||||||
|
String expression = forEachText.substring(2, forEachText.length() -1);
|
||||||
|
Object result = AlfrescoJavaScript.executeScript(executionContext, services, expression, null);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
throw new WorkflowException("forEach expression '" + forEachText + "' evaluates to null");
|
||||||
|
}
|
||||||
|
// expression evaluates to string
|
||||||
|
if (result instanceof String)
|
||||||
|
{
|
||||||
|
return buildStrings((String)result);
|
||||||
|
}
|
||||||
|
// expression evaluates to Node array
|
||||||
|
else if (result instanceof Serializable[])
|
||||||
|
{
|
||||||
|
return buildJbpmNodes((Serializable[]) result);
|
||||||
|
}
|
||||||
|
// expression evaluates to collection
|
||||||
|
else if (result instanceof Collection<?>)
|
||||||
|
{
|
||||||
|
return (Collection<?>)result;
|
||||||
|
}
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<?> buildStrings(String result)
|
||||||
|
{
|
||||||
|
String[] results = result.trim().split(",");
|
||||||
|
return Arrays.asList(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<?> buildJbpmNodes(Serializable[] nodes)
|
||||||
|
{
|
||||||
|
List<JBPMNode> jbpmNodes = new ArrayList<JBPMNode>(nodes.length);
|
||||||
|
for (Serializable node : nodes)
|
||||||
|
{
|
||||||
|
if (node instanceof NodeRef)
|
||||||
|
{
|
||||||
|
JBPMNode jbpmNode = new JBPMNode((NodeRef)node, services);
|
||||||
|
jbpmNodes.add(jbpmNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jbpmNodes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a token name
|
* Create a token name
|
||||||
*
|
*
|
||||||
@@ -184,33 +200,53 @@ public class ForEachFork extends JBPMSpringActionHandler
|
|||||||
*/
|
*/
|
||||||
protected String getTokenName(Token parent, String transitionName, int loopIndex)
|
protected String getTokenName(Token parent, String transitionName, int loopIndex)
|
||||||
{
|
{
|
||||||
String tokenName = null;
|
String suffix = "." + loopIndex;
|
||||||
if (transitionName != null && transitionName.length() > 0)
|
if (transitionName == null || transitionName.isEmpty())
|
||||||
{
|
{
|
||||||
if (!parent.hasChild(transitionName))
|
// No transition name
|
||||||
{
|
|
||||||
tokenName = transitionName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int i = 2;
|
|
||||||
tokenName = transitionName + Integer.toString(i);
|
|
||||||
while (parent.hasChild(tokenName))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
tokenName = transitionName + Integer.toString(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// no transition name
|
|
||||||
int size = (parent.getChildren() != null) ? parent.getChildren().size() + 1 : 1;
|
int size = (parent.getChildren() != null) ? parent.getChildren().size() + 1 : 1;
|
||||||
tokenName = "FOREACHFORK" + Integer.toString(size);
|
return buildTokenName("FOREACHFORK", suffix, size);
|
||||||
}
|
}
|
||||||
return tokenName + "." + loopIndex;
|
return findFirstAvailableTokenName(parent, transitionName, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String findFirstAvailableTokenName(Token parent, String transitionName, String suffix)
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
String tokenName = buildTokenName(transitionName, suffix, i);
|
||||||
|
if(!parent.hasChild(tokenName))
|
||||||
|
{
|
||||||
|
return tokenName;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildTokenName(String prefix, String suffix, int count)
|
||||||
|
{
|
||||||
|
String countStr = count<2 ? "": Integer.toString(count);
|
||||||
|
return prefix + countStr + suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the list of objects to be iterated over.
|
||||||
|
* @param foreach the list of objects to set
|
||||||
|
*/
|
||||||
|
public void setForeach(Element foreach)
|
||||||
|
{
|
||||||
|
this.foreach = foreach;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the name of the variable to which the eleements of <code>foreach</code> are assigned.
|
||||||
|
* @param var the variable name to set
|
||||||
|
*/
|
||||||
|
public void setVar(String var)
|
||||||
|
{
|
||||||
|
this.var = var;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fork Transition
|
* Fork Transition
|
||||||
|
@@ -21,25 +21,22 @@ package org.alfresco.repo.workflow.jbpm;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.extensions.surf.util.I18NUtil;
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
||||||
import org.alfresco.repo.workflow.TaskComponent;
|
import org.alfresco.repo.workflow.TaskComponent;
|
||||||
import org.alfresco.repo.workflow.WorkflowComponent;
|
import org.alfresco.repo.workflow.WorkflowComponent;
|
||||||
import org.alfresco.repo.workflow.WorkflowModel;
|
import org.alfresco.repo.workflow.WorkflowModel;
|
||||||
import org.alfresco.repo.workflow.WorkflowPackageComponent;
|
import org.alfresco.repo.workflow.WorkflowPackageComponent;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
|
||||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||||
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||||
@@ -49,8 +46,10 @@ import org.alfresco.service.cmr.workflow.WorkflowTask;
|
|||||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.BaseSpringTest;
|
import org.alfresco.util.BaseAlfrescoSpringTest;
|
||||||
|
import org.alfresco.util.PropertyMap;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.extensions.surf.util.I18NUtil;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,22 +57,39 @@ import org.springframework.core.io.ClassPathResource;
|
|||||||
*
|
*
|
||||||
* @author davidc
|
* @author davidc
|
||||||
*/
|
*/
|
||||||
public class JBPMEngineTest extends BaseSpringTest
|
public class JBPMEngineTest extends BaseAlfrescoSpringTest
|
||||||
{
|
{
|
||||||
AuthenticationComponent authenticationComponent;
|
/**
|
||||||
NodeService nodeService;
|
*
|
||||||
WorkflowComponent workflowComponent;
|
*/
|
||||||
TaskComponent taskComponent;
|
private static final String USER3 = "JbpmEngineTestJoe";
|
||||||
WorkflowPackageComponent packageComponent;
|
/**
|
||||||
WorkflowDefinition testWorkflowDef;
|
*
|
||||||
NodeRef testNodeRef;
|
*/
|
||||||
|
private static final String USER2 = "JbpmEngineTestJane";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final String USER1 = "JbpmEngineTestJohn";
|
||||||
|
private WorkflowComponent workflowComponent;
|
||||||
|
private TaskComponent taskComponent;
|
||||||
|
private WorkflowPackageComponent packageComponent;
|
||||||
|
private PersonService personService;
|
||||||
|
private WorkflowDefinition testWorkflowDef;
|
||||||
|
private NodeRef person1;
|
||||||
|
private NodeRef person2;
|
||||||
|
private NodeRef person3;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
protected void onSetUpInTransaction() throws Exception
|
protected void onSetUpInTransaction() throws Exception
|
||||||
{
|
{
|
||||||
// run as system
|
super.onSetUpInTransaction();
|
||||||
authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent");
|
|
||||||
authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName());
|
personService = (PersonService) applicationContext.getBean("PersonService");
|
||||||
|
person1 = createPerson(USER1);
|
||||||
|
person2 = createPerson(USER2);
|
||||||
|
person3 = createPerson(USER3);
|
||||||
|
|
||||||
BPMEngineRegistry registry = (BPMEngineRegistry)applicationContext.getBean("bpm_engineRegistry");
|
BPMEngineRegistry registry = (BPMEngineRegistry)applicationContext.getBean("bpm_engineRegistry");
|
||||||
workflowComponent = registry.getWorkflowComponent("jbpm");
|
workflowComponent = registry.getWorkflowComponent("jbpm");
|
||||||
@@ -93,20 +109,9 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
assertEquals("1", testWorkflowDef.version);
|
assertEquals("1", testWorkflowDef.version);
|
||||||
assertTrue(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
assertTrue(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
||||||
|
|
||||||
// get valid node ref
|
authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName());
|
||||||
nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName());
|
|
||||||
testNodeRef = nodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"));
|
|
||||||
nodeService.setProperty(testNodeRef, ContentModel.PROP_CREATED, new Date());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onTearDownInTransaction()
|
|
||||||
{
|
|
||||||
authenticationComponent.clearCurrentSecurityContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void testGetWorkflowDefinitions()
|
public void testGetWorkflowDefinitions()
|
||||||
{
|
{
|
||||||
List<WorkflowDefinition> workflowDefs = workflowComponent.getDefinitions();
|
List<WorkflowDefinition> workflowDefs = workflowComponent.getDefinitions();
|
||||||
@@ -135,6 +140,7 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
}
|
}
|
||||||
catch(WorkflowException e)
|
catch(WorkflowException e)
|
||||||
{
|
{
|
||||||
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Determine why process definition is loaded, even though it doesn't exist
|
// TODO: Determine why process definition is loaded, even though it doesn't exist
|
||||||
@@ -325,7 +331,7 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testCancelWorkflowInstance()
|
public void testCancelWorkflowInstance() throws Exception
|
||||||
{
|
{
|
||||||
WorkflowDefinition workflowDef = getTestDefinition();
|
WorkflowDefinition workflowDef = getTestDefinition();
|
||||||
workflowComponent.startWorkflow(workflowDef.id, null);
|
workflowComponent.startWorkflow(workflowDef.id, null);
|
||||||
@@ -348,10 +354,79 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See Alf-2764 in Jira.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void testCancelForEachFork() throws Exception
|
||||||
|
{
|
||||||
|
// Deploy Parallel Loop Review process definition.
|
||||||
|
ClassPathResource processDef = new ClassPathResource("test/alfresco/parallel_loop_review_processdefinition.xml");
|
||||||
|
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(),
|
||||||
|
MimetypeMap.MIMETYPE_XML);
|
||||||
|
WorkflowDefinition parallelDef = deployment.getDefinition();
|
||||||
|
assertNotNull(parallelDef);
|
||||||
|
|
||||||
|
// Set Current User to USER1.
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(USER1);
|
||||||
|
|
||||||
|
// Set up parameters
|
||||||
|
QName approvePercentName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "requiredApprovePercent");
|
||||||
|
NodeRef pckgNode = packageComponent.createPackage(null);
|
||||||
|
List<NodeRef> assignees = Arrays.asList(person1, person2, person3);
|
||||||
|
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||||
|
parameters.put(WorkflowModel.ASSOC_ASSIGNEES, (Serializable) assignees);
|
||||||
|
parameters.put(WorkflowModel.ASSOC_PACKAGE, pckgNode);
|
||||||
|
parameters.put(approvePercentName, 60f );
|
||||||
|
|
||||||
|
// Start workflow
|
||||||
|
WorkflowPath path = workflowComponent.startWorkflow(parallelDef.getId(), parameters);
|
||||||
|
WorkflowTask startTask = workflowComponent.getTasksForWorkflowPath(path.getId()).get(0);
|
||||||
|
taskComponent.endTask(startTask.getId(), null);
|
||||||
|
checkInstanceExists(path.instance.getId(), parallelDef.getId(), true);
|
||||||
|
|
||||||
|
// Set all users to reject document.
|
||||||
|
ParallelReject(USER1);
|
||||||
|
ParallelReject(USER2);
|
||||||
|
ParallelReject(USER3);
|
||||||
|
|
||||||
|
// Send review back round the loop.
|
||||||
|
List<WorkflowTask> tasks = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||||
|
assertEquals(1, tasks.size());
|
||||||
|
taskComponent.endTask(tasks.get(0).getId(), "again");
|
||||||
|
|
||||||
|
// Try to cancel workflow
|
||||||
|
WorkflowInstance cancelledWf = workflowComponent.cancelWorkflow(path.getInstance().getId());
|
||||||
|
checkInstanceExists(cancelledWf.getId(), parallelDef.getId(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkInstanceExists(String instanceId, String defId, boolean expected)
|
||||||
|
{
|
||||||
|
boolean match=false;
|
||||||
|
List<WorkflowInstance> activeWfs = workflowComponent.getActiveWorkflows(defId);
|
||||||
|
for (WorkflowInstance instance : activeWfs)
|
||||||
|
{
|
||||||
|
if(instance.getId().equals(instanceId))
|
||||||
|
{
|
||||||
|
match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertEquals( expected, match);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParallelReject(String user)
|
||||||
|
{
|
||||||
|
List<WorkflowTask> tasks = taskComponent.getAssignedTasks(user, WorkflowTaskState.IN_PROGRESS);
|
||||||
|
assertEquals(1, tasks.size());
|
||||||
|
WorkflowTask task = tasks.get(0);
|
||||||
|
taskComponent.endTask(task.getId(), "reject");
|
||||||
|
}
|
||||||
|
|
||||||
public void testSignal()
|
public void testSignal()
|
||||||
{
|
{
|
||||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||||
WorkflowDefinition workflowDef = getTestDefinition();
|
WorkflowDefinition workflowDef = getTestDefinition();
|
||||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||||
assertNotNull(path);
|
assertNotNull(path);
|
||||||
@@ -365,7 +440,7 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
WorkflowDefinition workflowDef = getTestDefinition();
|
WorkflowDefinition workflowDef = getTestDefinition();
|
||||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||||
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
||||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||||
assertNotNull(path);
|
assertNotNull(path);
|
||||||
@@ -395,7 +470,7 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
bpm_assignees.add("fred");
|
bpm_assignees.add("fred");
|
||||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||||
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "assignees"), (Serializable)bpm_assignees);
|
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "assignees"), (Serializable)bpm_assignees);
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||||
assertNotNull(path);
|
assertNotNull(path);
|
||||||
List<WorkflowTask> tasks = workflowComponent.getTasksForWorkflowPath(path.id);
|
List<WorkflowTask> tasks = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||||
@@ -411,7 +486,7 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
WorkflowDefinition workflowDef = getTestDefinition();
|
WorkflowDefinition workflowDef = getTestDefinition();
|
||||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||||
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
||||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||||
assertNotNull(path);
|
assertNotNull(path);
|
||||||
@@ -435,7 +510,7 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
WorkflowDefinition workflowDef = getTestDefinition();
|
WorkflowDefinition workflowDef = getTestDefinition();
|
||||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||||
assertNotNull(path);
|
assertNotNull(path);
|
||||||
assertNotNull(path);
|
assertNotNull(path);
|
||||||
@@ -453,7 +528,7 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
WorkflowDefinition workflowDef = getTestDefinition();
|
WorkflowDefinition workflowDef = getTestDefinition();
|
||||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||||
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
||||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||||
assertNotNull(path);
|
assertNotNull(path);
|
||||||
@@ -477,7 +552,7 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
|
|
||||||
WorkflowDefinition workflowDef = deployment.definition;
|
WorkflowDefinition workflowDef = deployment.definition;
|
||||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||||
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
||||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||||
assertNotNull(path);
|
assertNotNull(path);
|
||||||
@@ -501,6 +576,29 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private NodeRef createPerson(String userName)
|
||||||
|
{
|
||||||
|
// if user with given user name doesn't already exist then create user
|
||||||
|
if (this.authenticationService.authenticationExists(userName) == false)
|
||||||
|
{
|
||||||
|
// create user
|
||||||
|
this.authenticationService.createAuthentication(userName, "password".toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
// if person node with given user name doesn't already exist then create
|
||||||
|
// person
|
||||||
|
if (this.personService.personExists(userName) == false)
|
||||||
|
{
|
||||||
|
// create person properties
|
||||||
|
PropertyMap personProps = new PropertyMap();
|
||||||
|
personProps.put(ContentModel.PROP_USERNAME, userName);
|
||||||
|
|
||||||
|
// create person node for user
|
||||||
|
return personService.createPerson(personProps);
|
||||||
|
}
|
||||||
|
return personService.getPerson(userName);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter task list by workflow instance
|
* Filter task list by workflow instance
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user