Workflow:

- map jbpm task created date to alfresco task
- implement jbpm task default values (as defined by task model)
- implement task outcome property (i.e. record the transition taken on completed tasks)
- add definition of task node to WorkflowTask API Object

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3574 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2006-08-22 23:25:47 +00:00
parent 6f462eae09
commit 54bf835f2d
11 changed files with 278 additions and 29 deletions

View File

@@ -132,7 +132,10 @@
<value>org/jbpm/taskmgmt/log/TaskEndLog.hbm.xml</value> <value>org/jbpm/taskmgmt/log/TaskEndLog.hbm.xml</value>
<value>org/jbpm/taskmgmt/log/SwimlaneLog.hbm.xml</value> <value>org/jbpm/taskmgmt/log/SwimlaneLog.hbm.xml</value>
<value>org/jbpm/taskmgmt/log/SwimlaneCreateLog.hbm.xml</value> <value>org/jbpm/taskmgmt/log/SwimlaneCreateLog.hbm.xml</value>
<value>org/jbpm/taskmgmt/log/SwimlaneAssignLog.hbm.xml</value> <value>org/jbpm/taskmgmt/log/SwimlaneAssignLog.hbm.xml</value>
<!-- Alfresco TaskInstance sub-type -->
<value>org/alfresco/repo/workflow/jbpm/WorkflowTaskInstance.hbm.xml</value>
</list> </list>
</property> </property>
<property name="hibernateProperties" ref="hibernateConfigProperties" /> <property name="hibernateProperties" ref="hibernateConfigProperties" />

View File

@@ -103,7 +103,6 @@
<property name="bpm:status"> <property name="bpm:status">
<title>Status</title> <title>Status</title>
<type>d:text</type> <type>d:text</type>
<protected>true</protected>
<mandatory>true</mandatory> <mandatory>true</mandatory>
<default>Not Yet Started</default> <default>Not Yet Started</default>
<constraints> <constraints>
@@ -171,18 +170,6 @@
<properties> <properties>
<!-- -->
<!-- Associated Workflow -->
<!-- -->
<property name="bpm:workflowDefinitionId">
<title>Workflow Definition Id</title>
<type>d:text</type>
</property>
<property name="bpm:workflowInstanceId">
<title>Workflow Instance Id</title>
<type>d:text</type>
</property>
<!-- Task Context --> <!-- Task Context -->
<!-- e.g. Space, Document --> <!-- e.g. Space, Document -->
<property name="bpm:context"> <property name="bpm:context">
@@ -249,6 +236,22 @@
<properties> <properties>
<!-- -->
<!-- Associated Workflow -->
<!-- -->
<property name="bpm:workflowDefinitionId">
<title>Workflow Definition Id</title>
<type>d:text</type>
</property>
<property name="bpm:workflowDefinitionName">
<title>Workflow Definition Name</title>
<type>d:text</type>
</property>
<property name="bpm:workflowInstanceId">
<title>Workflow Instance Id</title>
<type>d:text</type>
</property>
<!-- TODO: Define properties (replicated from Workflow/Task Engine) for --> <!-- TODO: Define properties (replicated from Workflow/Task Engine) for -->
<!-- search within Alfresco e.g. task info, workflow info ... --> <!-- search within Alfresco e.g. task info, workflow info ... -->

View File

@@ -45,12 +45,16 @@ public interface WorkflowModel
// workflow task contstants // workflow task contstants
static final QName TYPE_WORKFLOW_TASK = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowTask"); static final QName TYPE_WORKFLOW_TASK = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowTask");
static final QName PROP_CONTEXT = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "context"); static final QName PROP_CONTEXT = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "context");
static final QName PROP_WORKFLOW_DEFINITION_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDefinitionId"); static final QName PROP_OUTCOME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "outcome");
static final QName PROP_WORKFLOW_INSTANCE_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowInstanceId"); static final QName PROP_PACKAGE_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageActionGroup");
static final QName PROP_PACKAGE_ITEM_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageItemActionGroup");
static final QName ASSOC_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"); static final QName ASSOC_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package");
// workflow package // workflow package
static final QName ASPECT_WORKFLOW_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPackage"); static final QName ASPECT_WORKFLOW_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPackage");
static final QName PROP_WORKFLOW_DEFINITION_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDefinitionId");
static final QName PROP_WORKFLOW_DEFINITION_NAME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDefinitionName");
static final QName PROP_WORKFLOW_INSTANCE_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowInstanceId");
// //

