/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.xmlui.aspect.workflow;
import org.apache.cocoon.environment.Request;
import org.apache.log4j.Logger;
import org.dspace.app.util.*;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.content.WorkspaceItem;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.handle.HandleManager;
import org.dspace.submit.AbstractProcessingStep;
import org.dspace.workflow.WorkflowItem;
import org.dspace.workflow.WorkflowManager;
import javax.servlet.ServletException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
/**
* This is a utility class to aid in the workflow flow scripts.
* Since data validation is cumbersome inside a flow script this
* is a collection of methods to perform processing at each step
* of the flow, the flow script will ties these operations
* together in a meaningful order but all actually processing
* is done through these various processes.
*
* @author Bram De Schouwer (bram.deschouwer at dot com)
* @author Kevin Van de Velde (kevin at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
* @author Mark Diggory (markd at atmire dot com)
*/
public class FlowUtils {
private static final Logger log = Logger.getLogger(FlowUtils.class);
/**
* Update the provided workflowItem to advance to the next workflow
* step. If this was the last thing needed before the item is
* committed to the repository then return true, otherwise false.
*
* @param context The current DSpace content
* @param id The unique ID of the current workflow
*/
public static boolean processApproveTask(Context context, String id) throws SQLException, UIException, ServletException, AuthorizeException, IOException
{
WorkflowItem workflowItem = findWorkflow(context, id);
Item item = workflowItem.getItem();
// Advance the item along the workflow
WorkflowManager.advance(context, workflowItem, context.getCurrentUser());
// FIXME: This should be a return value from advance()
// See if that gave the item a Handle. If it did,
// the item made it into the archive, so we
// should display a suitable page.
String handle = HandleManager.findHandle(context, item);
context.commit();
if (handle != null)
{
return true;
}
else
{
return false;
}
}
/**
* Return the given task back to the pool of unclaimed tasks for another user
* to select and preform.
*
* @param context The current DSpace content
* @param id The unique ID of the current workflow
*/
public static void processUnclaimTask(Context context, String id) throws SQLException, UIException, ServletException, AuthorizeException, IOException
{
WorkflowItem workflowItem = findWorkflow(context, id);
// Return task to pool
WorkflowManager.unclaim(context, workflowItem, context.getCurrentUser());
context.commit();
//Log this unclaim action
log.info(LogManager.getHeader(context, "unclaim_workflow",
"workflow_item_id=" + workflowItem.getID() + ",item_id="
+ workflowItem.getItem().getID() + ",collection_id="
+ workflowItem.getCollection().getID()
+ ",new_state=" + workflowItem.getState()));
}
/**
* Claim this task from the pool of unclaimed task so that this user may
* preform the task by either approving or rejecting it.
*
* @param context The current DSpace content
* @param id The unique ID of the current workflow
*/
public static void processClaimTask(Context context, String id) throws SQLException, UIException, ServletException, AuthorizeException, IOException
{
WorkflowItem workflowItem = findWorkflow(context, id);
if(workflowItem.getState() != WorkflowManager.WFSTATE_STEP1POOL &&
workflowItem.getState() != WorkflowManager.WFSTATE_STEP2POOL &&
workflowItem.getState() != WorkflowManager.WFSTATE_STEP3POOL){
//Only allow tasks in the pool to be claimed !
throw new AuthorizeException("Error while claiming task: this task has already been claimed !");
}
// Claim the task
WorkflowManager.claim(context, workflowItem, context.getCurrentUser());
context.commit();
//log this claim information
log.info(LogManager.getHeader(context, "claim_task", "workflow_item_id="
+ workflowItem.getID() + "item_id=" + workflowItem.getItem().getID()
+ "collection_id=" + workflowItem.getCollection().getID()
+ "newowner_id=" + workflowItem.getOwner().getID()
+ "new_state=" + workflowItem.getState()));
}
/**
* Verifies if the currently logged in user has proper rights to perform the workflow task on the item
* @param context the current dspace context
* @param workflowItemId the identifier of the workflow item
* @throws org.dspace.authorize.AuthorizeException thrown if the user doesn't have sufficient rights to perform the task at hand
* @throws java.sql.SQLException is thrown when something is wrong with the database
*/
public static void authorizeWorkflowItem(Context context, String workflowItemId) throws AuthorizeException, SQLException {
WorkflowItem workflowItem = WorkflowItem.find(context, Integer.parseInt(workflowItemId.substring(1)));
if((workflowItem.getState() == WorkflowManager.WFSTATE_STEP1 ||
workflowItem.getState() == WorkflowManager.WFSTATE_STEP2 ||
workflowItem.getState() == WorkflowManager.WFSTATE_STEP3) && workflowItem.getOwner().getID() != context.getCurrentUser().getID()){
throw new AuthorizeException("You are not allowed to perform this task.");
}else
if((workflowItem.getState() == WorkflowManager.WFSTATE_STEP1POOL ||
workflowItem.getState() == WorkflowManager.WFSTATE_STEP2POOL ||
workflowItem.getState() == WorkflowManager.WFSTATE_STEP3POOL)){
//Verify if the current user has the current workflowItem among his pooled tasks
boolean hasPooledTask = false;
List<WorkflowItem> pooledTasks = WorkflowManager.getPooledTasks(context, context.getCurrentUser());
for (WorkflowItem pooledItem : pooledTasks) {
if(pooledItem.getID() == workflowItem.getID()){
hasPooledTask = true;
}
}
if(!hasPooledTask){
throw new AuthorizeException("You are not allowed to perform this task.");
}
}
}
/**
* Reject the given task for the given reason. If the user did not provide
* a reason then an error is generated placing that field in error.
*
* @param context The current DSpace content
* @param id The unique ID of the current workflow
* @param request The current request object
*/
public static String processRejectTask(Context context, String id,Request request) throws SQLException, UIException, ServletException, AuthorizeException, IOException
{
WorkflowItem workflowItem = findWorkflow(context, id);
String reason = request.getParameter("reason");
if (reason != null && reason.length() > 1)
{
WorkspaceItem wsi = WorkflowManager.reject(context, workflowItem,context.getCurrentUser(), reason);
//Load the Submission Process for the collection this WSI is associated with
Collection c = wsi.getCollection();
SubmissionConfigReader subConfigReader = new SubmissionConfigReader();
SubmissionConfig subConfig = subConfigReader.getSubmissionConfig(c.getHandle(), false);
// Set the "stage_reached" column on the workspace item
// to the LAST page of the LAST step in the submission process
// (i.e. the page just before "Complete", which is at NumSteps-1)
int lastStep = subConfig.getNumberOfSteps()-2;
wsi.setStageReached(lastStep);
wsi.setPageReached(AbstractProcessingStep.LAST_PAGE_REACHED);
wsi.update();
context.commit();
//Submission rejected. Log this information
log.info(LogManager.getHeader(context, "reject_workflow", "workflow_item_id="
+ wsi.getID() + "item_id=" + wsi.getItem().getID()
+ "collection_id=" + wsi.getCollection().getID()
+ "eperson_id=" + context.getCurrentUser().getID()));
// Return no errors.
return null;
}
else
{
// If the user did not supply a reason then
// place the reason field in error.
return "reason";
}
}
/**
* Return the workflow identified by the given id, the id should be
* prepended with the character S to signify that it is a workflow
* instead of a workspace.
*
* @param context
* @param inProgressSubmissionID
* @return The found workflowitem or null if none found.
*/
public static WorkflowItem findWorkflow(Context context, String inProgressSubmissionID) throws SQLException, AuthorizeException, IOException {
int id = Integer.valueOf(inProgressSubmissionID.substring(1));
return WorkflowItem.find(context, id);
}
}