mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Big honkin' merge from head. Sheesh!
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3617 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* 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.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ScriptService;
|
||||
import org.dom4j.Element;
|
||||
import org.jbpm.context.def.VariableAccess;
|
||||
import org.jbpm.context.exe.ContextInstance;
|
||||
import org.jbpm.graph.exe.ExecutionContext;
|
||||
import org.jbpm.graph.exe.Token;
|
||||
import org.jbpm.jpdl.xml.JpdlXmlReader;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
/**
|
||||
* A jBPM Action Handler for executing Alfresco Script
|
||||
*
|
||||
* The configuration of this action is as follows:
|
||||
* <script language="javascript">
|
||||
* <expression>
|
||||
* the script to execute
|
||||
* </expression>
|
||||
* <variable name="watcha" access="write"/>
|
||||
* </script>
|
||||
*
|
||||
* It's exactly the same as jBPM's own script configuration.
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class AlfrescoJavaScript extends JBPMSpringActionHandler
|
||||
{
|
||||
private static final long serialVersionUID = -2908748080671212745L;
|
||||
|
||||
private static JpdlXmlReader jpdlReader = new JpdlXmlReader((InputSource)null);
|
||||
private ScriptService scriptService;
|
||||
private Element script;
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler#initialiseHandler(org.springframework.beans.factory.BeanFactory)
|
||||
*/
|
||||
@Override
|
||||
protected void initialiseHandler(BeanFactory factory)
|
||||
{
|
||||
scriptService = (ScriptService)factory.getBean(ServiceRegistry.SCRIPT_SERVICE.getLocalName());
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jbpm.graph.def.ActionHandler#execute(org.jbpm.graph.exe.ExecutionContext)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void execute(ExecutionContext executionContext) throws Exception
|
||||
{
|
||||
// extract action configuration
|
||||
String expression = null;
|
||||
List<VariableAccess> variableAccesses = null;
|
||||
|
||||
// is the script specified as text only, or as explicit expression, variable elements
|
||||
boolean isTextOnly = true;
|
||||
Iterator<Element> iter = script.elementIterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Element element = iter.next();
|
||||
if (element.getNodeType() == Element.ELEMENT_NODE)
|
||||
{
|
||||
isTextOnly = false;
|
||||
}
|
||||
}
|
||||
|
||||
// extract script and variables
|
||||
if (isTextOnly)
|
||||
{
|
||||
expression = script.getTextTrim();
|
||||
}
|
||||
else
|
||||
{
|
||||
variableAccesses = jpdlReader.readVariableAccesses(script);
|
||||
expression = script.element("expression").getTextTrim();
|
||||
}
|
||||
|
||||
// construct script arguments and execute
|
||||
Map<String, Object> inputMap = createInputMap(executionContext, variableAccesses);
|
||||
Object result = scriptService.executeScriptString(expression, inputMap);
|
||||
|
||||
// map script return variable to process context
|
||||
VariableAccess returnVariable = getWritableVariable(variableAccesses);
|
||||
if (returnVariable != null)
|
||||
{
|
||||
ContextInstance contextInstance = executionContext.getContextInstance();
|
||||
Token token = executionContext.getToken();
|
||||
contextInstance.setVariable(returnVariable.getVariableName(), result, token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct map of arguments to pass to script
|
||||
*
|
||||
* Based on the <variable> elements of the action configuration.
|
||||
*
|
||||
* @param executionContext the execution context
|
||||
* @param variableAccesses the variable configuration
|
||||
* @return the map of script arguments
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> createInputMap(ExecutionContext executionContext, List<VariableAccess> variableAccesses)
|
||||
{
|
||||
Map<String, Object> inputMap = new HashMap<String, Object>();
|
||||
|
||||
// initialise process variables
|
||||
Token token = executionContext.getToken();
|
||||
inputMap.put("executionContext", executionContext);
|
||||
inputMap.put("token", token);
|
||||
if (executionContext.getNode() != null)
|
||||
{
|
||||
inputMap.put("node", executionContext.getNode());
|
||||
}
|
||||
if (executionContext.getTask() != null)
|
||||
{
|
||||
inputMap.put("task", executionContext.getTask());
|
||||
}
|
||||
if (executionContext.getTaskInstance() != null)
|
||||
{
|
||||
inputMap.put("taskInstance", executionContext.getTaskInstance());
|
||||
}
|
||||
|
||||
// if no readable variableInstances are specified,
|
||||
ContextInstance contextInstance = executionContext.getContextInstance();
|
||||
if (!hasReadableVariable(variableAccesses))
|
||||
{
|
||||
// copy all the variableInstances of the context into the interpreter
|
||||
Map<String, Object> variables = contextInstance.getVariables(token);
|
||||
if (variables != null)
|
||||
{
|
||||
for (Map.Entry entry : variables.entrySet())
|
||||
{
|
||||
String variableName = (String) entry.getKey();
|
||||
Object variableValue = entry.getValue();
|
||||
inputMap.put(variableName, variableValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy the specified variableInstances into the interpreterz
|
||||
for (VariableAccess variableAccess : variableAccesses)
|
||||
{
|
||||
if (variableAccess.isReadable())
|
||||
{
|
||||
String variableName = variableAccess.getVariableName();
|
||||
String mappedName = variableAccess.getMappedName();
|
||||
Object variableValue = contextInstance.getVariable(variableName, token);
|
||||
inputMap.put(mappedName, variableValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return inputMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if there are variables to read from the process context
|
||||
*
|
||||
* @param variableAccesses the variables configuration
|
||||
* @return true => there are variables to read
|
||||
*/
|
||||
private boolean hasReadableVariable(List<VariableAccess> variableAccesses)
|
||||
{
|
||||
if (variableAccesses != null)
|
||||
{
|
||||
for (VariableAccess variableAccess : variableAccesses)
|
||||
{
|
||||
if (variableAccess.isReadable())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if there is a variable to write back to the process context
|
||||
*
|
||||
* @param variableAccesses the variables configuration
|
||||
* @return true => there is a variable to write
|
||||
*/
|
||||
private VariableAccess getWritableVariable(List<VariableAccess> variableAccesses)
|
||||
{
|
||||
if (variableAccesses != null)
|
||||
{
|
||||
for (VariableAccess variableAccess : variableAccesses)
|
||||
{
|
||||
if (variableAccess.isWritable())
|
||||
{
|
||||
return variableAccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
1636
source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
Normal file
1636
source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
Normal file
File diff suppressed because it is too large
Load Diff
469
source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java
Normal file
469
source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java
Normal file
@@ -0,0 +1,469 @@
|
||||
/*
|
||||
* 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.IOException;
|
||||
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.i18n.I18NUtil;
|
||||
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.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
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.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
/**
|
||||
* JBPM Engine Tests
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class JBPMEngineTest extends BaseSpringTest
|
||||
{
|
||||
AuthenticationComponent authenticationComponent;
|
||||
NodeService nodeService;
|
||||
WorkflowComponent workflowComponent;
|
||||
TaskComponent taskComponent;
|
||||
WorkflowDefinition testWorkflowDef;
|
||||
NodeRef testNodeRef;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
// run as system
|
||||
authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent");
|
||||
authenticationComponent.setCurrentUser("admin");
|
||||
|
||||
BPMEngineRegistry registry = (BPMEngineRegistry)applicationContext.getBean("bpm_engineRegistry");
|
||||
workflowComponent = registry.getWorkflowComponent("jbpm");
|
||||
taskComponent = registry.getTaskComponent("jbpm");
|
||||
|
||||
// deploy test process messages
|
||||
I18NUtil.registerResourceBundle("org/alfresco/repo/workflow/jbpm/test-messages");
|
||||
|
||||
// deploy test process definition
|
||||
ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/test_processdefinition.xml");
|
||||
assertFalse(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
||||
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||
testWorkflowDef = deployment.definition;
|
||||
assertNotNull(testWorkflowDef);
|
||||
assertEquals("test", testWorkflowDef.name);
|
||||
assertEquals("1", testWorkflowDef.version);
|
||||
assertTrue(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
||||
|
||||
// get valid node ref
|
||||
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()
|
||||
{
|
||||
List<WorkflowDefinition> workflowDefs = workflowComponent.getDefinitions();
|
||||
assertNotNull(workflowDefs);
|
||||
assertTrue(workflowDefs.size() > 0);
|
||||
}
|
||||
|
||||
|
||||
public void testDeployWorkflow() throws Exception
|
||||
{
|
||||
ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/test_processdefinition.xml");
|
||||
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||
testWorkflowDef = deployment.definition;
|
||||
assertNotNull(testWorkflowDef);
|
||||
assertEquals("test", testWorkflowDef.name);
|
||||
assertEquals("2", testWorkflowDef.version);
|
||||
}
|
||||
|
||||
|
||||
public void testStartWorkflow()
|
||||
{
|
||||
try
|
||||
{
|
||||
@SuppressWarnings("unused") WorkflowPath path = workflowComponent.startWorkflow("norfolknchance", null);
|
||||
fail("Failed to catch invalid definition id");
|
||||
}
|
||||
catch(WorkflowException e)
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: Determine why process definition is loaded, even though it doesn't exist
|
||||
// try
|
||||
// {
|
||||
// @SuppressWarnings("unused") WorkflowPosition pos = workflowComponent.startProcess("1000", null);
|
||||
// fail("Failed to catch workflow definition id that does not exist");
|
||||
// }
|
||||
// catch(WorkflowException e)
|
||||
// {
|
||||
// }
|
||||
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, null);
|
||||
assertNotNull(path);
|
||||
assertTrue(path.id.endsWith("-@"));
|
||||
assertNotNull(path.node);
|
||||
assertNotNull(path.instance);
|
||||
assertEquals(workflowDef.id, path.instance.definition.id);
|
||||
}
|
||||
|
||||
|
||||
public void testStartWorkflowParameters()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.PROP_TASK_ID, 3); // protected - shouldn't be written
|
||||
params.put(WorkflowModel.PROP_DUE_DATE, new Date()); // task instance field
|
||||
params.put(WorkflowModel.PROP_PRIORITY, 1); // task instance field
|
||||
params.put(WorkflowModel.PROP_PERCENT_COMPLETE, 10); // context variable
|
||||
params.put(QName.createQName("", "Message"), "Hello World"); // context variable outside of task definition
|
||||
params.put(QName.createQName("", "Array"), new String[] { "one", "two" }); // context variable outside of task definition
|
||||
params.put(QName.createQName("", "NodeRef"), new NodeRef("workspace://1/1001")); // context variable outside of task definition
|
||||
params.put(ContentModel.PROP_OWNER, "admin"); // task assignment
|
||||
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, params);
|
||||
assertNotNull(path);
|
||||
assertTrue(path.id.endsWith("-@"));
|
||||
assertNotNull(path.node);
|
||||
assertNotNull(path.instance);
|
||||
assertEquals(workflowDef.id, path.instance.definition.id);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
|
||||
WorkflowTask task = tasks1.get(0);
|
||||
assertTrue(task.properties.containsKey(WorkflowModel.PROP_TASK_ID));
|
||||
assertTrue(task.properties.containsKey(WorkflowModel.PROP_DUE_DATE));
|
||||
assertTrue(task.properties.containsKey(WorkflowModel.PROP_PRIORITY));
|
||||
assertTrue(task.properties.containsKey(WorkflowModel.PROP_PERCENT_COMPLETE));
|
||||
assertTrue(task.properties.containsKey(ContentModel.PROP_OWNER));
|
||||
|
||||
NodeRef initiator = path.instance.initiator;
|
||||
String initiatorUsername = (String)nodeService.getProperty(initiator, ContentModel.PROP_USERNAME);
|
||||
assertEquals("admin", initiatorUsername);
|
||||
}
|
||||
|
||||
|
||||
public void testUpdateTask()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.PROP_TASK_ID, 3); // protected - shouldn't be written
|
||||
params.put(WorkflowModel.PROP_DUE_DATE, new Date()); // task instance field
|
||||
params.put(WorkflowModel.PROP_PRIORITY, 1); // task instance field
|
||||
params.put(WorkflowModel.PROP_PERCENT_COMPLETE, 10); // context variable
|
||||
params.put(QName.createQName("", "Message"), "Hello World"); // context variable outside of task definition
|
||||
params.put(QName.createQName("", "Array"), new String[] { "one", "two" }); // context variable outside of task definition
|
||||
params.put(QName.createQName("", "NodeRef"), new NodeRef("workspace://1/1001")); // context variable outside of task definition
|
||||
params.put(ContentModel.PROP_OWNER, "admin"); // task assignment
|
||||
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, params);
|
||||
assertNotNull(path);
|
||||
assertTrue(path.id.endsWith("-@"));
|
||||
assertNotNull(path.node);
|
||||
assertNotNull(path.instance);
|
||||
assertEquals(workflowDef.id, path.instance.definition.id);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
|
||||
WorkflowTask task = tasks1.get(0);
|
||||
assertTrue(task.properties.containsKey(WorkflowModel.PROP_TASK_ID));
|
||||
assertTrue(task.properties.containsKey(WorkflowModel.PROP_DUE_DATE));
|
||||
assertTrue(task.properties.containsKey(WorkflowModel.PROP_PRIORITY));
|
||||
assertTrue(task.properties.containsKey(WorkflowModel.PROP_PERCENT_COMPLETE));
|
||||
assertTrue(task.properties.containsKey(ContentModel.PROP_OWNER));
|
||||
|
||||
// update with null parameters
|
||||
try
|
||||
{
|
||||
WorkflowTask taskU1 = taskComponent.updateTask(task.id, null, null, null);
|
||||
assertNotNull(taskU1);
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
fail("Task update failed with null parameters");
|
||||
}
|
||||
|
||||
// update property value
|
||||
Map<QName, Serializable> updateProperties2 = new HashMap<QName, Serializable>();
|
||||
updateProperties2.put(WorkflowModel.PROP_PERCENT_COMPLETE, 100);
|
||||
WorkflowTask taskU2 = taskComponent.updateTask(task.id, updateProperties2, null, null);
|
||||
assertEquals(100, taskU2.properties.get(WorkflowModel.PROP_PERCENT_COMPLETE));
|
||||
|
||||
// add to assocation
|
||||
QName assocName = QName.createQName("", "TestAssoc");
|
||||
List<NodeRef> toAdd = new ArrayList<NodeRef>();
|
||||
toAdd.add(new NodeRef("workspace://1/1001"));
|
||||
toAdd.add(new NodeRef("workspace://1/1002"));
|
||||
toAdd.add(new NodeRef("workspace://1/1003"));
|
||||
Map<QName, List<NodeRef>> addAssocs = new HashMap<QName, List<NodeRef>>();
|
||||
addAssocs.put(assocName, toAdd);
|
||||
WorkflowTask taskU3 = taskComponent.updateTask(task.id, null, addAssocs, null);
|
||||
assertNotNull(taskU3.properties.get(assocName));
|
||||
assertEquals(3, ((List<NodeRef>)taskU3.properties.get(assocName)).size());
|
||||
|
||||
// add to assocation again
|
||||
List<NodeRef> toAddAgain = new ArrayList<NodeRef>();
|
||||
toAddAgain.add(new NodeRef("workspace://1/1004"));
|
||||
toAddAgain.add(new NodeRef("workspace://1/1005"));
|
||||
Map<QName, List<NodeRef>> addAssocsAgain = new HashMap<QName, List<NodeRef>>();
|
||||
addAssocsAgain.put(assocName, toAddAgain);
|
||||
WorkflowTask taskU4 = taskComponent.updateTask(task.id, null, addAssocsAgain, null);
|
||||
assertNotNull(taskU4.properties.get(assocName));
|
||||
assertEquals(5, ((List<NodeRef>)taskU4.properties.get(assocName)).size());
|
||||
|
||||
// remove assocation
|
||||
List<NodeRef> toRemove = new ArrayList<NodeRef>();
|
||||
toRemove.add(new NodeRef("workspace://1/1002"));
|
||||
toRemove.add(new NodeRef("workspace://1/1003"));
|
||||
Map<QName, List<NodeRef>> removeAssocs = new HashMap<QName, List<NodeRef>>();
|
||||
removeAssocs.put(assocName, toRemove);
|
||||
WorkflowTask taskU5 = taskComponent.updateTask(task.id, null, null, removeAssocs);
|
||||
assertNotNull(taskU5.properties.get(assocName));
|
||||
assertEquals(3, ((List<NodeRef>)taskU5.properties.get(assocName)).size());
|
||||
}
|
||||
|
||||
|
||||
public void testGetWorkflowInstances()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
workflowComponent.startWorkflow(workflowDef.id, null);
|
||||
workflowComponent.startWorkflow(workflowDef.id, null);
|
||||
List<WorkflowInstance> instances = workflowComponent.getActiveWorkflows(workflowDef.id);
|
||||
assertNotNull(instances);
|
||||
assertEquals(2, instances.size());
|
||||
for (WorkflowInstance instance : instances)
|
||||
{
|
||||
assertEquals(workflowDef.id, instance.definition.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testGetPositions()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
workflowComponent.startWorkflow(workflowDef.id, null);
|
||||
List<WorkflowInstance> instances = workflowComponent.getActiveWorkflows(workflowDef.id);
|
||||
assertNotNull(instances);
|
||||
assertEquals(1, instances.size());
|
||||
List<WorkflowPath> paths = workflowComponent.getWorkflowPaths(instances.get(0).id);
|
||||
assertNotNull(paths);
|
||||
assertEquals(1, paths.size());
|
||||
assertEquals(instances.get(0).id, paths.get(0).instance.id);
|
||||
assertTrue(paths.get(0).id.endsWith("-@"));
|
||||
}
|
||||
|
||||
|
||||
public void testCancelWorkflowInstance()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
workflowComponent.startWorkflow(workflowDef.id, null);
|
||||
List<WorkflowInstance> instances1 = workflowComponent.getActiveWorkflows(workflowDef.id);
|
||||
assertNotNull(instances1);
|
||||
assertEquals(1, instances1.size());
|
||||
WorkflowInstance cancelledInstance = workflowComponent.cancelWorkflow(instances1.get(0).id);
|
||||
assertNotNull(cancelledInstance);
|
||||
assertFalse(cancelledInstance.active);
|
||||
List<WorkflowInstance> instances2 = workflowComponent.getActiveWorkflows(workflowDef.id);
|
||||
assertNotNull(instances2);
|
||||
assertEquals(0, instances2.size());
|
||||
}
|
||||
|
||||
|
||||
public void testSignal()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, null);
|
||||
assertNotNull(path);
|
||||
WorkflowPath updatedPath = workflowComponent.signal(path.id, path.node.transitions[1].id);
|
||||
assertNotNull(updatedPath);
|
||||
}
|
||||
|
||||
|
||||
public void testGetAssignedTasks()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
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);
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||
assertNotNull(path);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||
assertNotNull(tasks);
|
||||
assertEquals(1, tasks.size());
|
||||
WorkflowTask updatedTask = taskComponent.endTask(tasks.get(0).id, path.node.transitions[0].id);
|
||||
assertNotNull(updatedTask);
|
||||
List<WorkflowTask> completedTasks = taskComponent.getAssignedTasks("admin", WorkflowTaskState.COMPLETED);
|
||||
assertNotNull(completedTasks);
|
||||
completedTasks = filterTasksByWorkflowInstance(completedTasks, path.instance.id);
|
||||
assertEquals(1, completedTasks.size());
|
||||
List<WorkflowTask> assignedTasks = taskComponent.getAssignedTasks("admin", WorkflowTaskState.IN_PROGRESS);
|
||||
assertNotNull(assignedTasks);
|
||||
assignedTasks = filterTasksByWorkflowInstance(assignedTasks, path.instance.id);
|
||||
assertEquals(1, assignedTasks.size());
|
||||
assertEquals("review", assignedTasks.get(0).name);
|
||||
}
|
||||
|
||||
|
||||
public void testEndTask()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
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);
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||
assertNotNull(path);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
assertEquals(WorkflowTaskState.IN_PROGRESS, tasks1.get(0).state);
|
||||
WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).id, null);
|
||||
assertNotNull(updatedTask);
|
||||
assertEquals(WorkflowTaskState.COMPLETED, updatedTask.state);
|
||||
List<WorkflowTask> completedTasks = taskComponent.getAssignedTasks("admin", WorkflowTaskState.COMPLETED);
|
||||
assertNotNull(completedTasks);
|
||||
completedTasks = filterTasksByWorkflowInstance(completedTasks, path.instance.id);
|
||||
assertEquals(1, completedTasks.size());
|
||||
assertEquals(WorkflowTaskState.COMPLETED, completedTasks.get(0).state);
|
||||
}
|
||||
|
||||
|
||||
public void testGetTask()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
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);
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||
assertNotNull(path);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
WorkflowTask getTask = taskComponent.getTaskById(tasks1.get(0).id);
|
||||
assertNotNull(getTask);
|
||||
assertEquals(getTask.id, tasks1.get(0).id);
|
||||
}
|
||||
|
||||
|
||||
public void testNodeRef()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
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);
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
assertEquals(WorkflowTaskState.IN_PROGRESS, tasks1.get(0).state);
|
||||
WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).id, null);
|
||||
assertNotNull(updatedTask);
|
||||
}
|
||||
|
||||
|
||||
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>();
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
assertEquals(WorkflowTaskState.IN_PROGRESS, tasks1.get(0).state);
|
||||
WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).id, null);
|
||||
assertNotNull(updatedTask);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Locate the Test Workflow Definition
|
||||
*
|
||||
* @return workflow definition
|
||||
*/
|
||||
private WorkflowDefinition getTestDefinition()
|
||||
{
|
||||
return testWorkflowDef;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
96
source/java/org/alfresco/repo/workflow/jbpm/JBPMNode.java
Normal file
96
source/java/org/alfresco/repo/workflow/jbpm/JBPMNode.java
Normal file
@@ -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.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
|
||||
/**
|
||||
* Scriptable Node suitable for JBPM Beanshell access
|
||||
*
|
||||
* TODO: This implementation derives from the JavaScript Alfresco Node. At
|
||||
* some point we should look to having a script-independent node with various
|
||||
* script-specific sub-types (and value conversions).
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class JBPMNode extends org.alfresco.repo.jscript.Node
|
||||
{
|
||||
private static final long serialVersionUID = -826970280203254365L;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param services services
|
||||
*/
|
||||
public JBPMNode(NodeRef nodeRef, ServiceRegistry services)
|
||||
{
|
||||
super(nodeRef, services, null);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.jscript.Node#createValueConverter()
|
||||
*/
|
||||
@Override
|
||||
protected NodeValueConverter createValueConverter()
|
||||
{
|
||||
return new JBPMNodeConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Value converter for beanshell.
|
||||
*/
|
||||
private class JBPMNodeConverter extends org.alfresco.repo.jscript.Node.NodeValueConverter
|
||||
{
|
||||
@Override
|
||||
public Serializable convertValueForRepo(Serializable value)
|
||||
{
|
||||
if (value instanceof Date)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return super.convertValueForRepo(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable convertValueForScript(ServiceRegistry services, Scriptable scope, QName qname, Serializable value)
|
||||
{
|
||||
if (value instanceof NodeRef)
|
||||
{
|
||||
return new JBPMNode(((NodeRef)value), services);
|
||||
}
|
||||
else if (value instanceof Date)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return super.convertValueForScript(services, scope, qname, 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;
|
||||
}
|
@@ -41,9 +41,9 @@ public class JBPMSpringTest extends BaseSpringTest
|
||||
|
||||
|
||||
//@Override
|
||||
protected void xonSetUpInTransaction() throws Exception
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
jbpmTemplate = (JbpmTemplate)applicationContext.getBean("jbpm.template");
|
||||
jbpmTemplate = (JbpmTemplate)applicationContext.getBean("jbpm_template");
|
||||
descriptorService = (DescriptorService)applicationContext.getBean("DescriptorService");
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class JBPMSpringTest extends BaseSpringTest
|
||||
{
|
||||
}
|
||||
|
||||
public void xtestHelloWorld()
|
||||
public void testHelloWorld()
|
||||
throws Exception
|
||||
{
|
||||
// Between the 3 method calls below, all data is passed via the
|
||||
@@ -74,21 +74,21 @@ public class JBPMSpringTest extends BaseSpringTest
|
||||
theProcessInstanceContinuesWhenAnAsyncMessageIsReceived();
|
||||
}
|
||||
|
||||
public void xtestStep0()
|
||||
public void testStep0()
|
||||
throws Exception
|
||||
{
|
||||
deployProcessDefinition();
|
||||
setComplete();
|
||||
}
|
||||
|
||||
public void xtestStep1()
|
||||
public void testStep1()
|
||||
throws Exception
|
||||
{
|
||||
processInstanceIsCreatedWhenUserSubmitsWebappForm();
|
||||
setComplete();
|
||||
}
|
||||
|
||||
public void xtestStep2()
|
||||
public void testStep2()
|
||||
throws Exception
|
||||
{
|
||||
theProcessInstanceContinuesWhenAnAsyncMessageIsReceived();
|
||||
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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 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 NodeConverter 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() == JBPMNode.class);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jbpm.context.exe.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
public Object convert(Object o)
|
||||
{
|
||||
Object converted = null;
|
||||
if (o != null)
|
||||
{
|
||||
converted = ((JBPMNode)o).getNodeRef().toString();
|
||||
}
|
||||
return converted;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jbpm.context.exe.Converter#revert(java.lang.Object)
|
||||
*/
|
||||
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);
|
||||
reverted = new JBPMNode(new NodeRef((String)o), serviceRegistry);
|
||||
}
|
||||
return reverted;
|
||||
}
|
||||
|
||||
}
|
@@ -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.SerializableToByteArrayConverter;
|
||||
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 extends SerializableToByteArrayConverter
|
||||
{
|
||||
|
||||
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 = super.convert(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)
|
||||
{
|
||||
List<NodeRef> nodeRefs = (List<NodeRef>)super.revert(o);
|
||||
BeanFactoryReference factory = jbpmFactoryLocator.useBeanFactory(null);
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry)factory.getFactory().getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
|
||||
JBPMNodeList nodes = new JBPMNodeList();
|
||||
for (NodeRef nodeRef : nodeRefs)
|
||||
{
|
||||
nodes.add(new JBPMNode(nodeRef, serviceRegistry));
|
||||
}
|
||||
reverted = nodes;
|
||||
}
|
||||
return reverted;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.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.namespace.QName;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
/**
|
||||
* JBPM Engine Tests
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class NodeListConverterTest extends BaseSpringTest
|
||||
{
|
||||
AuthenticationComponent authenticationComponent;
|
||||
PersonService personService;
|
||||
WorkflowComponent workflowComponent;
|
||||
TaskComponent taskComponent;
|
||||
WorkflowDefinition testWorkflowDef;
|
||||
NodeRef testNodeRef;
|
||||
|
||||
private static String taskId = null;
|
||||
|
||||
|
||||
@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");
|
||||
|
||||
// deploy latest review and approve process definition
|
||||
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"));
|
||||
}
|
||||
|
||||
|
||||
public void testStep1Start()
|
||||
{
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, testNodeRef);
|
||||
Date reviewDueDate = new Date();
|
||||
params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewDueDate"), reviewDueDate);
|
||||
NodeRef reviewer = personService.getPerson("admin");
|
||||
params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewer"), reviewer);
|
||||
|
||||
WorkflowPath path = workflowComponent.startWorkflow(testWorkflowDef.id, params);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
|
||||
setComplete();
|
||||
taskId = tasks1.get(0).id;
|
||||
}
|
||||
|
||||
|
||||
public void testSetNodeRefList()
|
||||
{
|
||||
List<NodeRef> nodeRefs = new ArrayList<NodeRef>();
|
||||
nodeRefs.add(testNodeRef);
|
||||
nodeRefs.add(testNodeRef);
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.PROP_COMPLETED_ITEMS, (Serializable)nodeRefs);
|
||||
|
||||
WorkflowTask task = taskComponent.getTaskById(taskId);
|
||||
assertNull(task.properties.get(WorkflowModel.PROP_COMPLETED_ITEMS));
|
||||
|
||||
WorkflowTask updatedTask = taskComponent.updateTask(taskId, params, null, null);
|
||||
assertNotNull(updatedTask);
|
||||
assertTrue(updatedTask.properties.containsKey(WorkflowModel.PROP_COMPLETED_ITEMS));
|
||||
assertEquals(2, ((List)updatedTask.properties.get(WorkflowModel.PROP_COMPLETED_ITEMS)).size());
|
||||
|
||||
setComplete();
|
||||
}
|
||||
|
||||
|
||||
public void testUpdateNodeRefList()
|
||||
{
|
||||
List<NodeRef> nodeRefs = new ArrayList<NodeRef>();
|
||||
// nodeRefs.add(testNodeRef);
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.PROP_COMPLETED_ITEMS, (Serializable)nodeRefs);
|
||||
|
||||
// WorkflowTask task = taskComponent.getTaskById(taskId);
|
||||
// assertNotNull(task);
|
||||
// assertTrue(task.properties.containsKey(WorkflowModel.PROP_COMPLETED_ITEMS));
|
||||
// assertEquals(2, ((List)task.properties.get(WorkflowModel.PROP_COMPLETED_ITEMS)).size());
|
||||
|
||||
WorkflowTask updatedTask = taskComponent.updateTask(taskId, params, null, null);
|
||||
assertNotNull(updatedTask);
|
||||
assertTrue(updatedTask.properties.containsKey(WorkflowModel.PROP_COMPLETED_ITEMS));
|
||||
assertEquals(0, ((List)updatedTask.properties.get(WorkflowModel.PROP_COMPLETED_ITEMS)).size());
|
||||
|
||||
setComplete();
|
||||
}
|
||||
|
||||
}
|
@@ -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.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.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");
|
||||
|
||||
// deploy latest review and approve process definition
|
||||
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"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTearDownInTransaction()
|
||||
{
|
||||
authenticationComponent.clearCurrentSecurityContext();
|
||||
}
|
||||
|
||||
|
||||
public void testSubmitForReview()
|
||||
{
|
||||
WorkflowDefinition workflowDef = testWorkflowDef;
|
||||
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, testNodeRef);
|
||||
Date reviewDueDate = new Date();
|
||||
params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewDueDate"), reviewDueDate);
|
||||
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));
|
||||
WorkflowTask endedTask = taskComponent.endTask(task.id, null);
|
||||
assertNotNull(endedTask);
|
||||
assertTrue(endedTask.properties.containsKey(WorkflowModel.PROP_OUTCOME));
|
||||
assertEquals("", endedTask.properties.get(WorkflowModel.PROP_OUTCOME));
|
||||
|
||||
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));
|
||||
assertEquals(reviewDueDate, assignedTasks.get(0).properties.get(WorkflowModel.PROP_DUE_DATE));
|
||||
}
|
||||
|
||||
public void testCompletedItems()
|
||||
{
|
||||
WorkflowDefinition workflowDef = testWorkflowDef;
|
||||
|
||||
List<NodeRef> nodeRefs = new ArrayList<NodeRef>();
|
||||
nodeRefs.add(testNodeRef);
|
||||
nodeRefs.add(testNodeRef);
|
||||
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, testNodeRef);
|
||||
params.put(WorkflowModel.PROP_COMPLETED_ITEMS, (Serializable)nodeRefs);
|
||||
Date reviewDueDate = new Date();
|
||||
params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewDueDate"), reviewDueDate);
|
||||
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.PROP_COMPLETED_ITEMS));
|
||||
assertEquals(2, ((List)task.properties.get(WorkflowModel.PROP_COMPLETED_ITEMS)).size());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping default-access="field">
|
||||
|
||||
<subclass name="org.alfresco.repo.workflow.jbpm.WorkflowTaskInstance"
|
||||
extends="org.jbpm.taskmgmt.exe.TaskInstance"
|
||||
discriminator-value="W"/>
|
||||
|
||||
</hibernate-mapping>
|
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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 org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
import org.jbpm.graph.def.Transition;
|
||||
import org.jbpm.graph.exe.ExecutionContext;
|
||||
import org.jbpm.taskmgmt.exe.TaskInstance;
|
||||
import org.springframework.beans.factory.access.BeanFactoryLocator;
|
||||
import org.springframework.beans.factory.access.BeanFactoryReference;
|
||||
import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
|
||||
|
||||
|
||||
/**
|
||||
* Alfresco specific implementation of a jBPM task instance
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class WorkflowTaskInstance extends TaskInstance
|
||||
{
|
||||
private static final long serialVersionUID = 6824116036569411964L;
|
||||
|
||||
/** Alfresco JBPM Engine */
|
||||
private static JBPMEngine jbpmEngine = null;
|
||||
|
||||
/**
|
||||
* Gets the JBPM Engine instance
|
||||
*
|
||||
* @return JBPM Engine
|
||||
*/
|
||||
private JBPMEngine getJBPMEngine()
|
||||
{
|
||||
if (jbpmEngine == null)
|
||||
{
|
||||
BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
|
||||
BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
|
||||
jbpmEngine = (JBPMEngine)factory.getFactory().getBean("jbpm_engine");
|
||||
if (jbpmEngine == null)
|
||||
{
|
||||
throw new WorkflowException("Failed to retrieve JBPMEngine component");
|
||||
}
|
||||
}
|
||||
return jbpmEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*/
|
||||
public WorkflowTaskInstance()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param taskName
|
||||
* @param actorId
|
||||
*/
|
||||
public WorkflowTaskInstance(String taskName, String actorId)
|
||||
{
|
||||
super(taskName, actorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param taskName
|
||||
*/
|
||||
public WorkflowTaskInstance(String taskName)
|
||||
{
|
||||
super(taskName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(ExecutionContext executionContext)
|
||||
{
|
||||
super.create(executionContext);
|
||||
getJBPMEngine().setDefaultTaskProperties(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end(Transition transition)
|
||||
{
|
||||
// NOTE: Set the outcome first, so it's available during the submission of
|
||||
// task variables to the process context
|
||||
Transition outcome = (transition == null) ? token.getNode().getDefaultLeavingTransition() : transition;
|
||||
if (outcome != null)
|
||||
{
|
||||
getJBPMEngine().setTaskOutcome(this, outcome);
|
||||
}
|
||||
super.end(transition);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 org.jbpm.graph.exe.ExecutionContext;
|
||||
import org.jbpm.taskmgmt.TaskInstanceFactory;
|
||||
import org.jbpm.taskmgmt.exe.TaskInstance;
|
||||
|
||||
|
||||
/**
|
||||
* jBPM factory for creating Alfresco derived Task Instances
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class WorkflowTaskInstanceFactory implements TaskInstanceFactory
|
||||
{
|
||||
private static final long serialVersionUID = -8097108150047415711L;
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jbpm.taskmgmt.TaskInstanceFactory#createTaskInstance(org.jbpm.graph.exe.ExecutionContext)
|
||||
*/
|
||||
public TaskInstance createTaskInstance(ExecutionContext executionContext)
|
||||
{
|
||||
return new WorkflowTaskInstance();
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
<?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>
|
28
source/java/org/alfresco/repo/workflow/jbpm/jbpm.cfg.xml
Normal file
28
source/java/org/alfresco/repo/workflow/jbpm/jbpm.cfg.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<jbpm-configuration>
|
||||
|
||||
<jbpm-context>
|
||||
<service name="persistence" factory="org.jbpm.persistence.db.DbPersistenceServiceFactory" />
|
||||
<service name="message" factory="org.jbpm.msg.db.DbMessageServiceFactory" />
|
||||
<service name="scheduler" factory="org.jbpm.scheduler.db.DbSchedulerServiceFactory" />
|
||||
<service name="logging" factory="org.jbpm.logging.db.DbLoggingServiceFactory" />
|
||||
<service name="authentication" factory="org.jbpm.security.authentication.DefaultAuthenticationServiceFactory" />
|
||||
</jbpm-context>
|
||||
|
||||
<!-- configuration resource files pointing to default configuration files in jbpm-{version}.jar -->
|
||||
<string name="resource.hibernate.cfg.xml" value="hibernate.cfg.xml" />
|
||||
<string name="resource.business.calendar" value="org/jbpm/calendar/jbpm.business.calendar.properties" />
|
||||
<string name="resource.default.modules" value="org/jbpm/graph/def/jbpm.default.modules.properties" />
|
||||
<string name='resource.converter' value='org/alfresco/repo/workflow/jbpm/jbpm.converter.properties' />
|
||||
<string name="resource.action.types" value="org/jbpm/graph/action/action.types.xml" />
|
||||
<string name="resource.node.types" value="org/jbpm/graph/node/node.types.xml" />
|
||||
<string name="resource.parsers" value="org/jbpm/jpdl/par/jbpm.parsers.xml" />
|
||||
<string name="resource.varmapping" value="org/alfresco/repo/workflow/jbpm/jbpm.varmapping.xml" />
|
||||
|
||||
<long name="jbpm.msg.wait.timout" value="5000" singleton="true" />
|
||||
<int name="jbpm.byte.block.size" value="1024" singleton="true" />
|
||||
<string name="mail.smtp.host" value="localhost" />
|
||||
<bean name="jbpm.task.instance.factory" class="org.alfresco.repo.workflow.jbpm.WorkflowTaskInstanceFactory" singleton="true" />
|
||||
<bean name="jbpm.variable.resolver" class="org.jbpm.jpdl.el.impl.JbpmVariableResolver" singleton="true" />
|
||||
<bean name="jbpm.mail.address.resolver" class="org.jbpm.identity.mail.IdentityAddressResolver" singleton="true" />
|
||||
|
||||
</jbpm-configuration>
|
@@ -0,0 +1,19 @@
|
||||
# this file contains the mappings between converter types
|
||||
# and the char that is used in the database. this mapping
|
||||
# is used by the ConverterEnumType to store the VariableInstance
|
||||
# converter field. The Converters class provides singleton access
|
||||
# to these converter classes.
|
||||
|
||||
B org.jbpm.context.exe.converter.BooleanToStringConverter
|
||||
Y org.jbpm.context.exe.converter.BytesToByteArrayConverter
|
||||
E org.jbpm.context.exe.converter.ByteToLongConverter
|
||||
C org.jbpm.context.exe.converter.CharacterToStringConverter
|
||||
A org.jbpm.context.exe.converter.DateToLongConverter
|
||||
D org.jbpm.context.exe.converter.DoubleToStringConverter
|
||||
F org.jbpm.context.exe.converter.FloatToStringConverter
|
||||
G org.jbpm.context.exe.converter.FloatToDoubleConverter
|
||||
I org.jbpm.context.exe.converter.IntegerToLongConverter
|
||||
R org.jbpm.context.exe.converter.SerializableToByteArrayConverter
|
||||
H org.jbpm.context.exe.converter.ShortToLongConverter
|
||||
N org.alfresco.repo.workflow.jbpm.NodeConverter
|
||||
L org.alfresco.repo.workflow.jbpm.NodeListConverter
|
190
source/java/org/alfresco/repo/workflow/jbpm/jbpm.varmapping.xml
Normal file
190
source/java/org/alfresco/repo/workflow/jbpm/jbpm.varmapping.xml
Normal file
@@ -0,0 +1,190 @@
|
||||
<!--
|
||||
# This file specifies how jbpm will store variables into the database.
|
||||
#
|
||||
# If jbpm needs to determine how to store a variable into the database,
|
||||
# the jbpm-types below or scanned in sequence as they are specified here.
|
||||
# For each jbpm-type, jbpm will see if the give variable object matches
|
||||
# with the matcher bean. If there is a match, the converter (optional)
|
||||
# and the variable instance will be used to store and retrieve
|
||||
# the variable value for the rest of its lifetime till the variable is
|
||||
# deleted.
|
||||
-->
|
||||
<jbpm-types>
|
||||
|
||||
<list name="jbpm.types" singleton="true">
|
||||
|
||||
<!-- java.lang.String -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="java.lang.String" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.StringInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- java.lang.Boolean -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="java.lang.Boolean" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<converter class="org.jbpm.context.exe.converter.BooleanToStringConverter" />
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.StringInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- java.lang.Character -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="java.lang.Character" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<converter class="org.jbpm.context.exe.converter.CharacterToStringConverter" />
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.StringInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- java.lang.Long -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="java.lang.Long" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.LongInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- java.lang.Byte -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="java.lang.Byte" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<converter class="org.jbpm.context.exe.converter.ByteToLongConverter" />
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.LongInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- java.lang.Short -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="java.lang.Short" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<converter class="org.jbpm.context.exe.converter.ShortToLongConverter" />
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.LongInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- java.lang.Integer -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="java.lang.Integer" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<converter class="org.jbpm.context.exe.converter.IntegerToLongConverter" />
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.LongInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- java.lang.Double -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="java.lang.Double" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.DoubleInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- java.lang.Float -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="java.lang.Float" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<converter class="org.jbpm.context.exe.converter.FloatToDoubleConverter" />
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.DoubleInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- java.util.Date -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="java.util.Date" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.DateInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- org.alfresco.repo.workflow.jbpm.JBPMNode -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="org.alfresco.repo.workflow.jbpm.JBPMNode" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<converter class="org.alfresco.repo.workflow.jbpm.NodeConverter" />
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.StringInstance" />
|
||||
</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[] -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
|
||||
<field name="className"><string value="[B" /></field>
|
||||
</bean>
|
||||
</matcher>
|
||||
<converter class="org.jbpm.context.exe.converter.BytesToByteArrayConverter" />
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.ByteArrayInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- java.io.Serializable -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.SerializableMatcher" />
|
||||
</matcher>
|
||||
<converter class="org.jbpm.context.exe.converter.SerializableToByteArrayConverter" />
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.ByteArrayInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- hibernatable long id types -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.HibernateLongIdMatcher" />
|
||||
</matcher>
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.HibernateLongInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- hibernatable string id types -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.HibernateStringIdMatcher" />
|
||||
</matcher>
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.HibernateStringInstance" />
|
||||
</jbpm-type>
|
||||
|
||||
<!-- hibernatable ejb3 types -->
|
||||
<jbpm-type>
|
||||
<matcher>
|
||||
<bean class="org.jbpm.context.exe.matcher.Ejb3Matcher" />
|
||||
</matcher>
|
||||
<variable-instance class="org.jbpm.context.exe.variableinstance.Ejb3Instance" />
|
||||
</jbpm-type>
|
||||
|
||||
</list>
|
||||
|
||||
</jbpm-types>
|
@@ -0,0 +1,63 @@
|
||||
<?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,14 @@
|
||||
test.workflow.title=Test
|
||||
test.workflow.description=Workflow for testing purposes
|
||||
|
||||
test.node.start.title=Start
|
||||
test.node.start.description=The Start
|
||||
test.node.review.title=Review
|
||||
test.node.review.description=The Review
|
||||
test.node.end.title=End
|
||||
test.node.end.description=The End
|
||||
|
||||
test.node.start.transition.review=Review
|
||||
|
||||
test.task.submit.title=Submit Review Title
|
||||
test.task.submit.description=Submit Review Description
|
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="test">
|
||||
<swimlane name="initiator"></swimlane>
|
||||
|
||||
<start-state name="start">
|
||||
<task name="submit" swimlane="initiator">
|
||||
<controller>
|
||||
<variable name="reviewer" access="write,required" />
|
||||
<variable name="testNode" access="write,required" />
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="review">
|
||||
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
|
||||
<script>
|
||||
<expression>
|
||||
function result()
|
||||
{
|
||||
return ("Initiator: " + initiator.properties["cm:userName"] + ", process instance = " + executionContext.processInstance.id + ", testNode children = " + testNode.children.length);
|
||||
}
|
||||
result();
|
||||
</expression>
|
||||
<variable name="scriptResult" access="write"/>
|
||||
</script>
|
||||
</action>
|
||||
</transition>
|
||||
<transition name="end" to="end"/>
|
||||
</start-state>
|
||||
|
||||
<swimlane name="reviewer">
|
||||
<assignment actor-id="#{reviewer}"></assignment>
|
||||
</swimlane>
|
||||
|
||||
<task-node name="review">
|
||||
<event type="node-enter">
|
||||
<script>
|
||||
System.out.println("the reviewer is " + reviewer);
|
||||
System.out.println("node " + testNode.name + " contains " + testNode.children.length + " children");
|
||||
System.out.println("scriptResult = " + scriptResult);
|
||||
</script>
|
||||
</event>
|
||||
<task name="review" duedate="1 business day" blocking="true" swimlane="reviewer">
|
||||
<controller>
|
||||
<variable name="comment" access="read,write,required"></variable>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="end"></transition>
|
||||
</task-node>
|
||||
|
||||
<end-state name="end"></end-state>
|
||||
|
||||
</process-definition>
|
57
source/java/org/alfresco/repo/workflow/jbpm/test_script.xml
Normal file
57
source/java/org/alfresco/repo/workflow/jbpm/test_script.xml
Normal file
@@ -0,0 +1,57 @@
|
||||
<?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>
|
||||
<!-- following line fails as it attempts to convert properties of children to javascript objects -->
|
||||
<!-- except the beanshell line above has already pre-created the children without the javascript scope -->
|
||||
<!-- object -->
|
||||
<!-- var result = "testNode.created: " + testNode.properties["cm:created"] + ", testNode.children.length: " + testNode.children[0].properties["cm:name"]; -->
|
||||
<expression>
|
||||
var result = "testNode.created: " + testNode.properties["cm:created"] + ", testNode.children.length: " + testNode.children.length;
|
||||
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