mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Workflow:
1) Associations to people are recorded as person nodes in the process context (for access to name, e-mail etc) 2) Short-term solution for Beanshell, Javascript compatibility 3) Small adjustment to Review & Approve process definition to support workflow package git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3555 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -44,6 +44,7 @@ import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
|||||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||||
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.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||||
import org.alfresco.service.cmr.security.PersonService;
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
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;
|
||||||
@@ -98,7 +99,7 @@ public class JBPMEngine extends BPMEngine
|
|||||||
protected NodeService nodeService;
|
protected NodeService nodeService;
|
||||||
protected ServiceRegistry serviceRegistry;
|
protected ServiceRegistry serviceRegistry;
|
||||||
protected PersonService personService;
|
protected PersonService personService;
|
||||||
private JbpmTemplate jbpmTemplate;
|
protected JbpmTemplate jbpmTemplate;
|
||||||
|
|
||||||
// Note: jBPM query which is not provided out-of-the-box
|
// Note: jBPM query which is not provided out-of-the-box
|
||||||
// TODO: Check jBPM 3.2 and get this implemented in jBPM
|
// TODO: Check jBPM 3.2 and get this implemented in jBPM
|
||||||
@@ -1033,10 +1034,6 @@ public class JBPMEngine extends BPMEngine
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected Map<QName, Serializable> getTaskProperties(TaskInstance instance)
|
protected Map<QName, Serializable> getTaskProperties(TaskInstance instance)
|
||||||
{
|
{
|
||||||
// establish task definition
|
|
||||||
TypeDefinition taskDef = getAnonymousTaskDefinition(getTaskDefinition(instance.getTask()));
|
|
||||||
Map<QName, AssociationDefinition> taskAssocs = taskDef.getAssociations();
|
|
||||||
|
|
||||||
// map arbitrary task variables
|
// map arbitrary task variables
|
||||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(10);
|
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(10);
|
||||||
Map<String, Object> vars = instance.getVariablesLocally();
|
Map<String, Object> vars = instance.getVariablesLocally();
|
||||||
@@ -1050,32 +1047,23 @@ public class JBPMEngine extends BPMEngine
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Convert Nodes to NodeRefs
|
// Convert Nodes to NodeRefs
|
||||||
if (value instanceof org.alfresco.repo.jscript.Node)
|
if (value instanceof JBPMNode)
|
||||||
{
|
{
|
||||||
value = ((org.alfresco.repo.jscript.Node)value).getNodeRef();
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert Authority name to NodeRefs
|
|
||||||
QName qname = QName.createQName(key, this.namespaceService);
|
|
||||||
AssociationDefinition assocDef = taskAssocs.get(qname);
|
|
||||||
if (assocDef != null && assocDef.getTargetClass().equals(ContentModel.TYPE_PERSON))
|
|
||||||
{
|
|
||||||
// TODO: Also support group authorities
|
|
||||||
if (value instanceof String[])
|
|
||||||
{
|
|
||||||
value = mapNameToAuthority((String[])value);
|
|
||||||
}
|
|
||||||
else if (value instanceof String)
|
|
||||||
{
|
|
||||||
value = mapNameToAuthority(new String[] {(String)value});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new WorkflowException("Task variable '" + qname + "' value is invalid format");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// place task variable in map to return
|
// place task variable in map to return
|
||||||
|
QName qname = QName.createQName(key, this.namespaceService);
|
||||||
properties.put(qname, (Serializable)value);
|
properties.put(qname, (Serializable)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1091,10 +1079,16 @@ public class JBPMEngine extends BPMEngine
|
|||||||
Set pooledActors = instance.getPooledActors();
|
Set pooledActors = instance.getPooledActors();
|
||||||
if (pooledActors != null)
|
if (pooledActors != null)
|
||||||
{
|
{
|
||||||
String[] pooledActorIds = new String[pooledActors.size()];
|
List<NodeRef> pooledNodeRefs = new ArrayList<NodeRef>(pooledActors.size());
|
||||||
pooledActors.toArray(pooledActorIds);
|
for (String pooledActor : (Set<String>)pooledActors)
|
||||||
List<NodeRef> pooledActorNodeRefs = mapNameToAuthority(pooledActorIds);
|
{
|
||||||
properties.put(WorkflowModel.ASSOC_POOLED_ACTORS, (Serializable)pooledActorNodeRefs);
|
NodeRef pooledNodeRef = mapNameToAuthority(pooledActor);
|
||||||
|
if (pooledNodeRef != null)
|
||||||
|
{
|
||||||
|
pooledNodeRefs.add(pooledNodeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
properties.put(WorkflowModel.ASSOC_POOLED_ACTORS, (Serializable)pooledNodeRefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
@@ -1136,6 +1130,13 @@ public class JBPMEngine extends BPMEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert property value
|
||||||
|
value = (Serializable)DefaultTypeConverter.INSTANCE.convert(propDef.getDataType(), value);
|
||||||
|
if (value instanceof NodeRef)
|
||||||
|
{
|
||||||
|
value = new JBPMNode((NodeRef)value, serviceRegistry);
|
||||||
|
}
|
||||||
|
|
||||||
// map property to specific jBPM task instance field
|
// map property to specific jBPM task instance field
|
||||||
if (key.equals(WorkflowModel.PROP_DUE_DATE))
|
if (key.equals(WorkflowModel.PROP_DUE_DATE))
|
||||||
{
|
{
|
||||||
@@ -1171,28 +1172,26 @@ public class JBPMEngine extends BPMEngine
|
|||||||
AssociationDefinition assocDef = taskAssocs.get(key);
|
AssociationDefinition assocDef = taskAssocs.get(key);
|
||||||
if (assocDef != null)
|
if (assocDef != null)
|
||||||
{
|
{
|
||||||
// if association is to people, map them to authority names
|
// convert association to JBPMNodes
|
||||||
// TODO: support group authorities
|
value = convertAssociation(assocDef, value);
|
||||||
if (assocDef.getTargetClass().getName().equals(ContentModel.TYPE_PERSON))
|
|
||||||
{
|
|
||||||
String[] authorityNames = mapAuthorityToName((List<NodeRef>)value);
|
|
||||||
if (authorityNames != null && authorityNames.length > 0)
|
|
||||||
{
|
|
||||||
value = (Serializable) (assocDef.isTargetMany() ? authorityNames : authorityNames[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// map association to specific jBPM task instance field
|
// map association to specific jBPM task instance field
|
||||||
if (key.equals(WorkflowModel.ASSOC_POOLED_ACTORS))
|
if (key.equals(WorkflowModel.ASSOC_POOLED_ACTORS))
|
||||||
{
|
{
|
||||||
String[] pooledActors = null;
|
String[] pooledActors = null;
|
||||||
if (value instanceof String[])
|
if (value instanceof JBPMNodeList[])
|
||||||
{
|
{
|
||||||
pooledActors = (String[])value;
|
JBPMNodeList actors = (JBPMNodeList)value;
|
||||||
|
pooledActors = new String[actors.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (JBPMNode actor : actors)
|
||||||
|
{
|
||||||
|
pooledActors[i++] = actor.getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (value instanceof String)
|
else if (value instanceof JBPMNode)
|
||||||
{
|
{
|
||||||
pooledActors = new String[] {(String)value};
|
pooledActors = new String[] {((JBPMNode)value).getName()};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1202,64 +1201,88 @@ public class JBPMEngine extends BPMEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// untyped value, perform minimal conversion
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (value instanceof NodeRef)
|
||||||
|
{
|
||||||
|
value = new JBPMNode((NodeRef)value, serviceRegistry);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no specific mapping to jBPM task has been established, so place into
|
// no specific mapping to jBPM task has been established, so place into
|
||||||
// the generic task variable bag
|
// the generic task variable bag
|
||||||
String name = key.toPrefixString(this.namespaceService);
|
String name = key.toPrefixString(this.namespaceService);
|
||||||
if (value instanceof NodeRef)
|
|
||||||
{
|
|
||||||
value = new JBPMNode((NodeRef)value, serviceRegistry);
|
|
||||||
}
|
|
||||||
instance.setVariableLocally(name, value);
|
instance.setVariableLocally(name, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a list of Alfresco Authorities to a list of authority Names
|
* Convert a Repository association to JBPMNodeList or JBPMNode
|
||||||
*
|
*
|
||||||
* @param authorities the authorities to convert
|
* @param assocDef association definition
|
||||||
* @return the authority names
|
* @param value value to convert
|
||||||
|
* @return JBPMNodeList or JBPMNode
|
||||||
*/
|
*/
|
||||||
private String[] mapAuthorityToName(List<NodeRef> authorities)
|
private Serializable convertAssociation(AssociationDefinition assocDef, Serializable value)
|
||||||
{
|
{
|
||||||
String[] names = null;
|
boolean isMany = assocDef.isTargetMany();
|
||||||
if (authorities != null)
|
|
||||||
|
if (value instanceof NodeRef)
|
||||||
{
|
{
|
||||||
names = new String[authorities.size()];
|
if (isMany)
|
||||||
int i = 0;
|
|
||||||
for (NodeRef person : authorities)
|
|
||||||
{
|
{
|
||||||
String name = (String)nodeService.getProperty(person, ContentModel.PROP_USERNAME);
|
// convert single node ref to list of node refs
|
||||||
names[i++] = name;
|
JBPMNodeList values = new JBPMNodeList();
|
||||||
|
values.add(new JBPMNode((NodeRef)value, serviceRegistry));
|
||||||
|
value = (Serializable)values;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = new JBPMNode((NodeRef)value, serviceRegistry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return names;
|
|
||||||
|
if (value instanceof List)
|
||||||
|
{
|
||||||
|
if (isMany)
|
||||||
|
{
|
||||||
|
JBPMNodeList values = new JBPMNodeList();
|
||||||
|
for (NodeRef nodeRef : (List<NodeRef>)value)
|
||||||
|
{
|
||||||
|
values.add(new JBPMNode(nodeRef, serviceRegistry));
|
||||||
|
}
|
||||||
|
value = (Serializable)values;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = new JBPMNode((NodeRef)value, serviceRegistry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a list of authority Names to Alfresco Authorities
|
* Convert authority name to an Alfresco Authority
|
||||||
*
|
*
|
||||||
* @param names the authority names to convert
|
* @param names the authority names to convert
|
||||||
* @return the Alfresco authorities
|
* @return the Alfresco authorities
|
||||||
*/
|
*/
|
||||||
private List<NodeRef> mapNameToAuthority(String[] names)
|
private NodeRef mapNameToAuthority(String name)
|
||||||
{
|
{
|
||||||
List<NodeRef> authorities = null;
|
NodeRef authority = null;
|
||||||
if (names != null)
|
if (name != null)
|
||||||
{
|
{
|
||||||
authorities = new ArrayList<NodeRef>(names.length);
|
// TODO: Should this be an exception?
|
||||||
for (String name : names)
|
if (personService.personExists(name))
|
||||||
{
|
{
|
||||||
// TODO: Should this be an exception?
|
authority = personService.getPerson(name);
|
||||||
if (personService.personExists(name))
|
|
||||||
{
|
|
||||||
authorities.add(personService.getPerson(name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return authorities;
|
return authority;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.workflow.jbpm;
|
package org.alfresco.repo.workflow.jbpm;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -79,10 +80,11 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
assertEquals("Test", testWorkflowDef.title);
|
assertEquals("Test", testWorkflowDef.title);
|
||||||
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
|
// get valid node ref
|
||||||
NodeService nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName());
|
NodeService nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName());
|
||||||
testNodeRef = nodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "spacesStore"));
|
testNodeRef = nodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "spacesStore"));
|
||||||
|
nodeService.setProperty(testNodeRef, ContentModel.PROP_CREATED, new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -383,7 +385,6 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
||||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||||
assertNotNull(path);
|
assertNotNull(path);
|
||||||
assertNotNull(path);
|
|
||||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||||
assertNotNull(tasks1);
|
assertNotNull(tasks1);
|
||||||
assertEquals(1, tasks1.size());
|
assertEquals(1, tasks1.size());
|
||||||
@@ -393,18 +394,31 @@ public class JBPMEngineTest extends BaseSpringTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testScript()
|
public void testWorkflowPackageNodeRef()
|
||||||
{
|
{
|
||||||
WorkflowDefinition workflowDef = getTestDefinition();
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testScript()
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
// deploy test script definition
|
||||||
|
ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/test_script.xml");
|
||||||
|
assertFalse(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
||||||
|
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||||
|
assertNotNull(deployment);
|
||||||
|
|
||||||
|
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, "reviewer"), "admin");
|
|
||||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
||||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||||
assertNotNull(path);
|
assertNotNull(path);
|
||||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||||
assertNotNull(tasks1);
|
assertNotNull(tasks1);
|
||||||
assertEquals(1, tasks1.size());
|
assertEquals(1, tasks1.size());
|
||||||
WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).id, path.node.transitions[0].id);
|
assertEquals(WorkflowTaskState.IN_PROGRESS, tasks1.get(0).state);
|
||||||
|
WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).id, null);
|
||||||
assertNotNull(updatedTask);
|
assertNotNull(updatedTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@ package org.alfresco.repo.workflow.jbpm;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.alfresco.repo.jscript.Node;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
@@ -79,7 +80,11 @@ public class JBPMNode extends org.alfresco.repo.jscript.Node
|
|||||||
@Override
|
@Override
|
||||||
public Serializable convertValueForScript(ServiceRegistry services, Scriptable scope, QName qname, Serializable value)
|
public Serializable convertValueForScript(ServiceRegistry services, Scriptable scope, QName qname, Serializable value)
|
||||||
{
|
{
|
||||||
if (value instanceof Date)
|
if (value instanceof NodeRef)
|
||||||
|
{
|
||||||
|
return new JBPMNode(((NodeRef)value), services);
|
||||||
|
}
|
||||||
|
else if (value instanceof Date)
|
||||||
{
|
{
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
package org.alfresco.repo.workflow.jbpm;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
public class JBPMNodeList extends ArrayList<JBPMNode>
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1376915749912156471L;
|
||||||
|
}
|
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* 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.List;
|
||||||
|
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.jbpm.context.exe.Converter;
|
||||||
|
import org.springframework.beans.factory.access.BeanFactoryLocator;
|
||||||
|
import org.springframework.beans.factory.access.BeanFactoryReference;
|
||||||
|
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jBPM Converter for transforming Alfresco Node to string and back
|
||||||
|
*
|
||||||
|
* @author davidc
|
||||||
|
*/
|
||||||
|
public class NodeListConverter implements Converter
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static BeanFactoryLocator jbpmFactoryLocator = new JbpmFactoryLocator();
|
||||||
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.jbpm.context.exe.Converter#supports(java.lang.Object)
|
||||||
|
*/
|
||||||
|
public boolean supports(Object value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return (value.getClass() == JBPMNodeList.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.jbpm.context.exe.Converter#convert(java.lang.Object)
|
||||||
|
*/
|
||||||
|
public Object convert(Object o)
|
||||||
|
{
|
||||||
|
Object converted = null;
|
||||||
|
if (o != null)
|
||||||
|
{
|
||||||
|
JBPMNodeList nodes = (JBPMNodeList)o;
|
||||||
|
List<NodeRef> values = new ArrayList<NodeRef>(nodes.size());
|
||||||
|
for (JBPMNode node : nodes)
|
||||||
|
{
|
||||||
|
values.add(node.getNodeRef());
|
||||||
|
}
|
||||||
|
converted = values;
|
||||||
|
}
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.jbpm.context.exe.Converter#revert(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Object revert(Object o)
|
||||||
|
{
|
||||||
|
Object reverted = null;
|
||||||
|
if (o != null)
|
||||||
|
{
|
||||||
|
BeanFactoryReference factory = jbpmFactoryLocator.useBeanFactory(null);
|
||||||
|
ServiceRegistry serviceRegistry = (ServiceRegistry)factory.getFactory().getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||||
|
|
||||||
|
List<NodeRef> nodeRefs = (List<NodeRef>)o;
|
||||||
|
JBPMNodeList nodes = new JBPMNodeList();
|
||||||
|
for (NodeRef nodeRef : nodeRefs)
|
||||||
|
{
|
||||||
|
nodes.add(new JBPMNode(nodeRef, serviceRegistry));
|
||||||
|
}
|
||||||
|
reverted = nodes;
|
||||||
|
}
|
||||||
|
return reverted;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* 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.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||||
|
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
||||||
|
import org.alfresco.repo.workflow.TaskComponent;
|
||||||
|
import org.alfresco.repo.workflow.WorkflowComponent;
|
||||||
|
import org.alfresco.repo.workflow.WorkflowModel;
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.BaseSpringTest;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Review and Approve workflow specific Tests
|
||||||
|
*
|
||||||
|
* @author davidc
|
||||||
|
*/
|
||||||
|
public class ReviewAndApproveTest extends BaseSpringTest
|
||||||
|
{
|
||||||
|
AuthenticationComponent authenticationComponent;
|
||||||
|
PersonService personService;
|
||||||
|
WorkflowComponent workflowComponent;
|
||||||
|
TaskComponent taskComponent;
|
||||||
|
WorkflowDefinition testWorkflowDef;
|
||||||
|
NodeRef testNodeRef;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSetUpInTransaction() throws Exception
|
||||||
|
{
|
||||||
|
personService = (PersonService)applicationContext.getBean("personService");
|
||||||
|
BPMEngineRegistry registry = (BPMEngineRegistry)applicationContext.getBean("bpm_engineRegistry");
|
||||||
|
workflowComponent = registry.getWorkflowComponent("jbpm");
|
||||||
|
taskComponent = registry.getTaskComponent("jbpm");
|
||||||
|
|
||||||
|
// retrieve review and approve process definition
|
||||||
|
// ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml");
|
||||||
|
// assertTrue(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
||||||
|
// List<WorkflowDefinition> definitions = workflowComponent.getDefinitions();
|
||||||
|
// for (WorkflowDefinition definition : definitions)
|
||||||
|
// {
|
||||||
|
// if (definition.title.equals("Review & Approve"))
|
||||||
|
// {
|
||||||
|
// testWorkflowDef = definition;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml");
|
||||||
|
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||||
|
testWorkflowDef = deployment.definition;
|
||||||
|
assertNotNull(testWorkflowDef);
|
||||||
|
|
||||||
|
// run as system
|
||||||
|
authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent");
|
||||||
|
authenticationComponent.setSystemUserAsCurrentUser();
|
||||||
|
|
||||||
|
// get valid node ref
|
||||||
|
NodeService 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 testWorkflowPackage()
|
||||||
|
{
|
||||||
|
WorkflowDefinition workflowDef = testWorkflowDef;
|
||||||
|
|
||||||
|
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||||
|
params.put(WorkflowModel.ASSOC_PACKAGE, testNodeRef);
|
||||||
|
NodeRef reviewer = personService.getPerson("admin");
|
||||||
|
params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewer"), reviewer);
|
||||||
|
|
||||||
|
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, params);
|
||||||
|
assertNotNull(path);
|
||||||
|
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||||
|
assertNotNull(tasks1);
|
||||||
|
assertEquals(1, tasks1.size());
|
||||||
|
|
||||||
|
WorkflowTask task = tasks1.get(0);
|
||||||
|
assertTrue(task.properties.containsKey(WorkflowModel.ASSOC_PACKAGE));
|
||||||
|
taskComponent.endTask(task.id, null);
|
||||||
|
|
||||||
|
List<WorkflowTask> assignedTasks = taskComponent.getAssignedTasks("admin", WorkflowTaskState.IN_PROGRESS);
|
||||||
|
assertNotNull(assignedTasks);
|
||||||
|
assignedTasks = filterTasksByWorkflowInstance(assignedTasks, path.instance.id);
|
||||||
|
|
||||||
|
assertEquals(testNodeRef, assignedTasks.get(0).properties.get(WorkflowModel.ASSOC_PACKAGE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter task list by workflow instance
|
||||||
|
*
|
||||||
|
* @param tasks
|
||||||
|
* @param processInstanceId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<WorkflowTask> filterTasksByWorkflowInstance(List<WorkflowTask> tasks, String workflowInstanceId)
|
||||||
|
{
|
||||||
|
List<WorkflowTask> filteredTasks = new ArrayList<WorkflowTask>();
|
||||||
|
for (WorkflowTask task : tasks)
|
||||||
|
{
|
||||||
|
if (task.path.instance.id.equals(workflowInstanceId))
|
||||||
|
{
|
||||||
|
filteredTasks.add(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filteredTasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -15,4 +15,5 @@ G org.jbpm.context.exe.converter.FloatToDoubleConverter
|
|||||||
I org.jbpm.context.exe.converter.IntegerToLongConverter
|
I org.jbpm.context.exe.converter.IntegerToLongConverter
|
||||||
R org.jbpm.context.exe.converter.SerializableToByteArrayConverter
|
R org.jbpm.context.exe.converter.SerializableToByteArrayConverter
|
||||||
H org.jbpm.context.exe.converter.ShortToLongConverter
|
H org.jbpm.context.exe.converter.ShortToLongConverter
|
||||||
N org.alfresco.repo.workflow.jbpm.NodeConverter
|
N org.alfresco.repo.workflow.jbpm.NodeConverter
|
||||||
|
L org.alfresco.repo.workflow.jbpm.NodeListConverter
|
@@ -119,7 +119,7 @@
|
|||||||
<variable-instance class="org.jbpm.context.exe.variableinstance.DateInstance" />
|
<variable-instance class="org.jbpm.context.exe.variableinstance.DateInstance" />
|
||||||
</jbpm-type>
|
</jbpm-type>
|
||||||
|
|
||||||
<!-- org.alfresco.repo.jscript.Node -->
|
<!-- org.alfresco.repo.workflow.jbpm.JBPMNode -->
|
||||||
<jbpm-type>
|
<jbpm-type>
|
||||||
<matcher>
|
<matcher>
|
||||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||||
@@ -130,6 +130,17 @@
|
|||||||
<variable-instance class="org.jbpm.context.exe.variableinstance.StringInstance" />
|
<variable-instance class="org.jbpm.context.exe.variableinstance.StringInstance" />
|
||||||
</jbpm-type>
|
</jbpm-type>
|
||||||
|
|
||||||
|
<!-- org.alfresco.repo.workflow.jbpm.JBPMNodeList -->
|
||||||
|
<jbpm-type>
|
||||||
|
<matcher>
|
||||||
|
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||||
|
<field name="className"><string value="org.alfresco.repo.workflow.jbpm.JBPMNodeList" /></field>
|
||||||
|
</bean>
|
||||||
|
</matcher>
|
||||||
|
<converter class="org.alfresco.repo.workflow.jbpm.NodeListConverter" />
|
||||||
|
<variable-instance class="org.jbpm.context.exe.variableinstance.ByteArrayInstance" />
|
||||||
|
</jbpm-type>
|
||||||
|
|
||||||
<!-- byte[] -->
|
<!-- byte[] -->
|
||||||
<jbpm-type>
|
<jbpm-type>
|
||||||
<matcher>
|
<matcher>
|
||||||
|
@@ -1,23 +1,26 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:review">
|
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:review">
|
||||||
<swimlane name="Initiator"></swimlane>
|
|
||||||
|
<swimlane name="initiator"></swimlane>
|
||||||
<start-state name="start">
|
<start-state name="start">
|
||||||
<task name="wf:submitReviewTask" swimlane="Initiator" blocking="true">
|
<task name="wf:submitReviewTask" swimlane="Initiator" blocking="true">
|
||||||
<controller>
|
<controller>
|
||||||
<variable name="reviewer" access="write,required" mapped-name="wf:reviewer" />
|
<variable name="reviewer" access="write,required" mapped-name="wf:reviewer"/>
|
||||||
|
<variable name="package" access="write,required" mapped-name="bpm:package"/>
|
||||||
</controller>
|
</controller>
|
||||||
</task>
|
</task>
|
||||||
<transition name="" to="Review"></transition>
|
<transition name="" to="Review"></transition>
|
||||||
<transition name="end" to="end"></transition>
|
<transition name="end" to="end"></transition>
|
||||||
</start-state>
|
</start-state>
|
||||||
<swimlane name="Reviewer">
|
<swimlane name="Reviewer">
|
||||||
<assignment actor-id="#{reviewer}"></assignment>
|
<assignment actor-id="#{reviewer.properties['cm:userName']}"></assignment>
|
||||||
</swimlane>
|
</swimlane>
|
||||||
<task-node name="Review">
|
<task-node name="Review">
|
||||||
<task name="Review" duedate="1 business day" blocking="true" swimlane="Reviewer">
|
<task name="Review" duedate="1 business day" blocking="true" swimlane="Reviewer">
|
||||||
<controller>
|
<controller>
|
||||||
<variable name="comment" access="read,write,required"></variable>
|
<variable name="comment" access="read,write,required"></variable>
|
||||||
|
<variable name="package" access="read,required" mapped-name="bpm:package"/>
|
||||||
</controller>
|
</controller>
|
||||||
</task>
|
</task>
|
||||||
<transition name="reject" to="Rejected"></transition>
|
<transition name="reject" to="Rejected"></transition>
|
||||||
@@ -27,6 +30,7 @@
|
|||||||
<task name="Rejected" swimlane="Initiator">
|
<task name="Rejected" swimlane="Initiator">
|
||||||
<controller>
|
<controller>
|
||||||
<variable name="comment" access="read"></variable>
|
<variable name="comment" access="read"></variable>
|
||||||
|
<variable name="package" access="read,required" mapped-name="bpm:package"/>
|
||||||
</controller>
|
</controller>
|
||||||
</task>
|
</task>
|
||||||
<transition name="" to="end"></transition>
|
<transition name="" to="end"></transition>
|
||||||
@@ -35,6 +39,7 @@
|
|||||||
<task name="Approved" swimlane="Initiator">
|
<task name="Approved" swimlane="Initiator">
|
||||||
<controller>
|
<controller>
|
||||||
<variable name="comment" access="read"></variable>
|
<variable name="comment" access="read"></variable>
|
||||||
|
<variable name="package" access="read,required" mapped-name="bpm:package"/>
|
||||||
</controller>
|
</controller>
|
||||||
</task>
|
</task>
|
||||||
<transition name="" to="end"></transition>
|
<transition name="" to="end"></transition>
|
||||||
|
53
source/java/org/alfresco/repo/workflow/jbpm/test_script.xml
Normal file
53
source/java/org/alfresco/repo/workflow/jbpm/test_script.xml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="test_script">
|
||||||
|
<swimlane name="initiator"></swimlane>
|
||||||
|
|
||||||
|
<start-state name="start">
|
||||||
|
<task name="submit" swimlane="initiator">
|
||||||
|
<event type="task-assign">
|
||||||
|
<script>
|
||||||
|
System.out.println("taskInstance.create: " + taskInstance.create);
|
||||||
|
</script>
|
||||||
|
</event>
|
||||||
|
<controller>
|
||||||
|
<variable name="testNode" access="write,required" />
|
||||||
|
</controller>
|
||||||
|
</task>
|
||||||
|
<transition name="" to="doit"/>
|
||||||
|
</start-state>
|
||||||
|
|
||||||
|
<node name="doit">
|
||||||
|
<event type="node-enter">
|
||||||
|
<script>
|
||||||
|
<expression>
|
||||||
|
System.out.println("testNode.created: " + testNode.properties{"cm:created"});
|
||||||
|
System.out.println("test node " + testNode.name + " contains " + testNode.children.length + " children");
|
||||||
|
</expression>
|
||||||
|
<variable name="testNode" access="read"/>
|
||||||
|
</script>
|
||||||
|
</event>
|
||||||
|
<event type="node-enter">
|
||||||
|
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
|
||||||
|
<script>
|
||||||
|
<expression>
|
||||||
|
var result = "testNode.created: " + testNode.properties["cm:created"];
|
||||||
|
result;
|
||||||
|
</expression>
|
||||||
|
<variable name="testNode" access="read"/>
|
||||||
|
<variable name="alfrescoScriptResult" access="write"/>
|
||||||
|
</script>
|
||||||
|
</action>
|
||||||
|
</event>
|
||||||
|
<transition name="" to="end"/>
|
||||||
|
</node>
|
||||||
|
|
||||||
|
<end-state name="end">
|
||||||
|
<event type="node-enter">
|
||||||
|
<script>
|
||||||
|
System.out.println("javascript: " + alfrescoScriptResult);
|
||||||
|
</script>
|
||||||
|
</event>
|
||||||
|
</end-state>
|
||||||
|
|
||||||
|
</process-definition>
|
Reference in New Issue
Block a user