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/SwimlaneLog.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>
</property>
<property name="hibernateProperties" ref="hibernateConfigProperties" />

View File

@@ -103,7 +103,6 @@
<property name="bpm:status">
<title>Status</title>
<type>d:text</type>
<protected>true</protected>
<mandatory>true</mandatory>
<default>Not Yet Started</default>
<constraints>
@@ -171,18 +170,6 @@
<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 -->
<!-- e.g. Space, Document -->
<property name="bpm:context">
@@ -249,6 +236,22 @@
<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 -->
<!-- search within Alfresco e.g. task info, workflow info ... -->

View File

@@ -45,12 +45,16 @@ public interface WorkflowModel
// workflow task contstants
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_WORKFLOW_DEFINITION_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDefinitionId");
static final QName PROP_WORKFLOW_INSTANCE_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowInstanceId");
static final QName PROP_OUTCOME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "outcome");
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");
// workflow package
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.cmr.dictionary.AspectDefinition;
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.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
@@ -748,8 +749,8 @@ public class JBPMEngine extends BPMEngine
*/
public WorkflowTask startTask(String taskId)
{
// TODO Auto-generated method stub
return null;
// TODO:
throw new UnsupportedOperationException();
}
/* (non-Javadoc)
@@ -757,8 +758,8 @@ public class JBPMEngine extends BPMEngine
*/
public WorkflowTask suspendTask(String taskId)
{
// TODO Auto-generated method stub
return null;
// TODO:
throw new UnsupportedOperationException();
}
/* (non-Javadoc)
@@ -882,7 +883,6 @@ public class JBPMEngine extends BPMEngine
}
}
/**
* 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<QName> aspectNames = new ArrayList<QName>(aspects.size());
for (AspectDefinition aspect : aspects)
{
aspectNames.add(aspect.getName());
}
getMandatoryAspects(typeDef, 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
@@ -1075,6 +1091,7 @@ public class JBPMEngine extends BPMEngine
properties.put(WorkflowModel.PROP_DUE_DATE, instance.getDueDate());
properties.put(WorkflowModel.PROP_COMPLETION_DATE, instance.getEnd());
properties.put(WorkflowModel.PROP_PRIORITY, instance.getPriority());
properties.put(ContentModel.PROP_CREATED, instance.getCreate());
properties.put(ContentModel.PROP_OWNER, instance.getActorId());
// map jBPM task instance collections to associations
@@ -1230,6 +1247,57 @@ public class JBPMEngine extends BPMEngine
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
@@ -1479,6 +1547,8 @@ public class JBPMEngine extends BPMEngine
{
WorkflowTaskDefinition taskDef = new WorkflowTaskDefinition();
taskDef.id = task.getName();
Node node = (task.getStartState() == null ? task.getTaskNode() : task.getStartState());
taskDef.node = createWorkflowNode(node);
taskDef.metadata = getTaskDefinition(task);
return taskDef;
}

View File

@@ -109,7 +109,10 @@ public class ReviewAndApproveTest extends BaseSpringTest
WorkflowTask task = tasks1.get(0);
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);
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" />
<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.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.mail.address.resolver" class="org.jbpm.identity.mail.IdentityAddressResolver" singleton="true" />

View File

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

View File

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