Checkpoint for workflow features

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3518 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Gavin Cornwell
2006-08-15 14:46:43 +00:00
parent 168af80e4f
commit 66f1b61052
16 changed files with 647 additions and 151 deletions

View File

@@ -1,12 +1,24 @@
package org.alfresco.web.bean.workflow;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.transaction.UserTransaction;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.TransientNode;
import org.alfresco.web.config.DialogsConfigElement.DialogButtonConfig;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -17,51 +29,186 @@ import org.apache.commons.logging.LogFactory;
*/
public class ManageWorkItemDialog extends BaseDialogBean
{
private static final Log logger = LogFactory.getLog(ManageWorkItemDialog.class);
protected WorkflowService workflowService;
protected Node workItemNode;
protected WorkflowTask workItem;
protected String[] transitions;
protected static final String ID_PREFIX = "transition_";
protected static final String CLIENT_ID_PREFIX = "dialog:" + ID_PREFIX;
private static final Log logger = LogFactory.getLog(ManageWorkItemDialog.class);
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
String taskId = this.parameters.get("id");
this.workItem = this.workflowService.getTaskById(taskId);
if (this.workItem != null)
{
// setup a transient node to represent the work item we're managing
WorkflowTaskDefinition taskDef = this.workItem.definition;
this.workItemNode = new TransientNode(taskDef.metadata.getName(),
"task_" + System.currentTimeMillis(), this.workItem.properties);
if (logger.isDebugEnabled())
logger.debug("Created node for work item: " + this.workItemNode);
}
}
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
return null;
if (logger.isDebugEnabled())
logger.debug("Saving work item with params: " + this.workItemNode.getProperties());
// prepare the edited parameters for saving
Map<QName, Serializable> params = WorkflowBean.prepareWorkItemParams(this.workItemNode);
// update the task with the updated parameters
this.workflowService.updateTask(this.workItem.id, params, null, null);
return outcome;
}
@Override
public List<DialogButtonConfig> getAdditionalButtons()
{
List<DialogButtonConfig> buttons = new ArrayList<DialogButtonConfig>(1);
buttons.add(new DialogButtonConfig("reassign-button",
"Reassign", null, "#{ManageWorkItemDialog.reassign}", "false", null));
List<DialogButtonConfig> buttons = null;
if (this.workItem != null)
{
// get the transitions available from this work item and
// show them in the dialog as additional buttons
this.transitions = this.workItem.path.node.transitions;
if (this.transitions != null)
{
buttons = new ArrayList<DialogButtonConfig>(this.transitions.length);
for (String trans : this.transitions)
{
// TODO: Tidy this up when the service returns the list of labels
String label = trans;
if (label.length() == 0)
{
label = "Done";
}
buttons.add(new DialogButtonConfig(ID_PREFIX + trans, label, null,
"#{DialogManager.bean.transition}", "false", null));
}
}
}
return buttons;
return buttons;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "save");
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
// ------------------------------------------------------------------------------
// Event handlers
public void approve()
@SuppressWarnings("unused")
public String transition()
{
logger.info("approve button was pressed");
}
public void reject()
{
logger.info("reject button was pressed");
}
public void reassign()
{
logger.info("reassign button was pressed");
String outcome = getDefaultFinishOutcome();
// to find out which transition button was pressed we need
// to look for the button's id in the request parameters,
// the first non-null result is the button that was pressed.
FacesContext context = FacesContext.getCurrentInstance();
Map reqParams = context.getExternalContext().getRequestParameterMap();
String selectedTransition = null;
for (String trans : this.transitions)
{
Object result = reqParams.get(CLIENT_ID_PREFIX + trans);
if (result != null)
{
// this was the button that was pressed
selectedTransition = trans;
break;
}
}
if (selectedTransition != null)
{
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(context);
tx.begin();
// prepare the edited parameters for saving
Map<QName, Serializable> params = WorkflowBean.prepareWorkItemParams(this.workItemNode);
// update the task with the updated parameters
this.workflowService.updateTask(this.workItem.id, params, null, null);
// signal the selected transition to the workflow task
this.workflowService.endTask(this.workItem.id, selectedTransition);
// commit the changes
tx.commit();
if (logger.isDebugEnabled())
logger.debug("Ended work item with transition: " + selectedTransition);
}
catch (Throwable e)
{
// reset the flag so we can re-attempt the operation
isFinished = false;
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
Utils.addErrorMessage(formatErrorMessage(e));
outcome = this.getErrorOutcome(e);
}
}
return outcome;
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
public boolean getApproveDisabled()
/**
* Returns the Node representing the work item
*
* @return The node
*/
public Node getWorkItemNode()
{
return true;
return this.workItemNode;
}
/**
* Sets the workflow service to use
*
* @param workflowService
* WorkflowService instance
*/
public void setWorkflowService(WorkflowService workflowService)
{
this.workflowService = workflowService;
}
}

View File