View File

@@ -40,6 +40,7 @@ import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition;
@@ -748,8 +749,8 @@ public class JBPMEngine extends BPMEngine
*/ */
public WorkflowTask startTask(String taskId) public WorkflowTask startTask(String taskId)
{ {
// TODO Auto-generated method stub // TODO:
return null; throw new UnsupportedOperationException();
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -757,8 +758,8 @@ public class JBPMEngine extends BPMEngine
*/ */
public WorkflowTask suspendTask(String taskId) public WorkflowTask suspendTask(String taskId)
{ {
// TODO Auto-generated method stub // TODO:
return null; throw new UnsupportedOperationException();
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -882,7 +883,6 @@ public class JBPMEngine extends BPMEngine
} }
} }
/** /**
* Construct a Process Definition from the provided Process Definition stream * Construct a Process Definition from the provided Process Definition stream
* *
@@ -974,12 +974,28 @@ public class JBPMEngine extends BPMEngine
{ {
List<AspectDefinition> aspects = typeDef.getDefaultAspects(); List<AspectDefinition> aspects = typeDef.getDefaultAspects();
List<QName> aspectNames = new ArrayList<QName>(aspects.size()); List<QName> aspectNames = new ArrayList<QName>(aspects.size());
for (AspectDefinition aspect : aspects) getMandatoryAspects(typeDef, aspectNames);
{
aspectNames.add(aspect.getName());
}
return dictionaryService.getAnonymousType(typeDef.getName(), aspectNames); return dictionaryService.getAnonymousType(typeDef.getName(), aspectNames);
} }
/**
* Gets a flattened list of all mandatory aspects for a given class
*
* @param classDef the class
* @param aspects a list to hold the mandatory aspects
*/
private void getMandatoryAspects(ClassDefinition classDef, List<QName> aspects)
{
for (AspectDefinition aspect : classDef.getDefaultAspects())
{
QName aspectName = aspect.getName();
if (!aspects.contains(aspectName))
{
aspects.add(aspect.getName());
getMandatoryAspects(aspect, aspects);
}
}
}
/** /**
* Get JBoss JBPM Id from Engine Global Id * Get JBoss JBPM Id from Engine Global Id
@@ -1075,6 +1091,7 @@ public class JBPMEngine extends BPMEngine
properties.put(WorkflowModel.PROP_DUE_DATE, instance.getDueDate()); properties.put(WorkflowModel.PROP_DUE_DATE, instance.getDueDate());
properties.put(WorkflowModel.PROP_COMPLETION_DATE, instance.getEnd()); properties.put(WorkflowModel.PROP_COMPLETION_DATE, instance.getEnd());
properties.put(WorkflowModel.PROP_PRIORITY, instance.getPriority()); properties.put(WorkflowModel.PROP_PRIORITY, instance.getPriority());
properties.put(ContentModel.PROP_CREATED, instance.getCreate());
properties.put(ContentModel.PROP_OWNER, instance.getActorId()); properties.put(ContentModel.PROP_OWNER, instance.getActorId());
// map jBPM task instance collections to associations // map jBPM task instance collections to associations
@@ -1230,6 +1247,57 @@ public class JBPMEngine extends BPMEngine
instance.setVariableLocally(name, value); instance.setVariableLocally(name, value);
} }
} }
/**
* Sets Default Properties of Task
*
* @param instance task instance
*/
protected void setDefaultTaskProperties(TaskInstance instance)
{
Map<QName, Serializable> existingValues = null;
Map<QName, Serializable> defaultValues = new HashMap<QName, Serializable>();
// construct an anonymous type that flattens all mandatory aspects
ClassDefinition classDef = getAnonymousTaskDefinition(getTaskDefinition(instance.getTask()));
Map<QName, PropertyDefinition> propertyDefs = classDef.getProperties();
// for each property, determine if it has a default value
for (Map.Entry<QName, PropertyDefinition> entry : propertyDefs.entrySet())
{
String defaultValue = entry.getValue().getDefaultValue();
if (defaultValue != null)
{
if (existingValues == null)
{
existingValues = getTaskProperties(instance);
}
if (existingValues.get(entry.getKey()) == null)
{
defaultValues.put(entry.getKey(), defaultValue);
}
}
}
// assign the default values to the task
if (defaultValues.size() > 0)
{
setTaskProperties(instance, defaultValues);
}
}
/**
* Set Task Outcome based on specified Transition
*
* @param instance task instance
* @param transition transition
*/
protected void setTaskOutcome(TaskInstance instance, Transition transition)
{
Map<QName, Serializable> outcome = new HashMap<QName, Serializable>();
outcome.put(WorkflowModel.PROP_OUTCOME, transition.getName());
setTaskProperties(instance, outcome);
}
/** /**
* Convert a Repository association to JBPMNodeList or JBPMNode * Convert a Repository association to JBPMNodeList or JBPMNode
@@ -1479,6 +1547,8 @@ public class JBPMEngine extends BPMEngine
{ {
WorkflowTaskDefinition taskDef = new WorkflowTaskDefinition(); WorkflowTaskDefinition taskDef = new WorkflowTaskDefinition();
taskDef.id = task.getName(); taskDef.id = task.getName();
Node node = (task.getStartState() == null ? task.getTaskNode() : task.getStartState());
taskDef.node = createWorkflowNode(node);
taskDef.metadata = getTaskDefinition(task); taskDef.metadata = getTaskDefinition(task);
return taskDef; return taskDef;
} }

View File

@@ -109,7 +109,10 @@ public class ReviewAndApproveTest extends BaseSpringTest
WorkflowTask task = tasks1.get(0); WorkflowTask task = tasks1.get(0);
assertTrue(task.properties.containsKey(WorkflowModel.ASSOC_PACKAGE)); assertTrue(task.properties.containsKey(WorkflowModel.ASSOC_PACKAGE));
taskComponent.endTask(task.id, null); 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); List<WorkflowTask> assignedTasks = taskComponent.getAssignedTasks("admin", WorkflowTaskState.IN_PROGRESS);
assertNotNull(assignedTasks); assertNotNull(assignedTasks);

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

@@ -21,7 +21,7 @@
<long name="jbpm.msg.wait.timout" value="5000" singleton="true" /> <long name="jbpm.msg.wait.timout" value="5000" singleton="true" />
<int name="jbpm.byte.block.size" value="1024" singleton="true" /> <int name="jbpm.byte.block.size" value="1024" singleton="true" />
<string name="mail.smtp.host" value="localhost" /> <string name="mail.smtp.host" value="localhost" />
<bean name="jbpm.task.instance.factory" class="org.jbpm.taskmgmt.impl.DefaultTaskInstanceFactoryImpl" singleton="true" /> <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.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" /> <bean name="jbpm.mail.address.resolver" class="org.jbpm.identity.mail.IdentityAddressResolver" singleton="true" />

View File

@@ -25,7 +25,7 @@
<event type="task-create"> <event type="task-create">
<script> <script>
taskInstance.dueDate = reviewduedate; taskInstance.dueDate = reviewduedate;
// taskInstance.priority = reviewpriority; taskInstance.priority = reviewpriority;
</script> </script>
</event> </event>
<controller> <controller>

View File

@@ -31,6 +31,9 @@ public class WorkflowTaskDefinition
{ {
/** Unique id of Workflow Task Definition */ /** Unique id of Workflow Task Definition */
public String id; public String id;
/** Workflow Node this task created from */
public WorkflowNode node;
/** Task Metadata */ /** Task Metadata */
public TypeDefinition metadata; public TypeDefinition metadata;