mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Implemented temporary workflow form processor and associated test.
An item kind of "workflow" and itemId of "<workflow-def-name>" are now supported (only "jbpm$wf:adhoc" works though at the moment). Showing the form, selecting an assignee and submitting the form will start the ad hoc workflow and create a task for the selected assignee. NOTE: Support for 'packageItems' is not present yet. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21021 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -44,6 +44,10 @@ import org.alfresco.service.cmr.repository.ScriptLocation;
|
||||
import org.alfresco.service.cmr.repository.ScriptService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowInstance;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.NamespaceException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
@@ -64,6 +68,7 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest
|
||||
private ScriptService scriptService;
|
||||
private PersonService personService;
|
||||
private ContentService contentService;
|
||||
private WorkflowService workflowService;
|
||||
|
||||
private NodeRef document;
|
||||
private NodeRef associatedDoc;
|
||||
@@ -106,6 +111,7 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest
|
||||
private static final String USER_ONE = "UserOne_FormServiceImplTest";
|
||||
private static final String NODE_FORM_ITEM_KIND = "node";
|
||||
private static final String TYPE_FORM_ITEM_KIND = "type";
|
||||
private static final String WORKFLOW_FORM_ITEM_KIND = "workflow";
|
||||
|
||||
/**
|
||||
* Called during the transaction setup
|
||||
@@ -122,6 +128,7 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest
|
||||
this.scriptService = (ScriptService)this.applicationContext.getBean("ScriptService");
|
||||
this.personService = (PersonService)this.applicationContext.getBean("PersonService");
|
||||
this.contentService = (ContentService)this.applicationContext.getBean("ContentService");
|
||||
this.workflowService = (WorkflowService)this.applicationContext.getBean("WorkflowService");
|
||||
|
||||
AuthenticationComponent authenticationComponent = (AuthenticationComponent) this.applicationContext
|
||||
.getBean("authenticationComponent");
|
||||
@@ -1221,6 +1228,77 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest
|
||||
assertEquals(1, assocs.size());
|
||||
}
|
||||
|
||||
public void testWorkflowForm() throws Exception
|
||||
{
|
||||
// generate a form for a well known workflow-definition supplying
|
||||
// a legitimate set of fields for the workflow
|
||||
List<String> fields = new ArrayList<String>(8);
|
||||
fields.add("bpm:taskId");
|
||||
fields.add("bpm:description");
|
||||
fields.add("bpm:workflowDueDate");
|
||||
//fields.add("packageItems");
|
||||
|
||||
String workflowDefName = "jbpm$wf:adhoc";
|
||||
Form form = this.formService.getForm(new Item(WORKFLOW_FORM_ITEM_KIND, workflowDefName), fields);
|
||||
|
||||
// check a form got returned
|
||||
assertNotNull("Expecting form to be present", form);
|
||||
|
||||
// check item identifier matches
|
||||
assertEquals(WORKFLOW_FORM_ITEM_KIND, form.getItem().getKind());
|
||||
assertEquals(workflowDefName, form.getItem().getId());
|
||||
|
||||
// check the field definitions
|
||||
Collection<FieldDefinition> fieldDefs = form.getFieldDefinitions();
|
||||
assertNotNull("Expecting to find fields", fieldDefs);
|
||||
assertEquals("Expecting to find " + fields.size() + " fields", fields.size(), fieldDefs.size());
|
||||
|
||||
// check the fields are returned correctly
|
||||
Map<String, FieldDefinition> fieldDefMap = new HashMap<String, FieldDefinition>(fieldDefs.size());
|
||||
for (FieldDefinition fieldDef : fieldDefs)
|
||||
{
|
||||
fieldDefMap.put(fieldDef.getName(), fieldDef);
|
||||
}
|
||||
|
||||
// find the fields
|
||||
PropertyFieldDefinition idField = (PropertyFieldDefinition)fieldDefMap.get("bpm:taskId");
|
||||
PropertyFieldDefinition descriptionField = (PropertyFieldDefinition)fieldDefMap.get("bpm:description");
|
||||
PropertyFieldDefinition dueDateField = (PropertyFieldDefinition)fieldDefMap.get("bpm:workflowDueDate");
|
||||
//AssociationFieldDefinition packageItemsField = (AssociationFieldDefinition)fieldDefMap.get("packageItems");
|
||||
|
||||
// check fields are present
|
||||
assertNotNull("Expecting to find the bpm:taskId field", idField);
|
||||
assertNotNull("Expecting to find the bpm:description field", descriptionField);
|
||||
assertNotNull("Expecting to find the bpm:workflowDueDate field", dueDateField);
|
||||
//assertNotNull("Expecting to find the packageItems field", packageItemsField);
|
||||
|
||||
// get the number of tasks now
|
||||
List<WorkflowTask> tasks = this.workflowService.getAssignedTasks(USER_ONE,
|
||||
WorkflowTaskState.IN_PROGRESS);
|
||||
int tasksBefore = tasks.size();
|
||||
|
||||
// persist the form
|
||||
FormData data = new FormData();
|
||||
data.addFieldData("prop_bpm_description", "This is a new adhoc task");
|
||||
data.addFieldData("assoc_bpm_assignee_added",
|
||||
this.personService.getPerson(USER_ONE).toString());
|
||||
//data.addFieldData("packageItems_added", this.document.toString());
|
||||
|
||||
// persist the data
|
||||
WorkflowInstance workflow = (WorkflowInstance)this.formService.saveForm(
|
||||
new Item(WORKFLOW_FORM_ITEM_KIND, workflowDefName), data);
|
||||
|
||||
// verify that the workflow was started by checking the user has one
|
||||
// more task and the details on the workflow instance
|
||||
tasks = this.workflowService.getAssignedTasks(USER_ONE,
|
||||
WorkflowTaskState.IN_PROGRESS);
|
||||
int tasksAfter = tasks.size();
|
||||
assertTrue("Expecting there to be more tasks", tasksAfter > tasksBefore);
|
||||
|
||||
// check workflow instance details
|
||||
assertEquals(workflowDefName, workflow.definition.name);
|
||||
}
|
||||
|
||||
public void testNoForm() throws Exception
|
||||
{
|
||||
// test that a form can not be retrieved for a non-existent item
|
||||
|
@@ -18,8 +18,33 @@
|
||||
*/
|
||||
package org.alfresco.repo.forms.processor.workflow;
|
||||
|
||||
import org.alfresco.repo.forms.processor.node.TypeFormProcessor;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.forms.Form;
|
||||
import org.alfresco.repo.forms.FormData;
|
||||
import org.alfresco.repo.forms.FormNotFoundException;
|
||||
import org.alfresco.repo.forms.Item;
|
||||
import org.alfresco.repo.forms.processor.node.ContentModelFormProcessor;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
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.WorkflowService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Temporary FormProcessor implementation that can generate and persist
|
||||
@@ -27,8 +52,12 @@ import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
*
|
||||
* @author Gavin Cornwell
|
||||
*/
|
||||
public class WorkflowFormProcessor extends TypeFormProcessor
|
||||
public class WorkflowFormProcessor extends ContentModelFormProcessor<WorkflowDefinition, WorkflowInstance>
|
||||
{
|
||||
/** Logger */
|
||||
private static Log logger = LogFactory.getLog(WorkflowFormProcessor.class);
|
||||
|
||||
/** workflow service */
|
||||
protected WorkflowService workflowService;
|
||||
|
||||
/**
|
||||
@@ -40,4 +69,207 @@ public class WorkflowFormProcessor extends TypeFormProcessor
|
||||
{
|
||||
this.workflowService = workflowService;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see
|
||||
* org.alfresco.repo.forms.processor.node.ContentModelFormProcessor#getLogger
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
protected Log getLogger()
|
||||
{
|
||||
return logger;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see
|
||||
* org.alfresco.repo.forms.processor.node.NodeFormProcessor#getTypedItem
|
||||
* (org.alfresco.repo.forms.Item)
|
||||
*/
|
||||
@Override
|
||||
protected WorkflowDefinition getTypedItem(Item item)
|
||||
{
|
||||
WorkflowDefinition workflowDef = null;
|
||||
|
||||
try
|
||||
{
|
||||
// item id could be the raw workflow definition name or it could be
|
||||
// in a URL friendly format
|
||||
String workflowDefName = item.getId();
|
||||
if (workflowDefName.indexOf("$") == -1)
|
||||
{
|
||||
// decode the itemId
|
||||
workflowDefName = workflowDefName.replace("jbpm_", "jbpm$");
|
||||
workflowDefName = workflowDefName.replace('_', ':');
|
||||
}
|
||||
|
||||
// Extract the workflow definition
|
||||
workflowDef = this.workflowService.getDefinitionByName(workflowDefName);
|
||||
|
||||
if (workflowDef == null)
|
||||
{
|
||||
throw new FormNotFoundException(item,
|
||||
new IllegalArgumentException("Workflow definition does not exist: " + item.getId()));
|
||||
}
|
||||
}
|
||||
catch (WorkflowException we)
|
||||
{
|
||||
throw new FormNotFoundException(item, we);
|
||||
}
|
||||
|
||||
// return the type definition object for the requested type
|
||||
return workflowDef;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see
|
||||
* org.alfresco.repo.forms.processor.FilteredFormProcessor#internalGenerate
|
||||
* (java.lang.Object, java.util.List, java.util.List,
|
||||
* org.alfresco.repo.forms.Form, java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
protected void internalGenerate(WorkflowDefinition workflowDef, List<String> fields,
|
||||
List<String> forcedFields, Form form, Map<String, Object> context)
|
||||
{
|
||||
if (logger.isDebugEnabled()) logger.debug("Generating form for item: " + workflowDef);
|
||||
|
||||
// generate the form for the workflow definition
|
||||
form.getItem().setType(workflowDef.name);
|
||||
form.getItem().setUrl("/api/workflow-definition/" + workflowDef.id);
|
||||
|
||||
// get the type of the start task for the workflow definition
|
||||
TypeDefinition typeDef = workflowDef.getStartTaskDefinition().metadata;
|
||||
|
||||
if (fields != null && fields.size() > 0)
|
||||
{
|
||||
generateSelectedFields(null, typeDef, fields, forcedFields, form);
|
||||
}
|
||||
else
|
||||
{
|
||||
// setup field definitions and data
|
||||
generateAllPropertyFields(typeDef, form);
|
||||
generateAllAssociationFields(typeDef, form);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) logger.debug("Generating form: " + form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the field definitions for all the type's properties.
|
||||
*
|
||||
* @param typeDef The type being setup
|
||||
* @param form The Form instance to populate
|
||||
*/
|
||||
protected void generateAllPropertyFields(TypeDefinition typeDef, Form form)
|
||||
{
|
||||
// iterate round the property defintions and setup field definition
|
||||
Map<QName, PropertyDefinition> propDefs = typeDef.getProperties();
|
||||
for (PropertyDefinition propDef : propDefs.values())
|
||||
{
|
||||
generatePropertyField(propDef, form, this.namespaceService);
|
||||
}
|
||||
|
||||
// get all default aspects for the type and iterate round their
|
||||
// property definitions too
|
||||
List<AspectDefinition> aspects = typeDef.getDefaultAspects(true);
|
||||
for (AspectDefinition aspect : aspects)
|
||||
{
|
||||
propDefs = aspect.getProperties();
|
||||
for (PropertyDefinition propDef : propDefs.values())
|
||||
{
|
||||
generatePropertyField(propDef, form, this.namespaceService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the field definitions for all the type's associations.
|
||||
*
|
||||
* @param typeDef The type being setup
|
||||
* @param form The Form instance to populate
|
||||
*/
|
||||
protected void generateAllAssociationFields(TypeDefinition typeDef, Form form)
|
||||
{
|
||||
// iterate round the association defintions and setup field definition
|
||||
Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations();
|
||||
for (AssociationDefinition assocDef : assocDefs.values())
|
||||
{
|
||||
generateAssociationField(assocDef, form, this.namespaceService);
|
||||
}
|
||||
|
||||
// get all default aspects for the type and iterate round their
|
||||
// association definitions too
|
||||
List<AspectDefinition> aspects = typeDef.getDefaultAspects(true);
|
||||
for (AspectDefinition aspect : aspects)
|
||||
{
|
||||
assocDefs = aspect.getAssociations();
|
||||
for (AssociationDefinition assocDef : assocDefs.values())
|
||||
{
|
||||
generateAssociationField(assocDef, form, this.namespaceService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @see
|
||||
* org.alfresco.repo.forms.processor.node.NodeFormProcessor#internalPersist
|
||||
* (java.lang.Object, org.alfresco.repo.forms.FormData)
|
||||
*/
|
||||
@Override
|
||||
protected WorkflowInstance internalPersist(WorkflowDefinition workflowDef, final FormData data)
|
||||
{
|
||||
if (logger.isDebugEnabled()) logger.debug("Persisting form for: " + workflowDef);
|
||||
|
||||
WorkflowInstance workflow = null;
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>(8);
|
||||
|
||||
// create a package for the workflow
|
||||
NodeRef workflowPackage = this.workflowService.createPackage(null);
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, workflowPackage);
|
||||
|
||||
// TODO: iterate through form data to collect properties, for now
|
||||
// just hardcode the ones we know
|
||||
params.put(WorkflowModel.PROP_DESCRIPTION,
|
||||
(Serializable)data.getFieldData("prop_bpm_description").getValue());
|
||||
|
||||
NodeRef assignee = new NodeRef(data.getFieldData("assoc_bpm_assignee_added").getValue().toString());
|
||||
ArrayList<NodeRef> assigneeList = new ArrayList<NodeRef>(1);
|
||||
assigneeList.add(assignee);
|
||||
params.put(WorkflowModel.ASSOC_ASSIGNEE, assigneeList);
|
||||
|
||||
// TODO: add any package items
|
||||
|
||||
// TODO: add any context (this could re-use alf_destination)
|
||||
|
||||
// start the workflow to get access to the start task
|
||||
WorkflowPath path = this.workflowService.startWorkflow(workflowDef.getId(), params);
|
||||
if (path != null)
|
||||
{
|
||||
// get hold of the workflow instance for returning
|
||||
workflow = path.instance;
|
||||
|
||||
// extract the start task
|
||||
List<WorkflowTask> tasks = this.workflowService.getTasksForWorkflowPath(path.id);
|
||||
if (tasks.size() == 1)
|
||||
{
|
||||
WorkflowTask startTask = tasks.get(0);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found start task:" + startTask);
|
||||
|
||||
if (startTask.state == WorkflowTaskState.IN_PROGRESS)
|
||||
{
|
||||
// end the start task to trigger the first 'proper'
|
||||
// task in the workflow
|
||||
this.workflowService.endTask(startTask.id, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Started workflow: " + workflowDef.getId());
|
||||
}
|
||||
|
||||
// return the workflow just started
|
||||
return workflow;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user