/* * Creates a task pool for a given step */ @Override public void createPoolTasks( Context context, XmlWorkflowItem wi, RoleMembers assignees, Step step, WorkflowActionConfig action) throws SQLException, AuthorizeException { // create a tasklist entry for each eperson for (EPerson anEpa : assignees.getEPersons()) { PoolTask task = poolTaskService.create(context); task.setStepID(step.getId()); task.setWorkflowID(step.getWorkflow().getID()); task.setEperson(anEpa); task.setActionID(action.getId()); task.setWorkflowItem(wi); poolTaskService.update(context, task); // Make sure this user has a task grantUserAllItemPolicies(context, wi.getItem(), anEpa); } for (Group group : assignees.getGroups()) { PoolTask task = poolTaskService.create(context); task.setStepID(step.getId()); task.setWorkflowID(step.getWorkflow().getID()); task.setGroup(group); task.setActionID(action.getId()); task.setWorkflowItem(wi); poolTaskService.update(context, task); // Make sure this user has a task grantGroupAllItemPolicies(context, wi.getItem(), group); } }
/* * Deletes an eperson from the taskpool of a step */ @Override public void deletePooledTask(Context context, XmlWorkflowItem wi, PoolTask task) throws SQLException, AuthorizeException { if (task != null) { if (task.getEperson() != null) { removeUserItemPolicies(context, wi.getItem(), task.getEperson()); } else { removeGroupItemPolicies(context, wi.getItem(), task.getGroup()); } poolTaskService.delete(context, task); } }
@Override public void deleteClaimedTask(Context c, XmlWorkflowItem wi, ClaimedTask task) throws SQLException, AuthorizeException { if (task != null) { removeUserItemPolicies(c, wi.getItem(), task.getOwner()); claimedTaskService.delete(c, task); } }
@Override public void alertUsersOnTaskActivation( Context c, XmlWorkflowItem wfi, String emailTemplate, List<EPerson> epa, String... arguments) throws IOException, SQLException, MessagingException { if (noEMail.containsKey(wfi.getItem().getID())) { // suppress email, and delete key noEMail.remove(wfi.getItem().getID()); } else { Email mail = Email.getEmail(I18nUtil.getEmailFilename(c.getCurrentLocale(), emailTemplate)); for (String argument : arguments) { mail.addArgument(argument); } for (EPerson anEpa : epa) { mail.addRecipient(anEpa.getEmail()); } mail.send(); } }
@Override public void removeClaimedUser(Context context, XmlWorkflowItem wfi, EPerson user, String stepID) throws SQLException, IOException, WorkflowConfigurationException, AuthorizeException { // Check if we had reached our max number @ this moment int totalUsers = inProgressUserService.getNumberOfInProgressUsers(context, wfi) + inProgressUserService.getNumberOfFinishedUsers(context, wfi); // Then remove the current user from the inProgressUsers inProgressUserService.delete( context, inProgressUserService.findByWorkflowItemAndEPerson(context, wfi, user)); Workflow workflow = workflowFactory.getWorkflow(wfi.getCollection()); Step step = workflow.getStep(stepID); // WorkflowManager.deleteOwnedTask(c, user, wfi, step, step.getActionConfig()); // We had reached our total user, so recreate tasks for the user who don't have one if (totalUsers == step.getRequiredUsers()) { // Create a list of the users we are to ignore List<InProgressUser> toIgnore = inProgressUserService.findByWorkflowItem(context, wfi); // Remove the users to ignore RoleMembers roleMembers = step.getRole().getMembers(context, wfi); // Create a list out all the users we are to pool a task for for (InProgressUser ipu : toIgnore) { roleMembers.removeEperson(ipu.getUser()); } step.getUserSelectionMethod() .getProcessingAction() .regenerateTasks(context, wfi, roleMembers); } else { // If the user previously had a personal PoolTask, this must be regenerated. Therefore we call // the regeneration method // with only one EPerson RoleMembers role = step.getRole().getMembers(context, wfi); List<EPerson> epersons = role.getEPersons(); for (EPerson eperson : epersons) { if (eperson.getID().equals(user.getID())) { RoleMembers memberToRegenerateTasksFor = new RoleMembers(); memberToRegenerateTasksFor.addEPerson(user); step.getUserSelectionMethod() .getProcessingAction() .regenerateTasks(context, wfi, memberToRegenerateTasksFor); break; } } } // Update our item itemService.update(context, wfi.getItem()); }
protected void activateFirstStep( Context context, Workflow wf, Step firstStep, XmlWorkflowItem wfi) throws AuthorizeException, IOException, SQLException, WorkflowException, WorkflowConfigurationException { WorkflowActionConfig firstActionConfig = firstStep.getUserSelectionMethod(); firstActionConfig.getProcessingAction().activate(context, wfi); log.info( LogManager.getHeader( context, "start_workflow", firstActionConfig.getProcessingAction() + " workflow_item_id=" + wfi.getID() + "item_id=" + wfi.getItem().getID() + "collection_id=" + wfi.getCollection().getID())); // record the start of the workflow w/provenance message recordStart(context, wfi.getItem(), firstActionConfig.getProcessingAction()); // Fire an event ! logWorkflowEvent( context, firstStep.getWorkflow().getID(), null, null, wfi, null, firstStep, firstActionConfig); // If we don't have a UI activate it if (!firstActionConfig.requiresUI()) { ActionResult outcome = firstActionConfig.getProcessingAction().execute(context, wfi, firstStep, null); processOutcome(context, null, wf, firstStep, firstActionConfig, outcome, wfi, true); } }
/* * Claims an action for a given eperson */ @Override public void createOwnedTask( Context context, XmlWorkflowItem wi, Step step, WorkflowActionConfig action, EPerson e) throws SQLException, AuthorizeException { ClaimedTask task = claimedTaskService.create(context); task.setWorkflowItem(wi); task.setStepID(step.getId()); task.setActionID(action.getId()); task.setOwner(e); task.setWorkflowID(step.getWorkflow().getID()); claimedTaskService.update(context, task); // Make sure this user has a task grantUserAllItemPolicies(context, wi.getItem(), e); }
/** * Commit the contained item to the main archive. The item is associated with the relevant * collection, added to the search index, and any other tasks such as assigning dates are * performed. * * @param context The relevant DSpace Context. * @param wfi workflow item * @return the fully archived item. * @throws IOException A general class of exceptions produced by failed or interrupted I/O * operations. * @throws SQLException An exception that provides information on a database access error or other * errors. * @throws AuthorizeException Exception indicating the current user of the context does not have * permission to perform a particular action. */ @Override public Item archive(Context context, XmlWorkflowItem wfi) throws SQLException, IOException, AuthorizeException { // FIXME: Check auth Item item = wfi.getItem(); Collection collection = wfi.getCollection(); // Remove (if any) the workflowItemroles for this item workflowItemRoleService.deleteForWorkflowItem(context, wfi); log.info( LogManager.getHeader( context, "archive_item", "workflow_item_id=" + wfi.getID() + "item_id=" + item.getID() + "collection_id=" + collection.getID())); installItemService.installItem(context, wfi); // Notify notifyOfArchive(context, item, collection); // Clear any remaining workflow metadata itemService.clearMetadata( context, item, WorkflowRequirementsService.WORKFLOW_SCHEMA, Item.ANY, Item.ANY, Item.ANY); itemService.update(context, item); // Log the event log.info( LogManager.getHeader( context, "install_item", "workflow_item_id=" + wfi.getID() + ", item_id=" + item.getID() + "handle=FIXME")); return item; }
/** * Return the workflow item to the workspace of the submitter. The workflow item is removed, and a * workspace item created. * * @param c Context * @param wfi WorkflowItem to be 'dismantled' * @return the workspace item * @throws java.io.IOException ... * @throws java.sql.SQLException ... * @throws org.dspace.authorize.AuthorizeException ... */ protected WorkspaceItem returnToWorkspace(Context c, XmlWorkflowItem wfi) throws SQLException, IOException, AuthorizeException { // authorize a DSpaceActions.REJECT // stop workflow deleteAllTasks(c, wfi); c.turnOffAuthorisationSystem(); // Also clear all info for this step workflowRequirementsService.clearInProgressUsers(c, wfi); // Remove (if any) the workflowItemroles for this item workflowItemRoleService.deleteForWorkflowItem(c, wfi); Item myitem = wfi.getItem(); // Restore permissions for the submitter grantUserAllItemPolicies(c, myitem, myitem.getSubmitter()); // FIXME: How should this interact with the workflow system? // FIXME: Remove license // FIXME: Provenance statement? // Create the new workspace item row WorkspaceItem workspaceItem = workspaceItemService.create(c, wfi); workspaceItem.setMultipleFiles(wfi.hasMultipleFiles()); workspaceItem.setMultipleTitles(wfi.hasMultipleTitles()); workspaceItem.setPublishedBefore(wfi.isPublishedBefore()); workspaceItemService.update(c, workspaceItem); // myitem.update(); log.info( LogManager.getHeader( c, "return_to_workspace", "workflow_item_id=" + wfi.getID() + "workspace_item_id=" + workspaceItem.getID())); // Now remove the workflow object manually from the database xmlWorkflowItemService.deleteWrapper(c, wfi); return workspaceItem; }
protected void notifyOfReject(Context c, XmlWorkflowItem wi, EPerson e, String reason) { try { // Get the item title String title = wi.getItem().getName(); // Get the collection Collection coll = wi.getCollection(); // Get rejector's name String rejector = getEPersonName(e); Locale supportedLocale = I18nUtil.getEPersonLocale(e); Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_reject")); email.addRecipient(wi.getSubmitter().getEmail()); email.addArgument(title); email.addArgument(coll.getName()); email.addArgument(rejector); email.addArgument(reason); email.addArgument(ConfigurationManager.getProperty("dspace.url") + "/mydspace"); email.send(); } catch (Exception ex) { // log this email error log.warn( LogManager.getHeader( c, "notify_of_reject", "cannot email user" + " eperson_id" + e.getID() + " eperson_email" + e.getEmail() + " workflow_item_id" + wi.getID())); } }
@Override public WorkspaceItem sendWorkflowItemBackSubmission( Context context, XmlWorkflowItem wi, EPerson e, String provenance, String rejection_message) throws SQLException, AuthorizeException, IOException { String workflowID = null; String currentStepId = null; String currentActionConfigId = null; ClaimedTask claimedTask = claimedTaskService.findByWorkflowIdAndEPerson(context, wi, e); if (claimedTask != null) { // Log it workflowID = claimedTask.getWorkflowID(); currentStepId = claimedTask.getStepID(); currentActionConfigId = claimedTask.getActionID(); } context.turnOffAuthorisationSystem(); // rejection provenance Item myitem = wi.getItem(); // Get current date String now = DCDate.getCurrent().toString(); // Get user's name + email address String usersName = getEPersonName(e); // Here's what happened String provDescription = provenance + " Rejected by " + usersName + ", reason: " + rejection_message + " on " + now + " (GMT) "; // Add to item as a DC field itemService.addMetadata( context, myitem, MetadataSchema.DC_SCHEMA, "description", "provenance", "en", provDescription); // Clear any workflow schema related metadata itemService.clearMetadata( context, myitem, WorkflowRequirementsService.WORKFLOW_SCHEMA, Item.ANY, Item.ANY, Item.ANY); itemService.update(context, myitem); // convert into personal workspace WorkspaceItem wsi = returnToWorkspace(context, wi); // notify that it's been rejected notifyOfReject(context, wi, e, rejection_message); log.info( LogManager.getHeader( context, "reject_workflow", "workflow_item_id=" + wi.getID() + "item_id=" + wi.getItem().getID() + "collection_id=" + wi.getCollection().getID() + "eperson_id=" + e.getID())); logWorkflowEvent(context, workflowID, currentStepId, currentActionConfigId, wi, e, null, null); context.restoreAuthSystemState(); return wsi; }
protected void logWorkflowEvent( Context c, String workflowId, String previousStepId, String previousActionConfigId, XmlWorkflowItem wfi, EPerson actor, Step newStep, WorkflowActionConfig newActionConfig) throws SQLException { try { // Fire an event so we can log our action ! Item item = wfi.getItem(); Collection myCollection = wfi.getCollection(); String workflowStepString = null; List<EPerson> currentEpersonOwners = new ArrayList<EPerson>(); List<Group> currentGroupOwners = new ArrayList<Group>(); // These are only null if our item is sent back to the submission if (newStep != null && newActionConfig != null) { workflowStepString = workflowId + "." + newStep.getId() + "." + newActionConfig.getId(); // Retrieve the current owners of the task List<ClaimedTask> claimedTasks = claimedTaskService.find(c, wfi, newStep.getId()); List<PoolTask> pooledTasks = poolTaskService.find(c, wfi); for (PoolTask poolTask : pooledTasks) { if (poolTask.getEperson() != null) { currentEpersonOwners.add(poolTask.getEperson()); } else { currentGroupOwners.add(poolTask.getGroup()); } } for (ClaimedTask claimedTask : claimedTasks) { currentEpersonOwners.add(claimedTask.getOwner()); } } String previousWorkflowStepString = null; if (previousStepId != null && previousActionConfigId != null) { previousWorkflowStepString = workflowId + "." + previousStepId + "." + previousActionConfigId; } // Fire our usage event ! UsageWorkflowEvent usageWorkflowEvent = new UsageWorkflowEvent( c, item, wfi, workflowStepString, previousWorkflowStepString, myCollection, actor); usageWorkflowEvent.setEpersonOwners( currentEpersonOwners.toArray(new EPerson[currentEpersonOwners.size()])); usageWorkflowEvent.setGroupOwners( currentGroupOwners.toArray(new Group[currentGroupOwners.size()])); DSpaceServicesFactory.getInstance().getEventService().fireEvent(usageWorkflowEvent); } catch (Exception e) { // Catch all errors we do not want our workflow to crash because the logging threw an // exception log.error( LogManager.getHeader( c, "Error while logging workflow event", "Workflow Item: " + wfi.getID()), e); } }
@Override public WorkflowActionConfig processOutcome( Context c, EPerson user, Workflow workflow, Step currentStep, WorkflowActionConfig currentActionConfig, ActionResult currentOutcome, XmlWorkflowItem wfi, boolean enteredNewStep) throws IOException, AuthorizeException, SQLException, WorkflowException { if (currentOutcome.getType() == ActionResult.TYPE.TYPE_PAGE || currentOutcome.getType() == ActionResult.TYPE.TYPE_ERROR) { // Our outcome is a page or an error, so return our current action c.restoreAuthSystemState(); return currentActionConfig; } else if (currentOutcome.getType() == ActionResult.TYPE.TYPE_CANCEL || currentOutcome.getType() == ActionResult.TYPE.TYPE_SUBMISSION_PAGE) { // We either pressed the cancel button or got an order to return to the submission page, so // don't return an action // By not returning an action we ensure ourselfs that we go back to the submission page c.restoreAuthSystemState(); return null; } else if (currentOutcome.getType() == ActionResult.TYPE.TYPE_OUTCOME) { Step nextStep = null; WorkflowActionConfig nextActionConfig = null; try { // We have completed our action search & retrieve the next action if (currentOutcome.getResult() == ActionResult.OUTCOME_COMPLETE) { nextActionConfig = currentStep.getNextAction(currentActionConfig); } if (nextActionConfig != null) { // We remain in the current step since an action is found nextStep = currentStep; nextActionConfig.getProcessingAction().activate(c, wfi); if (nextActionConfig.requiresUI() && !enteredNewStep) { createOwnedTask(c, wfi, currentStep, nextActionConfig, user); return nextActionConfig; } else if (nextActionConfig.requiresUI() && enteredNewStep) { // We have entered a new step and have encountered a UI, return null since the current // user doesn't have anything to do with this c.restoreAuthSystemState(); return null; } else { ActionResult newOutcome = nextActionConfig.getProcessingAction().execute(c, wfi, currentStep, null); return processOutcome( c, user, workflow, currentStep, nextActionConfig, newOutcome, wfi, enteredNewStep); } } else if (enteredNewStep) { // If the user finished his/her step, we keep processing until there is a UI step action // or no step at all nextStep = workflow.getNextStep(c, wfi, currentStep, currentOutcome.getResult()); c.turnOffAuthorisationSystem(); nextActionConfig = processNextStep(c, user, workflow, currentOutcome, wfi, nextStep); // If we require a user interface return null so that the user is redirected to the // "submissions page" if (nextActionConfig == null || nextActionConfig.requiresUI()) { return null; } else { return nextActionConfig; } } else { ClaimedTask task = claimedTaskService.findByWorkflowIdAndEPerson(c, wfi, user); // Check if we have a task for this action (might not be the case with automatic steps) // First add it to our list of finished users, since no more actions remain workflowRequirementsService.addFinishedUser(c, wfi, user); c.turnOffAuthorisationSystem(); // Check if our requirements have been met if ((currentStep.isFinished(c, wfi) && currentOutcome.getResult() == ActionResult.OUTCOME_COMPLETE) || currentOutcome.getResult() != ActionResult.OUTCOME_COMPLETE) { // Delete all the table rows containing the users who performed this task workflowRequirementsService.clearInProgressUsers(c, wfi); // Remove all the tasks deleteAllTasks(c, wfi); nextStep = workflow.getNextStep(c, wfi, currentStep, currentOutcome.getResult()); nextActionConfig = processNextStep(c, user, workflow, currentOutcome, wfi, nextStep); // If we require a user interface return null so that the user is redirected to the // "submissions page" if (nextActionConfig == null || nextActionConfig.requiresUI()) { return null; } else { return nextActionConfig; } } else { // We are done with our actions so go to the submissions page but remove action // ClaimedAction first deleteClaimedTask(c, wfi, task); c.restoreAuthSystemState(); nextStep = currentStep; nextActionConfig = currentActionConfig; return null; } } } catch (Exception e) { log.error("error while processing workflow outcome", e); e.printStackTrace(); } finally { if ((nextStep != null && currentStep != null && nextActionConfig != null) || (wfi.getItem().isArchived() && currentStep != null)) { logWorkflowEvent( c, currentStep.getWorkflow().getID(), currentStep.getId(), currentActionConfig.getId(), wfi, user, nextStep, nextActionConfig); } } } log.error(LogManager.getHeader(c, "Invalid step outcome", "Workflow item id: " + wfi.getID())); throw new WorkflowException("Invalid step outcome"); }