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:
Britt Park
2006-08-27 01:01:30 +00:00
parent e2c66899cc
commit 8031cc6574
322 changed files with 20776 additions and 6550 deletions

View File

@@ -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;
}
}

File diff suppressed because it is too large Load Diff

View 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;
}
}

View 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);
}
}
}
}

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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;
}
}

View 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.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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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>

View 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>

View File

@@ -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

View 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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View 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>