@@ -1,6 +1,5 @@
package org.alfresco.web.bean.workflow;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -10,18 +9,14 @@ import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
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.WorkflowTaskDefinition;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.TransientNode;
import org.alfresco.web.bean.wizard.BaseWizardBean;
import org.apache.commons.logging.Log;
@@ -74,7 +69,8 @@ public class StartWorkflowWizard extends BaseWizardBean
logger.debug("Starting workflow with params: " + this.startTaskNode.getProperties());
// start the workflow to get access to the start task
WorkflowPath path = this.workflowService.startWorkflow(this.selectedWorkflow, prepareTaskParams());
WorkflowPath path = this.workflowService.startWorkflow(this.selectedWorkflow,
WorkflowBean.prepareWorkItemParams(this.startTaskNode));
if (path != null)
{
// extract the start task
@@ -239,48 +235,4 @@ public class StartWorkflowWizard extends BaseWizardBean
{
this.workflowService = workflowService;
}
protected Map<QName, Serializable> prepareTaskParams()
{
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
// marshal the properties and associations captured by the property sheet
// back into a Map to pass to the workflow service
// go through all the properties in the transient node and add them to
// params map
Map<String, Object> props = this.startTaskNode.getProperties();
for (String propName : props.keySet())
{
QName propQName = Repository.resolveToQName(propName);
params.put(propQName, (Serializable)props.get(propName));
}
// go through any associations that have been added to the start task
// and build a list of NodeRefs representing the targets
Map<String, Map<String, AssociationRef>> assocs = this.startTaskNode.getAddedAssociations();
for (String assocName : assocs.keySet())
{
QName assocQName = Repository.resolveToQName(assocName);
// get the associations added and create list of targets
Map<String, AssociationRef> addedAssocs = assocs.get(assocName);
List<NodeRef> targets = new ArrayList<NodeRef>(addedAssocs.size());
for (AssociationRef assoc : addedAssocs.values())
{
targets.add(assoc.getTargetRef());
}
// add the targets for this particular association
params.put(assocQName, (Serializable)targets);
}
// String reviewer = (String)this.startTaskNode.getProperties().get(
// ContentModel.PROP_NAME);
// Map<QName, Serializable> params = new HashMap<QName, Serializable>(1);
// params.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), reviewer);
return params;
}
}

View File

@@ -0,0 +1,140 @@
package org.alfresco.web.bean.workflow;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.TransientMapNode;
import org.alfresco.web.bean.repository.User;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Managed bean used for handling workflow related features
*
* @author gavinc
*/
public class WorkflowBean
{
protected WorkflowService workflowService;
protected List<Node> workItems;
private static final Log logger = LogFactory.getLog(WorkflowBean.class);
// ------------------------------------------------------------------------------
// Bean Getters and Setters
public List<Node> getWorkItemsToDo()
{
// get the current username
FacesContext fc = FacesContext.getCurrentInstance();
User user = Application.getCurrentUser(fc);
String userName = ISO9075.encode(user.getUserName());
// get the current in progress tasks for the current user
List<WorkflowTask> tasks = this.workflowService.getAssignedTasks(
userName, WorkflowTaskState.IN_PROGRESS);
// create a list of transient nodes to represent
this.workItems = new ArrayList<Node>(tasks.size());
for (WorkflowTask task : tasks)
{
createWorkItem(task);
}
return this.workItems;
}
/**
* Sets the workflow service to use
*
* @param workflowService WorkflowService instance
*/
public void setWorkflowService(WorkflowService workflowService)
{
this.workflowService = workflowService;
}
// ------------------------------------------------------------------------------
// Helper methods
public static Map<QName, Serializable> prepareWorkItemParams(Node node)
{
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
// marshal the properties and associations captured by the property sheet
// back into a Map to pass to the workflow service
// go through all the properties in the transient node and add them to
// params map
Map<String, Object> props = node.getProperties();
for (String propName : props.keySet())
{
QName propQName = Repository.resolveToQName(propName);
params.put(propQName, (Serializable)props.get(propName));
}
// go through any associations that have been added to the start task
// and build a list of NodeRefs representing the targets
Map<String, Map<String, AssociationRef>> assocs = node.getAddedAssociations();
for (String assocName : assocs.keySet())
{
QName assocQName = Repository.resolveToQName(assocName);
// get the associations added and create list of targets
Map<String, AssociationRef> addedAssocs = assocs.get(assocName);
List<NodeRef> targets = new ArrayList<NodeRef>(addedAssocs.size());
for (AssociationRef assoc : addedAssocs.values())
{
targets.add(assoc.getTargetRef());
}
// add the targets for this particular association
params.put(assocQName, (Serializable)targets);
}
return params;
}
/**
* Creates and populates a TransientNode to represent the given
* workflow task from the repository workflow engine
*
* @param task The task to create a representation of
*/
protected void createWorkItem(WorkflowTask task)
{
// get the type of the task
WorkflowTaskDefinition taskDef = task.definition;
// create the basic transient node
TransientMapNode node = new TransientMapNode(taskDef.metadata.getName(),
task.name, task.properties);
// add properties for the other useful metadata
node.getProperties().put(ContentModel.PROP_NAME.toString(), task.name);
node.getProperties().put("type", taskDef.metadata.getTitle());
node.getProperties().put("id", task.id);
if (logger.isDebugEnabled())
logger.debug("Created node for work item with id '" + task.id + "' " + node);
this.workItems.add(node);
}
}